Initial WebM release
diff --git a/vp8/common/alloccommon.c b/vp8/common/alloccommon.c
new file mode 100644
index 0000000..ac110f7
--- /dev/null
+++ b/vp8/common/alloccommon.c
@@ -0,0 +1,251 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "blockd.h"
+#include "vpx_mem/vpx_mem.h"
+#include "onyxc_int.h"
+#include "findnearmv.h"
+#include "entropymode.h"
+#include "systemdependent.h"
+#include "vpxerrors.h"
+
+#ifdef HAVE_CONFIG_H
+#include "vpx_config.h"
+#endif
+
+extern  void vp8_init_scan_order_mask();
+
+void vp8_update_mode_info_border(MODE_INFO *mi, int rows, int cols)
+{
+    int i;
+    vpx_memset(mi - cols - 1, 0, sizeof(MODE_INFO) * cols + 1);
+
+    for (i = 0; i < rows; i++)
+    {
+        vpx_memset(&mi[i*cols-1], 0, sizeof(MODE_INFO));
+    }
+}
+void vp8_de_alloc_frame_buffers(VP8_COMMON *oci)
+{
+    vp8_yv12_de_alloc_frame_buffer(&oci->temp_scale_frame);
+    vp8_yv12_de_alloc_frame_buffer(&oci->new_frame);
+    vp8_yv12_de_alloc_frame_buffer(&oci->last_frame);
+    vp8_yv12_de_alloc_frame_buffer(&oci->golden_frame);
+    vp8_yv12_de_alloc_frame_buffer(&oci->alt_ref_frame);
+    vp8_yv12_de_alloc_frame_buffer(&oci->post_proc_buffer);
+
+    vpx_free(oci->above_context[Y1CONTEXT]);
+    vpx_free(oci->above_context[UCONTEXT]);
+    vpx_free(oci->above_context[VCONTEXT]);
+    vpx_free(oci->above_context[Y2CONTEXT]);
+    vpx_free(oci->mip);
+
+    oci->above_context[Y1CONTEXT] = 0;
+    oci->above_context[UCONTEXT]  = 0;
+    oci->above_context[VCONTEXT]  = 0;
+    oci->above_context[Y2CONTEXT] = 0;
+    oci->mip = 0;
+
+    // Structure used to minitor GF useage
+    if (oci->gf_active_flags != 0)
+        vpx_free(oci->gf_active_flags);
+
+    oci->gf_active_flags = 0;
+}
+
+int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height)
+{
+    vp8_de_alloc_frame_buffers(oci);
+
+    // our internal buffers are always multiples of 16
+    if ((width & 0xf) != 0)
+        width += 16 - (width & 0xf);
+
+    if ((height & 0xf) != 0)
+        height += 16 - (height & 0xf);
+
+
+    if (vp8_yv12_alloc_frame_buffer(&oci->temp_scale_frame,   width, 16, VP8BORDERINPIXELS) < 0)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return ALLOC_FAILURE;
+    }
+
+
+    if (vp8_yv12_alloc_frame_buffer(&oci->new_frame,   width, height, VP8BORDERINPIXELS) < 0)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return ALLOC_FAILURE;
+    }
+
+    if (vp8_yv12_alloc_frame_buffer(&oci->last_frame,  width, height, VP8BORDERINPIXELS) < 0)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return ALLOC_FAILURE;
+    }
+
+    if (vp8_yv12_alloc_frame_buffer(&oci->golden_frame, width, height, VP8BORDERINPIXELS) < 0)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return ALLOC_FAILURE;
+    }
+
+    if (vp8_yv12_alloc_frame_buffer(&oci->alt_ref_frame, width, height, VP8BORDERINPIXELS) < 0)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return ALLOC_FAILURE;
+    }
+
+    if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer, width, height, VP8BORDERINPIXELS) < 0)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return ALLOC_FAILURE;
+    }
+
+    oci->mb_rows = height >> 4;
+    oci->mb_cols = width >> 4;
+    oci->MBs = oci->mb_rows * oci->mb_cols;
+    oci->mode_info_stride = oci->mb_cols + 1;
+    oci->mip = vpx_calloc((oci->mb_cols + 1) * (oci->mb_rows + 1), sizeof(MODE_INFO));
+
+    if (!oci->mip)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return ALLOC_FAILURE;
+    }
+
+    oci->mi = oci->mip + oci->mode_info_stride + 1;
+
+
+    oci->above_context[Y1CONTEXT] = vpx_calloc(sizeof(ENTROPY_CONTEXT) * oci->mb_cols * 4 , 1);
+
+    if (!oci->above_context[Y1CONTEXT])
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return ALLOC_FAILURE;
+    }
+
+    oci->above_context[UCONTEXT]  = vpx_calloc(sizeof(ENTROPY_CONTEXT) * oci->mb_cols * 2 , 1);
+
+    if (!oci->above_context[UCONTEXT])
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return ALLOC_FAILURE;
+    }
+
+    oci->above_context[VCONTEXT]  = vpx_calloc(sizeof(ENTROPY_CONTEXT) * oci->mb_cols * 2 , 1);
+
+    if (!oci->above_context[VCONTEXT])
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return ALLOC_FAILURE;
+    }
+
+    oci->above_context[Y2CONTEXT] = vpx_calloc(sizeof(ENTROPY_CONTEXT) * oci->mb_cols     , 1);
+
+    if (!oci->above_context[Y2CONTEXT])
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return ALLOC_FAILURE;
+    }
+
+    vp8_update_mode_info_border(oci->mi, oci->mb_rows, oci->mb_cols);
+
+    // Structures used to minitor GF usage
+    if (oci->gf_active_flags != 0)
+        vpx_free(oci->gf_active_flags);
+
+    oci->gf_active_flags = (unsigned char *)vpx_calloc(oci->mb_rows * oci->mb_cols, 1);
+
+    if (!oci->gf_active_flags)
+    {
+        vp8_de_alloc_frame_buffers(oci);
+        return ALLOC_FAILURE;
+    }
+
+    oci->gf_active_count = oci->mb_rows * oci->mb_cols;
+
+    return 0;
+}
+void vp8_setup_version(VP8_COMMON *cm)
+{
+    switch (cm->version)
+    {
+    case 0:
+        cm->no_lpf = 0;
+        cm->simpler_lpf = 0;
+        cm->use_bilinear_mc_filter = 0;
+        cm->full_pixel = 0;
+        break;
+    case 1:
+        cm->no_lpf = 0;
+        cm->simpler_lpf = 1;
+        cm->use_bilinear_mc_filter = 1;
+        cm->full_pixel = 0;
+        break;
+    case 2:
+        cm->no_lpf = 1;
+        cm->simpler_lpf = 0;
+        cm->use_bilinear_mc_filter = 1;
+        cm->full_pixel = 0;
+        break;
+    case 3:
+        cm->no_lpf = 1;
+        cm->simpler_lpf = 1;
+        cm->use_bilinear_mc_filter = 1;
+        cm->full_pixel = 1;
+        break;
+    default:
+        //4,5,6,7 are reserved for future use
+        cm->no_lpf = 0;
+        cm->simpler_lpf = 0;
+        cm->use_bilinear_mc_filter = 0;
+        cm->full_pixel = 0;
+        break;
+    }
+}
+void vp8_create_common(VP8_COMMON *oci)
+{
+    vp8_machine_specific_config(oci);
+    vp8_default_coef_probs(oci);
+    vp8_init_mbmode_probs(oci);
+    vp8_default_bmode_probs(oci->fc.bmode_prob);
+
+    oci->mb_no_coeff_skip = 1;
+    oci->no_lpf = 0;
+    oci->simpler_lpf = 0;
+    oci->use_bilinear_mc_filter = 0;
+    oci->full_pixel = 0;
+    oci->multi_token_partition = ONE_PARTITION;
+    oci->clr_type = REG_YUV;
+    oci->clamp_type = RECON_CLAMP_REQUIRED;
+
+    // Initialise reference frame sign bias structure to defaults
+    vpx_memset(oci->ref_frame_sign_bias, 0, sizeof(oci->ref_frame_sign_bias));
+
+    // Default disable buffer to buffer copying
+    oci->copy_buffer_to_gf = 0;
+    oci->copy_buffer_to_arf = 0;
+}
+
+void vp8_remove_common(VP8_COMMON *oci)
+{
+    vp8_de_alloc_frame_buffers(oci);
+}
+
+void vp8_initialize_common()
+{
+    vp8_coef_tree_initialize();
+
+    vp8_entropy_mode_init();
+
+    vp8_init_scan_order_mask();
+
+}
diff --git a/vp8/common/alloccommon.h b/vp8/common/alloccommon.h
new file mode 100644
index 0000000..73c7383
--- /dev/null
+++ b/vp8/common/alloccommon.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_ALLOCCOMMON_H
+#define __INC_ALLOCCOMMON_H
+
+#include "onyxc_int.h"
+
+void vp8_create_common(VP8_COMMON *oci);
+void vp8_remove_common(VP8_COMMON *oci);
+void vp8_de_alloc_frame_buffers(VP8_COMMON *oci);
+int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height);
+void vp8_setup_version(VP8_COMMON *oci);
+
+#endif
diff --git a/vp8/common/arm/armv6/bilinearfilter_v6.asm b/vp8/common/arm/armv6/bilinearfilter_v6.asm
new file mode 100644
index 0000000..4428cf8
--- /dev/null
+++ b/vp8/common/arm/armv6/bilinearfilter_v6.asm
@@ -0,0 +1,237 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_filter_block2d_bil_first_pass_armv6|
+    EXPORT  |vp8_filter_block2d_bil_second_pass_armv6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+;-------------------------------------
+; r0    unsigned char *src_ptr,
+; r1    unsigned short *output_ptr,
+; r2    unsigned int src_pixels_per_line,
+; r3    unsigned int output_height,
+; stack    unsigned int output_width,
+; stack    const short *vp8_filter
+;-------------------------------------
+; The output is transposed stroed in output array to make it easy for second pass filtering.
+|vp8_filter_block2d_bil_first_pass_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #40]                  ; vp8_filter address
+    ldr     r4, [sp, #36]                   ; output width
+
+    mov     r12, r3                         ; outer-loop counter
+    sub     r2, r2, r4                      ; src increment for height loop
+
+    ;;IF ARCHITECTURE=6
+    pld     [r0]
+    ;;ENDIF
+
+    ldr     r5, [r11]                       ; load up filter coefficients
+
+    mov     r3, r3, lsl #1                  ; output_height*2
+    add     r3, r3, #2                      ; plus 2 to make output buffer 4-bit aligned since height is actually (height+1)
+
+    mov     r11, r1                         ; save output_ptr for each row
+
+    cmp     r5, #128                        ; if filter coef = 128, then skip the filter
+    beq     bil_null_1st_filter
+
+|bil_height_loop_1st_v6|
+    ldrb    r6, [r0]                        ; load source data
+    ldrb    r7, [r0, #1]
+    ldrb    r8, [r0, #2]
+    mov     lr, r4, lsr #2                  ; 4-in-parellel loop counter
+
+|bil_width_loop_1st_v6|
+    ldrb    r9, [r0, #3]
+    ldrb    r10, [r0, #4]
+
+    pkhbt   r6, r6, r7, lsl #16             ; src[1] | src[0]
+    pkhbt   r7, r7, r8, lsl #16             ; src[2] | src[1]
+
+    smuad   r6, r6, r5                      ; apply the filter
+    pkhbt   r8, r8, r9, lsl #16             ; src[3] | src[2]
+    smuad   r7, r7, r5
+    pkhbt   r9, r9, r10, lsl #16            ; src[4] | src[3]
+
+    smuad   r8, r8, r5
+    smuad   r9, r9, r5
+
+    add     r0, r0, #4
+    subs    lr, lr, #1
+
+    add     r6, r6, #0x40                   ; round_shift_and_clamp
+    add     r7, r7, #0x40
+    usat    r6, #16, r6, asr #7
+    usat    r7, #16, r7, asr #7
+
+    strh    r6, [r1], r3                    ; result is transposed and stored
+
+    add     r8, r8, #0x40                   ; round_shift_and_clamp
+    strh    r7, [r1], r3
+    add     r9, r9, #0x40
+    usat    r8, #16, r8, asr #7
+    usat    r9, #16, r9, asr #7
+
+    strh    r8, [r1], r3                    ; result is transposed and stored
+
+    ldrneb  r6, [r0]                        ; load source data
+    strh    r9, [r1], r3
+
+    ldrneb  r7, [r0, #1]
+    ldrneb  r8, [r0, #2]
+
+    bne     bil_width_loop_1st_v6
+
+    add     r0, r0, r2                      ; move to next input row
+    subs    r12, r12, #1
+
+    ;;IF ARCHITECTURE=6
+    pld     [r0]
+    ;;ENDIF
+
+    add     r11, r11, #2                    ; move over to next column
+    mov     r1, r11
+
+    bne     bil_height_loop_1st_v6
+
+    ldmia   sp!, {r4 - r11, pc}
+
+|bil_null_1st_filter|
+|bil_height_loop_null_1st|
+    mov     lr, r4, lsr #2                  ; loop counter
+
+|bil_width_loop_null_1st|
+    ldrb    r6, [r0]                        ; load data
+    ldrb    r7, [r0, #1]
+    ldrb    r8, [r0, #2]
+    ldrb    r9, [r0, #3]
+
+    strh    r6, [r1], r3                    ; store it to immediate buffer
+    add     r0, r0, #4
+    strh    r7, [r1], r3
+    subs    lr, lr, #1
+    strh    r8, [r1], r3
+    strh    r9, [r1], r3
+
+    bne     bil_width_loop_null_1st
+
+    subs    r12, r12, #1
+    add     r0, r0, r2                      ; move to next input line
+    add     r11, r11, #2                    ; move over to next column
+    mov     r1, r11
+
+    bne     bil_height_loop_null_1st
+
+    ldmia   sp!, {r4 - r11, pc}
+
+    ENDP  ; |vp8_filter_block2d_bil_first_pass_armv6|
+
+
+;---------------------------------
+; r0    unsigned short *src_ptr,
+; r1    unsigned char *output_ptr,
+; r2    int output_pitch,
+; r3    unsigned int  output_height,
+; stack unsigned int  output_width,
+; stack const short *vp8_filter
+;---------------------------------
+|vp8_filter_block2d_bil_second_pass_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #40]                  ; vp8_filter address
+    ldr     r4, [sp, #36]                   ; output width
+
+    ldr     r5, [r11]                       ; load up filter coefficients
+    mov     r12, r4                         ; outer-loop counter = width, since we work on transposed data matrix
+    mov     r11, r1
+
+    cmp     r5, #128                        ; if filter coef = 128, then skip the filter
+    beq     bil_null_2nd_filter
+
+|bil_height_loop_2nd|
+    ldr     r6, [r0]                        ; load the data
+    ldr     r8, [r0, #4]
+    ldrh    r10, [r0, #8]
+    mov     lr, r3, lsr #2                  ; loop counter
+
+|bil_width_loop_2nd|
+    pkhtb   r7, r6, r8                      ; src[1] | src[2]
+    pkhtb   r9, r8, r10                     ; src[3] | src[4]
+
+    smuad   r6, r6, r5                      ; apply filter
+    smuad   r8, r8, r5                      ; apply filter
+
+    subs    lr, lr, #1
+
+    smuadx  r7, r7, r5                      ; apply filter
+    smuadx  r9, r9, r5                      ; apply filter
+
+    add     r0, r0, #8
+
+    add     r6, r6, #0x40                   ; round_shift_and_clamp
+    add     r7, r7, #0x40
+    usat    r6, #8, r6, asr #7
+    usat    r7, #8, r7, asr #7
+    strb    r6, [r1], r2                    ; the result is transposed back and stored
+
+    add     r8, r8, #0x40                   ; round_shift_and_clamp
+    strb    r7, [r1], r2
+    add     r9, r9, #0x40
+    usat    r8, #8, r8, asr #7
+    usat    r9, #8, r9, asr #7
+    strb    r8, [r1], r2                    ; the result is transposed back and stored
+
+    ldrne   r6, [r0]                        ; load data
+    strb    r9, [r1], r2
+    ldrne   r8, [r0, #4]
+    ldrneh  r10, [r0, #8]
+
+    bne     bil_width_loop_2nd
+
+    subs    r12, r12, #1
+    add     r0, r0, #4                      ; update src for next row
+    add     r11, r11, #1
+    mov     r1, r11
+
+    bne     bil_height_loop_2nd
+    ldmia   sp!, {r4 - r11, pc}
+
+|bil_null_2nd_filter|
+|bil_height_loop_null_2nd|
+    mov     lr, r3, lsr #2
+
+|bil_width_loop_null_2nd|
+    ldr     r6, [r0], #4                    ; load data
+    subs    lr, lr, #1
+    ldr     r8, [r0], #4
+
+    strb    r6, [r1], r2                    ; store data
+    mov     r7, r6, lsr #16
+    strb    r7, [r1], r2
+    mov     r9, r8, lsr #16
+    strb    r8, [r1], r2
+    strb    r9, [r1], r2
+
+    bne     bil_width_loop_null_2nd
+
+    subs    r12, r12, #1
+    add     r0, r0, #4
+    add     r11, r11, #1
+    mov     r1, r11
+
+    bne     bil_height_loop_null_2nd
+
+    ldmia   sp!, {r4 - r11, pc}
+    ENDP  ; |vp8_filter_block2d_second_pass_armv6|
+
+    END
diff --git a/vp8/common/arm/armv6/copymem16x16_v6.asm b/vp8/common/arm/armv6/copymem16x16_v6.asm
new file mode 100644
index 0000000..00e9739
--- /dev/null
+++ b/vp8/common/arm/armv6/copymem16x16_v6.asm
@@ -0,0 +1,181 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_copy_mem16x16_v6|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void copy_mem16x16_v6( unsigned char *src, int src_stride, unsigned char *dst, int dst_stride)
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_copy_mem16x16_v6| PROC
+    stmdb       sp!, {r4 - r7}
+    ;push   {r4-r7}
+
+    ;preload
+    pld     [r0]
+    pld     [r0, r1]
+    pld     [r0, r1, lsl #1]
+
+    ands    r4, r0, #15
+    beq     copy_mem16x16_fast
+
+    ands    r4, r0, #7
+    beq     copy_mem16x16_8
+
+    ands    r4, r0, #3
+    beq     copy_mem16x16_4
+
+    ;copy one byte each time
+    ldrb    r4, [r0]
+    ldrb    r5, [r0, #1]
+    ldrb    r6, [r0, #2]
+    ldrb    r7, [r0, #3]
+
+    mov     r12, #16
+
+copy_mem16x16_1_loop
+    strb    r4, [r2]
+    strb    r5, [r2, #1]
+    strb    r6, [r2, #2]
+    strb    r7, [r2, #3]
+
+    ldrb    r4, [r0, #4]
+    ldrb    r5, [r0, #5]
+    ldrb    r6, [r0, #6]
+    ldrb    r7, [r0, #7]
+
+    subs    r12, r12, #1
+
+    strb    r4, [r2, #4]
+    strb    r5, [r2, #5]
+    strb    r6, [r2, #6]
+    strb    r7, [r2, #7]
+
+    ldrb    r4, [r0, #8]
+    ldrb    r5, [r0, #9]
+    ldrb    r6, [r0, #10]
+    ldrb    r7, [r0, #11]
+
+    strb    r4, [r2, #8]
+    strb    r5, [r2, #9]
+    strb    r6, [r2, #10]
+    strb    r7, [r2, #11]
+
+    ldrb    r4, [r0, #12]
+    ldrb    r5, [r0, #13]
+    ldrb    r6, [r0, #14]
+    ldrb    r7, [r0, #15]
+
+    add     r0, r0, r1
+
+    strb    r4, [r2, #12]
+    strb    r5, [r2, #13]
+    strb    r6, [r2, #14]
+    strb    r7, [r2, #15]
+
+    add     r2, r2, r3
+
+    ldrneb  r4, [r0]
+    ldrneb  r5, [r0, #1]
+    ldrneb  r6, [r0, #2]
+    ldrneb  r7, [r0, #3]
+
+    bne     copy_mem16x16_1_loop
+
+    ldmia       sp!, {r4 - r7}
+    ;pop        {r4-r7}
+    mov     pc, lr
+
+;copy 4 bytes each time
+copy_mem16x16_4
+    ldr     r4, [r0]
+    ldr     r5, [r0, #4]
+    ldr     r6, [r0, #8]
+    ldr     r7, [r0, #12]
+
+    mov     r12, #16
+
+copy_mem16x16_4_loop
+    subs    r12, r12, #1
+    add     r0, r0, r1
+
+    str     r4, [r2]
+    str     r5, [r2, #4]
+    str     r6, [r2, #8]
+    str     r7, [r2, #12]
+
+    add     r2, r2, r3
+
+    ldrne   r4, [r0]
+    ldrne   r5, [r0, #4]
+    ldrne   r6, [r0, #8]
+    ldrne   r7, [r0, #12]
+
+    bne     copy_mem16x16_4_loop
+
+    ldmia       sp!, {r4 - r7}
+    ;pop        {r4-r7}
+    mov     pc, lr
+
+;copy 8 bytes each time
+copy_mem16x16_8
+    sub     r1, r1, #16
+    sub     r3, r3, #16
+
+    mov     r12, #16
+
+copy_mem16x16_8_loop
+    ldmia   r0!, {r4-r5}
+    ;ldm        r0, {r4-r5}
+    ldmia   r0!, {r6-r7}
+
+    add     r0, r0, r1
+
+    stmia   r2!, {r4-r5}
+    subs    r12, r12, #1
+    ;stm        r2, {r4-r5}
+    stmia   r2!, {r6-r7}
+
+    add     r2, r2, r3
+
+    bne     copy_mem16x16_8_loop
+
+    ldmia       sp!, {r4 - r7}
+    ;pop        {r4-r7}
+    mov     pc, lr
+
+;copy 16 bytes each time
+copy_mem16x16_fast
+    ;sub        r1, r1, #16
+    ;sub        r3, r3, #16
+
+    mov     r12, #16
+
+copy_mem16x16_fast_loop
+    ldmia   r0, {r4-r7}
+    ;ldm        r0, {r4-r7}
+    add     r0, r0, r1
+
+    subs    r12, r12, #1
+    stmia   r2, {r4-r7}
+    ;stm        r2, {r4-r7}
+    add     r2, r2, r3
+
+    bne     copy_mem16x16_fast_loop
+
+    ldmia       sp!, {r4 - r7}
+    ;pop        {r4-r7}
+    mov     pc, lr
+
+    ENDP  ; |vp8_copy_mem16x16_v6|
+
+    END
diff --git a/vp8/common/arm/armv6/copymem8x4_v6.asm b/vp8/common/arm/armv6/copymem8x4_v6.asm
new file mode 100644
index 0000000..94473ca
--- /dev/null
+++ b/vp8/common/arm/armv6/copymem8x4_v6.asm
@@ -0,0 +1,127 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_copy_mem8x4_v6|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void vp8_copy_mem8x4_v6( unsigned char *src, int src_stride, unsigned char *dst, int dst_stride)
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_copy_mem8x4_v6| PROC
+    ;push   {r4-r5}
+    stmdb  sp!, {r4-r5}
+
+    ;preload
+    pld     [r0]
+    pld     [r0, r1]
+    pld     [r0, r1, lsl #1]
+
+    ands    r4, r0, #7
+    beq     copy_mem8x4_fast
+
+    ands    r4, r0, #3
+    beq     copy_mem8x4_4
+
+    ;copy 1 byte each time
+    ldrb    r4, [r0]
+    ldrb    r5, [r0, #1]
+
+    mov     r12, #4
+
+copy_mem8x4_1_loop
+    strb    r4, [r2]
+    strb    r5, [r2, #1]
+
+    ldrb    r4, [r0, #2]
+    ldrb    r5, [r0, #3]
+
+    subs    r12, r12, #1
+
+    strb    r4, [r2, #2]
+    strb    r5, [r2, #3]
+
+    ldrb    r4, [r0, #4]
+    ldrb    r5, [r0, #5]
+
+    strb    r4, [r2, #4]
+    strb    r5, [r2, #5]
+
+    ldrb    r4, [r0, #6]
+    ldrb    r5, [r0, #7]
+
+    add     r0, r0, r1
+
+    strb    r4, [r2, #6]
+    strb    r5, [r2, #7]
+
+    add     r2, r2, r3
+
+    ldrneb  r4, [r0]
+    ldrneb  r5, [r0, #1]
+
+    bne     copy_mem8x4_1_loop
+
+    ldmia       sp!, {r4 - r5}
+    ;pop        {r4-r5}
+    mov     pc, lr
+
+;copy 4 bytes each time
+copy_mem8x4_4
+    ldr     r4, [r0]
+    ldr     r5, [r0, #4]
+
+    mov     r12, #4
+
+copy_mem8x4_4_loop
+    subs    r12, r12, #1
+    add     r0, r0, r1
+
+    str     r4, [r2]
+    str     r5, [r2, #4]
+
+    add     r2, r2, r3
+
+    ldrne   r4, [r0]
+    ldrne   r5, [r0, #4]
+
+    bne     copy_mem8x4_4_loop
+
+    ldmia  sp!, {r4-r5}
+    ;pop        {r4-r5}
+    mov     pc, lr
+
+;copy 8 bytes each time
+copy_mem8x4_fast
+    ;sub        r1, r1, #8
+    ;sub        r3, r3, #8
+
+    mov     r12, #4
+
+copy_mem8x4_fast_loop
+    ldmia   r0, {r4-r5}
+    ;ldm        r0, {r4-r5}
+    add     r0, r0, r1
+
+    subs    r12, r12, #1
+    stmia   r2, {r4-r5}
+    ;stm        r2, {r4-r5}
+    add     r2, r2, r3
+
+    bne     copy_mem8x4_fast_loop
+
+    ldmia  sp!, {r4-r5}
+    ;pop        {r4-r5}
+    mov     pc, lr
+
+    ENDP  ; |vp8_copy_mem8x4_v6|
+
+    END
diff --git a/vp8/common/arm/armv6/copymem8x8_v6.asm b/vp8/common/arm/armv6/copymem8x8_v6.asm
new file mode 100644
index 0000000..7cfa533
--- /dev/null
+++ b/vp8/common/arm/armv6/copymem8x8_v6.asm
@@ -0,0 +1,127 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_copy_mem8x8_v6|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void copy_mem8x8_v6( unsigned char *src, int src_stride, unsigned char *dst, int dst_stride)
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_copy_mem8x8_v6| PROC
+    ;push   {r4-r5}
+    stmdb  sp!, {r4-r5}
+
+    ;preload
+    pld     [r0]
+    pld     [r0, r1]
+    pld     [r0, r1, lsl #1]
+
+    ands    r4, r0, #7
+    beq     copy_mem8x8_fast
+
+    ands    r4, r0, #3
+    beq     copy_mem8x8_4
+
+    ;copy 1 byte each time
+    ldrb    r4, [r0]
+    ldrb    r5, [r0, #1]
+
+    mov     r12, #8
+
+copy_mem8x8_1_loop
+    strb    r4, [r2]
+    strb    r5, [r2, #1]
+
+    ldrb    r4, [r0, #2]
+    ldrb    r5, [r0, #3]
+
+    subs    r12, r12, #1
+
+    strb    r4, [r2, #2]
+    strb    r5, [r2, #3]
+
+    ldrb    r4, [r0, #4]
+    ldrb    r5, [r0, #5]
+
+    strb    r4, [r2, #4]
+    strb    r5, [r2, #5]
+
+    ldrb    r4, [r0, #6]
+    ldrb    r5, [r0, #7]
+
+    add     r0, r0, r1
+
+    strb    r4, [r2, #6]
+    strb    r5, [r2, #7]
+
+    add     r2, r2, r3
+
+    ldrneb  r4, [r0]
+    ldrneb  r5, [r0, #1]
+
+    bne     copy_mem8x8_1_loop
+
+    ldmia       sp!, {r4 - r5}
+    ;pop        {r4-r5}
+    mov     pc, lr
+
+;copy 4 bytes each time
+copy_mem8x8_4
+    ldr     r4, [r0]
+    ldr     r5, [r0, #4]
+
+    mov     r12, #8
+
+copy_mem8x8_4_loop
+    subs    r12, r12, #1
+    add     r0, r0, r1
+
+    str     r4, [r2]
+    str     r5, [r2, #4]
+
+    add     r2, r2, r3
+
+    ldrne   r4, [r0]
+    ldrne   r5, [r0, #4]
+
+    bne     copy_mem8x8_4_loop
+
+    ldmia       sp!, {r4 - r5}
+    ;pop        {r4-r5}
+    mov     pc, lr
+
+;copy 8 bytes each time
+copy_mem8x8_fast
+    ;sub        r1, r1, #8
+    ;sub        r3, r3, #8
+
+    mov     r12, #8
+
+copy_mem8x8_fast_loop
+    ldmia   r0, {r4-r5}
+    ;ldm        r0, {r4-r5}
+    add     r0, r0, r1
+
+    subs    r12, r12, #1
+    stmia   r2, {r4-r5}
+    ;stm        r2, {r4-r5}
+    add     r2, r2, r3
+
+    bne     copy_mem8x8_fast_loop
+
+    ldmia  sp!, {r4-r5}
+    ;pop        {r4-r5}
+    mov     pc, lr
+
+    ENDP  ; |vp8_copy_mem8x8_v6|
+
+    END
diff --git a/vp8/common/arm/armv6/filter_v6.asm b/vp8/common/arm/armv6/filter_v6.asm
new file mode 100644
index 0000000..a7863fc
--- /dev/null
+++ b/vp8/common/arm/armv6/filter_v6.asm
@@ -0,0 +1,383 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_filter_block2d_first_pass_armv6|
+    EXPORT  |vp8_filter_block2d_second_pass_armv6|
+    EXPORT  |vp8_filter_block2d_first_pass_only_armv6|
+    EXPORT  |vp8_filter_block2d_second_pass_only_armv6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+;-------------------------------------
+; r0    unsigned char *src_ptr
+; r1    short         *output_ptr
+; r2    unsigned int src_pixels_per_line
+; r3    unsigned int output_width
+; stack unsigned int output_height
+; stack const short *vp8_filter
+;-------------------------------------
+; vp8_filter the input and put in the output array.  Apply the 6 tap FIR filter with
+; the output being a 2 byte value and the intput being a 1 byte value.
+|vp8_filter_block2d_first_pass_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #40]                  ; vp8_filter address
+    ldr     r7, [sp, #36]                   ; output height
+
+    sub     r2, r2, r3                      ; inside loop increments input array,
+                                            ; so the height loop only needs to add
+                                            ; r2 - width to the input pointer
+
+    mov     r3, r3, lsl #1                  ; multiply width by 2 because using shorts
+    add     r12, r3, #16                    ; square off the output
+    sub     sp, sp, #4
+
+    ;;IF ARCHITECTURE=6
+    ;pld        [r0, #-2]
+    ;;pld       [r0, #30]
+    ;;ENDIF
+
+    ldr     r4, [r11]                       ; load up packed filter coefficients
+    ldr     r5, [r11, #4]
+    ldr     r6, [r11, #8]
+
+    str     r1, [sp]                        ; push destination to stack
+    mov     r7, r7, lsl #16                 ; height is top part of counter
+
+; six tap filter
+|height_loop_1st_6|
+    ldrb    r8, [r0, #-2]                   ; load source data
+    ldrb    r9, [r0, #-1]
+    ldrb    r10, [r0], #2
+    orr     r7, r7, r3, lsr #2              ; construct loop counter
+
+|width_loop_1st_6|
+    ldrb    r11, [r0, #-1]
+
+    pkhbt   lr, r8, r9, lsl #16             ; r9 | r8
+    pkhbt   r8, r9, r10, lsl #16            ; r10 | r9
+
+    ldrb    r9, [r0]
+
+    smuad   lr, lr, r4                      ; apply the filter
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+    smuad   r8, r8, r4
+    pkhbt   r11, r11, r9, lsl #16           ; r9 | r11
+
+    smlad   lr, r10, r5, lr
+    ldrb    r10, [r0, #1]
+    smlad   r8, r11, r5, r8
+    ldrb    r11, [r0, #2]
+
+    sub     r7, r7, #1
+
+    pkhbt   r9, r9, r10, lsl #16            ; r10 | r9
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+
+    smlad   lr, r9, r6, lr
+    smlad   r11, r10, r6, r8
+
+    ands    r10, r7, #0xff                  ; test loop counter
+
+    add     lr, lr, #0x40                   ; round_shift_and_clamp
+    ldrneb  r8, [r0, #-2]                   ; load data for next loop
+    usat    lr, #8, lr, asr #7
+    add     r11, r11, #0x40
+    ldrneb  r9, [r0, #-1]
+    usat    r11, #8, r11, asr #7
+
+    strh    lr, [r1], r12                   ; result is transposed and stored, which
+                                            ; will make second pass filtering easier.
+    ldrneb  r10, [r0], #2
+    strh    r11, [r1], r12
+
+    bne     width_loop_1st_6
+
+    ;;add       r9, r2, #30                 ; attempt to load 2 adjacent cache lines
+    ;;IF ARCHITECTURE=6
+    ;pld        [r0, r2]
+    ;;pld       [r0, r9]
+    ;;ENDIF
+
+    ldr     r1, [sp]                        ; load and update dst address
+    subs    r7, r7, #0x10000
+    add     r0, r0, r2                      ; move to next input line
+    add     r1, r1, #2                      ; move over to next column
+    str     r1, [sp]
+
+    bne     height_loop_1st_6
+
+    add     sp, sp, #4
+    ldmia   sp!, {r4 - r11, pc}
+
+    ENDP
+
+;---------------------------------
+; r0    short         *src_ptr,
+; r1    unsigned char *output_ptr,
+; r2    unsigned int output_pitch,
+; r3    unsigned int cnt,
+; stack const short *vp8_filter
+;---------------------------------
+|vp8_filter_block2d_second_pass_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #36]                  ; vp8_filter address
+    sub     sp, sp, #4
+    mov     r7, r3, lsl #16                 ; height is top part of counter
+    str     r1, [sp]                        ; push destination to stack
+
+    ldr     r4, [r11]                       ; load up packed filter coefficients
+    ldr     r5, [r11, #4]
+    ldr     r6, [r11, #8]
+
+    pkhbt   r12, r5, r4                     ; pack the filter differently
+    pkhbt   r11, r6, r5
+
+    sub     r0, r0, #4                      ; offset input buffer
+
+|height_loop_2nd|
+    ldr     r8, [r0]                        ; load the data
+    ldr     r9, [r0, #4]
+    orr     r7, r7, r3, lsr #1              ; loop counter
+
+|width_loop_2nd|
+    smuad   lr, r4, r8                      ; apply filter
+    sub     r7, r7, #1
+    smulbt  r8, r4, r8
+
+    ldr     r10, [r0, #8]
+
+    smlad   lr, r5, r9, lr
+    smladx  r8, r12, r9, r8
+
+    ldrh    r9, [r0, #12]
+
+    smlad   lr, r6, r10, lr
+    smladx  r8, r11, r10, r8
+
+    add     r0, r0, #4
+    smlatb  r10, r6, r9, r8
+
+    add     lr, lr, #0x40                   ; round_shift_and_clamp
+    ands    r8, r7, #0xff
+    usat    lr, #8, lr, asr #7
+    add     r10, r10, #0x40
+    strb    lr, [r1], r2                    ; the result is transposed back and stored
+    usat    r10, #8, r10, asr #7
+
+    ldrne   r8, [r0]                        ; load data for next loop
+    ldrne   r9, [r0, #4]
+    strb    r10, [r1], r2
+
+    bne     width_loop_2nd
+
+    ldr     r1, [sp]                        ; update dst for next loop
+    subs    r7, r7, #0x10000
+    add     r0, r0, #16                     ; updata src for next loop
+    add     r1, r1, #1
+    str     r1, [sp]
+
+    bne     height_loop_2nd
+
+    add     sp, sp, #4
+    ldmia   sp!, {r4 - r11, pc}
+
+    ENDP
+
+;------------------------------------
+; r0    unsigned char *src_ptr
+; r1    unsigned char *output_ptr,
+; r2    unsigned int src_pixels_per_line
+; r3    unsigned int cnt,
+; stack unsigned int output_pitch,
+; stack const short *vp8_filter
+;------------------------------------
+|vp8_filter_block2d_first_pass_only_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r4, [sp, #36]                   ; output pitch
+    ldr     r11, [sp, #40]                  ; HFilter address
+    sub     sp, sp, #8
+
+    mov     r7, r3
+    sub     r2, r2, r3                      ; inside loop increments input array,
+                                            ; so the height loop only needs to add
+                                            ; r2 - width to the input pointer
+
+    sub     r4, r4, r3
+    str     r4, [sp]                        ; save modified output pitch
+    str     r2, [sp, #4]
+
+    mov     r2, #0x40
+
+    ldr     r4, [r11]                       ; load up packed filter coefficients
+    ldr     r5, [r11, #4]
+    ldr     r6, [r11, #8]
+
+; six tap filter
+|height_loop_1st_only_6|
+    ldrb    r8, [r0, #-2]                   ; load data
+    ldrb    r9, [r0, #-1]
+    ldrb    r10, [r0], #2
+
+    mov     r12, r3, lsr #1                 ; loop counter
+
+|width_loop_1st_only_6|
+    ldrb    r11, [r0, #-1]
+
+    pkhbt   lr, r8, r9, lsl #16             ; r9 | r8
+    pkhbt   r8, r9, r10, lsl #16            ; r10 | r9
+
+    ldrb    r9, [r0]
+
+;;  smuad   lr, lr, r4
+    smlad   lr, lr, r4, r2
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+;;  smuad   r8, r8, r4
+    smlad   r8, r8, r4, r2
+    pkhbt   r11, r11, r9, lsl #16           ; r9 | r11
+
+    smlad   lr, r10, r5, lr
+    ldrb    r10, [r0, #1]
+    smlad   r8, r11, r5, r8
+    ldrb    r11, [r0, #2]
+
+    subs    r12, r12, #1
+
+    pkhbt   r9, r9, r10, lsl #16            ; r10 | r9
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+
+    smlad   lr, r9, r6, lr
+    smlad   r10, r10, r6, r8
+
+;;  add     lr, lr, #0x40                   ; round_shift_and_clamp
+    ldrneb  r8, [r0, #-2]                   ; load data for next loop
+    usat    lr, #8, lr, asr #7
+;;  add     r10, r10, #0x40
+    strb    lr, [r1], #1                    ; store the result
+    usat    r10, #8, r10, asr #7
+
+    ldrneb  r9, [r0, #-1]
+    strb    r10, [r1], #1
+    ldrneb  r10, [r0], #2
+
+    bne     width_loop_1st_only_6
+
+    ;;add       r9, r2, #30                 ; attempt to load 2 adjacent cache lines
+    ;;IF ARCHITECTURE=6
+    ;pld        [r0, r2]
+    ;;pld       [r0, r9]
+    ;;ENDIF
+
+    ldr     lr, [sp]                        ; load back output pitch
+    ldr     r12, [sp, #4]                   ; load back output pitch
+    subs    r7, r7, #1
+    add     r0, r0, r12                     ; updata src for next loop
+    add     r1, r1, lr                      ; update dst for next loop
+
+    bne     height_loop_1st_only_6
+
+    add     sp, sp, #8
+    ldmia   sp!, {r4 - r11, pc}
+    ENDP  ; |vp8_filter_block2d_first_pass_only_armv6|
+
+
+;------------------------------------
+; r0    unsigned char *src_ptr,
+; r1    unsigned char *output_ptr,
+; r2    unsigned int src_pixels_per_line
+; r3    unsigned int cnt,
+; stack unsigned int output_pitch,
+; stack const short *vp8_filter
+;------------------------------------
+|vp8_filter_block2d_second_pass_only_armv6| PROC
+    stmdb   sp!, {r4 - r11, lr}
+
+    ldr     r11, [sp, #40]                  ; VFilter address
+    ldr     r12, [sp, #36]                  ; output pitch
+
+    mov     r7, r3, lsl #16                 ; height is top part of counter
+    sub     r0, r0, r2, lsl #1              ; need 6 elements for filtering, 2 before, 3 after
+
+    sub     sp, sp, #8
+
+    ldr     r4, [r11]                       ; load up packed filter coefficients
+    ldr     r5, [r11, #4]
+    ldr     r6, [r11, #8]
+
+    str     r0, [sp]                        ; save r0 to stack
+    str     r1, [sp, #4]                    ; save dst to stack
+
+; six tap filter
+|width_loop_2nd_only_6|
+    ldrb    r8, [r0], r2                    ; load data
+    orr     r7, r7, r3                      ; loop counter
+    ldrb    r9, [r0], r2
+    ldrb    r10, [r0], r2
+
+|height_loop_2nd_only_6|
+    ; filter first column in this inner loop, than, move to next colum.
+    ldrb    r11, [r0], r2
+
+    pkhbt   lr, r8, r9, lsl #16             ; r9 | r8
+    pkhbt   r8, r9, r10, lsl #16            ; r10 | r9
+
+    ldrb    r9, [r0], r2
+
+    smuad   lr, lr, r4
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+    smuad   r8, r8, r4
+    pkhbt   r11, r11, r9, lsl #16           ; r9 | r11
+
+    smlad   lr, r10, r5, lr
+    ldrb    r10, [r0], r2
+    smlad   r8, r11, r5, r8
+    ldrb    r11, [r0]
+
+    sub     r7, r7, #2
+    sub     r0, r0, r2, lsl #2
+
+    pkhbt   r9, r9, r10, lsl #16            ; r10 | r9
+    pkhbt   r10, r10, r11, lsl #16          ; r11 | r10
+
+    smlad   lr, r9, r6, lr
+    smlad   r10, r10, r6, r8
+
+    ands    r9, r7, #0xff
+
+    add     lr, lr, #0x40                   ; round_shift_and_clamp
+    ldrneb  r8, [r0], r2                    ; load data for next loop
+    usat    lr, #8, lr, asr #7
+    add     r10, r10, #0x40
+    strb    lr, [r1], r12                   ; store the result for the column
+    usat    r10, #8, r10, asr #7
+
+    ldrneb  r9, [r0], r2
+    strb    r10, [r1], r12
+    ldrneb  r10, [r0], r2
+
+    bne     height_loop_2nd_only_6
+
+    ldr     r0, [sp]
+    ldr     r1, [sp, #4]
+    subs    r7, r7, #0x10000
+    add     r0, r0, #1                      ; move to filter next column
+    str     r0, [sp]
+    add     r1, r1, #1
+    str     r1, [sp, #4]
+
+    bne     width_loop_2nd_only_6
+
+    add     sp, sp, #8
+
+    ldmia   sp!, {r4 - r11, pc}
+    ENDP  ; |vp8_filter_block2d_second_pass_only_armv6|
+
+    END
diff --git a/vp8/common/arm/armv6/idct_v6.asm b/vp8/common/arm/armv6/idct_v6.asm
new file mode 100644
index 0000000..25c5165
--- /dev/null
+++ b/vp8/common/arm/armv6/idct_v6.asm
@@ -0,0 +1,376 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+;                   r0  r1  r2  r3  r4  r5  r6  r7  r8  r9  r10 r11 r12     r14
+    EXPORT  |vp8_short_idct4x4llm_1_v6|
+    EXPORT  |vp8_short_idct4x4llm_v6|
+    EXPORT  |vp8_short_idct4x4llm_v6_scott|
+    EXPORT  |vp8_short_idct4x4llm_v6_dual|
+
+    EXPORT  |vp8_dc_only_idct_armv6|
+
+    AREA    |.text|, CODE, READONLY
+
+;********************************************************************************
+;*  void short_idct4x4llm_1_v6(INT16 * input, INT16 * output, INT32 pitch)
+;*      r0  INT16 * input
+;*      r1  INT16 * output
+;*      r2  INT32 pitch
+;*  bench:  3/5
+;********************************************************************************
+
+|vp8_short_idct4x4llm_1_v6| PROC         ;   cycles  in  out pit
+            ;
+    ldrsh   r0, [r0]    ; load input[0] 1, r0 un 2
+    add r0, r0, #4  ;   1   +4
+    stmdb   sp!, {r4, r5, lr}   ; make room for wide writes 1                   backup
+    mov r0, r0, asr #3  ; (input[0] + 4) >> 3   1, r0 req`d ^1  >> 3
+    pkhbt   r4, r0, r0, lsl #16 ; pack r0 into r4   1, r0 req`d ^1                  pack
+    mov r5, r4  ; expand                        expand
+
+    strd    r4, [r1], r2    ; *output = r0, post inc    1
+    strd    r4, [r1], r2    ;   1
+    strd    r4, [r1], r2    ;   1
+    strd    r4, [r1]    ;   1
+            ;
+    ldmia   sp!, {r4, r5, pc}   ; replace vars, return                      restore
+    ENDP        ; |vp8_short_idct4x4llm_1_v6|
+;********************************************************************************
+;********************************************************************************
+;********************************************************************************
+
+;********************************************************************************
+;*  void short_idct4x4llm_v6(INT16 * input, INT16 * output, INT32 pitch)
+;*      r0  INT16 * input
+;*      r1  INT16 * output
+;*      r2  INT32 pitch
+;*  bench:
+;********************************************************************************
+
+|vp8_short_idct4x4llm_v6| PROC           ;   cycles  in  out pit
+            ;
+    stmdb   sp!, {r4-r11, lr}   ; backup registers  1                   backup
+            ;
+    mov r4, #0x00004E00 ;   1                   cst
+    orr r4, r4, #0x0000007B ; cospi8sqrt2minus1
+    mov r5, #0x00008A00 ;   1                       cst
+    orr r5, r5, #0x0000008C ; sinpi8sqrt2
+            ;
+    mov r6, #4  ; i=4   1                           i
+loop1           ;
+    ldrsh   r12, [r0, #8]   ; input[4]  1, r12 unavail 2                                                    [4]
+    ldrsh   r3, [r0, #24]   ; input[12] 1, r3 unavail 2             [12]
+    ldrsh   r8, [r0, #16]   ; input[8]  1, r8 unavail 2                                 [8]
+    ldrsh   r7, [r0], #0x2  ; input[0]  1, r7 unavail 2 ++                          [0]
+    smulwb  r10, r5, r12    ; ([4] * sinpi8sqrt2) >> 16 1, r10 un 2, r12/r5 ^1                                          t1
+    smulwb  r11, r4, r3 ; ([12] * cospi8sqrt2minus1) >> 16  1, r11 un 2, r3/r4 ^1                                               t2
+    add r9, r7, r8  ; a1 = [0] + [8]    1                                       a1
+    sub r7, r7, r8  ; b1 = [0] - [8]    1                               b1
+    add r11, r3, r11    ; temp2 1
+    rsb r11, r11, r10   ; c1 = temp1 - temp2    1                                               c1
+    smulwb  r3, r5, r3  ; ([12] * sinpi8sqrt2) >> 16    1, r3 un 2, r3/r5 ^ 1               t2
+    smulwb  r10, r4, r12    ; ([4] * cospi8sqrt2minus1) >> 16   1, r10 un 2, r12/r4 ^1                                          t1
+    add r8, r7, r11 ; b1 + c1   1                                   b+c
+    strh    r8, [r1, r2]    ; out[pitch] = b1+c1    1
+    sub r7, r7, r11 ; b1 - c1   1                               b-c
+    add r10, r12, r10   ; temp1 1
+    add r3, r10, r3 ; d1 = temp1 + temp2    1               d1
+    add r10, r9, r3 ; a1 + d1   1                                           a+d
+    sub r3, r9, r3  ; a1 - d1   1               a-d
+    add r8, r2, r2  ; pitch * 2 1                                   p*2
+    strh    r7, [r1, r8]    ; out[pitch*2] = b1-c1  1
+    add r7, r2, r2, lsl #1  ; pitch * 3 1                               p*3
+    strh    r3, [r1, r7]    ; out[pitch*3] = a1-d1  1
+    subs    r6, r6, #1  ; i--   1                           --
+    strh    r10, [r1], #0x2 ; out[0] = a1+d1    1       ++
+    bne loop1   ; if i>0, continue
+            ;
+    sub r1, r1, #8  ; set up out for next loop  1       -4
+            ; for this iteration, input=prev output
+    mov r6, #4  ; i=4   1                           i
+;   b   returnfull
+loop2           ;
+    ldrsh   r11, [r1, #2]   ; input[1]  1, r11 un 2                                             [1]
+    ldrsh   r8, [r1, #6]    ; input[3]  1, r8 un 2                                  [3]
+    ldrsh   r3, [r1, #4]    ; input[2]  1, r3 un 2              [2]
+    ldrsh   r0, [r1]    ; input[0]  1, r0 un 2  [0]
+    smulwb  r9, r5, r11 ; ([1] * sinpi8sqrt2) >> 16 1, r9 un 2, r5/r11 ^1                                       t1
+    smulwb  r10, r4, r8 ; ([3] * cospi8sqrt2minus1) >> 16   1, r10 un 2, r4/r8 ^1                                           t2
+    add r7, r0, r3  ; a1 = [0] + [2]    1                               a1
+    sub r0, r0, r3  ; b1 = [0] - [2]    1   b1
+    add r10, r8, r10    ; temp2 1
+    rsb r9, r10, r9 ; c1 = temp1 - temp2    1                                       c1
+    smulwb  r8, r5, r8  ; ([3] * sinpi8sqrt2) >> 16 1, r8 un 2, r5/r8 ^1                                    t2
+    smulwb  r10, r4, r11    ; ([1] * cospi8sqrt2minus1) >> 16   1, r10 un 2, r4/r11 ^1                                          t1
+    add r3, r0, r9  ; b1+c1 1               b+c
+    add r3, r3, #4  ; b1+c1+4   1               +4
+    add r10, r11, r10   ; temp1 1
+    mov r3, r3, asr #3  ; b1+c1+4 >> 3  1, r3 ^1                >>3
+    strh    r3, [r1, #2]    ; out[1] = b1+c1    1
+    add r10, r10, r8    ; d1 = temp1 + temp2    1                                           d1
+    add r3, r7, r10 ; a1+d1 1               a+d
+    add r3, r3, #4  ; a1+d1+4   1               +4
+    sub r7, r7, r10 ; a1-d1 1                               a-d
+    add r7, r7, #4  ; a1-d1+4   1                               +4
+    mov r3, r3, asr #3  ; a1+d1+4 >> 3  1, r3 ^1                >>3
+    mov r7, r7, asr #3  ; a1-d1+4 >> 3  1, r7 ^1                                >>3
+    strh    r7, [r1, #6]    ; out[3] = a1-d1    1
+    sub r0, r0, r9  ; b1-c1 1   b-c
+    add r0, r0, #4  ; b1-c1+4   1   +4
+    subs    r6, r6, #1  ; i--   1                           --
+    mov r0, r0, asr #3  ; b1-c1+4 >> 3  1, r0 ^1    >>3
+    strh    r0, [r1, #4]    ; out[2] = b1-c1    1
+    strh    r3, [r1], r2    ; out[0] = a1+d1    1
+;   add r1, r1, r2  ; out += pitch  1       ++
+    bne loop2   ; if i>0, continue
+returnfull          ;
+    ldmia   sp!, {r4 - r11, pc} ; replace vars, return                      restore
+    ENDP
+
+;********************************************************************************
+;********************************************************************************
+;********************************************************************************
+
+;********************************************************************************
+;*  void short_idct4x4llm_v6_scott(INT16 * input, INT16 * output, INT32 pitch)
+;*      r0  INT16 * input
+;*      r1  INT16 * output
+;*      r2  INT32 pitch
+;*  bench:
+;********************************************************************************
+
+|vp8_short_idct4x4llm_v6_scott| PROC         ;   cycles  in  out pit
+;   mov r0, #0  ;
+;   ldr r0, [r0]    ;
+    stmdb   sp!, {r4 - r11, lr} ; backup registers  1                   backup
+            ;
+    mov r3, #0x00004E00 ;                   cos
+    orr r3, r3, #0x0000007B ; cospi8sqrt2minus1
+    mov r4, #0x00008A00 ;                       sin
+    orr r4, r4, #0x0000008C ; sinpi8sqrt2
+            ;
+    mov r5, #0x2    ; i                         i
+            ;
+short_idct4x4llm_v6_scott_loop1          ;
+    ldr r10, [r0, #(4*2)]   ; i5 | i4                                               5,4
+    ldr r11, [r0, #(12*2)]  ; i13 | i12                                                 13,12
+            ;
+    smulwb  r6, r4, r10 ; ((ip[4] * sinpi8sqrt2) >> 16)                             lt1
+    smulwb  r7, r3, r11 ; ((ip[12] * cospi8sqrt2minus1) >> 16)                                  lt2
+            ;
+    smulwb  r12, r3, r10    ; ((ip[4] * cospi8sqrt2misu1) >> 16)                                                        l2t2
+    smulwb  r14, r4, r11    ; ((ip[12] * sinpi8sqrt2) >> 16)                                                                l2t1
+            ;
+    add r6, r6, r7  ; partial c1                                lt1-lt2
+    add r12, r12, r14   ; partial d1                                                        l2t2+l2t1
+            ;
+    smulwt  r14, r4, r10    ; ((ip[5] * sinpi8sqrt2) >> 16)                                                             ht1
+    smulwt  r7, r3, r11 ; ((ip[13] * cospi8sqrt2minus1) >> 16)                                  ht2
+            ;
+    smulwt  r8, r3, r10 ; ((ip[5] * cospi8sqrt2minus1) >> 16)                                       h2t1
+    smulwt  r9, r4, r11 ; ((ip[13] * sinpi8sqrt2) >> 16)                                            h2t2
+            ;
+    add r7, r14, r7 ; partial c1_2                                  ht1+ht2
+    sub r8, r8, r9  ; partial d1_2                                      h2t1-h2t2
+            ;
+    pkhbt   r6, r6, r7, lsl #16 ; partial c1_2 | partial c1_1                               pack
+    pkhbt   r12, r12, r8, lsl #16   ; partial d1_2 | partial d1_1                                                       pack
+            ;
+    usub16  r6, r6, r10 ; c1_2 | c1_1                               c
+    uadd16  r12, r12, r11   ; d1_2 | d1_1                                                       d
+            ;
+    ldr r10, [r0, #0]   ; i1 | i0                                               1,0
+    ldr r11, [r0, #(8*2)]   ; i9 | i10                                                  9,10
+            ;
+;;;;;;  add r0, r0, #0x4    ;       +4
+;;;;;;  add r1, r1, #0x4    ;           +4
+            ;
+    uadd16  r8, r10, r11    ; i1 + i9 | i0 + i8 aka a1                                      a
+    usub16  r9, r10, r11    ; i1 - i9 | i0 - i8 aka b1                                          b
+            ;
+    uadd16  r7, r8, r12 ; a1 + d1 pair                                  a+d
+    usub16  r14, r8, r12    ; a1 - d1 pair                                                              a-d
+            ;
+    str r7, [r1]    ; op[0] = a1 + d1
+    str r14, [r1, r2]   ; op[pitch*3] = a1 - d1
+            ;
+    add r0, r0, #0x4    ; op[pitch] = b1 + c1       ++
+    add r1, r1, #0x4    ; op[pitch*2] = b1 - c1         ++
+            ;
+    subs    r5, r5, #0x1    ;                           --
+    bne short_idct4x4llm_v6_scott_loop1  ;
+            ;
+    sub r1, r1, #16 ; reset output ptr
+    mov r5, #0x4    ;
+    mov r0, r1  ; input = output
+            ;
+short_idct4x4llm_v6_scott_loop2          ;
+            ;
+    subs    r5, r5, #0x1    ;
+    bne short_idct4x4llm_v6_scott_loop2  ;
+            ;
+    ldmia   sp!, {r4 - r11, pc} ;
+    ENDP        ;
+            ;
+;********************************************************************************
+;********************************************************************************
+;********************************************************************************
+
+;********************************************************************************
+;*  void short_idct4x4llm_v6_dual(INT16 * input, INT16 * output, INT32 pitch)
+;*      r0  INT16 * input
+;*      r1  INT16 * output
+;*      r2  INT32 pitch
+;*  bench:
+;********************************************************************************
+
+|vp8_short_idct4x4llm_v6_dual| PROC          ;   cycles  in  out pit
+            ;
+    stmdb   sp!, {r4-r11, lr}   ; backup registers  1                   backup
+    mov r3, #0x00004E00 ;                   cos
+    orr r3, r3, #0x0000007B ; cospi8sqrt2minus1
+    mov r4, #0x00008A00 ;                       sin
+    orr r4, r4, #0x0000008C ; sinpi8sqrt2
+    mov r5, #0x2    ; i=2                           i
+loop1_dual
+    ldr r6, [r0, #(4*2)]    ; i5 | i4                               5|4
+    ldr r12, [r0, #(12*2)]  ; i13 | i12                                                     13|12
+    ldr r14, [r0, #(8*2)]   ; i9 | i8                                                               9|8
+
+    smulwt  r9, r3, r6  ; (ip[5] * cospi8sqrt2minus1) >> 16                                         5c
+    smulwb  r7, r3, r6  ; (ip[4] * cospi8sqrt2minus1) >> 16                                 4c
+    smulwt  r10, r4, r6 ; (ip[5] * sinpi8sqrt2) >> 16                                               5s
+    smulwb  r8, r4, r6  ; (ip[4] * sinpi8sqrt2) >> 16                                       4s
+    pkhbt   r7, r7, r9, lsl #16 ; 5c | 4c
+    smulwt  r11, r3, r12    ; (ip[13] * cospi8sqrt2minus1) >> 16                                                    13c
+    pkhbt   r8, r8, r10, lsl #16    ; 5s | 4s
+    uadd16  r6, r6, r7  ; 5c+5 | 4c+4
+    smulwt  r7, r4, r12 ; (ip[13] * sinpi8sqrt2) >> 16                                  13s
+    smulwb  r9, r3, r12 ; (ip[12] * cospi8sqrt2minus1) >> 16                                            12c
+    smulwb  r10, r4, r12    ; (ip[12] * sinpi8sqrt2) >> 16                                              12s
+    subs    r5, r5, #0x1    ; i--                           --
+    pkhbt   r9, r9, r11, lsl #16    ; 13c | 12c
+    ldr r11, [r0], #0x4 ; i1 | i0       ++                                          1|0
+    pkhbt   r10, r10, r7, lsl #16   ; 13s | 12s
+    uadd16  r7, r12, r9 ; 13c+13 | 12c+12
+    usub16  r7, r8, r7  ; c                                 c
+    uadd16  r6, r6, r10 ; d                             d
+    uadd16  r10, r11, r14   ; a                                             a
+    usub16  r8, r11, r14    ; b                                     b
+    uadd16  r9, r10, r6 ; a+d                                           a+d
+    usub16  r10, r10, r6    ; a-d                                               a-d
+    uadd16  r6, r8, r7  ; b+c                               b+c
+    usub16  r7, r8, r7  ; b-c                                   b-c
+    str r6, [r1, r2]    ; o5 | o4
+    add r6, r2, r2  ; pitch * 2                             p2
+    str r7, [r1, r6]    ; o9 | o8
+    add r6,  r6, r2 ; pitch * 3                             p3
+    str r10, [r1, r6]   ; o13 | o12
+    str r9, [r1], #0x4  ; o1 | o0           ++
+    bne loop1_dual  ;
+    mov r5, #0x2    ; i=2                           i
+    sub r0, r1, #8  ; reset input/output        i/o
+loop2_dual
+    ldr r6, [r0, r2]    ; i5 | i4                               5|4
+    ldr r1, [r0]    ; i1 | i0           1|0
+    ldr r12, [r0, #0x4] ; i3 | i2                                                       3|2
+    add r14, r2, #0x4   ; pitch + 2                                                             p+2
+    ldr r14, [r0, r14]  ; i7 | i6                                                               7|6
+    smulwt  r9, r3, r6  ; (ip[5] * cospi8sqrt2minus1) >> 16                                         5c
+    smulwt  r7, r3, r1  ; (ip[1] * cospi8sqrt2minus1) >> 16                                 1c
+    smulwt  r10, r4, r6 ; (ip[5] * sinpi8sqrt2) >> 16                                               5s
+    smulwt  r8, r4, r1  ; (ip[1] * sinpi8sqrt2) >> 16                                       1s
+    pkhbt   r11, r6, r1, lsl #16    ; i0 | i4                                                   0|4
+    pkhbt   r7, r9, r7, lsl #16 ; 1c | 5c
+    pkhbt   r8, r10, r8, lsl #16    ; 1s | 5s = temp1 ©                                     tc1
+    pkhtb   r1, r1, r6, asr #16 ; i1 | i5           1|5
+    uadd16  r1, r7, r1  ; 1c+1 | 5c+5 = temp2 (d)           td2
+    pkhbt   r9, r14, r12, lsl #16   ; i2 | i6                                           2|6
+    uadd16  r10, r11, r9    ; a                                             a
+    usub16  r9, r11, r9 ; b                                         b
+    pkhtb   r6, r12, r14, asr #16   ; i3 | i7                               3|7
+    subs    r5, r5, #0x1    ; i--                           --
+    smulwt  r7, r3, r6  ; (ip[3] * cospi8sqrt2minus1) >> 16                                 3c
+    smulwt  r11, r4, r6 ; (ip[3] * sinpi8sqrt2) >> 16                                                   3s
+    smulwb  r12, r3, r6 ; (ip[7] * cospi8sqrt2minus1) >> 16                                                     7c
+    smulwb  r14, r4, r6 ; (ip[7] * sinpi8sqrt2) >> 16                                                               7s
+
+    pkhbt   r7, r12, r7, lsl #16    ; 3c | 7c
+    pkhbt   r11, r14, r11, lsl #16  ; 3s | 7s = temp1 (d)                                                   td1
+    uadd16  r6, r7, r6  ; 3c+3 | 7c+7 = temp2  (c)                              tc2
+    usub16  r12, r8, r6 ; c (o1 | o5)                                                       c
+    uadd16  r6, r11, r1 ; d (o3 | o7)                               d
+    uadd16  r7, r10, r6 ; a+d                                   a+d
+    mov r8, #0x4    ; set up 4's                                        4
+    orr r8, r8, #0x40000    ;                                       4|4
+    usub16  r6, r10, r6 ; a-d                               a-d
+    uadd16  r6, r6, r8  ; a-d+4                             3|7
+    uadd16  r7, r7, r8  ; a+d+4                                 0|4
+    uadd16  r10, r9, r12    ; b+c                                               b+c
+    usub16  r1, r9, r12 ; b-c           b-c
+    uadd16  r10, r10, r8    ; b+c+4                                             1|5
+    uadd16  r1, r1, r8  ; b-c+4         2|6
+    mov r8, r10, asr #19    ; o1 >> 3
+    strh    r8, [r0, #2]    ; o1
+    mov r8, r1, asr #19 ; o2 >> 3
+    strh    r8, [r0, #4]    ; o2
+    mov r8, r6, asr #19 ; o3 >> 3
+    strh    r8, [r0, #6]    ; o3
+    mov r8, r7, asr #19 ; o0 >> 3
+    strh    r8, [r0], r2    ; o0        +p
+    sxth    r10, r10    ;
+    mov r8, r10, asr #3 ; o5 >> 3
+    strh    r8, [r0, #2]    ; o5
+    sxth    r1, r1  ;
+    mov r8, r1, asr #3  ; o6 >> 3
+    strh    r8, [r0, #4]    ; o6
+    sxth    r6, r6  ;
+    mov r8, r6, asr #3  ; o7 >> 3
+    strh    r8, [r0, #6]    ; o7
+    sxth    r7, r7  ;
+    mov r8, r7, asr #3  ; o4 >> 3
+    strh    r8, [r0], r2    ; o4        +p
+;;;;;   subs    r5, r5, #0x1    ; i--                           --
+    bne loop2_dual  ;
+            ;
+    ldmia   sp!, {r4 - r11, pc} ; replace vars, return                      restore
+    ENDP
+
+
+; sjl added 10/17/08
+;void dc_only_idct_armv6(short input_dc, short *output, int pitch)
+|vp8_dc_only_idct_armv6| PROC
+    stmdb       sp!, {r4 - r6, lr}
+
+    add         r0, r0, #0x4
+    add         r4, r1, r2                      ; output + shortpitch
+    mov         r0, r0, ASR #0x3    ;aka a1
+    add         r5, r1, r2, LSL #1              ; output + shortpitch * 2
+    pkhbt       r0, r0, r0, lsl #16             ; a1 | a1
+    add         r6, r5, r2                      ; output + shortpitch * 3
+
+    str         r0, [r1, #0]
+    str         r0, [r1, #4]
+
+    str         r0, [r4, #0]
+    str         r0, [r4, #4]
+
+    str         r0, [r5, #0]
+    str         r0, [r5, #4]
+
+    str         r0, [r6, #0]
+    str         r0, [r6, #4]
+
+
+    ldmia       sp!, {r4 - r6, pc}
+
+    ENDP  ; |vp8_dc_only_idct_armv6|
+
+    END
diff --git a/vp8/common/arm/armv6/iwalsh_v6.asm b/vp8/common/arm/armv6/iwalsh_v6.asm
new file mode 100644
index 0000000..8747568
--- /dev/null
+++ b/vp8/common/arm/armv6/iwalsh_v6.asm
@@ -0,0 +1,151 @@
+;
+;  Copyright (c) 2010 The VP8 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 |vp8_short_inv_walsh4x4_armv6|
+    EXPORT |vp8_short_inv_walsh4x4_1_armv6|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+;short vp8_short_inv_walsh4x4_armv6(short *input, short *output)
+|vp8_short_inv_walsh4x4_armv6| PROC
+
+    stmdb       sp!, {r4 - r11, lr}
+
+    ldr         r2, [r0], #4         ; [1  |  0]
+    ldr         r3, [r0], #4         ; [3  |  2]
+    ldr         r4, [r0], #4         ; [5  |  4]
+    ldr         r5, [r0], #4         ; [7  |  6]
+    ldr         r6, [r0], #4         ; [9  |  8]
+    ldr         r7, [r0], #4         ; [11 | 10]
+    ldr         r8, [r0], #4         ; [13 | 12]
+    ldr         r9, [r0]             ; [15 | 14]
+
+    qadd16      r10, r2, r8          ; a1 [1+13  |  0+12]
+    qadd16      r11, r4, r6          ; b1 [5+9   |  4+8]
+    qsub16      r12, r4, r6          ; c1 [5-9   |  4-8]
+    qsub16      lr, r2, r8           ; d1 [1-13  |  0-12]
+
+    qadd16      r2, r10, r11         ; a1 + b1 [1  |  0]
+    qadd16      r4, r12, lr          ; c1 + d1 [5  |  4]
+    qsub16      r6, r10, r11         ; a1 - b1 [9  |  8]
+    qsub16      r8, lr, r12          ; d1 - c1 [13 | 12]
+
+    qadd16      r10, r3, r9          ; a1 [3+15  |  2+14]
+    qadd16      r11, r5, r7          ; b1 [7+11  |  6+10]
+    qsub16      r12, r5, r7          ; c1 [7-11  |  6-10]
+    qsub16      lr, r3, r9           ; d1 [3-15  |  2-14]
+
+    qadd16      r3, r10, r11         ; a1 + b1 [3  |  2]
+    qadd16      r5, r12, lr          ; c1 + d1 [7  |  6]
+    qsub16      r7, r10, r11         ; a1 - b1 [11 | 10]
+    qsub16      r9, lr, r12          ; d1 - c1 [15 | 14]
+
+    ; first transform complete
+
+    qsubaddx    r10, r2, r3          ; [c1|a1] [1-2   |   0+3]
+    qaddsubx    r11, r2, r3          ; [b1|d1] [1+2   |   0-3]
+    qsubaddx    r12, r4, r5          ; [c1|a1] [5-6   |   4+7]
+    qaddsubx    lr, r4, r5           ; [b1|d1] [5+6   |   4-7]
+
+    qaddsubx    r2, r10, r11         ; [b2|c2] [c1+d1 | a1-b1]
+    qaddsubx    r3, r11, r10         ; [a2|d2] [b1+a1 | d1-c1]
+    ldr         r10, c0x00030003
+    qaddsubx    r4, r12, lr          ; [b2|c2] [c1+d1 | a1-b1]
+    qaddsubx    r5, lr, r12          ; [a2|d2] [b1+a1 | d1-c1]
+
+    qadd16      r2, r2, r10          ; [b2+3|c2+3]
+    qadd16      r3, r3, r10          ; [a2+3|d2+3]
+    qadd16      r4, r4, r10          ; [b2+3|c2+3]
+    qadd16      r5, r5, r10          ; [a2+3|d2+3]
+
+    asr         r12, r2, #3          ; [1  |  x]
+    pkhtb       r12, r12, r3, asr #19; [1  |  0]
+    lsl         lr, r3, #16          ; [~3 |  x]
+    lsl         r2, r2, #16          ; [~2 |  x]
+    asr         lr, lr, #3           ; [3  |  x]
+    pkhtb       lr, lr, r2, asr #19  ; [3  |  2]
+
+    asr         r2, r4, #3           ; [5  |  x]
+    pkhtb       r2, r2, r5, asr #19  ; [5  |  4]
+    lsl         r3, r5, #16          ; [~7 |  x]
+    lsl         r4, r4, #16          ; [~6 |  x]
+    asr         r3, r3, #3           ; [7  |  x]
+    pkhtb       r3, r3, r4, asr #19  ; [7  |  6]
+
+    str         r12, [r1], #4
+    str         lr, [r1], #4
+    str         r2, [r1], #4
+    str         r3, [r1], #4
+
+    qsubaddx    r2, r6, r7           ; [c1|a1] [9-10  |  8+11]
+    qaddsubx    r3, r6, r7           ; [b1|d1] [9+10  |  8-11]
+    qsubaddx    r4, r8, r9           ; [c1|a1] [13-14 | 12+15]
+    qaddsubx    r5, r8, r9           ; [b1|d1] [13+14 | 12-15]
+
+    qaddsubx    r6, r2, r3           ; [b2|c2] [c1+d1 | a1-b1]
+    qaddsubx    r7, r3, r2           ; [a2|d2] [b1+a1 | d1-c1]
+    qaddsubx    r8, r4, r5           ; [b2|c2] [c1+d1 | a1-b1]
+    qaddsubx    r9, r5, r4           ; [a2|d2] [b1+a1 | d1-c1]
+
+    qadd16      r6, r6, r10          ; [b2+3|c2+3]
+    qadd16      r7, r7, r10          ; [a2+3|d2+3]
+    qadd16      r8, r8, r10          ; [b2+3|c2+3]
+    qadd16      r9, r9, r10          ; [a2+3|d2+3]
+
+    asr         r2, r6, #3           ; [9  |  x]
+    pkhtb       r2, r2, r7, asr #19  ; [9  |  8]
+    lsl         r3, r7, #16          ; [~11|  x]
+    lsl         r4, r6, #16          ; [~10|  x]
+    asr         r3, r3, #3           ; [11 |  x]
+    pkhtb       r3, r3, r4, asr #19  ; [11 | 10]
+
+    asr         r4, r8, #3           ; [13 |  x]
+    pkhtb       r4, r4, r9, asr #19  ; [13 | 12]
+    lsl         r5, r9, #16          ; [~15|  x]
+    lsl         r6, r8, #16          ; [~14|  x]
+    asr         r5, r5, #3           ; [15 |  x]
+    pkhtb       r5, r5, r6, asr #19  ; [15 | 14]
+
+    str         r2, [r1], #4
+    str         r3, [r1], #4
+    str         r4, [r1], #4
+    str         r5, [r1]
+
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_short_inv_walsh4x4_armv6|
+
+
+;short vp8_short_inv_walsh4x4_1_armv6(short *input, short *output)
+|vp8_short_inv_walsh4x4_1_armv6| PROC
+
+    ldrsh       r2, [r0]             ; [0]
+    add         r2, r2, #3           ; [0] + 3
+    asr         r2, r2, #3           ; a1 ([0]+3) >> 3
+    lsl         r2, r2, #16          ; [a1 |  x]
+    orr         r2, r2, r2, lsr #16  ; [a1 | a1]
+
+    str         r2, [r1], #4
+    str         r2, [r1], #4
+    str         r2, [r1], #4
+    str         r2, [r1], #4
+    str         r2, [r1], #4
+    str         r2, [r1], #4
+    str         r2, [r1], #4
+    str         r2, [r1]
+
+    bx          lr
+    ENDP        ; |vp8_short_inv_walsh4x4_1_armv6|
+
+; Constant Pool
+c0x00030003 DCD 0x00030003
+    END
diff --git a/vp8/common/arm/armv6/loopfilter_v6.asm b/vp8/common/arm/armv6/loopfilter_v6.asm
new file mode 100644
index 0000000..c2b02dc
--- /dev/null
+++ b/vp8/common/arm/armv6/loopfilter_v6.asm
@@ -0,0 +1,1263 @@
+;
+;  Copyright (c) 2010 The VP8 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 |vp8_loop_filter_horizontal_edge_armv6|
+    EXPORT |vp8_mbloop_filter_horizontal_edge_armv6|
+    EXPORT |vp8_loop_filter_vertical_edge_armv6|
+    EXPORT |vp8_mbloop_filter_vertical_edge_armv6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+    MACRO
+    TRANSPOSE_MATRIX $a0, $a1, $a2, $a3, $b0, $b1, $b2, $b3
+    ; input: $a0, $a1, $a2, $a3; output: $b0, $b1, $b2, $b3
+    ; a0: 03 02 01 00
+    ; a1: 13 12 11 10
+    ; a2: 23 22 21 20
+    ; a3: 33 32 31 30
+    ;     b3 b2 b1 b0
+
+    uxtb16      $b1, $a1                    ; xx 12 xx 10
+    uxtb16      $b0, $a0                    ; xx 02 xx 00
+    uxtb16      $b3, $a3                    ; xx 32 xx 30
+    uxtb16      $b2, $a2                    ; xx 22 xx 20
+    orr         $b1, $b0, $b1, lsl #8       ; 12 02 10 00
+    orr         $b3, $b2, $b3, lsl #8       ; 32 22 30 20
+
+    uxtb16      $a1, $a1, ror #8            ; xx 13 xx 11
+    uxtb16      $a3, $a3, ror #8            ; xx 33 xx 31
+    uxtb16      $a0, $a0, ror #8            ; xx 03 xx 01
+    uxtb16      $a2, $a2, ror #8            ; xx 23 xx 21
+    orr         $a0, $a0, $a1, lsl #8       ; 13 03 11 01
+    orr         $a2, $a2, $a3, lsl #8       ; 33 23 31 21
+
+    pkhtb       $b2, $b3, $b1, asr #16      ; 32 22 12 02   -- p1
+    pkhbt       $b0, $b1, $b3, lsl #16      ; 30 20 10 00   -- p3
+
+    pkhtb       $b3, $a2, $a0, asr #16      ; 33 23 13 03   -- p0
+    pkhbt       $b1, $a0, $a2, lsl #16      ; 31 21 11 01   -- p2
+    MEND
+
+
+src         RN  r0
+pstep       RN  r1
+count       RN  r5
+
+;r0     unsigned char *src_ptr,
+;r1     int src_pixel_step,
+;r2     const char *flimit,
+;r3     const char *limit,
+;stack  const char *thresh,
+;stack  int  count
+
+;Note: All 16 elements in flimit are equal. So, in the code, only one load is needed
+;for flimit. Same way applies to limit and thresh.
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+|vp8_loop_filter_horizontal_edge_armv6| PROC
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+    stmdb       sp!, {r4 - r11, lr}
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+    ldr         count, [sp, #40]            ; count for 8-in-parallel
+    ldr         r6, [sp, #36]               ; load thresh address
+    sub         sp, sp, #16                 ; create temp buffer
+
+    ldr         r9, [src], pstep            ; p3
+    ldr         r4, [r2], #4                ; flimit
+    ldr         r10, [src], pstep           ; p2
+    ldr         r2, [r3], #4                ; limit
+    ldr         r11, [src], pstep           ; p1
+    uadd8       r4, r4, r4                  ; flimit * 2
+    ldr         r3, [r6], #4                ; thresh
+    mov         count, count, lsl #1        ; 4-in-parallel
+    uadd8       r4, r4, r2                  ; flimit * 2 + limit
+
+|Hnext8|
+    ; vp8_filter_mask() function
+    ; calculate breakout conditions
+    ldr         r12, [src], pstep           ; p0
+
+    uqsub8      r6, r9, r10                 ; p3 - p2
+    uqsub8      r7, r10, r9                 ; p2 - p3
+    uqsub8      r8, r10, r11                ; p2 - p1
+    uqsub8      r10, r11, r10               ; p1 - p2
+
+    orr         r6, r6, r7                  ; abs (p3-p2)
+    orr         r8, r8, r10                 ; abs (p2-p1)
+    uqsub8      lr, r6, r2                  ; compare to limit. lr: vp8_filter_mask
+    uqsub8      r8, r8, r2                  ; compare to limit
+    uqsub8      r6, r11, r12                ; p1 - p0
+    orr         lr, lr, r8
+    uqsub8      r7, r12, r11                ; p0 - p1
+    ldr         r9, [src], pstep            ; q0
+    ldr         r10, [src], pstep           ; q1
+    orr         r6, r6, r7                  ; abs (p1-p0)
+    uqsub8      r7, r6, r2                  ; compare to limit
+    uqsub8      r8, r6, r3                  ; compare to thresh  -- save r8 for later
+    orr         lr, lr, r7
+
+    uqsub8      r6, r11, r10                ; p1 - q1
+    uqsub8      r7, r10, r11                ; q1 - p1
+    uqsub8      r11, r12, r9                ; p0 - q0
+    uqsub8      r12, r9, r12                ; q0 - p0
+    orr         r6, r6, r7                  ; abs (p1-q1)
+    ldr         r7, c0x7F7F7F7F
+    orr         r12, r11, r12               ; abs (p0-q0)
+    ldr         r11, [src], pstep           ; q2
+    uqadd8      r12, r12, r12               ; abs (p0-q0) * 2
+    and         r6, r7, r6, lsr #1          ; abs (p1-q1) / 2
+    uqsub8      r7, r9, r10                 ; q0 - q1
+    uqadd8      r12, r12, r6                ; abs (p0-q0)*2 + abs (p1-q1)/2
+    uqsub8      r6, r10, r9                 ; q1 - q0
+    uqsub8      r12, r12, r4                ; compare to flimit
+    uqsub8      r9, r11, r10                ; q2 - q1
+
+    orr         lr, lr, r12
+
+    ldr         r12, [src], pstep           ; q3
+    uqsub8      r10, r10, r11               ; q1 - q2
+    orr         r6, r7, r6                  ; abs (q1-q0)
+    orr         r10, r9, r10                ; abs (q2-q1)
+    uqsub8      r7, r6, r2                  ; compare to limit
+    uqsub8      r10, r10, r2                ; compare to limit
+    uqsub8      r6, r6, r3                  ; compare to thresh -- save r6 for later
+    orr         lr, lr, r7
+    orr         lr, lr, r10
+
+    uqsub8      r10, r12, r11               ; q3 - q2
+    uqsub8      r9, r11, r12                ; q2 - q3
+
+    mvn         r11, #0                     ; r11 == -1
+
+    orr         r10, r10, r9                ; abs (q3-q2)
+    uqsub8      r10, r10, r2                ; compare to limit
+
+    mov         r12, #0
+    orr         lr, lr, r10
+    sub         src, src, pstep, lsl #2
+
+    usub8       lr, r12, lr                 ; use usub8 instead of ssub8
+    sel         lr, r11, r12                ; filter mask: lr
+
+    cmp         lr, #0
+    beq         hskip_filter                 ; skip filtering
+
+    sub         src, src, pstep, lsl #1     ; move src pointer down by 6 lines
+
+    ;vp8_hevmask() function
+    ;calculate high edge variance
+    orr         r10, r6, r8                 ; calculate vp8_hevmask
+
+    ldr         r7, [src], pstep            ; p1
+
+    usub8       r10, r12, r10               ; use usub8 instead of ssub8
+    sel         r6, r12, r11                ; obtain vp8_hevmask: r6
+
+    ;vp8_filter() function
+    ldr         r8, [src], pstep            ; p0
+    ldr         r12, c0x80808080
+    ldr         r9, [src], pstep            ; q0
+    ldr         r10, [src], pstep           ; q1
+
+    eor         r7, r7, r12                 ; p1 offset to convert to a signed value
+    eor         r8, r8, r12                 ; p0 offset to convert to a signed value
+    eor         r9, r9, r12                 ; q0 offset to convert to a signed value
+    eor         r10, r10, r12               ; q1 offset to convert to a signed value
+
+    str         r9, [sp]                    ; store qs0 temporarily
+    str         r8, [sp, #4]                ; store ps0 temporarily
+    str         r10, [sp, #8]               ; store qs1 temporarily
+    str         r7, [sp, #12]               ; store ps1 temporarily
+
+    qsub8       r7, r7, r10                 ; vp8_signed_char_clamp(ps1-qs1)
+    qsub8       r8, r9, r8                  ; vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+
+    and         r7, r7, r6                  ; vp8_filter (r7) &= hev
+
+    qadd8       r7, r7, r8
+    ldr         r9, c0x03030303             ; r9 = 3 --modified for vp8
+
+    qadd8       r7, r7, r8
+    ldr         r10, c0x04040404
+
+    qadd8       r7, r7, r8
+    and         r7, r7, lr                  ; vp8_filter &= mask;
+
+    ;modify code for vp8 -- Filter1 = vp8_filter (r7)
+    qadd8       r8 , r7 , r9                ; Filter2 (r8) = vp8_signed_char_clamp(vp8_filter+3)
+    qadd8       r7 , r7 , r10               ; vp8_filter = vp8_signed_char_clamp(vp8_filter+4)
+
+    mov         r9, #0
+    shadd8      r8 , r8 , r9                ; Filter2 >>= 3
+    shadd8      r7 , r7 , r9                ; vp8_filter >>= 3
+    shadd8      r8 , r8 , r9
+    shadd8      r7 , r7 , r9
+    shadd8      lr , r8 , r9                ; lr: Filter2
+    shadd8      r7 , r7 , r9                ; r7: filter
+
+    ;usub8      lr, r8, r10                 ; s = (s==4)*-1
+    ;sel        lr, r11, r9
+    ;usub8      r8, r10, r8
+    ;sel        r8, r11, r9
+    ;and        r8, r8, lr                  ; -1 for each element that equals 4
+
+    ;calculate output
+    ;qadd8      lr, r8, r7                  ; u = vp8_signed_char_clamp(s + vp8_filter)
+
+    ldr         r8, [sp]                    ; load qs0
+    ldr         r9, [sp, #4]                ; load ps0
+
+    ldr         r10, c0x01010101
+
+    qsub8       r8 ,r8, r7                  ; u = vp8_signed_char_clamp(qs0 - vp8_filter)
+    qadd8       r9, r9, lr                  ; u = vp8_signed_char_clamp(ps0 + Filter2)
+
+    ;end of modification for vp8
+
+    mov         lr, #0
+    sadd8       r7, r7 , r10                ; vp8_filter += 1
+    shadd8      r7, r7, lr                  ; vp8_filter >>= 1
+
+    ldr         r11, [sp, #12]              ; load ps1
+    ldr         r10, [sp, #8]               ; load qs1
+
+    bic         r7, r7, r6                  ; vp8_filter &= ~hev
+    sub         src, src, pstep, lsl #2
+
+    qadd8       r11, r11, r7                ; u = vp8_signed_char_clamp(ps1 + vp8_filter)
+    qsub8       r10, r10,r7                 ; u = vp8_signed_char_clamp(qs1 - vp8_filter)
+
+    eor         r11, r11, r12               ; *op1 = u^0x80
+    str         r11, [src], pstep           ; store op1
+    eor         r9, r9, r12                 ; *op0 = u^0x80
+    str         r9, [src], pstep            ; store op0 result
+    eor         r8, r8, r12                 ; *oq0 = u^0x80
+    str         r8, [src], pstep            ; store oq0 result
+    eor         r10, r10, r12               ; *oq1 = u^0x80
+    str         r10, [src], pstep           ; store oq1
+
+    sub         src, src, pstep, lsl #1
+
+|hskip_filter|
+    add         src, src, #4
+    sub         src, src, pstep, lsl #2
+
+    subs        count, count, #1
+
+    ;pld            [src]
+    ;pld            [src, pstep]
+    ;pld            [src, pstep, lsl #1]
+    ;pld            [src, pstep, lsl #2]
+    ;pld            [src, pstep, lsl #3]
+
+    ldrne       r9, [src], pstep            ; p3
+    ldrne       r10, [src], pstep           ; p2
+    ldrne       r11, [src], pstep           ; p1
+
+    bne         Hnext8
+
+    add         sp, sp, #16
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_loop_filter_horizontal_edge_armv6|
+
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+|vp8_mbloop_filter_horizontal_edge_armv6| PROC
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+    stmdb       sp!, {r4 - r11, lr}
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+    ldr         count, [sp, #40]            ; count for 8-in-parallel
+    ldr         r6, [sp, #36]               ; load thresh address
+    sub         sp, sp, #16                 ; create temp buffer
+
+    ldr         r9, [src], pstep            ; p3
+    ldr         r4, [r2], #4                ; flimit
+    ldr         r10, [src], pstep           ; p2
+    ldr         r2, [r3], #4                ; limit
+    ldr         r11, [src], pstep           ; p1
+    uadd8       r4, r4, r4                  ; flimit * 2
+    ldr         r3, [r6], #4                ; thresh
+    mov         count, count, lsl #1        ; 4-in-parallel
+    uadd8       r4, r4, r2                  ; flimit * 2 + limit
+
+|MBHnext8|
+
+    ; vp8_filter_mask() function
+    ; calculate breakout conditions
+    ldr         r12, [src], pstep           ; p0
+
+    uqsub8      r6, r9, r10                 ; p3 - p2
+    uqsub8      r7, r10, r9                 ; p2 - p3
+    uqsub8      r8, r10, r11                ; p2 - p1
+    uqsub8      r10, r11, r10               ; p1 - p2
+
+    orr         r6, r6, r7                  ; abs (p3-p2)
+    orr         r8, r8, r10                 ; abs (p2-p1)
+    uqsub8      lr, r6, r2                  ; compare to limit. lr: vp8_filter_mask
+    uqsub8      r8, r8, r2                  ; compare to limit
+
+    uqsub8      r6, r11, r12                ; p1 - p0
+    orr         lr, lr, r8
+    uqsub8      r7, r12, r11                ; p0 - p1
+    ldr         r9, [src], pstep            ; q0
+    ldr         r10, [src], pstep           ; q1
+    orr         r6, r6, r7                  ; abs (p1-p0)
+    uqsub8      r7, r6, r2                  ; compare to limit
+    uqsub8      r8, r6, r3                  ; compare to thresh  -- save r8 for later
+    orr         lr, lr, r7
+
+    uqsub8      r6, r11, r10                ; p1 - q1
+    uqsub8      r7, r10, r11                ; q1 - p1
+    uqsub8      r11, r12, r9                ; p0 - q0
+    uqsub8      r12, r9, r12                ; q0 - p0
+    orr         r6, r6, r7                  ; abs (p1-q1)
+    ldr         r7, c0x7F7F7F7F
+    orr         r12, r11, r12               ; abs (p0-q0)
+    ldr         r11, [src], pstep           ; q2
+    uqadd8      r12, r12, r12               ; abs (p0-q0) * 2
+    and         r6, r7, r6, lsr #1          ; abs (p1-q1) / 2
+    uqsub8      r7, r9, r10                 ; q0 - q1
+    uqadd8      r12, r12, r6                ; abs (p0-q0)*2 + abs (p1-q1)/2
+    uqsub8      r6, r10, r9                 ; q1 - q0
+    uqsub8      r12, r12, r4                ; compare to flimit
+    uqsub8      r9, r11, r10                ; q2 - q1
+
+    orr         lr, lr, r12
+
+    ldr         r12, [src], pstep           ; q3
+
+    uqsub8      r10, r10, r11               ; q1 - q2
+    orr         r6, r7, r6                  ; abs (q1-q0)
+    orr         r10, r9, r10                ; abs (q2-q1)
+    uqsub8      r7, r6, r2                  ; compare to limit
+    uqsub8      r10, r10, r2                ; compare to limit
+    uqsub8      r6, r6, r3                  ; compare to thresh -- save r6 for later
+    orr         lr, lr, r7
+    orr         lr, lr, r10
+
+    uqsub8      r10, r12, r11               ; q3 - q2
+    uqsub8      r9, r11, r12                ; q2 - q3
+
+    mvn         r11, #0                     ; r11 == -1
+
+    orr         r10, r10, r9                ; abs (q3-q2)
+    uqsub8      r10, r10, r2                ; compare to limit
+
+    mov         r12, #0
+
+    orr         lr, lr, r10
+
+    usub8       lr, r12, lr                 ; use usub8 instead of ssub8
+    sel         lr, r11, r12                ; filter mask: lr
+
+    cmp         lr, #0
+    beq         mbhskip_filter               ; skip filtering
+
+    ;vp8_hevmask() function
+    ;calculate high edge variance
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 6 lines
+    sub         src, src, pstep, lsl #1
+
+    orr         r10, r6, r8
+    ldr         r7, [src], pstep            ; p1
+
+    usub8       r10, r12, r10
+    sel         r6, r12, r11                ; hev mask: r6
+
+    ;vp8_mbfilter() function
+    ;p2, q2 are only needed at the end. Don't need to load them in now.
+    ldr         r8, [src], pstep            ; p0
+    ldr         r12, c0x80808080
+    ldr         r9, [src], pstep            ; q0
+    ldr         r10, [src]                  ; q1
+
+    eor         r7, r7, r12                 ; ps1
+    eor         r8, r8, r12                 ; ps0
+    eor         r9, r9, r12                 ; qs0
+    eor         r10, r10, r12               ; qs1
+
+    qsub8       r12, r9, r8                 ; vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    str         r7, [sp, #12]               ; store ps1 temporarily
+    qsub8       r7, r7, r10                 ; vp8_signed_char_clamp(ps1-qs1)
+    str         r10, [sp, #8]               ; store qs1 temporarily
+    qadd8       r7, r7, r12
+    str         r9, [sp]                    ; store qs0 temporarily
+    qadd8       r7, r7, r12
+    str         r8, [sp, #4]                ; store ps0 temporarily
+    qadd8       r7, r7, r12                 ; vp8_filter: r7
+
+    ldr         r10, c0x03030303            ; r10 = 3 --modified for vp8
+    ldr         r9, c0x04040404
+
+    and         r7, r7, lr                  ; vp8_filter &= mask (lr is free)
+
+    mov         r12, r7                     ; Filter2: r12
+    and         r12, r12, r6                ; Filter2 &= hev
+
+    ;modify code for vp8
+    ;save bottom 3 bits so that we round one side +4 and the other +3
+    qadd8       r8 , r12 , r9               ; Filter1 (r8) = vp8_signed_char_clamp(Filter2+4)
+    qadd8       r12 , r12 , r10             ; Filter2 (r12) = vp8_signed_char_clamp(Filter2+3)
+
+    mov         r10, #0
+    shadd8      r8 , r8 , r10               ; Filter1 >>= 3
+    shadd8      r12 , r12 , r10             ; Filter2 >>= 3
+    shadd8      r8 , r8 , r10
+    shadd8      r12 , r12 , r10
+    shadd8      r8 , r8 , r10               ; r8: Filter1
+    shadd8      r12 , r12 , r10             ; r12: Filter2
+
+    ldr         r9, [sp]                    ; load qs0
+    ldr         r11, [sp, #4]               ; load ps0
+
+    qsub8       r9 , r9, r8                 ; qs0 = vp8_signed_char_clamp(qs0 - Filter1)
+    qadd8       r11, r11, r12               ; ps0 = vp8_signed_char_clamp(ps0 + Filter2)
+
+    ;save bottom 3 bits so that we round one side +4 and the other +3
+    ;and            r8, r12, r10                ; s = Filter2 & 7 (s: r8)
+    ;qadd8      r12 , r12 , r9              ; Filter2 = vp8_signed_char_clamp(Filter2+4)
+    ;mov            r10, #0
+    ;shadd8     r12 , r12 , r10             ; Filter2 >>= 3
+    ;usub8      lr, r8, r9                  ; s = (s==4)*-1
+    ;sel            lr, r11, r10
+    ;shadd8     r12 , r12 , r10
+    ;usub8      r8, r9, r8
+    ;sel            r8, r11, r10
+    ;ldr            r9, [sp]                    ; load qs0
+    ;ldr            r11, [sp, #4]               ; load ps0
+    ;shadd8     r12 , r12 , r10
+    ;and            r8, r8, lr                  ; -1 for each element that equals 4
+    ;qadd8      r10, r8, r12                ; u = vp8_signed_char_clamp(s + Filter2)
+    ;qsub8      r9 , r9, r12                ; qs0 = vp8_signed_char_clamp(qs0 - Filter2)
+    ;qadd8      r11, r11, r10               ; ps0 = vp8_signed_char_clamp(ps0 + u)
+
+    ;end of modification for vp8
+
+    bic         r12, r7, r6                 ; vp8_filter &= ~hev    ( r6 is free)
+    ;mov        r12, r7
+
+    ;roughly 3/7th difference across boundary
+    mov         lr, #0x1b                   ; 27
+    mov         r7, #0x3f                   ; 63
+
+    sxtb16      r6, r12
+    sxtb16      r10, r12, ror #8
+    smlabb      r8, r6, lr, r7
+    smlatb      r6, r6, lr, r7
+    smlabb      r7, r10, lr, r7
+    smultb      r10, r10, lr
+    ssat        r8, #8, r8, asr #7
+    ssat        r6, #8, r6, asr #7
+    add         r10, r10, #63
+    ssat        r7, #8, r7, asr #7
+    ssat        r10, #8, r10, asr #7
+
+    ldr         lr, c0x80808080
+
+    pkhbt       r6, r8, r6, lsl #16
+    pkhbt       r10, r7, r10, lsl #16
+    uxtb16      r6, r6
+    uxtb16      r10, r10
+
+    sub         src, src, pstep
+
+    orr         r10, r6, r10, lsl #8        ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7)
+
+    qsub8       r8, r9, r10                 ; s = vp8_signed_char_clamp(qs0 - u)
+    qadd8       r10, r11, r10               ; s = vp8_signed_char_clamp(ps0 + u)
+    eor         r8, r8, lr                  ; *oq0 = s^0x80
+    str         r8, [src]                   ; store *oq0
+    sub         src, src, pstep
+    eor         r10, r10, lr                ; *op0 = s^0x80
+    str         r10, [src]                  ; store *op0
+
+    ;roughly 2/7th difference across boundary
+    mov         lr, #0x12                   ; 18
+    mov         r7, #0x3f                   ; 63
+
+    sxtb16      r6, r12
+    sxtb16      r10, r12, ror #8
+    smlabb      r8, r6, lr, r7
+    smlatb      r6, r6, lr, r7
+    smlabb      r9, r10, lr, r7
+    smlatb      r10, r10, lr, r7
+    ssat        r8, #8, r8, asr #7
+    ssat        r6, #8, r6, asr #7
+    ssat        r9, #8, r9, asr #7
+    ssat        r10, #8, r10, asr #7
+
+    ldr         lr, c0x80808080
+
+    pkhbt       r6, r8, r6, lsl #16
+    pkhbt       r10, r9, r10, lsl #16
+
+    ldr         r9, [sp, #8]                ; load qs1
+    ldr         r11, [sp, #12]              ; load ps1
+
+    uxtb16      r6, r6
+    uxtb16      r10, r10
+
+    sub         src, src, pstep
+
+    orr         r10, r6, r10, lsl #8        ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7)
+
+    qadd8       r11, r11, r10               ; s = vp8_signed_char_clamp(ps1 + u)
+    qsub8       r8, r9, r10                 ; s = vp8_signed_char_clamp(qs1 - u)
+    eor         r11, r11, lr                ; *op1 = s^0x80
+    str         r11, [src], pstep           ; store *op1
+    eor         r8, r8, lr                  ; *oq1 = s^0x80
+    add         src, src, pstep, lsl #1
+
+    mov         r7, #0x3f                   ; 63
+
+    str         r8, [src], pstep            ; store *oq1
+
+    ;roughly 1/7th difference across boundary
+    mov         lr, #0x9                    ; 9
+    ldr         r9, [src]                   ; load q2
+
+    sxtb16      r6, r12
+    sxtb16      r10, r12, ror #8
+    smlabb      r8, r6, lr, r7
+    smlatb      r6, r6, lr, r7
+    smlabb      r12, r10, lr, r7
+    smlatb      r10, r10, lr, r7
+    ssat        r8, #8, r8, asr #7
+    ssat        r6, #8, r6, asr #7
+    ssat        r12, #8, r12, asr #7
+    ssat        r10, #8, r10, asr #7
+
+    sub         src, src, pstep, lsl #2
+
+    pkhbt       r6, r8, r6, lsl #16
+    pkhbt       r10, r12, r10, lsl #16
+
+    sub         src, src, pstep
+    ldr         lr, c0x80808080
+
+    ldr         r11, [src]                  ; load p2
+
+    uxtb16      r6, r6
+    uxtb16      r10, r10
+
+    eor         r9, r9, lr
+    eor         r11, r11, lr
+
+    orr         r10, r6, r10, lsl #8        ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7)
+
+    qadd8       r8, r11, r10                ; s = vp8_signed_char_clamp(ps2 + u)
+    qsub8       r10, r9, r10                ; s = vp8_signed_char_clamp(qs2 - u)
+    eor         r8, r8, lr                  ; *op2 = s^0x80
+    str         r8, [src], pstep, lsl #2    ; store *op2
+    add         src, src, pstep
+    eor         r10, r10, lr                ; *oq2 = s^0x80
+    str         r10, [src], pstep, lsl #1   ; store *oq2
+
+|mbhskip_filter|
+    add         src, src, #4
+    sub         src, src, pstep, lsl #3
+    subs        count, count, #1
+
+    ldrne       r9, [src], pstep            ; p3
+    ldrne       r10, [src], pstep           ; p2
+    ldrne       r11, [src], pstep           ; p1
+
+    bne         MBHnext8
+
+    add         sp, sp, #16
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_mbloop_filter_horizontal_edge_armv6|
+
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+|vp8_loop_filter_vertical_edge_armv6| PROC
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+    stmdb       sp!, {r4 - r11, lr}
+
+    sub         src, src, #4                ; move src pointer down by 4
+    ldr         count, [sp, #40]            ; count for 8-in-parallel
+    ldr         r12, [sp, #36]              ; load thresh address
+    sub         sp, sp, #16                 ; create temp buffer
+
+    ldr         r6, [src], pstep            ; load source data
+    ldr         r4, [r2], #4                ; flimit
+    ldr         r7, [src], pstep
+    ldr         r2, [r3], #4                ; limit
+    ldr         r8, [src], pstep
+    uadd8       r4, r4, r4                  ; flimit * 2
+    ldr         r3, [r12], #4               ; thresh
+    ldr         lr, [src], pstep
+    mov         count, count, lsl #1        ; 4-in-parallel
+    uadd8       r4, r4, r2                  ; flimit * 2 + limit
+
+|Vnext8|
+
+    ; vp8_filter_mask() function
+    ; calculate breakout conditions
+    ; transpose the source data for 4-in-parallel operation
+    TRANSPOSE_MATRIX r6, r7, r8, lr, r9, r10, r11, r12
+
+    uqsub8      r7, r9, r10                 ; p3 - p2
+    uqsub8      r8, r10, r9                 ; p2 - p3
+    uqsub8      r9, r10, r11                ; p2 - p1
+    uqsub8      r10, r11, r10               ; p1 - p2
+    orr         r7, r7, r8                  ; abs (p3-p2)
+    orr         r10, r9, r10                ; abs (p2-p1)
+    uqsub8      lr, r7, r2                  ; compare to limit. lr: vp8_filter_mask
+    uqsub8      r10, r10, r2                ; compare to limit
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+
+    orr         lr, lr, r10
+
+    uqsub8      r6, r11, r12                ; p1 - p0
+    uqsub8      r7, r12, r11                ; p0 - p1
+    add         src, src, #4                ; move src pointer up by 4
+    orr         r6, r6, r7                  ; abs (p1-p0)
+    str         r11, [sp, #12]              ; save p1
+    uqsub8      r10, r6, r2                 ; compare to limit
+    uqsub8      r11, r6, r3                 ; compare to thresh
+    orr         lr, lr, r10
+
+    ; transpose uses 8 regs(r6 - r12 and lr). Need to save reg value now
+    ; transpose the source data for 4-in-parallel operation
+    ldr         r6, [src], pstep            ; load source data
+    str         r11, [sp]                   ; push r11 to stack
+    ldr         r7, [src], pstep
+    str         r12, [sp, #4]               ; save current reg before load q0 - q3 data
+    ldr         r8, [src], pstep
+    str         lr, [sp, #8]
+    ldr         lr, [src], pstep
+
+    TRANSPOSE_MATRIX r6, r7, r8, lr, r9, r10, r11, r12
+
+    ldr         lr, [sp, #8]                ; load back (f)limit accumulator
+
+    uqsub8      r6, r12, r11                ; q3 - q2
+    uqsub8      r7, r11, r12                ; q2 - q3
+    uqsub8      r12, r11, r10               ; q2 - q1
+    uqsub8      r11, r10, r11               ; q1 - q2
+    orr         r6, r6, r7                  ; abs (q3-q2)
+    orr         r7, r12, r11                ; abs (q2-q1)
+    uqsub8      r6, r6, r2                  ; compare to limit
+    uqsub8      r7, r7, r2                  ; compare to limit
+    ldr         r11, [sp, #4]               ; load back p0
+    ldr         r12, [sp, #12]              ; load back p1
+    orr         lr, lr, r6
+    orr         lr, lr, r7
+
+    uqsub8      r6, r11, r9                 ; p0 - q0
+    uqsub8      r7, r9, r11                 ; q0 - p0
+    uqsub8      r8, r12, r10                ; p1 - q1
+    uqsub8      r11, r10, r12               ; q1 - p1
+    orr         r6, r6, r7                  ; abs (p0-q0)
+    ldr         r7, c0x7F7F7F7F
+    orr         r8, r8, r11                 ; abs (p1-q1)
+    uqadd8      r6, r6, r6                  ; abs (p0-q0) * 2
+    and         r8, r7, r8, lsr #1          ; abs (p1-q1) / 2
+    uqsub8      r11, r10, r9                ; q1 - q0
+    uqadd8      r6, r8, r6                  ; abs (p0-q0)*2 + abs (p1-q1)/2
+    uqsub8      r12, r9, r10                ; q0 - q1
+    uqsub8      r6, r6, r4                  ; compare to flimit
+
+    orr         r9, r11, r12                ; abs (q1-q0)
+    uqsub8      r8, r9, r2                  ; compare to limit
+    uqsub8      r10, r9, r3                 ; compare to thresh
+    orr         lr, lr, r6
+    orr         lr, lr, r8
+
+    mvn         r11, #0                     ; r11 == -1
+    mov         r12, #0
+
+    usub8       lr, r12, lr
+    ldr         r9, [sp]                    ; load the compared result
+    sel         lr, r11, r12                ; filter mask: lr
+
+    cmp         lr, #0
+    beq         vskip_filter                 ; skip filtering
+
+    ;vp8_hevmask() function
+    ;calculate high edge variance
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+
+    orr         r9, r9, r10
+
+    ldrh        r7, [src, #-2]
+    ldrh        r8, [src], pstep
+
+    usub8       r9, r12, r9
+    sel         r6, r12, r11                ; hev mask: r6
+
+    ;vp8_filter() function
+    ; load soure data to r6, r11, r12, lr
+    ldrh        r9, [src, #-2]
+    ldrh        r10, [src], pstep
+
+    pkhbt       r12, r7, r8, lsl #16
+
+    ldrh        r7, [src, #-2]
+    ldrh        r8, [src], pstep
+
+    pkhbt       r11, r9, r10, lsl #16
+
+    ldrh        r9, [src, #-2]
+    ldrh        r10, [src], pstep
+
+    ; Transpose needs 8 regs(r6 - r12, and lr). Save r6 and lr first
+    str         r6, [sp]
+    str         lr, [sp, #4]
+
+    pkhbt       r6, r7, r8, lsl #16
+    pkhbt       lr, r9, r10, lsl #16
+
+    ;transpose r12, r11, r6, lr to r7, r8, r9, r10
+    TRANSPOSE_MATRIX r12, r11, r6, lr, r7, r8, r9, r10
+
+    ;load back hev_mask r6 and filter_mask lr
+    ldr         r12, c0x80808080
+    ldr         r6, [sp]
+    ldr         lr, [sp, #4]
+
+    eor         r7, r7, r12                 ; p1 offset to convert to a signed value
+    eor         r8, r8, r12                 ; p0 offset to convert to a signed value
+    eor         r9, r9, r12                 ; q0 offset to convert to a signed value
+    eor         r10, r10, r12               ; q1 offset to convert to a signed value
+
+    str         r9, [sp]                    ; store qs0 temporarily
+    str         r8, [sp, #4]                ; store ps0 temporarily
+    str         r10, [sp, #8]               ; store qs1 temporarily
+    str         r7, [sp, #12]               ; store ps1 temporarily
+
+    qsub8       r7, r7, r10                 ; vp8_signed_char_clamp(ps1-qs1)
+    qsub8       r8, r9, r8                  ; vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+
+    and         r7, r7, r6                  ;  vp8_filter (r7) &= hev (r7 : filter)
+
+    qadd8       r7, r7, r8
+    ldr         r9, c0x03030303             ; r9 = 3 --modified for vp8
+
+    qadd8       r7, r7, r8
+    ldr         r10, c0x04040404
+
+    qadd8       r7, r7, r8
+    ;mvn         r11, #0                     ; r11 == -1
+
+    and         r7, r7, lr                  ; vp8_filter &= mask
+
+    ;modify code for vp8 -- Filter1 = vp8_filter (r7)
+    qadd8       r8 , r7 , r9                ; Filter2 (r8) = vp8_signed_char_clamp(vp8_filter+3)
+    qadd8       r7 , r7 , r10               ; vp8_filter = vp8_signed_char_clamp(vp8_filter+4)
+
+    mov         r9, #0
+    shadd8      r8 , r8 , r9                ; Filter2 >>= 3
+    shadd8      r7 , r7 , r9                ; vp8_filter >>= 3
+    shadd8      r8 , r8 , r9
+    shadd8      r7 , r7 , r9
+    shadd8      lr , r8 , r9                ; lr: filter2
+    shadd8      r7 , r7 , r9                ; r7: filter
+
+    ;usub8      lr, r8, r10                 ; s = (s==4)*-1
+    ;sel            lr, r11, r9
+    ;usub8      r8, r10, r8
+    ;sel            r8, r11, r9
+    ;and            r8, r8, lr                  ; -1 for each element that equals 4 -- r8: s
+
+    ;calculate output
+    ;qadd8      lr, r8, r7                  ; u = vp8_signed_char_clamp(s + vp8_filter)
+
+    ldr         r8, [sp]                    ; load qs0
+    ldr         r9, [sp, #4]                ; load ps0
+
+    ldr         r10, c0x01010101
+
+    qsub8       r8, r8, r7                  ; u = vp8_signed_char_clamp(qs0 - vp8_filter)
+    qadd8       r9, r9, lr                  ; u = vp8_signed_char_clamp(ps0 + Filter2)
+    ;end of modification for vp8
+
+    eor         r8, r8, r12
+    eor         r9, r9, r12
+
+    mov         lr, #0
+
+    sadd8       r7, r7, r10
+    shadd8      r7, r7, lr
+
+    ldr         r10, [sp, #8]               ; load qs1
+    ldr         r11, [sp, #12]              ; load ps1
+
+    bic         r7, r7, r6                  ; r7: vp8_filter
+
+    qsub8       r10 , r10, r7               ; u = vp8_signed_char_clamp(qs1 - vp8_filter)
+    qadd8       r11, r11, r7                ; u = vp8_signed_char_clamp(ps1 + vp8_filter)
+    eor         r10, r10, r12
+    eor         r11, r11, r12
+
+    sub         src, src, pstep, lsl #2
+
+    ;we can use TRANSPOSE_MATRIX macro to transpose output - input: q1, q0, p0, p1
+    ;output is b0, b1, b2, b3
+    ;b0: 03 02 01 00
+    ;b1: 13 12 11 10
+    ;b2: 23 22 21 20
+    ;b3: 33 32 31 30
+    ;    p1 p0 q0 q1
+    ;   (a3 a2 a1 a0)
+    TRANSPOSE_MATRIX r11, r9, r8, r10, r6, r7, r12, lr
+
+    strh        r6, [src, #-2]              ; store the result
+    mov         r6, r6, lsr #16
+    strh        r6, [src], pstep
+
+    strh        r7, [src, #-2]
+    mov         r7, r7, lsr #16
+    strh        r7, [src], pstep
+
+    strh        r12, [src, #-2]
+    mov         r12, r12, lsr #16
+    strh        r12, [src], pstep
+
+    strh        lr, [src, #-2]
+    mov         lr, lr, lsr #16
+    strh        lr, [src], pstep
+
+|vskip_filter|
+    sub         src, src, #4
+    subs        count, count, #1
+
+    ldrne       r6, [src], pstep            ; load source data
+    ldrne       r7, [src], pstep
+    ldrne       r8, [src], pstep
+    ldrne       lr, [src], pstep
+
+    bne         Vnext8
+
+    add         sp, sp, #16
+
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_loop_filter_vertical_edge_armv6|
+
+
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+|vp8_mbloop_filter_vertical_edge_armv6| PROC
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+    stmdb       sp!, {r4 - r11, lr}
+
+    sub         src, src, #4                ; move src pointer down by 4
+    ldr         count, [sp, #40]            ; count for 8-in-parallel
+    ldr         r12, [sp, #36]              ; load thresh address
+    sub         sp, sp, #16                 ; create temp buffer
+
+    ldr         r6, [src], pstep            ; load source data
+    ldr         r4, [r2], #4                ; flimit
+    ldr         r7, [src], pstep
+    ldr         r2, [r3], #4                ; limit
+    ldr         r8, [src], pstep
+    uadd8       r4, r4, r4                  ; flimit * 2
+    ldr         r3, [r12], #4               ; thresh
+    ldr         lr, [src], pstep
+    mov         count, count, lsl #1        ; 4-in-parallel
+    uadd8       r4, r4, r2                  ; flimit * 2 + limit
+
+|MBVnext8|
+    ; vp8_filter_mask() function
+    ; calculate breakout conditions
+    ; transpose the source data for 4-in-parallel operation
+    TRANSPOSE_MATRIX r6, r7, r8, lr, r9, r10, r11, r12
+
+    uqsub8      r7, r9, r10                 ; p3 - p2
+    uqsub8      r8, r10, r9                 ; p2 - p3
+    uqsub8      r9, r10, r11                ; p2 - p1
+    uqsub8      r10, r11, r10               ; p1 - p2
+    orr         r7, r7, r8                  ; abs (p3-p2)
+    orr         r10, r9, r10                ; abs (p2-p1)
+    uqsub8      lr, r7, r2                  ; compare to limit. lr: vp8_filter_mask
+    uqsub8      r10, r10, r2                ; compare to limit
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+
+    orr         lr, lr, r10
+
+    uqsub8      r6, r11, r12                ; p1 - p0
+    uqsub8      r7, r12, r11                ; p0 - p1
+    add         src, src, #4                ; move src pointer up by 4
+    orr         r6, r6, r7                  ; abs (p1-p0)
+    str         r11, [sp, #12]              ; save p1
+    uqsub8      r10, r6, r2                 ; compare to limit
+    uqsub8      r11, r6, r3                 ; compare to thresh
+    orr         lr, lr, r10
+
+    ; transpose uses 8 regs(r6 - r12 and lr). Need to save reg value now
+    ; transpose the source data for 4-in-parallel operation
+    ldr         r6, [src], pstep            ; load source data
+    str         r11, [sp]                   ; push r11 to stack
+    ldr         r7, [src], pstep
+    str         r12, [sp, #4]               ; save current reg before load q0 - q3 data
+    ldr         r8, [src], pstep
+    str         lr, [sp, #8]
+    ldr         lr, [src], pstep
+
+    TRANSPOSE_MATRIX r6, r7, r8, lr, r9, r10, r11, r12
+
+    ldr         lr, [sp, #8]                ; load back (f)limit accumulator
+
+    uqsub8      r6, r12, r11                ; q3 - q2
+    uqsub8      r7, r11, r12                ; q2 - q3
+    uqsub8      r12, r11, r10               ; q2 - q1
+    uqsub8      r11, r10, r11               ; q1 - q2
+    orr         r6, r6, r7                  ; abs (q3-q2)
+    orr         r7, r12, r11                ; abs (q2-q1)
+    uqsub8      r6, r6, r2                  ; compare to limit
+    uqsub8      r7, r7, r2                  ; compare to limit
+    ldr         r11, [sp, #4]               ; load back p0
+    ldr         r12, [sp, #12]              ; load back p1
+    orr         lr, lr, r6
+    orr         lr, lr, r7
+
+    uqsub8      r6, r11, r9                 ; p0 - q0
+    uqsub8      r7, r9, r11                 ; q0 - p0
+    uqsub8      r8, r12, r10                ; p1 - q1
+    uqsub8      r11, r10, r12               ; q1 - p1
+    orr         r6, r6, r7                  ; abs (p0-q0)
+    ldr         r7, c0x7F7F7F7F
+    orr         r8, r8, r11                 ; abs (p1-q1)
+    uqadd8      r6, r6, r6                  ; abs (p0-q0) * 2
+    and         r8, r7, r8, lsr #1          ; abs (p1-q1) / 2
+    uqsub8      r11, r10, r9                ; q1 - q0
+    uqadd8      r6, r8, r6                  ; abs (p0-q0)*2 + abs (p1-q1)/2
+    uqsub8      r12, r9, r10                ; q0 - q1
+    uqsub8      r6, r6, r4                  ; compare to flimit
+
+    orr         r9, r11, r12                ; abs (q1-q0)
+    uqsub8      r8, r9, r2                  ; compare to limit
+    uqsub8      r10, r9, r3                 ; compare to thresh
+    orr         lr, lr, r6
+    orr         lr, lr, r8
+
+    mvn         r11, #0                     ; r11 == -1
+    mov         r12, #0
+
+    usub8       lr, r12, lr
+    ldr         r9, [sp]                    ; load the compared result
+    sel         lr, r11, r12                ; filter mask: lr
+
+    cmp         lr, #0
+    beq         mbvskip_filter               ; skip filtering
+
+
+    ;vp8_hevmask() function
+    ;calculate high edge variance
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+
+    orr         r9, r9, r10
+
+    ldrh        r7, [src, #-2]
+    ldrh        r8, [src], pstep
+
+    usub8       r9, r12, r9
+    sel         r6, r12, r11                ; hev mask: r6
+
+
+    ; vp8_mbfilter() function
+    ; p2, q2 are only needed at the end. Don't need to load them in now.
+    ; Transpose needs 8 regs(r6 - r12, and lr). Save r6 and lr first
+    ; load soure data to r6, r11, r12, lr
+    ldrh        r9, [src, #-2]
+    ldrh        r10, [src], pstep
+
+    pkhbt       r12, r7, r8, lsl #16
+
+    ldrh        r7, [src, #-2]
+    ldrh        r8, [src], pstep
+
+    pkhbt       r11, r9, r10, lsl #16
+
+    ldrh        r9, [src, #-2]
+    ldrh        r10, [src], pstep
+
+    str         r6, [sp]                    ; save r6
+    str         lr, [sp, #4]                ; save lr
+
+    pkhbt       r6, r7, r8, lsl #16
+    pkhbt       lr, r9, r10, lsl #16
+
+    ;transpose r12, r11, r6, lr to p1, p0, q0, q1
+    TRANSPOSE_MATRIX r12, r11, r6, lr, r7, r8, r9, r10
+
+    ;load back hev_mask r6 and filter_mask lr
+    ldr         r12, c0x80808080
+    ldr         r6, [sp]
+    ldr         lr, [sp, #4]
+
+    eor         r7, r7, r12                 ; ps1
+    eor         r8, r8, r12                 ; ps0
+    eor         r9, r9, r12                 ; qs0
+    eor         r10, r10, r12               ; qs1
+
+    qsub8       r12, r9, r8                 ; vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    str         r7, [sp, #12]               ; store ps1 temporarily
+    qsub8       r7, r7, r10                 ; vp8_signed_char_clamp(ps1-qs1)
+    str         r10, [sp, #8]               ; store qs1 temporarily
+    qadd8       r7, r7, r12
+    str         r9, [sp]                    ; store qs0 temporarily
+    qadd8       r7, r7, r12
+    str         r8, [sp, #4]                ; store ps0 temporarily
+    qadd8       r7, r7, r12                 ; vp8_filter: r7
+
+    ldr         r10, c0x03030303            ; r10 = 3 --modified for vp8
+    ldr         r9, c0x04040404
+    ;mvn         r11, #0                     ; r11 == -1
+
+    and         r7, r7, lr                  ; vp8_filter &= mask (lr is free)
+
+    mov         r12, r7                     ; Filter2: r12
+    and         r12, r12, r6                ; Filter2 &= hev
+
+    ;modify code for vp8
+    ;save bottom 3 bits so that we round one side +4 and the other +3
+    qadd8       r8 , r12 , r9               ; Filter1 (r8) = vp8_signed_char_clamp(Filter2+4)
+    qadd8       r12 , r12 , r10             ; Filter2 (r12) = vp8_signed_char_clamp(Filter2+3)
+
+    mov         r10, #0
+    shadd8      r8 , r8 , r10               ; Filter1 >>= 3
+    shadd8      r12 , r12 , r10             ; Filter2 >>= 3
+    shadd8      r8 , r8 , r10
+    shadd8      r12 , r12 , r10
+    shadd8      r8 , r8 , r10               ; r8: Filter1
+    shadd8      r12 , r12 , r10             ; r12: Filter2
+
+    ldr         r9, [sp]                    ; load qs0
+    ldr         r11, [sp, #4]               ; load ps0
+
+    qsub8       r9 , r9, r8                 ; qs0 = vp8_signed_char_clamp(qs0 - Filter1)
+    qadd8       r11, r11, r12               ; ps0 = vp8_signed_char_clamp(ps0 + Filter2)
+
+    ;save bottom 3 bits so that we round one side +4 and the other +3
+    ;and            r8, r12, r10                ; s = Filter2 & 7 (s: r8)
+    ;qadd8      r12 , r12 , r9              ; Filter2 = vp8_signed_char_clamp(Filter2+4)
+    ;mov            r10, #0
+    ;shadd8     r12 , r12 , r10             ; Filter2 >>= 3
+    ;usub8      lr, r8, r9                  ; s = (s==4)*-1
+    ;sel            lr, r11, r10
+    ;shadd8     r12 , r12 , r10
+    ;usub8      r8, r9, r8
+    ;sel            r8, r11, r10
+    ;ldr            r9, [sp]                    ; load qs0
+    ;ldr            r11, [sp, #4]               ; load ps0
+    ;shadd8     r12 , r12 , r10
+    ;and            r8, r8, lr                  ; -1 for each element that equals 4
+    ;qadd8      r10, r8, r12                ; u = vp8_signed_char_clamp(s + Filter2)
+    ;qsub8      r9 , r9, r12                ; qs0 = vp8_signed_char_clamp(qs0 - Filter2)
+    ;qadd8      r11, r11, r10               ; ps0 = vp8_signed_char_clamp(ps0 + u)
+
+    ;end of modification for vp8
+
+    bic         r12, r7, r6                 ;vp8_filter &= ~hev    ( r6 is free)
+    ;mov            r12, r7
+
+    ;roughly 3/7th difference across boundary
+    mov         lr, #0x1b                   ; 27
+    mov         r7, #0x3f                   ; 63
+
+    sxtb16      r6, r12
+    sxtb16      r10, r12, ror #8
+    smlabb      r8, r6, lr, r7
+    smlatb      r6, r6, lr, r7
+    smlabb      r7, r10, lr, r7
+    smultb      r10, r10, lr
+    ssat        r8, #8, r8, asr #7
+    ssat        r6, #8, r6, asr #7
+    add         r10, r10, #63
+    ssat        r7, #8, r7, asr #7
+    ssat        r10, #8, r10, asr #7
+
+    ldr         lr, c0x80808080
+
+    pkhbt       r6, r8, r6, lsl #16
+    pkhbt       r10, r7, r10, lsl #16
+    uxtb16      r6, r6
+    uxtb16      r10, r10
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+
+    orr         r10, r6, r10, lsl #8        ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7)
+
+    qsub8       r8, r9, r10                 ; s = vp8_signed_char_clamp(qs0 - u)
+    qadd8       r10, r11, r10               ; s = vp8_signed_char_clamp(ps0 + u)
+    eor         r8, r8, lr                  ; *oq0 = s^0x80
+    eor         r10, r10, lr                ; *op0 = s^0x80
+
+    strb        r10, [src, #-1]             ; store op0 result
+    strb        r8, [src], pstep            ; store oq0 result
+    mov         r10, r10, lsr #8
+    mov         r8, r8, lsr #8
+    strb        r10, [src, #-1]
+    strb        r8, [src], pstep
+    mov         r10, r10, lsr #8
+    mov         r8, r8, lsr #8
+    strb        r10, [src, #-1]
+    strb        r8, [src], pstep
+    mov         r10, r10, lsr #8
+    mov         r8, r8, lsr #8
+    strb        r10, [src, #-1]
+    strb        r8, [src], pstep
+
+    ;roughly 2/7th difference across boundary
+    mov         lr, #0x12                   ; 18
+    mov         r7, #0x3f                   ; 63
+
+    sxtb16      r6, r12
+    sxtb16      r10, r12, ror #8
+    smlabb      r8, r6, lr, r7
+    smlatb      r6, r6, lr, r7
+    smlabb      r9, r10, lr, r7
+    smlatb      r10, r10, lr, r7
+    ssat        r8, #8, r8, asr #7
+    ssat        r6, #8, r6, asr #7
+    ssat        r9, #8, r9, asr #7
+    ssat        r10, #8, r10, asr #7
+
+    sub         src, src, pstep, lsl #2     ; move src pointer down by 4 lines
+
+    pkhbt       r6, r8, r6, lsl #16
+    pkhbt       r10, r9, r10, lsl #16
+
+    ldr         r9, [sp, #8]                ; load qs1
+    ldr         r11, [sp, #12]              ; load ps1
+    ldr         lr, c0x80808080
+
+    uxtb16      r6, r6
+    uxtb16      r10, r10
+
+    add         src, src, #2
+
+    orr         r10, r6, r10, lsl #8        ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7)
+
+    qsub8       r8, r9, r10                 ; s = vp8_signed_char_clamp(qs1 - u)
+    qadd8       r10, r11, r10               ; s = vp8_signed_char_clamp(ps1 + u)
+    eor         r8, r8, lr                  ; *oq1 = s^0x80
+    eor         r10, r10, lr                ; *op1 = s^0x80
+
+    ldrb        r11, [src, #-5]             ; load p2 for 1/7th difference across boundary
+    strb        r10, [src, #-4]             ; store op1
+    strb        r8, [src, #-1]              ; store oq1
+    ldrb        r9, [src], pstep            ; load q2 for 1/7th difference across boundary
+
+    mov         r10, r10, lsr #8
+    mov         r8, r8, lsr #8
+
+    ldrb        r6, [src, #-5]
+    strb        r10, [src, #-4]
+    strb        r8, [src, #-1]
+    ldrb        r7, [src], pstep
+
+    mov         r10, r10, lsr #8
+    mov         r8, r8, lsr #8
+    orr         r11, r11, r6, lsl #8
+    orr         r9, r9, r7, lsl #8
+
+    ldrb        r6, [src, #-5]
+    strb        r10, [src, #-4]
+    strb        r8, [src, #-1]
+    ldrb        r7, [src], pstep
+
+    mov         r10, r10, lsr #8
+    mov         r8, r8, lsr #8
+    orr         r11, r11, r6, lsl #16
+    orr         r9, r9, r7, lsl #16
+
+    ldrb        r6, [src, #-5]
+    strb        r10, [src, #-4]
+    strb        r8, [src, #-1]
+    ldrb        r7, [src], pstep
+    orr         r11, r11, r6, lsl #24
+    orr         r9, r9, r7, lsl #24
+
+    ;roughly 1/7th difference across boundary
+    eor         r9, r9, lr
+    eor         r11, r11, lr
+
+    mov         lr, #0x9                    ; 9
+    mov         r7, #0x3f                   ; 63
+
+    sxtb16      r6, r12
+    sxtb16      r10, r12, ror #8
+    smlabb      r8, r6, lr, r7
+    smlatb      r6, r6, lr, r7
+    smlabb      r12, r10, lr, r7
+    smlatb      r10, r10, lr, r7
+    ssat        r8, #8, r8, asr #7
+    ssat        r6, #8, r6, asr #7
+    ssat        r12, #8, r12, asr #7
+    ssat        r10, #8, r10, asr #7
+
+    sub         src, src, pstep, lsl #2
+
+    pkhbt       r6, r8, r6, lsl #16
+    pkhbt       r10, r12, r10, lsl #16
+
+    uxtb16      r6, r6
+    uxtb16      r10, r10
+
+    ldr         lr, c0x80808080
+
+    orr         r10, r6, r10, lsl #8        ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7)
+
+    qadd8       r8, r11, r10                ; s = vp8_signed_char_clamp(ps2 + u)
+    qsub8       r10, r9, r10                ; s = vp8_signed_char_clamp(qs2 - u)
+    eor         r8, r8, lr                  ; *op2 = s^0x80
+    eor         r10, r10, lr                ; *oq2 = s^0x80
+
+    strb        r8, [src, #-5]              ; store *op2
+    strb        r10, [src], pstep           ; store *oq2
+    mov         r8, r8, lsr #8
+    mov         r10, r10, lsr #8
+    strb        r8, [src, #-5]
+    strb        r10, [src], pstep
+    mov         r8, r8, lsr #8
+    mov         r10, r10, lsr #8
+    strb        r8, [src, #-5]
+    strb        r10, [src], pstep
+    mov         r8, r8, lsr #8
+    mov         r10, r10, lsr #8
+    strb        r8, [src, #-5]
+    strb        r10, [src], pstep
+
+    ;adjust src pointer for next loop
+    sub         src, src, #2
+
+|mbvskip_filter|
+    sub         src, src, #4
+    subs        count, count, #1
+
+    ldrne       r6, [src], pstep            ; load source data
+    ldrne       r7, [src], pstep
+    ldrne       r8, [src], pstep
+    ldrne       lr, [src], pstep
+
+    bne         MBVnext8
+
+    add         sp, sp, #16
+
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_mbloop_filter_vertical_edge_armv6|
+
+; Constant Pool
+c0x80808080 DCD     0x80808080
+c0x03030303 DCD     0x03030303
+c0x04040404 DCD     0x04040404
+c0x01010101 DCD     0x01010101
+c0x7F7F7F7F DCD     0x7F7F7F7F
+
+    END
diff --git a/vp8/common/arm/armv6/recon_v6.asm b/vp8/common/arm/armv6/recon_v6.asm
new file mode 100644
index 0000000..085ff80
--- /dev/null
+++ b/vp8/common/arm/armv6/recon_v6.asm
@@ -0,0 +1,280 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_recon_b_armv6|
+    EXPORT  |vp8_recon2b_armv6|
+    EXPORT  |vp8_recon4b_armv6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+prd     RN  r0
+dif     RN  r1
+dst     RN  r2
+stride      RN  r3
+
+;void recon_b(unsigned char *pred_ptr, short *diff_ptr, unsigned char *dst_ptr, int stride)
+; R0 char* pred_ptr
+; R1 short * dif_ptr
+; R2 char * dst_ptr
+; R3 int stride
+
+; Description:
+; Loop through the block adding the Pred and Diff together.  Clamp and then
+; store back into the Dst.
+
+; Restrictions :
+; all buffers are expected to be 4 byte aligned coming in and
+; going out.
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+;
+;
+;
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_recon_b_armv6| PROC
+    stmdb   sp!, {r4 - r9, lr}
+
+    ;0, 1, 2, 3
+    ldr     r4, [prd], #16          ; 3 | 2 | 1 | 0
+    ldr     r6, [dif, #0]           ;     1 |     0
+    ldr     r7, [dif, #4]           ;     3 |     2
+
+    pkhbt   r8, r6, r7, lsl #16     ;     2 |     0
+    pkhtb   r9, r7, r6, asr #16     ;     3 |     1
+
+    uxtab16 r8, r8, r4              ;     2 |     0  +  3 | 2 | 2 | 0
+    uxtab16 r9, r9, r4, ror #8      ;     3 |     1  +  0 | 3 | 2 | 1
+
+    usat16  r8, #8, r8
+    usat16  r9, #8, r9
+    add     dif, dif, #32
+    orr     r8, r8, r9, lsl #8
+
+    str     r8, [dst], stride
+
+    ;0, 1, 2, 3
+    ldr     r4, [prd], #16          ; 3 | 2 | 1 | 0
+;;  ldr     r6, [dif, #8]           ;     1 |     0
+;;  ldr     r7, [dif, #12]          ;     3 |     2
+    ldr     r6, [dif, #0]           ;     1 |     0
+    ldr     r7, [dif, #4]           ;     3 |     2
+
+    pkhbt   r8, r6, r7, lsl #16     ;     2 |     0
+    pkhtb   r9, r7, r6, asr #16     ;     3 |     1
+
+    uxtab16 r8, r8, r4              ;     2 |     0  +  3 | 2 | 2 | 0
+    uxtab16 r9, r9, r4, ror #8      ;     3 |     1  +  0 | 3 | 2 | 1
+
+    usat16  r8, #8, r8
+    usat16  r9, #8, r9
+    add     dif, dif, #32
+    orr     r8, r8, r9, lsl #8
+
+    str     r8, [dst], stride
+
+    ;0, 1, 2, 3
+    ldr     r4, [prd], #16          ; 3 | 2 | 1 | 0
+;;  ldr     r6, [dif, #16]          ;     1 |     0
+;;  ldr     r7, [dif, #20]          ;     3 |     2
+    ldr     r6, [dif, #0]           ;     1 |     0
+    ldr     r7, [dif, #4]           ;     3 |     2
+
+    pkhbt   r8, r6, r7, lsl #16     ;     2 |     0
+    pkhtb   r9, r7, r6, asr #16     ;     3 |     1
+
+    uxtab16 r8, r8, r4              ;     2 |     0  +  3 | 2 | 2 | 0
+    uxtab16 r9, r9, r4, ror #8      ;     3 |     1  +  0 | 3 | 2 | 1
+
+    usat16  r8, #8, r8
+    usat16  r9, #8, r9
+    add     dif, dif, #32
+    orr     r8, r8, r9, lsl #8
+
+    str     r8, [dst], stride
+
+    ;0, 1, 2, 3
+    ldr     r4, [prd], #16          ; 3 | 2 | 1 | 0
+;;  ldr     r6, [dif, #24]          ;     1 |     0
+;;  ldr     r7, [dif, #28]          ;     3 |     2
+    ldr     r6, [dif, #0]           ;     1 |     0
+    ldr     r7, [dif, #4]           ;     3 |     2
+
+    pkhbt   r8, r6, r7, lsl #16     ;     2 |     0
+    pkhtb   r9, r7, r6, asr #16     ;     3 |     1
+
+    uxtab16 r8, r8, r4              ;     2 |     0  +  3 | 2 | 2 | 0
+    uxtab16 r9, r9, r4, ror #8      ;     3 |     1  +  0 | 3 | 2 | 1
+
+    usat16  r8, #8, r8
+    usat16  r9, #8, r9
+    orr     r8, r8, r9, lsl #8
+
+    str     r8, [dst], stride
+
+    ldmia   sp!, {r4 - r9, pc}
+
+    ENDP    ; |recon_b|
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+;
+;
+;
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+; R0 char  *pred_ptr
+; R1 short *dif_ptr
+; R2 char  *dst_ptr
+; R3 int stride
+|vp8_recon4b_armv6| PROC
+    stmdb   sp!, {r4 - r9, lr}
+
+    mov     lr, #4
+
+recon4b_loop
+    ;0, 1, 2, 3
+    ldr     r4, [prd], #4           ; 3 | 2 | 1 | 0
+    ldr     r6, [dif, #0]           ;     1 |     0
+    ldr     r7, [dif, #4]           ;     3 |     2
+
+    pkhbt   r8, r6, r7, lsl #16     ;     2 |     0
+    pkhtb   r9, r7, r6, asr #16     ;     3 |     1
+
+    uxtab16 r8, r8, r4              ;     2 |     0  +  3 | 2 | 2 | 0
+    uxtab16 r9, r9, r4, ror #8      ;     3 |     1  +  0 | 3 | 2 | 1
+
+    usat16  r8, #8, r8
+    usat16  r9, #8, r9
+    orr     r8, r8, r9, lsl #8
+
+    str     r8, [dst]
+
+    ;4, 5, 6, 7
+    ldr     r4, [prd], #4
+;;  ldr     r6, [dif, #32]
+;;  ldr     r7, [dif, #36]
+    ldr     r6, [dif, #8]
+    ldr     r7, [dif, #12]
+
+    pkhbt   r8, r6, r7, lsl #16
+    pkhtb   r9, r7, r6, asr #16
+
+    uxtab16 r8, r8, r4
+    uxtab16 r9, r9, r4, ror #8
+    usat16  r8, #8, r8
+    usat16  r9, #8, r9
+    orr     r8, r8, r9, lsl #8
+
+    str     r8, [dst, #4]
+
+    ;8, 9, 10, 11
+    ldr     r4, [prd], #4
+;;  ldr     r6, [dif, #64]
+;;  ldr     r7, [dif, #68]
+    ldr     r6, [dif, #16]
+    ldr     r7, [dif, #20]
+
+    pkhbt   r8, r6, r7, lsl #16
+    pkhtb   r9, r7, r6, asr #16
+
+    uxtab16 r8, r8, r4
+    uxtab16 r9, r9, r4, ror #8
+    usat16  r8, #8, r8
+    usat16  r9, #8, r9
+    orr     r8, r8, r9, lsl #8
+
+    str     r8, [dst, #8]
+
+    ;12, 13, 14, 15
+    ldr     r4, [prd], #4
+;;  ldr     r6, [dif, #96]
+;;  ldr     r7, [dif, #100]
+    ldr     r6, [dif, #24]
+    ldr     r7, [dif, #28]
+
+    pkhbt   r8, r6, r7, lsl #16
+    pkhtb   r9, r7, r6, asr #16
+
+    uxtab16 r8, r8, r4
+    uxtab16 r9, r9, r4, ror #8
+    usat16  r8, #8, r8
+    usat16  r9, #8, r9
+    orr     r8, r8, r9, lsl #8
+
+    str     r8, [dst, #12]
+
+    add     dst, dst, stride
+;;  add     dif, dif, #8
+    add     dif, dif, #32
+
+    subs    lr, lr, #1
+    bne     recon4b_loop
+
+    ldmia   sp!, {r4 - r9, pc}
+
+    ENDP    ; |Recon4B|
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+;
+;
+;
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+; R0 char  *pred_ptr
+; R1 short *dif_ptr
+; R2 char  *dst_ptr
+; R3 int stride
+|vp8_recon2b_armv6| PROC
+    stmdb   sp!, {r4 - r9, lr}
+
+    mov     lr, #4
+
+recon2b_loop
+    ;0, 1, 2, 3
+    ldr     r4, [prd], #4
+    ldr     r6, [dif, #0]
+    ldr     r7, [dif, #4]
+
+    pkhbt   r8, r6, r7, lsl #16
+    pkhtb   r9, r7, r6, asr #16
+
+    uxtab16 r8, r8, r4
+    uxtab16 r9, r9, r4, ror #8
+    usat16  r8, #8, r8
+    usat16  r9, #8, r9
+    orr     r8, r8, r9, lsl #8
+
+    str     r8, [dst]
+
+    ;4, 5, 6, 7
+    ldr     r4, [prd], #4
+;;  ldr     r6, [dif, #32]
+;;  ldr     r7, [dif, #36]
+    ldr     r6, [dif, #8]
+    ldr     r7, [dif, #12]
+
+    pkhbt   r8, r6, r7, lsl #16
+    pkhtb   r9, r7, r6, asr #16
+
+    uxtab16 r8, r8, r4
+    uxtab16 r9, r9, r4, ror #8
+    usat16  r8, #8, r8
+    usat16  r9, #8, r9
+    orr     r8, r8, r9, lsl #8
+
+    str     r8, [dst, #4]
+
+    add     dst, dst, stride
+;;  add     dif, dif, #8
+    add     dif, dif, #16
+
+    subs    lr, lr, #1
+    bne     recon2b_loop
+
+    ldmia   sp!, {r4 - r9, pc}
+
+    ENDP    ; |Recon2B|
+
+    END
diff --git a/vp8/common/arm/armv6/simpleloopfilter_v6.asm b/vp8/common/arm/armv6/simpleloopfilter_v6.asm
new file mode 100644
index 0000000..15c6c7d
--- /dev/null
+++ b/vp8/common/arm/armv6/simpleloopfilter_v6.asm
@@ -0,0 +1,321 @@
+;
+;  Copyright (c) 2010 The VP8 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 |vp8_loop_filter_simple_horizontal_edge_armv6|
+    EXPORT |vp8_loop_filter_simple_vertical_edge_armv6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+    MACRO
+    TRANSPOSE_MATRIX $a0, $a1, $a2, $a3, $b0, $b1, $b2, $b3
+    ; input: $a0, $a1, $a2, $a3; output: $b0, $b1, $b2, $b3
+    ; a0: 03 02 01 00
+    ; a1: 13 12 11 10
+    ; a2: 23 22 21 20
+    ; a3: 33 32 31 30
+    ;     b3 b2 b1 b0
+
+    uxtb16      $b1, $a1                    ; xx 12 xx 10
+    uxtb16      $b0, $a0                    ; xx 02 xx 00
+    uxtb16      $b3, $a3                    ; xx 32 xx 30
+    uxtb16      $b2, $a2                    ; xx 22 xx 20
+    orr         $b1, $b0, $b1, lsl #8       ; 12 02 10 00
+    orr         $b3, $b2, $b3, lsl #8       ; 32 22 30 20
+
+    uxtb16      $a1, $a1, ror #8            ; xx 13 xx 11
+    uxtb16      $a3, $a3, ror #8            ; xx 33 xx 31
+    uxtb16      $a0, $a0, ror #8            ; xx 03 xx 01
+    uxtb16      $a2, $a2, ror #8            ; xx 23 xx 21
+    orr         $a0, $a0, $a1, lsl #8       ; 13 03 11 01
+    orr         $a2, $a2, $a3, lsl #8       ; 33 23 31 21
+
+    pkhtb       $b2, $b3, $b1, asr #16      ; 32 22 12 02   -- p1
+    pkhbt       $b0, $b1, $b3, lsl #16      ; 30 20 10 00   -- p3
+
+    pkhtb       $b3, $a2, $a0, asr #16      ; 33 23 13 03   -- p0
+    pkhbt       $b1, $a0, $a2, lsl #16      ; 31 21 11 01   -- p2
+    MEND
+
+
+src         RN  r0
+pstep       RN  r1
+
+;r0     unsigned char *src_ptr,
+;r1     int src_pixel_step,
+;r2     const char *flimit,
+;r3     const char *limit,
+;stack  const char *thresh,
+;stack  int  count
+
+;Note: All 16 elements in flimit are equal. So, in the code, only one load is needed
+;for flimit. Same way applies to limit and thresh.
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+|vp8_loop_filter_simple_horizontal_edge_armv6| PROC
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+    stmdb       sp!, {r4 - r11, lr}
+
+    sub         src, src, pstep, lsl #1     ; move src pointer down by 2 lines
+
+    ldr         r12, [r3], #4               ; limit
+    ldr         r3, [src], pstep            ; p1
+
+    ldr         r9, [sp, #36]               ; count for 8-in-parallel
+    ldr         r4, [src], pstep            ; p0
+
+    ldr         r7, [r2], #4                ; flimit
+    ldr         r5, [src], pstep            ; q0
+    ldr         r2, c0x80808080
+
+    ldr         r6, [src]                   ; q1
+
+    uadd8       r7, r7, r7                  ; flimit * 2
+    mov         r9, r9, lsl #1              ; 4-in-parallel
+    uadd8       r12, r7, r12                ; flimit * 2 + limit
+
+|simple_hnext8|
+    ; vp8_simple_filter_mask() function
+
+    uqsub8      r7, r3, r6                  ; p1 - q1
+    uqsub8      r8, r6, r3                  ; q1 - p1
+    uqsub8      r10, r4, r5                 ; p0 - q0
+    uqsub8      r11, r5, r4                 ; q0 - p0
+    orr         r8, r8, r7                  ; abs(p1 - q1)
+    ldr         lr, c0x7F7F7F7F             ; 01111111 mask
+    orr         r10, r10, r11               ; abs(p0 - q0)
+    and         r8, lr, r8, lsr #1          ; abs(p1 - q1) / 2
+    uqadd8      r10, r10, r10               ; abs(p0 - q0) * 2
+    mvn         lr, #0                      ; r10 == -1
+    uqadd8      r10, r10, r8                ; abs(p0 - q0)*2 + abs(p1 - q1)/2
+    ; STALL waiting on r10 :(
+    uqsub8      r10, r10, r12               ; compare to flimit
+    mov         r8, #0
+
+    usub8       r10, r8, r10                ; use usub8 instead of ssub8
+    ; STALL (maybe?) when are flags set? :/
+    sel         r10, lr, r8                 ; filter mask: lr
+
+    cmp         r10, #0
+    beq         simple_hskip_filter         ; skip filtering
+
+    ;vp8_simple_filter() function
+
+    eor         r3, r3, r2                  ; p1 offset to convert to a signed value
+    eor         r6, r6, r2                  ; q1 offset to convert to a signed value
+    eor         r4, r4, r2                  ; p0 offset to convert to a signed value
+    eor         r5, r5, r2                  ; q0 offset to convert to a signed value
+
+    qsub8       r3, r3, r6                  ; vp8_filter (r3) = vp8_signed_char_clamp(p1-q1)
+    qsub8       r6, r5, r4                  ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( q0 - p0))
+
+    qadd8       r3, r3, r6
+    ldr         r8, c0x03030303             ; r8 = 3
+
+    qadd8       r3, r3, r6
+    ldr         r7, c0x04040404
+
+    qadd8       r3, r3, r6
+    and         r3, r3, lr                  ; vp8_filter &= mask;
+
+    ;save bottom 3 bits so that we round one side +4 and the other +3
+    qadd8       r8 , r3 , r8                ; Filter2 (r8) = vp8_signed_char_clamp(vp8_filter+3)
+    qadd8       r3 , r3 , r7                ; Filter1 (r3) = vp8_signed_char_clamp(vp8_filter+4)
+
+    mov         r7, #0
+    shadd8      r8 , r8 , r7                ; Filter2 >>= 3
+    shadd8      r3 , r3 , r7                ; Filter1 >>= 3
+    shadd8      r8 , r8 , r7
+    shadd8      r3 , r3 , r7
+    shadd8      r8 , r8 , r7                ; r8: Filter2
+    shadd8      r3 , r3 , r7                ; r7: filter1
+
+    ;calculate output
+    sub         src, src, pstep, lsl #1
+
+    qadd8       r4, r4, r8                  ; u = vp8_signed_char_clamp(p0 + Filter2)
+    qsub8       r5 ,r5, r3                  ; u = vp8_signed_char_clamp(q0 - Filter1)
+    eor         r4, r4, r2                  ; *op0 = u^0x80
+    str         r4, [src], pstep            ; store op0 result
+    eor         r5, r5, r2                  ; *oq0 = u^0x80
+    str         r5, [src], pstep            ; store oq0 result
+
+|simple_hskip_filter|
+    add         src, src, #4
+    sub         src, src, pstep
+    sub         src, src, pstep, lsl #1
+
+    subs        r9, r9, #1
+
+    ;pld            [src]
+    ;pld            [src, pstep]
+    ;pld            [src, pstep, lsl #1]
+
+    ldrne           r3, [src], pstep            ; p1
+    ldrne           r4, [src], pstep            ; p0
+    ldrne           r5, [src], pstep            ; q0
+    ldrne           r6, [src]                   ; q1
+
+    bne         simple_hnext8
+
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_loop_filter_simple_horizontal_edge_armv6|
+
+
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+|vp8_loop_filter_simple_vertical_edge_armv6| PROC
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+    stmdb       sp!, {r4 - r11, lr}
+
+    ldr         r12, [r2], #4               ; r12: flimit
+    ldr         r2, c0x80808080
+    ldr         r7, [r3], #4                ; limit
+
+    ; load soure data to r7, r8, r9, r10
+    ldrh        r3, [src, #-2]
+    ldrh        r4, [src], pstep
+    uadd8       r12, r12, r12               ; flimit * 2
+
+    ldrh        r5, [src, #-2]
+    ldrh        r6, [src], pstep
+    uadd8       r12, r12, r7                ; flimit * 2 + limit
+
+    pkhbt       r7, r3, r4, lsl #16
+
+    ldrh        r3, [src, #-2]
+    ldrh        r4, [src], pstep
+    ldr         r11, [sp, #40]              ; count (r11) for 8-in-parallel
+
+    pkhbt       r8, r5, r6, lsl #16
+
+    ldrh        r5, [src, #-2]
+    ldrh        r6, [src], pstep
+    mov         r11, r11, lsl #1            ; 4-in-parallel
+
+|simple_vnext8|
+    ; vp8_simple_filter_mask() function
+    pkhbt       r9, r3, r4, lsl #16
+    pkhbt       r10, r5, r6, lsl #16
+
+    ;transpose r7, r8, r9, r10 to r3, r4, r5, r6
+    TRANSPOSE_MATRIX r7, r8, r9, r10, r3, r4, r5, r6
+
+    uqsub8      r7, r3, r6                  ; p1 - q1
+    uqsub8      r8, r6, r3                  ; q1 - p1
+    uqsub8      r9, r4, r5                  ; p0 - q0
+    uqsub8      r10, r5, r4                 ; q0 - p0
+    orr         r7, r7, r8                  ; abs(p1 - q1)
+    orr         r9, r9, r10                 ; abs(p0 - q0)
+    ldr         lr, c0x7F7F7F7F             ; 0111 1111 mask
+    uqadd8      r9, r9, r9                  ; abs(p0 - q0) * 2
+    and         r7, lr, r7, lsr #1          ; abs(p1 - q1) / 2
+    mov         r8, #0
+    uqadd8      r7, r7, r9                  ; abs(p0 - q0)*2 + abs(p1 - q1)/2
+    mvn         r10, #0                     ; r10 == -1
+    uqsub8      r7, r7, r12                 ; compare to flimit
+
+    usub8       r7, r8, r7
+    sel         r7, r10, r8                 ; filter mask: lr
+
+    cmp         lr, #0
+    beq         simple_vskip_filter         ; skip filtering
+
+    ;vp8_simple_filter() function
+    eor         r3, r3, r2                  ; p1 offset to convert to a signed value
+    eor         r6, r6, r2                  ; q1 offset to convert to a signed value
+    eor         r4, r4, r2                  ; p0 offset to convert to a signed value
+    eor         r5, r5, r2                  ; q0 offset to convert to a signed value
+
+    qsub8       r3, r3, r6                  ; vp8_filter (r3) = vp8_signed_char_clamp(p1-q1)
+    qsub8       r6, r5, r4                  ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( q0 - p0))
+
+    qadd8       r3, r3, r6
+    ldr         r8, c0x03030303             ; r8 = 3
+
+    qadd8       r3, r3, r6
+    ldr         r7, c0x04040404
+
+    qadd8       r3, r3, r6
+    and         r3, r3, lr                  ; vp8_filter &= mask
+
+    ;save bottom 3 bits so that we round one side +4 and the other +3
+    qadd8       r8 , r3 , r8                ; Filter2 (r8) = vp8_signed_char_clamp(vp8_filter+3)
+    qadd8       r3 , r3 , r7                ; Filter1 (r3) = vp8_signed_char_clamp(vp8_filter+4)
+
+    mov         r7, #0
+    shadd8      r8 , r8 , r7                ; Filter2 >>= 3
+    shadd8      r3 , r3 , r7                ; Filter1 >>= 3
+    shadd8      r8 , r8 , r7
+    shadd8      r3 , r3 , r7
+    shadd8      r8 , r8 , r7                ; r8: filter2
+    shadd8      r3 , r3 , r7                ; r7: filter1
+
+    ;calculate output
+    sub         src, src, pstep, lsl #2
+
+    qadd8       r4, r4, r8                  ; u = vp8_signed_char_clamp(p0 + Filter2)
+    qsub8       r5, r5, r3                  ; u = vp8_signed_char_clamp(q0 - Filter1)
+    eor         r4, r4, r2                  ; *op0 = u^0x80
+    eor         r5, r5, r2                  ; *oq0 = u^0x80
+
+    strb        r4, [src, #-1]              ; store the result
+    mov         r4, r4, lsr #8
+    strb        r5, [src], pstep
+    mov         r5, r5, lsr #8
+
+    strb        r4, [src, #-1]
+    mov         r4, r4, lsr #8
+    strb        r5, [src], pstep
+    mov         r5, r5, lsr #8
+
+    strb        r4, [src, #-1]
+    mov         r4, r4, lsr #8
+    strb        r5, [src], pstep
+    mov         r5, r5, lsr #8
+
+    strb        r4, [src, #-1]
+    strb        r5, [src], pstep
+
+|simple_vskip_filter|
+    subs        r11, r11, #1
+
+    ;pld            [src]
+    ;pld            [src, pstep]
+    ;pld            [src, pstep, lsl #1]
+
+    ; load soure data to r7, r8, r9, r10
+    ldrneh      r3, [src, #-2]
+    ldrneh      r4, [src], pstep
+
+    ldrneh      r5, [src, #-2]
+    ldrneh      r6, [src], pstep
+
+    pkhbt       r7, r3, r4, lsl #16
+
+    ldrneh      r3, [src, #-2]
+    ldrneh      r4, [src], pstep
+
+    pkhbt       r8, r5, r6, lsl #16
+
+    ldrneh      r5, [src, #-2]
+    ldrneh      r6, [src], pstep
+
+    bne         simple_vnext8
+
+    ldmia       sp!, {r4 - r12, pc}
+    ENDP        ; |vp8_loop_filter_simple_vertical_edge_armv6|
+
+; Constant Pool
+c0x80808080 DCD     0x80808080
+c0x03030303 DCD     0x03030303
+c0x04040404 DCD     0x04040404
+c0x01010101 DCD     0x01010101
+c0x7F7F7F7F DCD     0x7F7F7F7F
+
+    END
diff --git a/vp8/common/arm/armv6/sixtappredict8x4_v6.asm b/vp8/common/arm/armv6/sixtappredict8x4_v6.asm
new file mode 100644
index 0000000..551d863
--- /dev/null
+++ b/vp8/common/arm/armv6/sixtappredict8x4_v6.asm
@@ -0,0 +1,277 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_sixtap_predict8x4_armv6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+;-------------------------------------
+; r0    unsigned char *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; stack unsigned char *dst_ptr,
+; stack int  dst_pitch
+;-------------------------------------
+;note: In first pass, store the result in transpose(8linesx9columns) on stack. Temporary stack size is 184.
+;Line width is 20 that is 9 short data plus 2 to make it 4bytes aligned. In second pass, load data from stack,
+;and the result is stored in transpose.
+|vp8_sixtap_predict8x4_armv6| PROC
+    stmdb       sp!, {r4 - r11, lr}
+    sub         sp, sp, #184                ;reserve space on stack for temporary storage: 20x(8+1) +4
+
+    cmp         r2, #0                      ;skip first_pass filter if xoffset=0
+    str         r3, [sp], #4                ;store yoffset
+    beq         skip_firstpass_filter
+
+;first-pass filter
+    ldr         r12, _filter8_coeff_
+    sub         r0, r0, r1, lsl #1
+
+    add         r2, r12, r2, lsl #4         ;calculate filter location
+    add         r0, r0, #3                  ;adjust src only for loading convinience
+
+    ldr         r3, [r2]                    ; load up packed filter coefficients
+    ldr         r4, [r2, #4]
+    ldr         r5, [r2, #8]
+
+    mov         r2, #0x90000                ; height=9 is top part of counter
+
+    sub         r1, r1, #8
+    mov         lr, #20
+
+|first_pass_hloop_v6|
+    ldrb        r6, [r0, #-5]               ; load source data
+    ldrb        r7, [r0, #-4]
+    ldrb        r8, [r0, #-3]
+    ldrb        r9, [r0, #-2]
+    ldrb        r10, [r0, #-1]
+
+    orr         r2, r2, #0x4                ; construct loop counter. width=8=4x2
+
+    pkhbt       r6, r6, r7, lsl #16         ; r7 | r6
+    pkhbt       r7, r7, r8, lsl #16         ; r8 | r7
+
+    pkhbt       r8, r8, r9, lsl #16         ; r9 | r8
+    pkhbt       r9, r9, r10, lsl #16        ; r10 | r9
+
+|first_pass_wloop_v6|
+    smuad       r11, r6, r3                 ; vp8_filter[0], vp8_filter[1]
+    smuad       r12, r7, r3
+
+    ldrb        r6, [r0], #1
+
+    smlad       r11, r8, r4, r11            ; vp8_filter[2], vp8_filter[3]
+    ldrb        r7, [r0], #1
+    smlad       r12, r9, r4, r12
+
+    pkhbt       r10, r10, r6, lsl #16       ; r10 | r9
+    pkhbt       r6, r6, r7, lsl #16         ; r11 | r10
+    smlad       r11, r10, r5, r11           ; vp8_filter[4], vp8_filter[5]
+    smlad       r12, r6, r5, r12
+
+    sub         r2, r2, #1
+
+    add         r11, r11, #0x40             ; round_shift_and_clamp
+    tst         r2, #0xff                   ; test loop counter
+    usat        r11, #8, r11, asr #7
+    add         r12, r12, #0x40
+    strh        r11, [sp], lr               ; result is transposed and stored, which
+    usat        r12, #8, r12, asr #7
+
+    strh        r12, [sp], lr
+
+    movne       r11, r6
+    movne       r12, r7
+
+    movne       r6, r8
+    movne       r7, r9
+    movne       r8, r10
+    movne       r9, r11
+    movne       r10, r12
+
+    bne         first_pass_wloop_v6
+
+    ;;add       r9, ppl, #30                ; attempt to load 2 adjacent cache lines
+    ;;IF ARCHITECTURE=6
+    ;pld        [src, ppl]
+    ;;pld       [src, r9]
+    ;;ENDIF
+
+    subs        r2, r2, #0x10000
+
+    mov         r6, #158
+    sub         sp, sp, r6
+
+    add         r0, r0, r1                  ; move to next input line
+
+    bne         first_pass_hloop_v6
+
+;second pass filter
+secondpass_filter
+    mov         r1, #18
+    sub         sp, sp, r1                  ; 18+4
+
+    ldr         r3, [sp, #-4]               ; load back yoffset
+    ldr         r0, [sp, #216]              ; load dst address from stack 180+36
+    ldr         r1, [sp, #220]              ; load dst stride from stack 180+40
+
+    cmp         r3, #0
+    beq         skip_secondpass_filter
+
+    ldr         r12, _filter8_coeff_
+    add         lr, r12, r3, lsl #4         ;calculate filter location
+
+    mov         r2, #0x00080000
+
+    ldr         r3, [lr]                    ; load up packed filter coefficients
+    ldr         r4, [lr, #4]
+    ldr         r5, [lr, #8]
+
+    pkhbt       r12, r4, r3                 ; pack the filter differently
+    pkhbt       r11, r5, r4
+
+second_pass_hloop_v6
+    ldr         r6, [sp]                    ; load the data
+    ldr         r7, [sp, #4]
+
+    orr         r2, r2, #2                  ; loop counter
+
+second_pass_wloop_v6
+    smuad       lr, r3, r6                  ; apply filter
+    smulbt      r10, r3, r6
+
+    ldr         r8, [sp, #8]
+
+    smlad       lr, r4, r7, lr
+    smladx      r10, r12, r7, r10
+
+    ldrh        r9, [sp, #12]
+
+    smlad       lr, r5, r8, lr
+    smladx      r10, r11, r8, r10
+
+    add         sp, sp, #4
+    smlatb      r10, r5, r9, r10
+
+    sub         r2, r2, #1
+
+    add         lr, lr, #0x40               ; round_shift_and_clamp
+    tst         r2, #0xff
+    usat        lr, #8, lr, asr #7
+    add         r10, r10, #0x40
+    strb        lr, [r0], r1                ; the result is transposed back and stored
+    usat        r10, #8, r10, asr #7
+
+    strb        r10, [r0],r1
+
+    movne       r6, r7
+    movne       r7, r8
+
+    bne         second_pass_wloop_v6
+
+    subs        r2, r2, #0x10000
+    add         sp, sp, #12                 ; updata src for next loop (20-8)
+    sub         r0, r0, r1, lsl #2
+    add         r0, r0, #1
+
+    bne         second_pass_hloop_v6
+
+    add         sp, sp, #20
+    ldmia       sp!, {r4 - r11, pc}
+
+;--------------------
+skip_firstpass_filter
+    sub         r0, r0, r1, lsl #1
+    sub         r1, r1, #8
+    mov         r2, #9
+    mov         r3, #20
+
+skip_firstpass_hloop
+    ldrb        r4, [r0], #1                ; load data
+    subs        r2, r2, #1
+    ldrb        r5, [r0], #1
+    strh        r4, [sp], r3                ; store it to immediate buffer
+    ldrb        r6, [r0], #1                ; load data
+    strh        r5, [sp], r3
+    ldrb        r7, [r0], #1
+    strh        r6, [sp], r3
+    ldrb        r8, [r0], #1
+    strh        r7, [sp], r3
+    ldrb        r9, [r0], #1
+    strh        r8, [sp], r3
+    ldrb        r10, [r0], #1
+    strh        r9, [sp], r3
+    ldrb        r11, [r0], #1
+    strh        r10, [sp], r3
+    add         r0, r0, r1                  ; move to next input line
+    strh        r11, [sp], r3
+
+    mov         r4, #158
+    sub         sp, sp, r4                  ; move over to next column
+    bne         skip_firstpass_hloop
+
+    b           secondpass_filter
+
+;--------------------
+skip_secondpass_filter
+    mov         r2, #8
+    add         sp, sp, #4                  ;start from src[0] instead of src[-2]
+
+skip_secondpass_hloop
+    ldr         r6, [sp], #4
+    subs        r2, r2, #1
+    ldr         r8, [sp], #4
+
+    mov         r7, r6, lsr #16             ; unpack
+    strb        r6, [r0], r1
+    mov         r9, r8, lsr #16
+    strb        r7, [r0], r1
+    add         sp, sp, #12                 ; 20-8
+    strb        r8, [r0], r1
+    strb        r9, [r0], r1
+
+    sub         r0, r0, r1, lsl #2
+    add         r0, r0, #1
+
+    bne         skip_secondpass_hloop
+
+    add         sp, sp, #16                 ; 180 - (160 +4)
+
+    ldmia       sp!, {r4 - r11, pc}
+
+    ENDP
+
+;-----------------
+    AREA    subpelfilters8_dat, DATA, READWRITE         ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_filter8_coeff_
+    DCD     filter8_coeff
+filter8_coeff
+    DCD     0x00000000,     0x00000080,     0x00000000,     0x00000000
+    DCD     0xfffa0000,     0x000c007b,     0x0000ffff,     0x00000000
+    DCD     0xfff50002,     0x0024006c,     0x0001fff8,     0x00000000
+    DCD     0xfff70000,     0x0032005d,     0x0000fffa,     0x00000000
+    DCD     0xfff00003,     0x004d004d,     0x0003fff0,     0x00000000
+    DCD     0xfffa0000,     0x005d0032,     0x0000fff7,     0x00000000
+    DCD     0xfff80001,     0x006c0024,     0x0002fff5,     0x00000000
+    DCD     0xffff0000,     0x007b000c,     0x0000fffa,     0x00000000
+
+    ;DCD        0,  0,  128,    0,   0,  0
+    ;DCD        0, -6,  123,   12,  -1,  0
+    ;DCD        2, -11, 108,   36,  -8,  1
+    ;DCD        0, -9,   93,   50,  -6,  0
+    ;DCD        3, -16,  77,   77, -16,  3
+    ;DCD        0, -6,   50,   93,  -9,  0
+    ;DCD        1, -8,   36,  108, -11,  2
+    ;DCD        0, -1,   12,  123,  -6,  0
+
+    END
diff --git a/vp8/common/arm/bilinearfilter_arm.c b/vp8/common/arm/bilinearfilter_arm.c
new file mode 100644
index 0000000..bf972a3
--- /dev/null
+++ b/vp8/common/arm/bilinearfilter_arm.c
@@ -0,0 +1,211 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <math.h>
+#include "subpixel.h"
+
+#define BLOCK_HEIGHT_WIDTH 4
+#define VP8_FILTER_WEIGHT 128
+#define VP8_FILTER_SHIFT  7
+
+static const short bilinear_filters[8][2] =
+{
+    { 128,   0 },
+    { 112,  16 },
+    {  96,  32 },
+    {  80,  48 },
+    {  64,  64 },
+    {  48,  80 },
+    {  32,  96 },
+    {  16, 112 }
+};
+
+
+extern void vp8_filter_block2d_bil_first_pass_armv6
+(
+    unsigned char *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short *vp8_filter
+);
+
+extern void vp8_filter_block2d_bil_second_pass_armv6
+(
+    unsigned short *src_ptr,
+    unsigned char  *output_ptr,
+    int output_pitch,
+    unsigned int  output_height,
+    unsigned int  output_width,
+    const short *vp8_filter
+);
+
+/*
+void vp8_filter_block2d_bil_first_pass_6
+(
+    unsigned char *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short *vp8_filter
+)
+{
+    unsigned int i, j;
+
+    for ( i=0; i<output_height; i++ )
+    {
+        for ( j=0; j<output_width; j++ )
+        {
+            // Apply bilinear filter
+            output_ptr[j] = ( ( (int)src_ptr[0]          * vp8_filter[0]) +
+                               ((int)src_ptr[1] * vp8_filter[1]) +
+                                (VP8_FILTER_WEIGHT/2) ) >> VP8_FILTER_SHIFT;
+            src_ptr++;
+        }
+
+        // Next row...
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_width;
+    }
+}
+
+void vp8_filter_block2d_bil_second_pass_6
+(
+    unsigned short *src_ptr,
+    unsigned char  *output_ptr,
+    int output_pitch,
+    unsigned int  output_height,
+    unsigned int  output_width,
+    const short *vp8_filter
+)
+{
+    unsigned int  i,j;
+    int  Temp;
+
+    for ( i=0; i<output_height; i++ )
+    {
+        for ( j=0; j<output_width; j++ )
+        {
+            // Apply filter
+            Temp =  ((int)src_ptr[0]         * vp8_filter[0]) +
+                    ((int)src_ptr[output_width] * vp8_filter[1]) +
+                    (VP8_FILTER_WEIGHT/2);
+            output_ptr[j] = (unsigned int)(Temp >> VP8_FILTER_SHIFT);
+            src_ptr++;
+        }
+
+        // Next row...
+        //src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_pitch;
+    }
+}
+*/
+
+void vp8_filter_block2d_bil_armv6
+(
+    unsigned char *src_ptr,
+    unsigned char *output_ptr,
+    unsigned int   src_pixels_per_line,
+    unsigned int   dst_pitch,
+    const short      *HFilter,
+    const short      *VFilter,
+    int            Width,
+    int            Height
+)
+{
+
+    unsigned short FData[36*16]; // Temp data bufffer used in filtering
+
+    // First filter 1-D horizontally...
+    // pixel_step = 1;
+    vp8_filter_block2d_bil_first_pass_armv6(src_ptr, FData, src_pixels_per_line, Height + 1, Width, HFilter);
+
+    // then 1-D vertically...
+    vp8_filter_block2d_bil_second_pass_armv6(FData, output_ptr, dst_pitch, Height, Width, VFilter);
+}
+
+
+void vp8_bilinear_predict4x4_armv6
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+
+    HFilter = bilinear_filters[xoffset];
+    VFilter = bilinear_filters[yoffset];
+
+    vp8_filter_block2d_bil_armv6(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 4, 4);
+}
+
+void vp8_bilinear_predict8x8_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+
+    HFilter = bilinear_filters[xoffset];
+    VFilter = bilinear_filters[yoffset];
+
+    vp8_filter_block2d_bil_armv6(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 8);
+}
+
+void vp8_bilinear_predict8x4_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+
+    HFilter = bilinear_filters[xoffset];
+    VFilter = bilinear_filters[yoffset];
+
+    vp8_filter_block2d_bil_armv6(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 4);
+}
+
+void vp8_bilinear_predict16x16_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+
+    HFilter = bilinear_filters[xoffset];
+    VFilter = bilinear_filters[yoffset];
+
+    vp8_filter_block2d_bil_armv6(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 16, 16);
+}
diff --git a/vp8/common/arm/filter_arm.c b/vp8/common/arm/filter_arm.c
new file mode 100644
index 0000000..2a4640c
--- /dev/null
+++ b/vp8/common/arm/filter_arm.c
@@ -0,0 +1,234 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include <math.h>
+#include "subpixel.h"
+#include "vpx_ports/mem.h"
+
+#define BLOCK_HEIGHT_WIDTH 4
+#define VP8_FILTER_WEIGHT 128
+#define VP8_FILTER_SHIFT  7
+
+DECLARE_ALIGNED(16, static const short, sub_pel_filters[8][6]) =
+{
+    { 0,  0,  128,    0,   0,  0 },         // note that 1/8 pel positions are just as per alpha -0.5 bicubic
+    { 0, -6,  123,   12,  -1,  0 },
+    { 2, -11, 108,   36,  -8,  1 },         // New 1/4 pel 6 tap filter
+    { 0, -9,   93,   50,  -6,  0 },
+    { 3, -16,  77,   77, -16,  3 },         // New 1/2 pel 6 tap filter
+    { 0, -6,   50,   93,  -9,  0 },
+    { 1, -8,   36,  108, -11,  2 },         // New 1/4 pel 6 tap filter
+    { 0, -1,   12,  123,  -6,  0 },
+};
+
+
+extern void vp8_filter_block2d_first_pass_armv6
+(
+    unsigned char *src_ptr,
+    short         *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int output_width,
+    unsigned int output_height,
+    const short *vp8_filter
+);
+
+extern void vp8_filter_block2d_second_pass_armv6
+(
+    short         *src_ptr,
+    unsigned char *output_ptr,
+    unsigned int output_pitch,
+    unsigned int cnt,
+    const short *vp8_filter
+);
+
+extern void vp8_filter_block2d_first_pass_only_armv6
+(
+    unsigned char *src_ptr,
+    unsigned char *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int cnt,
+    unsigned int output_pitch,
+    const short *vp8_filter
+);
+
+
+extern void vp8_filter_block2d_second_pass_only_armv6
+(
+    unsigned char *src_ptr,
+    unsigned char *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int cnt,
+    unsigned int output_pitch,
+    const short *vp8_filter
+);
+
+#if HAVE_ARMV6
+void vp8_sixtap_predict_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    DECLARE_ALIGNED_ARRAY(4, short, FData, 12*4); // Temp data bufffer used in filtering
+
+
+    HFilter = sub_pel_filters[xoffset];   // 6 tap
+    VFilter = sub_pel_filters[yoffset];       // 6 tap
+
+    // Vfilter is null. First pass only
+    if (xoffset && !yoffset)
+    {
+        //vp8_filter_block2d_first_pass_armv6 ( src_ptr, FData+2, src_pixels_per_line, 4, 4, HFilter );
+        //vp8_filter_block2d_second_pass_armv6 ( FData+2, dst_ptr, dst_pitch, 4, VFilter );
+
+        vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 4, dst_pitch, HFilter);
+    }
+    // Hfilter is null. Second pass only
+    else if (!xoffset && yoffset)
+    {
+        vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 4, dst_pitch, VFilter);
+    }
+    else
+    {
+        // Vfilter is a 4 tap filter
+        if (yoffset & 0x1)
+            vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 4, 7, HFilter);
+        // Vfilter is 6 tap filter
+        else
+            vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 4, 9, HFilter);
+
+        vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 4, VFilter);
+    }
+}
+
+/*
+void vp8_sixtap_predict8x4_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    DECLARE_ALIGNED_ARRAY(4, short, FData, 16*8); // Temp data bufffer used in filtering
+
+    HFilter = sub_pel_filters[xoffset];   // 6 tap
+    VFilter = sub_pel_filters[yoffset];       // 6 tap
+
+
+//  if (xoffset && !yoffset)
+//  {
+//      vp8_filter_block2d_first_pass_only_armv6 (  src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, HFilter );
+//  }
+    // Hfilter is null. Second pass only
+//  else if (!xoffset && yoffset)
+//  {
+//      vp8_filter_block2d_second_pass_only_armv6 ( src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, VFilter );
+//  }
+//  else
+//  {
+//      if (yoffset & 0x1)
+    //      vp8_filter_block2d_first_pass_armv6 ( src_ptr-src_pixels_per_line, FData+1, src_pixels_per_line, 8, 7, HFilter );
+    //  else
+
+        vp8_filter_block2d_first_pass_armv6 ( src_ptr-(2*src_pixels_per_line), FData, src_pixels_per_line, 8, 9, HFilter );
+
+        vp8_filter_block2d_second_pass_armv6 ( FData+2, dst_ptr, dst_pitch, 4, 8, VFilter );
+//  }
+}
+*/
+
+void vp8_sixtap_predict8x8_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    DECLARE_ALIGNED_ARRAY(4, short, FData, 16*8); // Temp data bufffer used in filtering
+
+    HFilter = sub_pel_filters[xoffset];   // 6 tap
+    VFilter = sub_pel_filters[yoffset];       // 6 tap
+
+    if (xoffset && !yoffset)
+    {
+        vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, HFilter);
+    }
+    // Hfilter is null. Second pass only
+    else if (!xoffset && yoffset)
+    {
+        vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 8, dst_pitch, VFilter);
+    }
+    else
+    {
+        if (yoffset & 0x1)
+            vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 8, 11, HFilter);
+        else
+            vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 8, 13, HFilter);
+
+        vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 8, VFilter);
+    }
+}
+
+
+void vp8_sixtap_predict16x16_armv6
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    DECLARE_ALIGNED_ARRAY(4, short, FData, 24*16);    // Temp data bufffer used in filtering
+
+    HFilter = sub_pel_filters[xoffset];   // 6 tap
+    VFilter = sub_pel_filters[yoffset];       // 6 tap
+
+    if (xoffset && !yoffset)
+    {
+        vp8_filter_block2d_first_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 16, dst_pitch, HFilter);
+    }
+    // Hfilter is null. Second pass only
+    else if (!xoffset && yoffset)
+    {
+        vp8_filter_block2d_second_pass_only_armv6(src_ptr, dst_ptr, src_pixels_per_line, 16, dst_pitch, VFilter);
+    }
+    else
+    {
+        if (yoffset & 0x1)
+            vp8_filter_block2d_first_pass_armv6(src_ptr - src_pixels_per_line, FData + 1, src_pixels_per_line, 16, 19, HFilter);
+        else
+            vp8_filter_block2d_first_pass_armv6(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 16, 21, HFilter);
+
+        vp8_filter_block2d_second_pass_armv6(FData + 2, dst_ptr, dst_pitch, 16, VFilter);
+    }
+
+}
+#endif
diff --git a/vp8/common/arm/idct_arm.h b/vp8/common/arm/idct_arm.h
new file mode 100644
index 0000000..f9ed21e
--- /dev/null
+++ b/vp8/common/arm/idct_arm.h
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef IDCT_ARM_H
+#define IDCT_ARM_H
+
+#if HAVE_ARMV6
+extern prototype_idct(vp8_short_idct4x4llm_1_v6);
+extern prototype_idct(vp8_short_idct4x4llm_v6_dual);
+extern prototype_idct_scalar(vp8_dc_only_idct_armv6);
+extern prototype_second_order(vp8_short_inv_walsh4x4_1_armv6);
+extern prototype_second_order(vp8_short_inv_walsh4x4_armv6);
+
+#undef  vp8_idct_idct1
+#define vp8_idct_idct1 vp8_short_idct4x4llm_1_v6
+
+#undef  vp8_idct_idct16
+#define vp8_idct_idct16 vp8_short_idct4x4llm_v6_dual
+
+#undef  vp8_idct_idct1_scalar
+#define vp8_idct_idct1_scalar vp8_dc_only_idct_armv6
+
+#undef  vp8_idct_iwalsh1
+#define vp8_idct_iwalsh1 vp8_short_inv_walsh4x4_1_armv6
+
+#undef  vp8_idct_iwalsh16
+#define vp8_idct_iwalsh16 vp8_short_inv_walsh4x4_armv6
+#endif
+
+#if HAVE_ARMV7
+extern prototype_idct(vp8_short_idct4x4llm_1_neon);
+extern prototype_idct(vp8_short_idct4x4llm_neon);
+extern prototype_idct_scalar(vp8_dc_only_idct_neon);
+extern prototype_second_order(vp8_short_inv_walsh4x4_1_neon);
+extern prototype_second_order(vp8_short_inv_walsh4x4_neon);
+
+#undef  vp8_idct_idct1
+#define vp8_idct_idct1 vp8_short_idct4x4llm_1_neon
+
+#undef  vp8_idct_idct16
+#define vp8_idct_idct16 vp8_short_idct4x4llm_neon
+
+#undef  vp8_idct_idct1_scalar
+#define vp8_idct_idct1_scalar vp8_dc_only_idct_neon
+
+#undef  vp8_idct_iwalsh1
+#define vp8_idct_iwalsh1 vp8_short_inv_walsh4x4_1_neon
+
+#undef  vp8_idct_iwalsh16
+#define vp8_idct_iwalsh16 vp8_short_inv_walsh4x4_neon
+#endif
+
+#endif
diff --git a/vp8/common/arm/loopfilter_arm.c b/vp8/common/arm/loopfilter_arm.c
new file mode 100644
index 0000000..fa7c626
--- /dev/null
+++ b/vp8/common/arm/loopfilter_arm.c
@@ -0,0 +1,246 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include <math.h>
+#include "loopfilter.h"
+#include "onyxc_int.h"
+
+typedef void loop_filter_uvfunction
+(
+    unsigned char *u,   // source pointer
+    int p,              // pitch
+    const signed char *flimit,
+    const signed char *limit,
+    const signed char *thresh,
+    unsigned char *v
+);
+
+extern prototype_loopfilter(vp8_loop_filter_horizontal_edge_armv6);
+extern prototype_loopfilter(vp8_loop_filter_vertical_edge_armv6);
+extern prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_armv6);
+extern prototype_loopfilter(vp8_mbloop_filter_vertical_edge_armv6);
+extern prototype_loopfilter(vp8_loop_filter_simple_horizontal_edge_armv6);
+extern prototype_loopfilter(vp8_loop_filter_simple_vertical_edge_armv6);
+
+extern prototype_loopfilter(vp8_loop_filter_horizontal_edge_y_neon);
+extern prototype_loopfilter(vp8_loop_filter_vertical_edge_y_neon);
+extern prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_y_neon);
+extern prototype_loopfilter(vp8_mbloop_filter_vertical_edge_y_neon);
+extern prototype_loopfilter(vp8_loop_filter_simple_horizontal_edge_neon);
+extern prototype_loopfilter(vp8_loop_filter_simple_vertical_edge_neon);
+
+extern loop_filter_uvfunction vp8_loop_filter_horizontal_edge_uv_neon;
+extern loop_filter_uvfunction vp8_loop_filter_vertical_edge_uv_neon;
+extern loop_filter_uvfunction vp8_mbloop_filter_horizontal_edge_uv_neon;
+extern loop_filter_uvfunction vp8_mbloop_filter_vertical_edge_uv_neon;
+
+
+#if HAVE_ARMV6
+//ARMV6 loopfilter functions
+// Horizontal MB filtering
+void vp8_loop_filter_mbh_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                               int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_mbloop_filter_horizontal_edge_armv6(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_horizontal_edge_armv6(u_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_horizontal_edge_armv6(v_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+}
+
+void vp8_loop_filter_mbhs_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                                int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_horizontal_edge_armv6(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+}
+
+// Vertical MB Filtering
+void vp8_loop_filter_mbv_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                               int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_mbloop_filter_vertical_edge_armv6(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_vertical_edge_armv6(u_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_vertical_edge_armv6(v_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+}
+
+void vp8_loop_filter_mbvs_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                                int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_vertical_edge_armv6(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+}
+
+// Horizontal B Filtering
+void vp8_loop_filter_bh_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_loop_filter_horizontal_edge_armv6(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_horizontal_edge_armv6(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_horizontal_edge_armv6(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_horizontal_edge_armv6(u_ptr + 4 * uv_stride, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_horizontal_edge_armv6(v_ptr + 4 * uv_stride, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+}
+
+void vp8_loop_filter_bhs_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                               int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_horizontal_edge_armv6(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_horizontal_edge_armv6(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_horizontal_edge_armv6(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+}
+
+// Vertical B Filtering
+void vp8_loop_filter_bv_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_loop_filter_vertical_edge_armv6(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_vertical_edge_armv6(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_vertical_edge_armv6(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_vertical_edge_armv6(u_ptr + 4, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_vertical_edge_armv6(v_ptr + 4, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+}
+
+void vp8_loop_filter_bvs_armv6(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                               int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_vertical_edge_armv6(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_vertical_edge_armv6(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_vertical_edge_armv6(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+}
+#endif
+
+#if HAVE_ARMV7
+// NEON loopfilter functions
+// Horizontal MB filtering
+void vp8_loop_filter_mbh_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_mbloop_filter_horizontal_edge_y_neon(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_horizontal_edge_uv_neon(u_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, v_ptr);
+}
+
+void vp8_loop_filter_mbhs_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                               int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_horizontal_edge_neon(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+}
+
+// Vertical MB Filtering
+void vp8_loop_filter_mbv_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_mbloop_filter_vertical_edge_y_neon(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_vertical_edge_uv_neon(u_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, v_ptr);
+}
+
+void vp8_loop_filter_mbvs_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                               int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_vertical_edge_neon(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+}
+
+// Horizontal B Filtering
+void vp8_loop_filter_bh_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_loop_filter_horizontal_edge_y_neon(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_horizontal_edge_y_neon(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_horizontal_edge_y_neon(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_horizontal_edge_uv_neon(u_ptr + 4 * uv_stride, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, v_ptr + 4 * uv_stride);
+}
+
+void vp8_loop_filter_bhs_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_horizontal_edge_neon(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_horizontal_edge_neon(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_horizontal_edge_neon(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+}
+
+// Vertical B Filtering
+void vp8_loop_filter_bv_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_loop_filter_vertical_edge_y_neon(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_vertical_edge_y_neon(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_vertical_edge_y_neon(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_vertical_edge_uv_neon(u_ptr + 4, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, v_ptr + 4);
+}
+
+void vp8_loop_filter_bvs_neon(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_vertical_edge_neon(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_vertical_edge_neon(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_vertical_edge_neon(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+}
+#endif
diff --git a/vp8/common/arm/loopfilter_arm.h b/vp8/common/arm/loopfilter_arm.h
new file mode 100644
index 0000000..4bb4945
--- /dev/null
+++ b/vp8/common/arm/loopfilter_arm.h
@@ -0,0 +1,84 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef LOOPFILTER_ARM_H
+#define LOOPFILTER_ARM_H
+
+#if HAVE_ARMV6
+extern prototype_loopfilter_block(vp8_loop_filter_mbv_armv6);
+extern prototype_loopfilter_block(vp8_loop_filter_bv_armv6);
+extern prototype_loopfilter_block(vp8_loop_filter_mbh_armv6);
+extern prototype_loopfilter_block(vp8_loop_filter_bh_armv6);
+extern prototype_loopfilter_block(vp8_loop_filter_mbvs_armv6);
+extern prototype_loopfilter_block(vp8_loop_filter_bvs_armv6);
+extern prototype_loopfilter_block(vp8_loop_filter_mbhs_armv6);
+extern prototype_loopfilter_block(vp8_loop_filter_bhs_armv6);
+
+#undef  vp8_lf_normal_mb_v
+#define vp8_lf_normal_mb_v vp8_loop_filter_mbv_armv6
+
+#undef  vp8_lf_normal_b_v
+#define vp8_lf_normal_b_v vp8_loop_filter_bv_armv6
+
+#undef  vp8_lf_normal_mb_h
+#define vp8_lf_normal_mb_h vp8_loop_filter_mbh_armv6
+
+#undef  vp8_lf_normal_b_h
+#define vp8_lf_normal_b_h vp8_loop_filter_bh_armv6
+
+#undef  vp8_lf_simple_mb_v
+#define vp8_lf_simple_mb_v vp8_loop_filter_mbvs_armv6
+
+#undef  vp8_lf_simple_b_v
+#define vp8_lf_simple_b_v vp8_loop_filter_bvs_armv6
+
+#undef  vp8_lf_simple_mb_h
+#define vp8_lf_simple_mb_h vp8_loop_filter_mbhs_armv6
+
+#undef  vp8_lf_simple_b_h
+#define vp8_lf_simple_b_h vp8_loop_filter_bhs_armv6
+#endif
+
+#if HAVE_ARMV7
+extern prototype_loopfilter_block(vp8_loop_filter_mbv_neon);
+extern prototype_loopfilter_block(vp8_loop_filter_bv_neon);
+extern prototype_loopfilter_block(vp8_loop_filter_mbh_neon);
+extern prototype_loopfilter_block(vp8_loop_filter_bh_neon);
+extern prototype_loopfilter_block(vp8_loop_filter_mbvs_neon);
+extern prototype_loopfilter_block(vp8_loop_filter_bvs_neon);
+extern prototype_loopfilter_block(vp8_loop_filter_mbhs_neon);
+extern prototype_loopfilter_block(vp8_loop_filter_bhs_neon);
+
+#undef  vp8_lf_normal_mb_v
+#define vp8_lf_normal_mb_v vp8_loop_filter_mbv_neon
+
+#undef  vp8_lf_normal_b_v
+#define vp8_lf_normal_b_v vp8_loop_filter_bv_neon
+
+#undef  vp8_lf_normal_mb_h
+#define vp8_lf_normal_mb_h vp8_loop_filter_mbh_neon
+
+#undef  vp8_lf_normal_b_h
+#define vp8_lf_normal_b_h vp8_loop_filter_bh_neon
+
+#undef  vp8_lf_simple_mb_v
+#define vp8_lf_simple_mb_v vp8_loop_filter_mbvs_neon
+
+#undef  vp8_lf_simple_b_v
+#define vp8_lf_simple_b_v vp8_loop_filter_bvs_neon
+
+#undef  vp8_lf_simple_mb_h
+#define vp8_lf_simple_mb_h vp8_loop_filter_mbhs_neon
+
+#undef  vp8_lf_simple_b_h
+#define vp8_lf_simple_b_h vp8_loop_filter_bhs_neon
+#endif
+
+#endif
diff --git a/vp8/common/arm/neon/bilinearpredict16x16_neon.asm b/vp8/common/arm/neon/bilinearpredict16x16_neon.asm
new file mode 100644
index 0000000..a2fea2b
--- /dev/null
+++ b/vp8/common/arm/neon/bilinearpredict16x16_neon.asm
@@ -0,0 +1,361 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_bilinear_predict16x16_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; r4    unsigned char *dst_ptr,
+; stack(r5) int  dst_pitch
+
+|vp8_bilinear_predict16x16_neon| PROC
+    push            {r4-r5, lr}
+
+    ldr             r12, _bifilter16_coeff_
+    ldr             r4, [sp, #12]           ;load parameters from stack
+    ldr             r5, [sp, #16]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_bfilter16x16_only
+
+    add             r2, r12, r2, lsl #3     ;calculate filter location
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+
+    vld1.s32        {d31}, [r2]             ;load first_pass filter
+
+    beq             firstpass_bfilter16x16_only
+
+    sub             sp, sp, #272            ;reserve space on stack for temporary storage
+    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
+    mov             lr, sp
+    vld1.u8         {d5, d6, d7}, [r0], r1
+
+    mov             r2, #3                  ;loop counter
+    vld1.u8         {d8, d9, d10}, [r0], r1
+
+    vdup.8          d0, d31[0]              ;first_pass filter (d0 d1)
+    vld1.u8         {d11, d12, d13}, [r0], r1
+
+    vdup.8          d1, d31[4]
+
+;First Pass: output_height lines x output_width columns (17x16)
+filt_blk2d_fp16x16_loop_neon
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q8, d3, d0
+    vmull.u8        q9, d5, d0
+    vmull.u8        q10, d6, d0
+    vmull.u8        q11, d8, d0
+    vmull.u8        q12, d9, d0
+    vmull.u8        q13, d11, d0
+    vmull.u8        q14, d12, d0
+
+    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
+    vext.8          d5, d5, d6, #1
+    vext.8          d8, d8, d9, #1
+    vext.8          d11, d11, d12, #1
+
+    vmlal.u8        q7, d2, d1              ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q9, d5, d1
+    vmlal.u8        q11, d8, d1
+    vmlal.u8        q13, d11, d1
+
+    vext.8          d3, d3, d4, #1
+    vext.8          d6, d6, d7, #1
+    vext.8          d9, d9, d10, #1
+    vext.8          d12, d12, d13, #1
+
+    vmlal.u8        q8, d3, d1              ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q10, d6, d1
+    vmlal.u8        q12, d9, d1
+    vmlal.u8        q14, d12, d1
+
+    subs            r2, r2, #1
+
+    vqrshrn.u16    d14, q7, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d15, q8, #7
+    vqrshrn.u16    d16, q9, #7
+    vqrshrn.u16    d17, q10, #7
+    vqrshrn.u16    d18, q11, #7
+    vqrshrn.u16    d19, q12, #7
+    vqrshrn.u16    d20, q13, #7
+
+    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
+    vqrshrn.u16    d21, q14, #7
+    vld1.u8         {d5, d6, d7}, [r0], r1
+
+    vst1.u8         {d14, d15, d16, d17}, [lr]!     ;store result
+    vld1.u8         {d8, d9, d10}, [r0], r1
+    vst1.u8         {d18, d19, d20, d21}, [lr]!
+    vld1.u8         {d11, d12, d13}, [r0], r1
+
+    bne             filt_blk2d_fp16x16_loop_neon
+
+;First-pass filtering for rest 5 lines
+    vld1.u8         {d14, d15, d16}, [r0], r1
+
+    vmull.u8        q9, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q10, d3, d0
+    vmull.u8        q11, d5, d0
+    vmull.u8        q12, d6, d0
+    vmull.u8        q13, d8, d0
+    vmull.u8        q14, d9, d0
+
+    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
+    vext.8          d5, d5, d6, #1
+    vext.8          d8, d8, d9, #1
+
+    vmlal.u8        q9, d2, d1              ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q11, d5, d1
+    vmlal.u8        q13, d8, d1
+
+    vext.8          d3, d3, d4, #1
+    vext.8          d6, d6, d7, #1
+    vext.8          d9, d9, d10, #1
+
+    vmlal.u8        q10, d3, d1             ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q12, d6, d1
+    vmlal.u8        q14, d9, d1
+
+    vmull.u8        q1, d11, d0
+    vmull.u8        q2, d12, d0
+    vmull.u8        q3, d14, d0
+    vmull.u8        q4, d15, d0
+
+    vext.8          d11, d11, d12, #1       ;construct src_ptr[1]
+    vext.8          d14, d14, d15, #1
+
+    vmlal.u8        q1, d11, d1             ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q3, d14, d1
+
+    vext.8          d12, d12, d13, #1
+    vext.8          d15, d15, d16, #1
+
+    vmlal.u8        q2, d12, d1             ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q4, d15, d1
+
+    vqrshrn.u16    d10, q9, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d11, q10, #7
+    vqrshrn.u16    d12, q11, #7
+    vqrshrn.u16    d13, q12, #7
+    vqrshrn.u16    d14, q13, #7
+    vqrshrn.u16    d15, q14, #7
+    vqrshrn.u16    d16, q1, #7
+    vqrshrn.u16    d17, q2, #7
+    vqrshrn.u16    d18, q3, #7
+    vqrshrn.u16    d19, q4, #7
+
+    vst1.u8         {d10, d11, d12, d13}, [lr]!         ;store result
+    vst1.u8         {d14, d15, d16, d17}, [lr]!
+    vst1.u8         {d18, d19}, [lr]!
+
+;Second pass: 16x16
+;secondpass_filter
+    add             r3, r12, r3, lsl #3
+    sub             lr, lr, #272
+
+    vld1.u32        {d31}, [r3]             ;load second_pass filter
+
+    vld1.u8         {d22, d23}, [lr]!       ;load src data
+
+    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+    mov             r12, #4                 ;loop counter
+
+filt_blk2d_sp16x16_loop_neon
+    vld1.u8         {d24, d25}, [lr]!
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * vp8_filter[0])
+    vld1.u8         {d26, d27}, [lr]!
+    vmull.u8        q2, d23, d0
+    vld1.u8         {d28, d29}, [lr]!
+    vmull.u8        q3, d24, d0
+    vld1.u8         {d30, d31}, [lr]!
+
+    vmull.u8        q4, d25, d0
+    vmull.u8        q5, d26, d0
+    vmull.u8        q6, d27, d0
+    vmull.u8        q7, d28, d0
+    vmull.u8        q8, d29, d0
+
+    vmlal.u8        q1, d24, d1             ;(src_ptr[pixel_step] * vp8_filter[1])
+    vmlal.u8        q2, d25, d1
+    vmlal.u8        q3, d26, d1
+    vmlal.u8        q4, d27, d1
+    vmlal.u8        q5, d28, d1
+    vmlal.u8        q6, d29, d1
+    vmlal.u8        q7, d30, d1
+    vmlal.u8        q8, d31, d1
+
+    subs            r12, r12, #1
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+    vqrshrn.u16    d4, q3, #7
+    vqrshrn.u16    d5, q4, #7
+    vqrshrn.u16    d6, q5, #7
+    vqrshrn.u16    d7, q6, #7
+    vqrshrn.u16    d8, q7, #7
+    vqrshrn.u16    d9, q8, #7
+
+    vst1.u8         {d2, d3}, [r4], r5      ;store result
+    vst1.u8         {d4, d5}, [r4], r5
+    vst1.u8         {d6, d7}, [r4], r5
+    vmov            q11, q15
+    vst1.u8         {d8, d9}, [r4], r5
+
+    bne             filt_blk2d_sp16x16_loop_neon
+
+    add             sp, sp, #272
+
+    pop             {r4-r5,pc}
+
+;--------------------
+firstpass_bfilter16x16_only
+    mov             r2, #4                      ;loop counter
+    vdup.8          d0, d31[0]                  ;first_pass filter (d0 d1)
+    vdup.8          d1, d31[4]
+
+;First Pass: output_height lines x output_width columns (16x16)
+filt_blk2d_fpo16x16_loop_neon
+    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
+    vld1.u8         {d5, d6, d7}, [r0], r1
+    vld1.u8         {d8, d9, d10}, [r0], r1
+    vld1.u8         {d11, d12, d13}, [r0], r1
+
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q8, d3, d0
+    vmull.u8        q9, d5, d0
+    vmull.u8        q10, d6, d0
+    vmull.u8        q11, d8, d0
+    vmull.u8        q12, d9, d0
+    vmull.u8        q13, d11, d0
+    vmull.u8        q14, d12, d0
+
+    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
+    vext.8          d5, d5, d6, #1
+    vext.8          d8, d8, d9, #1
+    vext.8          d11, d11, d12, #1
+
+    vmlal.u8        q7, d2, d1              ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q9, d5, d1
+    vmlal.u8        q11, d8, d1
+    vmlal.u8        q13, d11, d1
+
+    vext.8          d3, d3, d4, #1
+    vext.8          d6, d6, d7, #1
+    vext.8          d9, d9, d10, #1
+    vext.8          d12, d12, d13, #1
+
+    vmlal.u8        q8, d3, d1              ;(src_ptr[0] * vp8_filter[1])
+    vmlal.u8        q10, d6, d1
+    vmlal.u8        q12, d9, d1
+    vmlal.u8        q14, d12, d1
+
+    subs            r2, r2, #1
+
+    vqrshrn.u16    d14, q7, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d15, q8, #7
+    vqrshrn.u16    d16, q9, #7
+    vqrshrn.u16    d17, q10, #7
+    vqrshrn.u16    d18, q11, #7
+    vqrshrn.u16    d19, q12, #7
+    vqrshrn.u16    d20, q13, #7
+    vst1.u8         {d14, d15}, [r4], r5        ;store result
+    vqrshrn.u16    d21, q14, #7
+
+    vst1.u8         {d16, d17}, [r4], r5
+    vst1.u8         {d18, d19}, [r4], r5
+    vst1.u8         {d20, d21}, [r4], r5
+
+    bne             filt_blk2d_fpo16x16_loop_neon
+    pop             {r4-r5,pc}
+
+;---------------------
+secondpass_bfilter16x16_only
+;Second pass: 16x16
+;secondpass_filter
+    add             r3, r12, r3, lsl #3
+    mov             r12, #4                     ;loop counter
+    vld1.u32        {d31}, [r3]                 ;load second_pass filter
+    vld1.u8         {d22, d23}, [r0], r1        ;load src data
+
+    vdup.8          d0, d31[0]                  ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+
+filt_blk2d_spo16x16_loop_neon
+    vld1.u8         {d24, d25}, [r0], r1
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * vp8_filter[0])
+    vld1.u8         {d26, d27}, [r0], r1
+    vmull.u8        q2, d23, d0
+    vld1.u8         {d28, d29}, [r0], r1
+    vmull.u8        q3, d24, d0
+    vld1.u8         {d30, d31}, [r0], r1
+
+    vmull.u8        q4, d25, d0
+    vmull.u8        q5, d26, d0
+    vmull.u8        q6, d27, d0
+    vmull.u8        q7, d28, d0
+    vmull.u8        q8, d29, d0
+
+    vmlal.u8        q1, d24, d1             ;(src_ptr[pixel_step] * vp8_filter[1])
+    vmlal.u8        q2, d25, d1
+    vmlal.u8        q3, d26, d1
+    vmlal.u8        q4, d27, d1
+    vmlal.u8        q5, d28, d1
+    vmlal.u8        q6, d29, d1
+    vmlal.u8        q7, d30, d1
+    vmlal.u8        q8, d31, d1
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+    vqrshrn.u16    d4, q3, #7
+    vqrshrn.u16    d5, q4, #7
+    vqrshrn.u16    d6, q5, #7
+    vqrshrn.u16    d7, q6, #7
+    vqrshrn.u16    d8, q7, #7
+    vqrshrn.u16    d9, q8, #7
+
+    vst1.u8         {d2, d3}, [r4], r5      ;store result
+    subs            r12, r12, #1
+    vst1.u8         {d4, d5}, [r4], r5
+    vmov            q11, q15
+    vst1.u8         {d6, d7}, [r4], r5
+    vst1.u8         {d8, d9}, [r4], r5
+
+    bne             filt_blk2d_spo16x16_loop_neon
+    pop             {r4-r5,pc}
+
+    ENDP
+
+;-----------------
+    AREA    bifilters16_dat, DATA, READWRITE            ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_bifilter16_coeff_
+    DCD     bifilter16_coeff
+bifilter16_coeff
+    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
+
+    END
diff --git a/vp8/common/arm/neon/bilinearpredict4x4_neon.asm b/vp8/common/arm/neon/bilinearpredict4x4_neon.asm
new file mode 100644
index 0000000..74d2db5
--- /dev/null
+++ b/vp8/common/arm/neon/bilinearpredict4x4_neon.asm
@@ -0,0 +1,134 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_bilinear_predict4x4_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; r4    unsigned char *dst_ptr,
+; stack(lr) int  dst_pitch
+
+|vp8_bilinear_predict4x4_neon| PROC
+    push            {r4, lr}
+
+    ldr             r12, _bifilter4_coeff_
+    ldr             r4, [sp, #8]            ;load parameters from stack
+    ldr             lr, [sp, #12]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             skip_firstpass_filter
+
+;First pass: output_height lines x output_width columns (5x4)
+    vld1.u8         {d2}, [r0], r1          ;load src data
+    add             r2, r12, r2, lsl #3     ;calculate Hfilter location (2coeffsx4bytes=8bytes)
+
+    vld1.u8         {d3}, [r0], r1
+    vld1.u32        {d31}, [r2]             ;first_pass filter
+
+    vld1.u8         {d4}, [r0], r1
+    vdup.8          d0, d31[0]              ;first_pass filter (d0-d1)
+    vld1.u8         {d5}, [r0], r1
+    vdup.8          d1, d31[4]
+    vld1.u8         {d6}, [r0], r1
+
+    vshr.u64        q4, q1, #8              ;construct src_ptr[1]
+    vshr.u64        q5, q2, #8
+    vshr.u64        d12, d6, #8
+
+    vzip.32         d2, d3                  ;put 2-line data in 1 register (src_ptr[0])
+    vzip.32         d4, d5
+    vzip.32         d8, d9                  ;put 2-line data in 1 register (src_ptr[1])
+    vzip.32         d10, d11
+
+    vmull.u8        q7, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q8, d4, d0
+    vmull.u8        q9, d6, d0
+
+    vmlal.u8        q7, d8, d1              ;(src_ptr[1] * vp8_filter[1])
+    vmlal.u8        q8, d10, d1
+    vmlal.u8        q9, d12, d1
+
+    vqrshrn.u16    d28, q7, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d29, q8, #7
+    vqrshrn.u16    d30, q9, #7
+
+;Second pass: 4x4
+secondpass_filter
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+    beq             skip_secondpass_filter
+
+    add             r3, r12, r3, lsl #3 ;calculate Vfilter location
+    vld1.u32        {d31}, [r3]         ;load second_pass filter
+
+    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0-d5)
+    vdup.8          d1, d31[4]
+
+    vmull.u8        q1, d28, d0
+    vmull.u8        q2, d29, d0
+
+    vext.8          d26, d28, d29, #4       ;construct src_ptr[pixel_step]
+    vext.8          d27, d29, d30, #4
+
+    vmlal.u8        q1, d26, d1
+    vmlal.u8        q2, d27, d1
+
+    add             r0, r4, lr
+    add             r1, r0, lr
+    add             r2, r1, lr
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+
+    vst1.32         {d2[0]}, [r4]           ;store result
+    vst1.32         {d2[1]}, [r0]
+    vst1.32         {d3[0]}, [r1]
+    vst1.32         {d3[1]}, [r2]
+
+    pop             {r4, pc}
+
+;--------------------
+skip_firstpass_filter
+
+    vld1.32         {d28[0]}, [r0], r1      ;load src data
+    vld1.32         {d28[1]}, [r0], r1
+    vld1.32         {d29[0]}, [r0], r1
+    vld1.32         {d29[1]}, [r0], r1
+    vld1.32         {d30[0]}, [r0], r1
+
+    b               secondpass_filter
+
+;---------------------
+skip_secondpass_filter
+    vst1.32         {d28[0]}, [r4], lr      ;store result
+    vst1.32         {d28[1]}, [r4], lr
+    vst1.32         {d29[0]}, [r4], lr
+    vst1.32         {d29[1]}, [r4], lr
+
+    pop             {r4, pc}
+
+    ENDP
+
+;-----------------
+    AREA    bilinearfilters4_dat, DATA, READWRITE           ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_bifilter4_coeff_
+    DCD     bifilter4_coeff
+bifilter4_coeff
+    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
+
+    END
diff --git a/vp8/common/arm/neon/bilinearpredict8x4_neon.asm b/vp8/common/arm/neon/bilinearpredict8x4_neon.asm
new file mode 100644
index 0000000..46ebb0e
--- /dev/null
+++ b/vp8/common/arm/neon/bilinearpredict8x4_neon.asm
@@ -0,0 +1,139 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_bilinear_predict8x4_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; r4    unsigned char *dst_ptr,
+; stack(lr) int  dst_pitch
+
+|vp8_bilinear_predict8x4_neon| PROC
+    push            {r4, lr}
+
+    ldr             r12, _bifilter8x4_coeff_
+    ldr             r4, [sp, #8]            ;load parameters from stack
+    ldr             lr, [sp, #12]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             skip_firstpass_filter
+
+;First pass: output_height lines x output_width columns (5x8)
+    add             r2, r12, r2, lsl #3     ;calculate filter location
+
+    vld1.u8         {q1}, [r0], r1          ;load src data
+    vld1.u32        {d31}, [r2]             ;load first_pass filter
+    vld1.u8         {q2}, [r0], r1
+    vdup.8          d0, d31[0]              ;first_pass filter (d0 d1)
+    vld1.u8         {q3}, [r0], r1
+    vdup.8          d1, d31[4]
+    vld1.u8         {q4}, [r0], r1
+
+    vmull.u8        q6, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vld1.u8         {q5}, [r0], r1
+    vmull.u8        q7, d4, d0
+    vmull.u8        q8, d6, d0
+    vmull.u8        q9, d8, d0
+    vmull.u8        q10, d10, d0
+
+    vext.8          d3, d2, d3, #1          ;construct src_ptr[-1]
+    vext.8          d5, d4, d5, #1
+    vext.8          d7, d6, d7, #1
+    vext.8          d9, d8, d9, #1
+    vext.8          d11, d10, d11, #1
+
+    vmlal.u8        q6, d3, d1              ;(src_ptr[1] * vp8_filter[1])
+    vmlal.u8        q7, d5, d1
+    vmlal.u8        q8, d7, d1
+    vmlal.u8        q9, d9, d1
+    vmlal.u8        q10, d11, d1
+
+    vqrshrn.u16    d22, q6, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d23, q7, #7
+    vqrshrn.u16    d24, q8, #7
+    vqrshrn.u16    d25, q9, #7
+    vqrshrn.u16    d26, q10, #7
+
+;Second pass: 4x8
+secondpass_filter
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+    beq             skip_secondpass_filter
+
+    add             r3, r12, r3, lsl #3
+    add             r0, r4, lr
+
+    vld1.u32        {d31}, [r3]             ;load second_pass filter
+    add             r1, r0, lr
+
+    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q2, d23, d0
+    vmull.u8        q3, d24, d0
+    vmull.u8        q4, d25, d0
+
+    vmlal.u8        q1, d23, d1             ;(src_ptr[pixel_step] * vp8_filter[1])
+    vmlal.u8        q2, d24, d1
+    vmlal.u8        q3, d25, d1
+    vmlal.u8        q4, d26, d1
+
+    add             r2, r1, lr
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+    vqrshrn.u16    d4, q3, #7
+    vqrshrn.u16    d5, q4, #7
+
+    vst1.u8         {d2}, [r4]              ;store result
+    vst1.u8         {d3}, [r0]
+    vst1.u8         {d4}, [r1]
+    vst1.u8         {d5}, [r2]
+
+    pop             {r4, pc}
+
+;--------------------
+skip_firstpass_filter
+    vld1.u8         {d22}, [r0], r1         ;load src data
+    vld1.u8         {d23}, [r0], r1
+    vld1.u8         {d24}, [r0], r1
+    vld1.u8         {d25}, [r0], r1
+    vld1.u8         {d26}, [r0], r1
+
+    b               secondpass_filter
+
+;---------------------
+skip_secondpass_filter
+    vst1.u8         {d22}, [r4], lr         ;store result
+    vst1.u8         {d23}, [r4], lr
+    vst1.u8         {d24}, [r4], lr
+    vst1.u8         {d25}, [r4], lr
+
+    pop             {r4, pc}
+
+    ENDP
+
+;-----------------
+    AREA    bifilters8x4_dat, DATA, READWRITE           ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_bifilter8x4_coeff_
+    DCD     bifilter8x4_coeff
+bifilter8x4_coeff
+    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
+
+    END
diff --git a/vp8/common/arm/neon/bilinearpredict8x8_neon.asm b/vp8/common/arm/neon/bilinearpredict8x8_neon.asm
new file mode 100644
index 0000000..80728d4
--- /dev/null
+++ b/vp8/common/arm/neon/bilinearpredict8x8_neon.asm
@@ -0,0 +1,187 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_bilinear_predict8x8_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; r4    unsigned char *dst_ptr,
+; stack(lr) int  dst_pitch
+
+|vp8_bilinear_predict8x8_neon| PROC
+    push            {r4, lr}
+
+    ldr             r12, _bifilter8_coeff_
+    ldr             r4, [sp, #8]            ;load parameters from stack
+    ldr             lr, [sp, #12]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             skip_firstpass_filter
+
+;First pass: output_height lines x output_width columns (9x8)
+    add             r2, r12, r2, lsl #3     ;calculate filter location
+
+    vld1.u8         {q1}, [r0], r1          ;load src data
+    vld1.u32        {d31}, [r2]             ;load first_pass filter
+    vld1.u8         {q2}, [r0], r1
+    vdup.8          d0, d31[0]              ;first_pass filter (d0 d1)
+    vld1.u8         {q3}, [r0], r1
+    vdup.8          d1, d31[4]
+    vld1.u8         {q4}, [r0], r1
+
+    vmull.u8        q6, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q7, d4, d0
+    vmull.u8        q8, d6, d0
+    vmull.u8        q9, d8, d0
+
+    vext.8          d3, d2, d3, #1          ;construct src_ptr[-1]
+    vext.8          d5, d4, d5, #1
+    vext.8          d7, d6, d7, #1
+    vext.8          d9, d8, d9, #1
+
+    vmlal.u8        q6, d3, d1              ;(src_ptr[1] * vp8_filter[1])
+    vmlal.u8        q7, d5, d1
+    vmlal.u8        q8, d7, d1
+    vmlal.u8        q9, d9, d1
+
+    vld1.u8         {q1}, [r0], r1          ;load src data
+    vqrshrn.u16    d22, q6, #7              ;shift/round/saturate to u8
+    vld1.u8         {q2}, [r0], r1
+    vqrshrn.u16    d23, q7, #7
+    vld1.u8         {q3}, [r0], r1
+    vqrshrn.u16    d24, q8, #7
+    vld1.u8         {q4}, [r0], r1
+    vqrshrn.u16    d25, q9, #7
+
+    ;first_pass filtering on the rest 5-line data
+    vld1.u8         {q5}, [r0], r1
+
+    vmull.u8        q6, d2, d0              ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q7, d4, d0
+    vmull.u8        q8, d6, d0
+    vmull.u8        q9, d8, d0
+    vmull.u8        q10, d10, d0
+
+    vext.8          d3, d2, d3, #1          ;construct src_ptr[-1]
+    vext.8          d5, d4, d5, #1
+    vext.8          d7, d6, d7, #1
+    vext.8          d9, d8, d9, #1
+    vext.8          d11, d10, d11, #1
+
+    vmlal.u8        q6, d3, d1              ;(src_ptr[1] * vp8_filter[1])
+    vmlal.u8        q7, d5, d1
+    vmlal.u8        q8, d7, d1
+    vmlal.u8        q9, d9, d1
+    vmlal.u8        q10, d11, d1
+
+    vqrshrn.u16    d26, q6, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d27, q7, #7
+    vqrshrn.u16    d28, q8, #7
+    vqrshrn.u16    d29, q9, #7
+    vqrshrn.u16    d30, q10, #7
+
+;Second pass: 8x8
+secondpass_filter
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+    beq             skip_secondpass_filter
+
+    add             r3, r12, r3, lsl #3
+    add             r0, r4, lr
+
+    vld1.u32        {d31}, [r3]             ;load second_pass filter
+    add             r1, r0, lr
+
+    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * vp8_filter[0])
+    vmull.u8        q2, d23, d0
+    vmull.u8        q3, d24, d0
+    vmull.u8        q4, d25, d0
+    vmull.u8        q5, d26, d0
+    vmull.u8        q6, d27, d0
+    vmull.u8        q7, d28, d0
+    vmull.u8        q8, d29, d0
+
+    vmlal.u8        q1, d23, d1             ;(src_ptr[pixel_step] * vp8_filter[1])
+    vmlal.u8        q2, d24, d1
+    vmlal.u8        q3, d25, d1
+    vmlal.u8        q4, d26, d1
+    vmlal.u8        q5, d27, d1
+    vmlal.u8        q6, d28, d1
+    vmlal.u8        q7, d29, d1
+    vmlal.u8        q8, d30, d1
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+    vqrshrn.u16    d4, q3, #7
+    vqrshrn.u16    d5, q4, #7
+    vqrshrn.u16    d6, q5, #7
+    vqrshrn.u16    d7, q6, #7
+    vqrshrn.u16    d8, q7, #7
+    vqrshrn.u16    d9, q8, #7
+
+    vst1.u8         {d2}, [r4]              ;store result
+    vst1.u8         {d3}, [r0]
+    vst1.u8         {d4}, [r1], lr
+    vst1.u8         {d5}, [r1], lr
+    vst1.u8         {d6}, [r1], lr
+    vst1.u8         {d7}, [r1], lr
+    vst1.u8         {d8}, [r1], lr
+    vst1.u8         {d9}, [r1], lr
+
+    pop             {r4, pc}
+
+;--------------------
+skip_firstpass_filter
+    vld1.u8         {d22}, [r0], r1         ;load src data
+    vld1.u8         {d23}, [r0], r1
+    vld1.u8         {d24}, [r0], r1
+    vld1.u8         {d25}, [r0], r1
+    vld1.u8         {d26}, [r0], r1
+    vld1.u8         {d27}, [r0], r1
+    vld1.u8         {d28}, [r0], r1
+    vld1.u8         {d29}, [r0], r1
+    vld1.u8         {d30}, [r0], r1
+
+    b               secondpass_filter
+
+;---------------------
+skip_secondpass_filter
+    vst1.u8         {d22}, [r4], lr         ;store result
+    vst1.u8         {d23}, [r4], lr
+    vst1.u8         {d24}, [r4], lr
+    vst1.u8         {d25}, [r4], lr
+    vst1.u8         {d26}, [r4], lr
+    vst1.u8         {d27}, [r4], lr
+    vst1.u8         {d28}, [r4], lr
+    vst1.u8         {d29}, [r4], lr
+
+    pop             {r4, pc}
+
+    ENDP
+
+;-----------------
+    AREA    bifilters8_dat, DATA, READWRITE         ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_bifilter8_coeff_
+    DCD     bifilter8_coeff
+bifilter8_coeff
+    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
+
+    END
diff --git a/vp8/common/arm/neon/buildintrapredictorsmby_neon.asm b/vp8/common/arm/neon/buildintrapredictorsmby_neon.asm
new file mode 100644
index 0000000..f42ac63
--- /dev/null
+++ b/vp8/common/arm/neon/buildintrapredictorsmby_neon.asm
@@ -0,0 +1,583 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_build_intra_predictors_mby_neon_func|
+    EXPORT  |vp8_build_intra_predictors_mby_s_neon_func|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char *y_buffer
+; r1    unsigned char *ypred_ptr
+; r2    int y_stride
+; r3    int mode
+; stack int Up
+; stack int Left
+
+|vp8_build_intra_predictors_mby_neon_func| PROC
+    push            {r4-r8, lr}
+
+    cmp             r3, #0
+    beq             case_dc_pred
+    cmp             r3, #1
+    beq             case_v_pred
+    cmp             r3, #2
+    beq             case_h_pred
+    cmp             r3, #3
+    beq             case_tm_pred
+
+case_dc_pred
+    ldr             r4, [sp, #24]       ; Up
+    ldr             r5, [sp, #28]       ; Left
+
+    ; Default the DC average to 128
+    mov             r12, #128
+    vdup.u8         q0, r12
+
+    ; Zero out running sum
+    mov             r12, #0
+
+    ; compute shift and jump
+    adds            r7, r4, r5
+    beq             skip_dc_pred_up_left
+
+    ; Load above row, if it exists
+    cmp             r4, #0
+    beq             skip_dc_pred_up
+
+    sub             r6, r0, r2
+    vld1.8          {q1}, [r6]
+    vpaddl.u8       q2, q1
+    vpaddl.u16      q3, q2
+    vpaddl.u32      q4, q3
+
+    vmov.32         r4, d8[0]
+    vmov.32         r6, d9[0]
+
+    add             r12, r4, r6
+
+    ; Move back to interger registers
+
+skip_dc_pred_up
+
+    cmp             r5, #0
+    beq             skip_dc_pred_left
+
+    sub             r0, r0, #1
+
+    ; Load left row, if it exists
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0]
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+skip_dc_pred_left
+    add             r7, r7, #3          ; Shift
+    sub             r4, r7, #1
+    mov             r5, #1
+    add             r12, r12, r5, lsl r4
+    mov             r5, r12, lsr r7     ; expected_dc
+
+    vdup.u8         q0, r5
+
+skip_dc_pred_up_left
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+
+    pop             {r4-r8,pc}
+case_v_pred
+    ; Copy down above row
+    sub             r6, r0, r2
+    vld1.8          {q0}, [r6]
+
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q0}, [r1]!
+    pop             {r4-r8,pc}
+
+case_h_pred
+    ; Load 4x yleft_col
+    sub             r0, r0, #1
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q1}, [r1]!
+    vst1.u8         {q2}, [r1]!
+    vst1.u8         {q3}, [r1]!
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q1}, [r1]!
+    vst1.u8         {q2}, [r1]!
+    vst1.u8         {q3}, [r1]!
+
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q1}, [r1]!
+    vst1.u8         {q2}, [r1]!
+    vst1.u8         {q3}, [r1]!
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q1}, [r1]!
+    vst1.u8         {q2}, [r1]!
+    vst1.u8         {q3}, [r1]!
+
+    pop             {r4-r8,pc}
+
+case_tm_pred
+    ; Load yabove_row
+    sub             r3, r0, r2
+    vld1.8          {q8}, [r3]
+
+    ; Load ytop_left
+    sub             r3, r3, #1
+    ldrb            r7, [r3]
+
+    vdup.u16        q7, r7
+
+    ; Compute yabove_row - ytop_left
+    mov             r3, #1
+    vdup.u8         q0, r3
+
+    vmull.u8        q4, d16, d0
+    vmull.u8        q5, d17, d0
+
+    vsub.s16        q4, q4, q7
+    vsub.s16        q5, q5, q7
+
+    ; Load 4x yleft_col
+    sub             r0, r0, #1
+    mov             r12, #4
+
+case_tm_pred_loop
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u16        q0, r3
+    vdup.u16        q1, r4
+    vdup.u16        q2, r5
+    vdup.u16        q3, r6
+
+    vqadd.s16       q8, q0, q4
+    vqadd.s16       q9, q0, q5
+
+    vqadd.s16       q10, q1, q4
+    vqadd.s16       q11, q1, q5
+
+    vqadd.s16       q12, q2, q4
+    vqadd.s16       q13, q2, q5
+
+    vqadd.s16       q14, q3, q4
+    vqadd.s16       q15, q3, q5
+
+    vqshrun.s16     d0, q8, #0
+    vqshrun.s16     d1, q9, #0
+
+    vqshrun.s16     d2, q10, #0
+    vqshrun.s16     d3, q11, #0
+
+    vqshrun.s16     d4, q12, #0
+    vqshrun.s16     d5, q13, #0
+
+    vqshrun.s16     d6, q14, #0
+    vqshrun.s16     d7, q15, #0
+
+    vst1.u8         {q0}, [r1]!
+    vst1.u8         {q1}, [r1]!
+    vst1.u8         {q2}, [r1]!
+    vst1.u8         {q3}, [r1]!
+
+    subs            r12, r12, #1
+    bne             case_tm_pred_loop
+
+    pop             {r4-r8,pc}
+
+    ENDP
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; r0    unsigned char *y_buffer
+; r1    unsigned char *ypred_ptr
+; r2    int y_stride
+; r3    int mode
+; stack int Up
+; stack int Left
+
+|vp8_build_intra_predictors_mby_s_neon_func| PROC
+    push            {r4-r8, lr}
+
+    mov             r1, r0      ;   unsigned char *ypred_ptr = x->dst.y_buffer; //x->Predictor;
+
+    cmp             r3, #0
+    beq             case_dc_pred_s
+    cmp             r3, #1
+    beq             case_v_pred_s
+    cmp             r3, #2
+    beq             case_h_pred_s
+    cmp             r3, #3
+    beq             case_tm_pred_s
+
+case_dc_pred_s
+    ldr             r4, [sp, #24]       ; Up
+    ldr             r5, [sp, #28]       ; Left
+
+    ; Default the DC average to 128
+    mov             r12, #128
+    vdup.u8         q0, r12
+
+    ; Zero out running sum
+    mov             r12, #0
+
+    ; compute shift and jump
+    adds            r7, r4, r5
+    beq             skip_dc_pred_up_left_s
+
+    ; Load above row, if it exists
+    cmp             r4, #0
+    beq             skip_dc_pred_up_s
+
+    sub             r6, r0, r2
+    vld1.8          {q1}, [r6]
+    vpaddl.u8       q2, q1
+    vpaddl.u16      q3, q2
+    vpaddl.u32      q4, q3
+
+    vmov.32         r4, d8[0]
+    vmov.32         r6, d9[0]
+
+    add             r12, r4, r6
+
+    ; Move back to interger registers
+
+skip_dc_pred_up_s
+
+    cmp             r5, #0
+    beq             skip_dc_pred_left_s
+
+    sub             r0, r0, #1
+
+    ; Load left row, if it exists
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0]
+
+    add             r12, r12, r3
+    add             r12, r12, r4
+    add             r12, r12, r5
+    add             r12, r12, r6
+
+skip_dc_pred_left_s
+    add             r7, r7, #3          ; Shift
+    sub             r4, r7, #1
+    mov             r5, #1
+    add             r12, r12, r5, lsl r4
+    mov             r5, r12, lsr r7     ; expected_dc
+
+    vdup.u8         q0, r5
+
+skip_dc_pred_up_left_s
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+
+    pop             {r4-r8,pc}
+case_v_pred_s
+    ; Copy down above row
+    sub             r6, r0, r2
+    vld1.8          {q0}, [r6]
+
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q0}, [r1], r2
+    pop             {r4-r8,pc}
+
+case_h_pred_s
+    ; Load 4x yleft_col
+    sub             r0, r0, #1
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q1}, [r1], r2
+    vst1.u8         {q2}, [r1], r2
+    vst1.u8         {q3}, [r1], r2
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q1}, [r1], r2
+    vst1.u8         {q2}, [r1], r2
+    vst1.u8         {q3}, [r1], r2
+
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q1}, [r1], r2
+    vst1.u8         {q2}, [r1], r2
+    vst1.u8         {q3}, [r1], r2
+
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u8         q0, r3
+    vdup.u8         q1, r4
+    vdup.u8         q2, r5
+    vdup.u8         q3, r6
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q1}, [r1], r2
+    vst1.u8         {q2}, [r1], r2
+    vst1.u8         {q3}, [r1], r2
+
+    pop             {r4-r8,pc}
+
+case_tm_pred_s
+    ; Load yabove_row
+    sub             r3, r0, r2
+    vld1.8          {q8}, [r3]
+
+    ; Load ytop_left
+    sub             r3, r3, #1
+    ldrb            r7, [r3]
+
+    vdup.u16        q7, r7
+
+    ; Compute yabove_row - ytop_left
+    mov             r3, #1
+    vdup.u8         q0, r3
+
+    vmull.u8        q4, d16, d0
+    vmull.u8        q5, d17, d0
+
+    vsub.s16        q4, q4, q7
+    vsub.s16        q5, q5, q7
+
+    ; Load 4x yleft_col
+    sub             r0, r0, #1
+    mov             r12, #4
+
+case_tm_pred_loop_s
+    ldrb            r3, [r0], r2
+    ldrb            r4, [r0], r2
+    ldrb            r5, [r0], r2
+    ldrb            r6, [r0], r2
+    vdup.u16        q0, r3
+    vdup.u16        q1, r4
+    vdup.u16        q2, r5
+    vdup.u16        q3, r6
+
+    vqadd.s16       q8, q0, q4
+    vqadd.s16       q9, q0, q5
+
+    vqadd.s16       q10, q1, q4
+    vqadd.s16       q11, q1, q5
+
+    vqadd.s16       q12, q2, q4
+    vqadd.s16       q13, q2, q5
+
+    vqadd.s16       q14, q3, q4
+    vqadd.s16       q15, q3, q5
+
+    vqshrun.s16     d0, q8, #0
+    vqshrun.s16     d1, q9, #0
+
+    vqshrun.s16     d2, q10, #0
+    vqshrun.s16     d3, q11, #0
+
+    vqshrun.s16     d4, q12, #0
+    vqshrun.s16     d5, q13, #0
+
+    vqshrun.s16     d6, q14, #0
+    vqshrun.s16     d7, q15, #0
+
+    vst1.u8         {q0}, [r1], r2
+    vst1.u8         {q1}, [r1], r2
+    vst1.u8         {q2}, [r1], r2
+    vst1.u8         {q3}, [r1], r2
+
+    subs            r12, r12, #1
+    bne             case_tm_pred_loop_s
+
+    pop             {r4-r8,pc}
+
+    ENDP
+
+
+    END
diff --git a/vp8/common/arm/neon/copymem16x16_neon.asm b/vp8/common/arm/neon/copymem16x16_neon.asm
new file mode 100644
index 0000000..89d5e10
--- /dev/null
+++ b/vp8/common/arm/neon/copymem16x16_neon.asm
@@ -0,0 +1,58 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_copy_mem16x16_neon|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void copy_mem16x16_neon( unsigned char *src, int src_stride, unsigned char *dst, int dst_stride)
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_copy_mem16x16_neon| PROC
+
+    vld1.u8     {q0}, [r0], r1
+    vld1.u8     {q1}, [r0], r1
+    vld1.u8     {q2}, [r0], r1
+    vst1.u8     {q0}, [r2], r3
+    vld1.u8     {q3}, [r0], r1
+    vst1.u8     {q1}, [r2], r3
+    vld1.u8     {q4}, [r0], r1
+    vst1.u8     {q2}, [r2], r3
+    vld1.u8     {q5}, [r0], r1
+    vst1.u8     {q3}, [r2], r3
+    vld1.u8     {q6}, [r0], r1
+    vst1.u8     {q4}, [r2], r3
+    vld1.u8     {q7}, [r0], r1
+    vst1.u8     {q5}, [r2], r3
+    vld1.u8     {q8}, [r0], r1
+    vst1.u8     {q6}, [r2], r3
+    vld1.u8     {q9}, [r0], r1
+    vst1.u8     {q7}, [r2], r3
+    vld1.u8     {q10}, [r0], r1
+    vst1.u8     {q8}, [r2], r3
+    vld1.u8     {q11}, [r0], r1
+    vst1.u8     {q9}, [r2], r3
+    vld1.u8     {q12}, [r0], r1
+    vst1.u8     {q10}, [r2], r3
+    vld1.u8     {q13}, [r0], r1
+    vst1.u8     {q11}, [r2], r3
+    vld1.u8     {q14}, [r0], r1
+    vst1.u8     {q12}, [r2], r3
+    vld1.u8     {q15}, [r0], r1
+    vst1.u8     {q13}, [r2], r3
+    vst1.u8     {q14}, [r2], r3
+    vst1.u8     {q15}, [r2], r3
+
+    mov     pc, lr
+
+    ENDP  ; |vp8_copy_mem16x16_neon|
+
+    END
diff --git a/vp8/common/arm/neon/copymem8x4_neon.asm b/vp8/common/arm/neon/copymem8x4_neon.asm
new file mode 100644
index 0000000..302f734
--- /dev/null
+++ b/vp8/common/arm/neon/copymem8x4_neon.asm
@@ -0,0 +1,33 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_copy_mem8x4_neon|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void copy_mem8x4_neon( unsigned char *src, int src_stride, unsigned char *dst, int dst_stride)
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_copy_mem8x4_neon| PROC
+    vld1.u8     {d0}, [r0], r1
+    vld1.u8     {d1}, [r0], r1
+    vst1.u8     {d0}, [r2], r3
+    vld1.u8     {d2}, [r0], r1
+    vst1.u8     {d1}, [r2], r3
+    vld1.u8     {d3}, [r0], r1
+    vst1.u8     {d2}, [r2], r3
+    vst1.u8     {d3}, [r2], r3
+
+    mov     pc, lr
+
+    ENDP  ; |vp8_copy_mem8x4_neon|
+
+    END
diff --git a/vp8/common/arm/neon/copymem8x8_neon.asm b/vp8/common/arm/neon/copymem8x8_neon.asm
new file mode 100644
index 0000000..50d39ef
--- /dev/null
+++ b/vp8/common/arm/neon/copymem8x8_neon.asm
@@ -0,0 +1,42 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_copy_mem8x8_neon|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    Block, CODE, READONLY ; name this block of code
+;void copy_mem8x8_neon( unsigned char *src, int src_stride, unsigned char *dst, int dst_stride)
+;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+|vp8_copy_mem8x8_neon| PROC
+
+    vld1.u8     {d0}, [r0], r1
+    vld1.u8     {d1}, [r0], r1
+    vst1.u8     {d0}, [r2], r3
+    vld1.u8     {d2}, [r0], r1
+    vst1.u8     {d1}, [r2], r3
+    vld1.u8     {d3}, [r0], r1
+    vst1.u8     {d2}, [r2], r3
+    vld1.u8     {d4}, [r0], r1
+    vst1.u8     {d3}, [r2], r3
+    vld1.u8     {d5}, [r0], r1
+    vst1.u8     {d4}, [r2], r3
+    vld1.u8     {d6}, [r0], r1
+    vst1.u8     {d5}, [r2], r3
+    vld1.u8     {d7}, [r0], r1
+    vst1.u8     {d6}, [r2], r3
+    vst1.u8     {d7}, [r2], r3
+
+    mov     pc, lr
+
+    ENDP  ; |vp8_copy_mem8x8_neon|
+
+    END
diff --git a/vp8/common/arm/neon/iwalsh_neon.asm b/vp8/common/arm/neon/iwalsh_neon.asm
new file mode 100644
index 0000000..4fc744c
--- /dev/null
+++ b/vp8/common/arm/neon/iwalsh_neon.asm
@@ -0,0 +1,95 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_short_inv_walsh4x4_neon|
+    EXPORT  |vp8_short_inv_walsh4x4_1_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+;short vp8_short_inv_walsh4x4_neon(short *input, short *output)
+|vp8_short_inv_walsh4x4_neon| PROC
+
+    ; read in all four lines of values: d0->d3
+    vldm.64 r0, {q0, q1}
+
+    ; first for loop
+
+    vadd.s16 d4, d0, d3 ;a = [0] + [12]
+    vadd.s16 d5, d1, d2 ;b = [4] + [8]
+    vsub.s16 d6, d1, d2 ;c = [4] - [8]
+    vsub.s16 d7, d0, d3 ;d = [0] - [12]
+
+    vadd.s16 d0, d4, d5 ;a + b
+    vadd.s16 d1, d6, d7 ;c + d
+    vsub.s16 d2, d4, d5 ;a - b
+    vsub.s16 d3, d7, d6 ;d - c
+
+    vtrn.32 d0, d2 ;d0:  0  1  8  9
+                   ;d2:  2  3 10 11
+    vtrn.32 d1, d3 ;d1:  4  5 12 13
+                   ;d3:  6  7 14 15
+
+    vtrn.16 d0, d1 ;d0:  0  4  8 12
+                   ;d1:  1  5  9 13
+    vtrn.16 d2, d3 ;d2:  2  6 10 14
+                   ;d3:  3  7 11 15
+
+    ; second for loop
+
+    vadd.s16 d4, d0, d3 ;a = [0] + [3]
+    vadd.s16 d5, d1, d2 ;b = [1] + [2]
+    vsub.s16 d6, d1, d2 ;c = [1] - [2]
+    vsub.s16 d7, d0, d3 ;d = [0] - [3]
+
+    vadd.s16 d0, d4, d5 ;e = a + b
+    vadd.s16 d1, d6, d7 ;f = c + d
+    vsub.s16 d2, d4, d5 ;g = a - b
+    vsub.s16 d3, d7, d6 ;h = d - c
+
+    vmov.i16 q2, #3
+    vadd.i16 q0, q0, q2 ;e/f += 3
+    vadd.i16 q1, q1, q2 ;g/h += 3
+
+    vshr.s16 q0, q0, #3 ;e/f >> 3
+    vshr.s16 q1, q1, #3 ;g/h >> 3
+
+    vtrn.32 d0, d2
+    vtrn.32 d1, d3
+    vtrn.16 d0, d1
+    vtrn.16 d2, d3
+
+    vstmia.16 r1!, {q0}
+    vstmia.16 r1!, {q1}
+
+    bx lr
+    ENDP    ; |vp8_short_inv_walsh4x4_neon|
+
+
+;short vp8_short_inv_walsh4x4_1_neon(short *input, short *output)
+|vp8_short_inv_walsh4x4_1_neon| PROC
+    ; load a full line into a neon register
+    vld1.16  {q0}, [r0]
+    ; extract first element and replicate
+    vdup.16 q1, d0[0]
+    ; add 3 to all values
+    vmov.i16 q2, #3
+    vadd.i16 q3, q1, q2
+    ; right shift
+    vshr.s16 q3, q3, #3
+    ; write it back
+    vstmia.16 r1!, {q3}
+    vstmia.16 r1!, {q3}
+
+    bx lr
+    ENDP    ; |vp8_short_inv_walsh4x4_1_neon|
+
+    END
diff --git a/vp8/common/arm/neon/loopfilterhorizontaledge_uv_neon.asm b/vp8/common/arm/neon/loopfilterhorizontaledge_uv_neon.asm
new file mode 100644
index 0000000..e3e8e8a
--- /dev/null
+++ b/vp8/common/arm/neon/loopfilterhorizontaledge_uv_neon.asm
@@ -0,0 +1,205 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_loop_filter_horizontal_edge_uv_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;Note: flimit, limit, and thresh shpuld be positive numbers. All 16 elements in flimit
+;are equal. So, in the code, only one load is needed
+;for flimit. Same way applies to limit and thresh.
+; r0    unsigned char *u,
+; r1    int p, //pitch
+; r2    const signed char *flimit,
+; r3    const signed char *limit,
+; stack(r4) const signed char *thresh,
+; stack(r5) unsigned char *v
+
+|vp8_loop_filter_horizontal_edge_uv_neon| PROC
+    sub         r0, r0, r1, lsl #2          ; move u pointer down by 4 lines
+    vld1.s8     {d0[], d1[]}, [r2]          ; flimit
+
+    ldr         r2, [sp, #4]                ; load v ptr
+    ldr         r12, [sp, #0]               ; load thresh pointer
+
+    sub         r2, r2, r1, lsl #2          ; move v pointer down by 4 lines
+
+    vld1.u8     {d6}, [r0], r1              ; p3
+    vld1.u8     {d7}, [r2], r1              ; p3
+    vld1.u8     {d8}, [r0], r1              ; p2
+    vld1.u8     {d9}, [r2], r1              ; p2
+    vld1.u8     {d10}, [r0], r1             ; p1
+    vld1.u8     {d11}, [r2], r1             ; p1
+    vld1.u8     {d12}, [r0], r1             ; p0
+    vld1.u8     {d13}, [r2], r1             ; p0
+    vld1.u8     {d14}, [r0], r1             ; q0
+    vld1.u8     {d15}, [r2], r1             ; q0
+    vld1.u8     {d16}, [r0], r1             ; q1
+    vld1.u8     {d17}, [r2], r1             ; q1
+    vld1.u8     {d18}, [r0], r1             ; q2
+    vld1.u8     {d19}, [r2], r1             ; q2
+    vld1.u8     {d20}, [r0], r1             ; q3
+    vld1.u8     {d21}, [r2], r1             ; q3
+
+    vld1.s8     {d2[], d3[]}, [r3]          ; limit
+    vld1.s8     {d4[], d5[]}, [r12]         ; thresh
+
+    ldr         r12, _lfhuv_coeff_
+    ;vp8_filter_mask() function
+    ;vp8_hevmask() function
+    vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
+    vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
+    vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
+    vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
+    vabd.u8     q3, q9, q8                  ; abs(q2 - q1)
+    vabd.u8     q4, q10, q9                 ; abs(q3 - q2)
+    vabd.u8     q9, q6, q7                  ; abs(p0 - q0)
+
+    vcge.u8     q15, q1, q11                ; (abs(p3 - p2) > limit)*-1
+    vcge.u8     q12, q1, q12                ; (abs(p2 - p1) > limit)*-1
+    vcge.u8     q10, q1, q13                ; (abs(p1 - p0) > limit)*-1
+    vcge.u8     q11, q1, q14                ; (abs(q1 - q0) > limit)*-1
+
+    vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh)*-1
+    vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh)*-1
+
+    vcge.u8     q3, q1, q3                  ; (abs(q2 - q1) > limit)*-1
+    vcge.u8     q4, q1, q4                  ; (abs(q3 - q2) > limit)*-1
+    vadd.u8     q0, q0, q0                  ; flimit * 2
+    vadd.u8     q0, q0, q1                  ; flimit * 2 + limit
+
+    vand        q15, q15, q12
+    vand        q10, q10, q11
+    vand        q3, q3, q4
+
+    vabd.u8     q2, q5, q8                  ; abs(p1 - q1)
+    vqadd.u8    q9, q9, q9                  ; abs(p0 - q0) * 2
+    vshr.u8     q2, q2, #1                  ; abs(p1 - q1) / 2
+    vqadd.u8    q9, q9, q2                  ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+    vcge.u8     q9, q0, q9                  ; (abs(p0 - q0)*2 + abs(p1-q1)/2 > flimit*2 + limit)*-1
+
+    vld1.u8     {q0}, [r12]!
+
+    vand        q15, q15, q10
+
+    ;vp8_filter() function
+    veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
+    veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
+    veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
+    veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
+;;;;;;;;;;;;;;
+    vld1.u8     {q10}, [r12]!
+
+    ;vqsub.s8   q2, q7, q6                  ; ( qs0 - ps0)
+    vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
+    vsubl.s8    q11, d15, d13
+
+    vand        q3, q3, q9
+    vmovl.u8    q4, d20
+
+    vqsub.s8    q1, q5, q8                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
+    vorr        q14, q13, q14               ; q14: vp8_hevmask
+
+    ;vmul.i8    q2, q2, q10                 ; 3 * ( qs0 - ps0)
+    vmul.i16    q2, q2, q4                  ; 3 * ( qs0 - ps0)
+    vmul.i16    q11, q11, q4
+
+    vand        q1, q1, q14                 ; vp8_filter &= hev
+    vand        q15, q15, q3                ; q15: vp8_filter_mask
+    ;;
+    ;vld1.u8        {q4}, [r12]!            ;no need 7 any more
+
+    ;vqadd.s8   q1, q1, q2
+    vaddw.s8    q2, q2, d2
+    vaddw.s8    q11, q11, d3
+
+    vld1.u8     {q9}, [r12]!
+    ;
+    vqmovn.s16  d2, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d3, q11
+    ;;
+
+    vand        q1, q1, q15                 ; vp8_filter &= mask
+    ;;
+;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Change for VP8 from VP7
+;   vand        q2, q1, q4                  ; s = vp8_filter & 7
+;   vqadd.s8    q1, q1, q9                  ; vp8_filter = vp8_signed_char_clamp(vp8_filter+4)
+    ;;;;
+;   vshr.s8     q1, q1, #3                  ; vp8_filter >>= 3
+;   vceq.i8     q2, q2, q9                  ; s = (s==4)*-1
+    ;;
+;   ;calculate output
+;   vqsub.s8    q10, q7, q1                 ; u = vp8_signed_char_clamp(qs0 - vp8_filter)
+;   vqadd.s8    q11, q2, q1                 ; u = vp8_signed_char_clamp(s + vp8_filter)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; q10=3
+    vqadd.s8    q2, q1, q10                 ; Filter2 = vp8_signed_char_clamp(vp8_filter+3)
+    vqadd.s8    q1, q1, q9                  ; Filter1 = vp8_signed_char_clamp(vp8_filter+4)
+    vshr.s8     q2, q2, #3                  ; Filter2 >>= 3
+    vshr.s8     q1, q1, #3                  ; Filter1 >>= 3
+
+    ;calculate output
+    vqadd.s8    q11, q6, q2             ; u = vp8_signed_char_clamp(ps0 + Filter2)
+    vqsub.s8    q10, q7, q1                 ; u = vp8_signed_char_clamp(qs0 - Filter1)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+    vrshr.s8    q1, q1, #1                  ;round/shift:  vp8_filter += 1; vp8_filter >>= 1
+
+    sub         r0, r0, r1, lsl #2
+    sub         r0, r0, r1, lsl #1
+    ;
+
+    vbic        q1, q1, q14                 ; vp8_filter &= ~hev
+
+    sub         r2, r2, r1, lsl #2
+    sub         r2, r2, r1, lsl #1
+    ;;
+
+    vqadd.s8    q13, q5, q1                 ; u = vp8_signed_char_clamp(ps1 + vp8_filter)
+    ;vqadd.s8   q11, q6, q11                ; u = vp8_signed_char_clamp(ps0 + u)
+    vqsub.s8    q12, q8, q1                 ; u = vp8_signed_char_clamp(qs1 - vp8_filter)
+    ;
+
+    veor        q5, q13, q0                 ; *op1 = u^0x80
+    veor        q6, q11, q0                 ; *op0 = u^0x80
+    veor        q7, q10, q0                 ; *oq0 = u^0x80
+    veor        q8, q12, q0                 ; *oq1 = u^0x80
+    ;
+
+    vst1.u8     {d10}, [r0], r1             ; store u op1
+    vst1.u8     {d11}, [r2], r1             ; store v op1
+    vst1.u8     {d12}, [r0], r1             ; store u op0
+    vst1.u8     {d13}, [r2], r1             ; store v op0
+    vst1.u8     {d14}, [r0], r1             ; store u oq0
+    vst1.u8     {d15}, [r2], r1             ; store v oq0
+    vst1.u8     {d16}, [r0], r1             ; store u oq1
+    vst1.u8     {d17}, [r2], r1             ; store v oq1
+
+    bx          lr
+    ENDP        ; |vp8_loop_filter_horizontal_edge_uv_neon|
+
+;-----------------
+    AREA    hloopfilteruv_dat, DATA, READWRITE          ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_lfhuv_coeff_
+    DCD     lfhuv_coeff
+lfhuv_coeff
+    DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
+    DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
+    DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
+    DCD     0x01010101, 0x01010101, 0x01010101, 0x01010101
+
+    END
diff --git a/vp8/common/arm/neon/loopfilterhorizontaledge_y_neon.asm b/vp8/common/arm/neon/loopfilterhorizontaledge_y_neon.asm
new file mode 100644
index 0000000..f11055d
--- /dev/null
+++ b/vp8/common/arm/neon/loopfilterhorizontaledge_y_neon.asm
@@ -0,0 +1,188 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_loop_filter_horizontal_edge_y_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;Note: flimit, limit, and thresh shpuld be positive numbers. All 16 elements in flimit
+;are equal. So, in the code, only one load is needed
+;for flimit. Same way applies to limit and thresh.
+; r0    unsigned char *s,
+; r1    int p, //pitch
+; r2    const signed char *flimit,
+; r3    const signed char *limit,
+; stack(r4) const signed char *thresh,
+; //stack(r5)   int count --unused
+
+|vp8_loop_filter_horizontal_edge_y_neon| PROC
+    sub         r0, r0, r1, lsl #2          ; move src pointer down by 4 lines
+    ldr         r12, [sp, #0]               ; load thresh pointer
+
+    vld1.u8     {q3}, [r0], r1              ; p3
+    vld1.s8     {d0[], d1[]}, [r2]          ; flimit
+    vld1.u8     {q4}, [r0], r1              ; p2
+    vld1.s8     {d2[], d3[]}, [r3]          ; limit
+    vld1.u8     {q5}, [r0], r1              ; p1
+    vld1.s8     {d4[], d5[]}, [r12]         ; thresh
+    vld1.u8     {q6}, [r0], r1              ; p0
+    ldr         r12, _lfhy_coeff_
+    vld1.u8     {q7}, [r0], r1              ; q0
+
+    ;vp8_filter_mask() function
+    ;vp8_hevmask() function
+    vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
+    vld1.u8     {q8}, [r0], r1              ; q1
+    vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
+    vld1.u8     {q9}, [r0], r1              ; q2
+    vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
+    vld1.u8     {q10}, [r0], r1             ; q3
+    vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
+    vabd.u8     q3, q9, q8                  ; abs(q2 - q1)
+    vabd.u8     q4, q10, q9                 ; abs(q3 - q2)
+    vabd.u8     q9, q6, q7                  ; abs(p0 - q0)
+
+    vcge.u8     q15, q1, q11                ; (abs(p3 - p2) > limit)*-1
+    vcge.u8     q12, q1, q12                ; (abs(p2 - p1) > limit)*-1
+    vcge.u8     q10, q1, q13                ; (abs(p1 - p0) > limit)*-1
+    vcge.u8     q11, q1, q14                ; (abs(q1 - q0) > limit)*-1
+
+    vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh)*-1
+    vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh)*-1
+
+    vcge.u8     q3, q1, q3                  ; (abs(q2 - q1) > limit)*-1
+    vcge.u8     q4, q1, q4                  ; (abs(q3 - q2) > limit)*-1
+    vadd.u8     q0, q0, q0                  ; flimit * 2
+    vadd.u8     q0, q0, q1                  ; flimit * 2 + limit
+
+    vand        q15, q15, q12
+    vand        q10, q10, q11
+    vand        q3, q3, q4
+
+    vabd.u8     q2, q5, q8                  ; abs(p1 - q1)
+    vqadd.u8    q9, q9, q9                  ; abs(p0 - q0) * 2
+    vshr.u8     q2, q2, #1                  ; abs(p1 - q1) / 2
+    vqadd.u8    q9, q9, q2                  ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+    vcge.u8     q9, q0, q9                  ; (abs(p0 - q0)*2 + abs(p1-q1)/2 > flimit*2 + limit)*-1
+
+    vld1.u8     {q0}, [r12]!
+
+    vand        q15, q15, q10
+
+    ;vp8_filter() function
+    veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
+    veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
+    veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
+    veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
+;;;;;;;;;;;;;;
+    vld1.u8     {q10}, [r12]!
+
+    ;vqsub.s8   q2, q7, q6                  ; ( qs0 - ps0)
+    vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
+    vsubl.s8    q11, d15, d13
+
+    vand        q3, q3, q9
+    vmovl.u8    q4, d20
+
+    vqsub.s8    q1, q5, q8                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
+    vorr        q14, q13, q14               ; q14: vp8_hevmask
+
+    ;vmul.i8    q2, q2, q10                 ; 3 * ( qs0 - ps0)
+    vmul.i16    q2, q2, q4                  ; 3 * ( qs0 - ps0)
+    vmul.i16    q11, q11, q4
+
+    vand        q1, q1, q14                 ; vp8_filter &= hev
+    vand        q15, q15, q3                ; q15: vp8_filter_mask
+    ;;
+    ;vld1.u8        {q4}, [r12]!            ;no need 7 any more
+
+    ;vqadd.s8   q1, q1, q2
+    vaddw.s8    q2, q2, d2
+    vaddw.s8    q11, q11, d3
+
+    vld1.u8     {q9}, [r12]!
+    ;
+    vqmovn.s16  d2, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d3, q11
+    ;;
+
+    vand        q1, q1, q15                 ; vp8_filter &= mask
+    ;;
+;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Change for VP8 from VP7
+;   vand        q2, q1, q4                  ; s = vp8_filter & 7
+;   vqadd.s8    q1, q1, q9                  ; vp8_filter = vp8_signed_char_clamp(vp8_filter+4)
+    ;;;;
+;   vshr.s8     q1, q1, #3                  ; vp8_filter >>= 3
+;   vceq.i8     q2, q2, q9                  ; s = (s==4)*-1
+    ;;
+;   ;calculate output
+;   vqsub.s8    q10, q7, q1                 ; u = vp8_signed_char_clamp(qs0 - vp8_filter)
+;   vqadd.s8    q11, q2, q1                 ; u = vp8_signed_char_clamp(s + vp8_filter)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; q10=3
+    vqadd.s8    q2, q1, q10                 ; Filter2 = vp8_signed_char_clamp(vp8_filter+3)
+    vqadd.s8    q1, q1, q9                  ; Filter1 = vp8_signed_char_clamp(vp8_filter+4)
+    vshr.s8     q2, q2, #3                  ; Filter2 >>= 3
+    vshr.s8     q1, q1, #3                  ; Filter1 >>= 3
+
+    ;calculate output
+    vqadd.s8    q11, q6, q2                 ; u = vp8_signed_char_clamp(ps0 + Filter2)
+    vqsub.s8    q10, q7, q1                 ; u = vp8_signed_char_clamp(qs0 - Filter1)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+    vrshr.s8    q1, q1, #1                  ;round/shift:  vp8_filter += 1; vp8_filter >>= 1
+
+    sub         r0, r0, r1, lsl #2
+    sub         r0, r0, r1, lsl #1
+    ;
+
+    vbic        q1, q1, q14                 ; vp8_filter &= ~hev
+    ;
+    add         r2, r1, r0
+
+    vqadd.s8    q13, q5, q1                 ; u = vp8_signed_char_clamp(ps1 + vp8_filter)
+    ;vqadd.s8   q11, q6, q11                ; u = vp8_signed_char_clamp(ps0 + u)
+    vqsub.s8    q12, q8, q1                 ; u = vp8_signed_char_clamp(qs1 - vp8_filter)
+
+    add         r3, r2, r1
+
+    veor        q5, q13, q0                 ; *op1 = u^0x80
+    veor        q6, q11, q0                 ; *op0 = u^0x80
+    veor        q7, q10, q0                 ; *oq0 = u^0x80
+    veor        q8, q12, q0                 ; *oq1 = u^0x80
+
+    add         r12, r3, r1
+
+    vst1.u8     {q5}, [r0]                  ; store op1
+    vst1.u8     {q6}, [r2]                  ; store op0
+    vst1.u8     {q7}, [r3]                  ; store oq0
+    vst1.u8     {q8}, [r12]                 ; store oq1
+
+    bx          lr
+    ENDP        ; |vp8_loop_filter_horizontal_edge_y_neon|
+
+;-----------------
+    AREA    hloopfiltery_dat, DATA, READWRITE           ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_lfhy_coeff_
+    DCD     lfhy_coeff
+lfhy_coeff
+    DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
+    DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
+    DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
+    DCD     0x01010101, 0x01010101, 0x01010101, 0x01010101
+
+    END
diff --git a/vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm b/vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm
new file mode 100644
index 0000000..6d74fab
--- /dev/null
+++ b/vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm
@@ -0,0 +1,117 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_loop_filter_simple_horizontal_edge_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;Note: flimit, limit, and thresh shpuld be positive numbers. All 16 elements in flimit
+;are equal. So, in the code, only one load is needed
+;for flimit. Same way applies to limit and thresh.
+; r0    unsigned char *s,
+; r1    int p, //pitch
+; r2    const signed char *flimit,
+; r3    const signed char *limit,
+; stack(r4) const signed char *thresh,
+; //stack(r5)   int count --unused
+
+|vp8_loop_filter_simple_horizontal_edge_neon| PROC
+    sub         r0, r0, r1, lsl #1          ; move src pointer down by 2 lines
+
+    ldr         r12, _lfhy_coeff_
+    vld1.u8     {q5}, [r0], r1              ; p1
+    vld1.s8     {d2[], d3[]}, [r2]          ; flimit
+    vld1.s8     {d26[], d27[]}, [r3]        ; limit -> q13
+    vld1.u8     {q6}, [r0], r1              ; p0
+    vld1.u8     {q0}, [r12]!                ; 0x80
+    vld1.u8     {q7}, [r0], r1              ; q0
+    vld1.u8     {q10}, [r12]!               ; 0x03
+    vld1.u8     {q8}, [r0]                  ; q1
+
+    ;vp8_filter_mask() function
+    vabd.u8     q15, q6, q7                 ; abs(p0 - q0)
+    vabd.u8     q14, q5, q8                 ; abs(p1 - q1)
+    vqadd.u8    q15, q15, q15               ; abs(p0 - q0) * 2
+    vshr.u8     q14, q14, #1                ; abs(p1 - q1) / 2
+    vqadd.u8    q15, q15, q14               ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+
+    ;vp8_filter() function
+    veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
+    veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
+    veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
+    veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
+
+    vadd.u8     q1, q1, q1                  ; flimit * 2
+    vadd.u8     q1, q1, q13                 ; flimit * 2 + limit
+    vcge.u8     q15, q1, q15                ; (abs(p0 - q0)*2 + abs(p1-q1)/2 > flimit*2 + limit)*-1
+
+;;;;;;;;;;
+    ;vqsub.s8   q2, q7, q6                  ; ( qs0 - ps0)
+    vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
+    vsubl.s8    q3, d15, d13
+
+    vqsub.s8    q4, q5, q8                  ; q4: vp8_filter = vp8_signed_char_clamp(ps1-qs1)
+
+    ;vmul.i8    q2, q2, q10                 ;  3 * ( qs0 - ps0)
+    vadd.s16    q11, q2, q2                 ;  3 * ( qs0 - ps0)
+    vadd.s16    q12, q3, q3
+
+    vld1.u8     {q9}, [r12]!                ; 0x04
+
+    vadd.s16    q2, q2, q11
+    vadd.s16    q3, q3, q12
+
+    vaddw.s8    q2, q2, d8                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q3, q3, d9
+
+    ;vqadd.s8   q4, q4, q2                  ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d8, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d9, q3
+;;;;;;;;;;;;;
+
+    vand        q4, q4, q15                 ; vp8_filter &= mask
+
+    vqadd.s8    q2, q4, q10                 ; Filter2 = vp8_signed_char_clamp(vp8_filter+3)
+    vqadd.s8    q4, q4, q9                  ; Filter1 = vp8_signed_char_clamp(vp8_filter+4)
+    vshr.s8     q2, q2, #3                  ; Filter2 >>= 3
+    vshr.s8     q4, q4, #3                  ; Filter1 >>= 3
+
+    sub         r0, r0, r1, lsl #1
+
+    ;calculate output
+    vqadd.s8    q11, q6, q2                 ; u = vp8_signed_char_clamp(ps0 + Filter2)
+    vqsub.s8    q10, q7, q4                 ; u = vp8_signed_char_clamp(qs0 - Filter1)
+
+    add         r3, r0, r1
+
+    veor        q6, q11, q0                 ; *op0 = u^0x80
+    veor        q7, q10, q0                 ; *oq0 = u^0x80
+
+    vst1.u8     {q6}, [r0]                  ; store op0
+    vst1.u8     {q7}, [r3]                  ; store oq0
+
+    bx          lr
+    ENDP        ; |vp8_loop_filter_simple_horizontal_edge_neon|
+
+;-----------------
+    AREA    hloopfiltery_dat, DATA, READWRITE           ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_lfhy_coeff_
+    DCD     lfhy_coeff
+lfhy_coeff
+    DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
+    DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
+    DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
+
+    END
diff --git a/vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm b/vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm
new file mode 100644
index 0000000..2bb6222
--- /dev/null
+++ b/vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm
@@ -0,0 +1,158 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_loop_filter_simple_vertical_edge_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;Note: flimit, limit, and thresh should be positive numbers. All 16 elements in flimit
+;are equal. So, in the code, only one load is needed
+;for flimit. Same way applies to limit and thresh.
+; r0    unsigned char *s,
+; r1    int p, //pitch
+; r2    const signed char *flimit,
+; r3    const signed char *limit,
+; stack(r4) const signed char *thresh,
+; //stack(r5)   int count --unused
+
+|vp8_loop_filter_simple_vertical_edge_neon| PROC
+    sub         r0, r0, #2                  ; move src pointer down by 2 columns
+
+    vld4.8      {d6[0], d7[0], d8[0], d9[0]}, [r0], r1
+    vld1.s8     {d2[], d3[]}, [r2]          ; flimit
+    vld1.s8     {d26[], d27[]}, [r3]        ; limit -> q13
+    vld4.8      {d6[1], d7[1], d8[1], d9[1]}, [r0], r1
+    ldr         r12, _vlfy_coeff_
+    vld4.8      {d6[2], d7[2], d8[2], d9[2]}, [r0], r1
+    vld4.8      {d6[3], d7[3], d8[3], d9[3]}, [r0], r1
+    vld4.8      {d6[4], d7[4], d8[4], d9[4]}, [r0], r1
+    vld4.8      {d6[5], d7[5], d8[5], d9[5]}, [r0], r1
+    vld4.8      {d6[6], d7[6], d8[6], d9[6]}, [r0], r1
+    vld4.8      {d6[7], d7[7], d8[7], d9[7]}, [r0], r1
+
+    vld4.8      {d10[0], d11[0], d12[0], d13[0]}, [r0], r1
+    vld1.u8     {q0}, [r12]!                ; 0x80
+    vld4.8      {d10[1], d11[1], d12[1], d13[1]}, [r0], r1
+    vld1.u8     {q11}, [r12]!               ; 0x03
+    vld4.8      {d10[2], d11[2], d12[2], d13[2]}, [r0], r1
+    vld1.u8     {q12}, [r12]!               ; 0x04
+    vld4.8      {d10[3], d11[3], d12[3], d13[3]}, [r0], r1
+    vld4.8      {d10[4], d11[4], d12[4], d13[4]}, [r0], r1
+    vld4.8      {d10[5], d11[5], d12[5], d13[5]}, [r0], r1
+    vld4.8      {d10[6], d11[6], d12[6], d13[6]}, [r0], r1
+    vld4.8      {d10[7], d11[7], d12[7], d13[7]}, [r0], r1
+
+    vswp        d7, d10
+    vswp        d12, d9
+    ;vswp       q4, q5                      ; p1:q3, p0:q5, q0:q4, q1:q6
+
+    ;vp8_filter_mask() function
+    ;vp8_hevmask() function
+    sub         r0, r0, r1, lsl #4
+    vabd.u8     q15, q5, q4                 ; abs(p0 - q0)
+    vabd.u8     q14, q3, q6                 ; abs(p1 - q1)
+    vqadd.u8    q15, q15, q15               ; abs(p0 - q0) * 2
+    vshr.u8     q14, q14, #1                ; abs(p1 - q1) / 2
+    vqadd.u8    q15, q15, q14               ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+
+    veor        q4, q4, q0                  ; qs0: q0 offset to convert to a signed value
+    veor        q5, q5, q0                  ; ps0: p0 offset to convert to a signed value
+    veor        q3, q3, q0                  ; ps1: p1 offset to convert to a signed value
+    veor        q6, q6, q0                  ; qs1: q1 offset to convert to a signed value
+
+    vadd.u8     q1, q1, q1                  ; flimit * 2
+    vadd.u8     q1, q1, q13                 ; flimit * 2 + limit
+    vcge.u8     q15, q1, q15                ; abs(p0 - q0)*2 + abs(p1-q1)/2 > flimit*2 + limit)*-1
+
+    ;vp8_filter() function
+;;;;;;;;;;
+    ;vqsub.s8   q2, q5, q4                  ; ( qs0 - ps0)
+    vsubl.s8    q2, d8, d10                 ; ( qs0 - ps0)
+    vsubl.s8    q13, d9, d11
+
+    vqsub.s8    q1, q3, q6                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
+
+    ;vmul.i8    q2, q2, q11                 ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vadd.s16    q10, q2, q2                 ;  3 * ( qs0 - ps0)
+    vadd.s16    q14, q13, q13
+    vadd.s16    q2, q2, q10
+    vadd.s16    q13, q13, q14
+
+    ;vqadd.s8   q1, q1, q2
+    vaddw.s8    q2, q2, d2                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q13, q13, d3
+
+    vqmovn.s16  d2, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d3, q13
+
+    add         r0, r0, #1
+    add         r2, r0, r1
+;;;;;;;;;;;
+
+    vand        q1, q1, q15                 ; vp8_filter &= mask
+
+    vqadd.s8    q2, q1, q11                 ; Filter2 = vp8_signed_char_clamp(vp8_filter+3)
+    vqadd.s8    q1, q1, q12                 ; Filter1 = vp8_signed_char_clamp(vp8_filter+4)
+    vshr.s8     q2, q2, #3                  ; Filter2 >>= 3
+    vshr.s8     q1, q1, #3                  ; Filter1 >>= 3
+
+    ;calculate output
+    vqsub.s8    q10, q4, q1                 ; u = vp8_signed_char_clamp(qs0 - Filter1)
+    vqadd.s8    q11, q5, q2                 ; u = vp8_signed_char_clamp(ps0 + Filter2)
+
+    veor        q7, q10, q0                 ; *oq0 = u^0x80
+    veor        q6, q11, q0                 ; *op0 = u^0x80
+
+    add         r3, r2, r1
+    vswp        d13, d14
+    add         r12, r3, r1
+
+    ;store op1, op0, oq0, oq1
+    vst2.8      {d12[0], d13[0]}, [r0]
+    vst2.8      {d12[1], d13[1]}, [r2]
+    vst2.8      {d12[2], d13[2]}, [r3]
+    vst2.8      {d12[3], d13[3]}, [r12], r1
+    add         r0, r12, r1
+    vst2.8      {d12[4], d13[4]}, [r12]
+    vst2.8      {d12[5], d13[5]}, [r0], r1
+    add         r2, r0, r1
+    vst2.8      {d12[6], d13[6]}, [r0]
+    vst2.8      {d12[7], d13[7]}, [r2], r1
+    add         r3, r2, r1
+    vst2.8      {d14[0], d15[0]}, [r2]
+    vst2.8      {d14[1], d15[1]}, [r3], r1
+    add         r12, r3, r1
+    vst2.8      {d14[2], d15[2]}, [r3]
+    vst2.8      {d14[3], d15[3]}, [r12], r1
+    add         r0, r12, r1
+    vst2.8      {d14[4], d15[4]}, [r12]
+    vst2.8      {d14[5], d15[5]}, [r0], r1
+    add         r2, r0, r1
+    vst2.8      {d14[6], d15[6]}, [r0]
+    vst2.8      {d14[7], d15[7]}, [r2]
+
+    bx          lr
+    ENDP        ; |vp8_loop_filter_simple_vertical_edge_neon|
+
+;-----------------
+    AREA    vloopfiltery_dat, DATA, READWRITE           ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_vlfy_coeff_
+    DCD     vlfy_coeff
+vlfy_coeff
+    DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
+    DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
+    DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
+
+    END
diff --git a/vp8/common/arm/neon/loopfilterverticaledge_uv_neon.asm b/vp8/common/arm/neon/loopfilterverticaledge_uv_neon.asm
new file mode 100644
index 0000000..d79cc68
--- /dev/null
+++ b/vp8/common/arm/neon/loopfilterverticaledge_uv_neon.asm
@@ -0,0 +1,231 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_loop_filter_vertical_edge_uv_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;Note: flimit, limit, and thresh shpuld be positive numbers. All 16 elements in flimit
+;are equal. So, in the code, only one load is needed
+;for flimit. Same way applies to limit and thresh.
+; r0    unsigned char *u,
+; r1    int p, //pitch
+; r2    const signed char *flimit,
+; r3    const signed char *limit,
+; stack(r4) const signed char *thresh,
+; stack(r5) unsigned char *v
+
+|vp8_loop_filter_vertical_edge_uv_neon| PROC
+    sub         r0, r0, #4          ; move u pointer down by 4 columns
+    vld1.s8     {d0[], d1[]}, [r2]          ; flimit
+
+    ldr         r2, [sp, #4]                ; load v ptr
+    ldr         r12, [sp, #0]               ; load thresh pointer
+
+    sub         r2, r2, #4          ; move v pointer down by 4 columns
+
+    vld1.u8     {d6}, [r0], r1              ;load u data
+    vld1.u8     {d7}, [r2], r1              ;load v data
+    vld1.u8     {d8}, [r0], r1
+    vld1.u8     {d9}, [r2], r1
+    vld1.u8     {d10}, [r0], r1
+    vld1.u8     {d11}, [r2], r1
+    vld1.u8     {d12}, [r0], r1
+    vld1.u8     {d13}, [r2], r1
+    vld1.u8     {d14}, [r0], r1
+    vld1.u8     {d15}, [r2], r1
+    vld1.u8     {d16}, [r0], r1
+    vld1.u8     {d17}, [r2], r1
+    vld1.u8     {d18}, [r0], r1
+    vld1.u8     {d19}, [r2], r1
+    vld1.u8     {d20}, [r0], r1
+    vld1.u8     {d21}, [r2], r1
+
+    ;transpose to 8x16 matrix
+    vtrn.32     q3, q7
+    vtrn.32     q4, q8
+    vtrn.32     q5, q9
+    vtrn.32     q6, q10
+
+    vtrn.16     q3, q5
+    vtrn.16     q4, q6
+    vtrn.16     q7, q9
+    vtrn.16     q8, q10
+
+    vtrn.8      q3, q4
+    vtrn.8      q5, q6
+    vtrn.8      q7, q8
+    vtrn.8      q9, q10
+
+    vld1.s8     {d2[], d3[]}, [r3]          ; limit
+    vld1.s8     {d4[], d5[]}, [r12]         ; thresh
+
+    ldr         r12, _vlfuv_coeff_
+    ;vp8_filter_mask() function
+    ;vp8_hevmask() function
+    vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
+    vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
+    vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
+    vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
+    vabd.u8     q3, q9, q8                  ; abs(q2 - q1)
+    vabd.u8     q4, q10, q9                 ; abs(q3 - q2)
+    vabd.u8     q9, q6, q7                  ; abs(p0 - q0)
+
+    vcge.u8     q15, q1, q11                ; (abs(p3 - p2) > limit)*-1
+    vcge.u8     q12, q1, q12                ; (abs(p2 - p1) > limit)*-1
+    vcge.u8     q10, q1, q13                ; (abs(p1 - p0) > limit)*-1
+    vcge.u8     q11, q1, q14                ; (abs(q1 - q0) > limit)*-1
+
+    vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh)*-1
+    vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh)*-1
+
+    vcge.u8     q3, q1, q3                  ; (abs(q2 - q1) > limit)*-1
+    vcge.u8     q4, q1, q4                  ; (abs(q3 - q2) > limit)*-1
+    vadd.u8     q0, q0, q0                  ; flimit * 2
+    vadd.u8     q0, q0, q1                  ; flimit * 2 + limit
+
+    vand        q15, q15, q12
+    vand        q10, q10, q11
+    vand        q3, q3, q4
+
+    vabd.u8     q2, q5, q8                  ; abs(p1 - q1)
+    vqadd.u8    q9, q9, q9                  ; abs(p0 - q0) * 2
+    vshr.u8     q2, q2, #1                  ; abs(p1 - q1) / 2
+    vqadd.u8    q9, q9, q2                  ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+    vcge.u8     q9, q0, q9                  ; (abs(p0 - q0)*2 + abs(p1-q1)/2 > flimit*2 + limit)*-1
+
+    vld1.u8     {q0}, [r12]!
+
+    vand        q15, q15, q10
+
+
+    ;vp8_filter() function
+    veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
+    veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
+    veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
+    veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
+;;;;;;;;;;;;;;
+    vld1.u8     {q10}, [r12]!
+
+    ;vqsub.s8   q2, q7, q6                  ; ( qs0 - ps0)
+    vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
+    vsubl.s8    q11, d15, d13
+
+    vand        q3, q3, q9
+    vmovl.u8    q4, d20
+
+    vqsub.s8    q1, q5, q8                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
+    vorr        q14, q13, q14               ; q14: vp8_hevmask
+
+    ;vmul.i8    q2, q2, q10                 ; 3 * ( qs0 - ps0)
+    vmul.i16    q2, q2, q4                  ; 3 * ( qs0 - ps0)
+    vmul.i16    q11, q11, q4
+
+    vand        q1, q1, q14                 ; vp8_filter &= hev
+    vand        q15, q15, q3                ; q15: vp8_filter_mask
+    ;;
+    ;vld1.u8        {q4}, [r12]!            ;no need 7 any more
+
+    ;vqadd.s8   q1, q1, q2
+    vaddw.s8    q2, q2, d2
+    vaddw.s8    q11, q11, d3
+
+    vld1.u8     {q9}, [r12]!
+    ;
+    vqmovn.s16  d2, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d3, q11
+    ;;
+
+    vand        q1, q1, q15                 ; vp8_filter &= mask
+    ;;
+;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Change for VP8 from VP7
+;   vand        q2, q1, q4                  ; s = vp8_filter & 7
+;   vqadd.s8    q1, q1, q9                  ; vp8_filter = vp8_signed_char_clamp(vp8_filter+4)
+    ;;;;
+;   vshr.s8     q1, q1, #3                  ; vp8_filter >>= 3
+;   vceq.i8     q2, q2, q9                  ; s = (s==4)*-1
+    ;;
+;   ;calculate output
+;   vqsub.s8    q10, q7, q1                 ; u = vp8_signed_char_clamp(qs0 - vp8_filter)
+;   vqadd.s8    q11, q2, q1                 ; u = vp8_signed_char_clamp(s + vp8_filter)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; q10=3
+    vqadd.s8    q2, q1, q10                 ; Filter2 = vp8_signed_char_clamp(vp8_filter+3)
+    vqadd.s8    q1, q1, q9                  ; Filter1 = vp8_signed_char_clamp(vp8_filter+4)
+    vshr.s8     q2, q2, #3                  ; Filter2 >>= 3
+    vshr.s8     q1, q1, #3                  ; Filter1 >>= 3
+    ;calculate output
+    vqadd.s8    q11, q6, q2             ; u = vp8_signed_char_clamp(ps0 + Filter2)
+    vqsub.s8    q10, q7, q1                 ; u = vp8_signed_char_clamp(qs0 - Filter1)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+    vrshr.s8    q1, q1, #1                  ;round/shift:  vp8_filter += 1; vp8_filter >>= 1
+
+    sub         r0, r0, r1, lsl #3
+    add         r0, r0, #2
+
+    vbic        q1, q1, q14                 ; vp8_filter &= ~hev
+
+    sub         r2, r2, r1, lsl #3
+    add         r2, r2, #2
+
+    vqadd.s8    q13, q5, q1                 ; u = vp8_signed_char_clamp(ps1 + vp8_filter)
+    ;vqadd.s8   q11, q6, q11                ; u = vp8_signed_char_clamp(ps0 + u)
+    vqsub.s8    q12, q8, q1                 ; u = vp8_signed_char_clamp(qs1 - vp8_filter)
+
+    veor        q7, q10, q0                 ; *oq0 = u^0x80
+    veor        q5, q13, q0                 ; *op1 = u^0x80
+    veor        q6, q11, q0                 ; *op0 = u^0x80
+    veor        q8, q12, q0                 ; *oq1 = u^0x80
+
+    vswp        d12, d11
+    vswp        d16, d13
+    vswp        d14, d12
+    vswp        d16, d15
+
+    ;store op1, op0, oq0, oq1
+    vst4.8      {d10[0], d11[0], d12[0], d13[0]}, [r0], r1
+    vst4.8      {d14[0], d15[0], d16[0], d17[0]}, [r2], r1
+    vst4.8      {d10[1], d11[1], d12[1], d13[1]}, [r0], r1
+    vst4.8      {d14[1], d15[1], d16[1], d17[1]}, [r2], r1
+    vst4.8      {d10[2], d11[2], d12[2], d13[2]}, [r0], r1
+    vst4.8      {d14[2], d15[2], d16[2], d17[2]}, [r2], r1
+    vst4.8      {d10[3], d11[3], d12[3], d13[3]}, [r0], r1
+    vst4.8      {d14[3], d15[3], d16[3], d17[3]}, [r2], r1
+    vst4.8      {d10[4], d11[4], d12[4], d13[4]}, [r0], r1
+    vst4.8      {d14[4], d15[4], d16[4], d17[4]}, [r2], r1
+    vst4.8      {d10[5], d11[5], d12[5], d13[5]}, [r0], r1
+    vst4.8      {d14[5], d15[5], d16[5], d17[5]}, [r2], r1
+    vst4.8      {d10[6], d11[6], d12[6], d13[6]}, [r0], r1
+    vst4.8      {d14[6], d15[6], d16[6], d17[6]}, [r2], r1
+    vst4.8      {d10[7], d11[7], d12[7], d13[7]}, [r0], r1
+    vst4.8      {d14[7], d15[7], d16[7], d17[7]}, [r2], r1
+
+    bx          lr
+    ENDP        ; |vp8_loop_filter_vertical_edge_uv_neon|
+
+;-----------------
+    AREA    vloopfilteruv_dat, DATA, READWRITE          ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_vlfuv_coeff_
+    DCD     vlfuv_coeff
+vlfuv_coeff
+    DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
+    DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
+    DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
+    DCD     0x01010101, 0x01010101, 0x01010101, 0x01010101
+
+    END
diff --git a/vp8/common/arm/neon/loopfilterverticaledge_y_neon.asm b/vp8/common/arm/neon/loopfilterverticaledge_y_neon.asm
new file mode 100644
index 0000000..3a230a9
--- /dev/null
+++ b/vp8/common/arm/neon/loopfilterverticaledge_y_neon.asm
@@ -0,0 +1,235 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_loop_filter_vertical_edge_y_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;Note: flimit, limit, and thresh shpuld be positive numbers. All 16 elements in flimit
+;are equal. So, in the code, only one load is needed
+;for flimit. Same way applies to limit and thresh.
+; r0    unsigned char *s,
+; r1    int p, //pitch
+; r2    const signed char *flimit,
+; r3    const signed char *limit,
+; stack(r4) const signed char *thresh,
+; //stack(r5)   int count --unused
+
+|vp8_loop_filter_vertical_edge_y_neon| PROC
+    sub         r0, r0, #4                  ; move src pointer down by 4 columns
+    ldr         r12, [sp, #0]               ; load thresh pointer
+
+    vld1.u8     {d6}, [r0], r1              ; load first 8-line src data
+    vld1.s8     {d0[], d1[]}, [r2]          ; flimit
+    vld1.u8     {d8}, [r0], r1
+    vld1.s8     {d2[], d3[]}, [r3]          ; limit
+    vld1.u8     {d10}, [r0], r1
+    vld1.s8     {d4[], d5[]}, [r12]         ; thresh
+    vld1.u8     {d12}, [r0], r1
+    ldr         r12, _vlfy_coeff_
+    vld1.u8     {d14}, [r0], r1
+    vld1.u8     {d16}, [r0], r1
+    vld1.u8     {d18}, [r0], r1
+    vld1.u8     {d20}, [r0], r1
+
+    vld1.u8     {d7}, [r0], r1              ; load second 8-line src data
+    vld1.u8     {d9}, [r0], r1
+    vld1.u8     {d11}, [r0], r1
+    vld1.u8     {d13}, [r0], r1
+    vld1.u8     {d15}, [r0], r1
+    vld1.u8     {d17}, [r0], r1
+    vld1.u8     {d19}, [r0], r1
+    vld1.u8     {d21}, [r0], r1
+
+    ;transpose to 8x16 matrix
+    vtrn.32     q3, q7
+    vtrn.32     q4, q8
+    vtrn.32     q5, q9
+    vtrn.32     q6, q10
+
+    vtrn.16     q3, q5
+    vtrn.16     q4, q6
+    vtrn.16     q7, q9
+    vtrn.16     q8, q10
+
+    vtrn.8      q3, q4
+    vtrn.8      q5, q6
+    vtrn.8      q7, q8
+    vtrn.8      q9, q10
+
+    ;vp8_filter_mask() function
+    ;vp8_hevmask() function
+    vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
+    vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
+    vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
+    vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
+    vabd.u8     q3, q9, q8                  ; abs(q2 - q1)
+    vabd.u8     q4, q10, q9                 ; abs(q3 - q2)
+    vabd.u8     q9, q6, q7                  ; abs(p0 - q0)
+
+    vcge.u8     q15, q1, q11                ; (abs(p3 - p2) > limit)*-1
+    vcge.u8     q12, q1, q12                ; (abs(p2 - p1) > limit)*-1
+    vcge.u8     q10, q1, q13                ; (abs(p1 - p0) > limit)*-1
+    vcge.u8     q11, q1, q14                ; (abs(q1 - q0) > limit)*-1
+
+    vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh)*-1
+    vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh)*-1
+
+    vcge.u8     q3, q1, q3                  ; (abs(q2 - q1) > limit)*-1
+    vcge.u8     q4, q1, q4                  ; (abs(q3 - q2) > limit)*-1
+    vadd.u8     q0, q0, q0                  ; flimit * 2
+    vadd.u8     q0, q0, q1                  ; flimit * 2 + limit
+
+    vand        q15, q15, q12
+    vand        q10, q10, q11
+    vand        q3, q3, q4
+
+    vabd.u8     q2, q5, q8                  ; abs(p1 - q1)
+    vqadd.u8    q9, q9, q9                  ; abs(p0 - q0) * 2
+    vshr.u8     q2, q2, #1                  ; abs(p1 - q1) / 2
+    vqadd.u8    q9, q9, q2                  ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+    vcge.u8     q9, q0, q9                  ; (abs(p0 - q0)*2 + abs(p1-q1)/2 > flimit*2 + limit)*-1
+
+    vld1.u8     {q0}, [r12]!
+
+    vand        q15, q15, q10
+
+
+    ;vp8_filter() function
+    veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
+    veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
+    veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
+    veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
+;;;;;;;;;;;;;;
+    vld1.u8     {q10}, [r12]!
+
+    ;vqsub.s8   q2, q7, q6                  ; ( qs0 - ps0)
+    vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
+    vsubl.s8    q11, d15, d13
+
+    vand        q3, q3, q9
+    vmovl.u8    q4, d20
+
+    vqsub.s8    q1, q5, q8                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
+    vorr        q14, q13, q14               ; q14: vp8_hevmask
+
+    ;vmul.i8    q2, q2, q10                 ; 3 * ( qs0 - ps0)
+    vmul.i16    q2, q2, q4                  ; 3 * ( qs0 - ps0)
+    vmul.i16    q11, q11, q4
+
+    vand        q1, q1, q14                 ; vp8_filter &= hev
+    vand        q15, q15, q3                ; q15: vp8_filter_mask
+    ;;
+    ;vld1.u8        {q4}, [r12]!            ;no need 7 any more
+
+    ;vqadd.s8   q1, q1, q2
+    vaddw.s8    q2, q2, d2
+    vaddw.s8    q11, q11, d3
+
+    vld1.u8     {q9}, [r12]!
+    ;
+    vqmovn.s16  d2, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d3, q11
+    ;;
+
+    vand        q1, q1, q15                 ; vp8_filter &= mask
+    ;;
+;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Change for VP8 from VP7
+;   vand        q2, q1, q4                  ; s = vp8_filter & 7
+;   vqadd.s8    q1, q1, q9                  ; vp8_filter = vp8_signed_char_clamp(vp8_filter+4)
+    ;;;;
+;   vshr.s8     q1, q1, #3                  ; vp8_filter >>= 3
+;   vceq.i8     q2, q2, q9                  ; s = (s==4)*-1
+    ;;
+;   ;calculate output
+;   vqsub.s8    q10, q7, q1                 ; u = vp8_signed_char_clamp(qs0 - vp8_filter)
+;   vqadd.s8    q11, q2, q1                 ; u = vp8_signed_char_clamp(s + vp8_filter)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; q10=3
+    vqadd.s8    q2, q1, q10                 ; Filter2 = vp8_signed_char_clamp(vp8_filter+3)
+    vqadd.s8    q1, q1, q9                  ; Filter1 = vp8_signed_char_clamp(vp8_filter+4)
+    vshr.s8     q2, q2, #3                  ; Filter2 >>= 3
+    vshr.s8     q1, q1, #3                  ; Filter1 >>= 3
+    ;calculate output
+    vqadd.s8    q11, q6, q2             ; u = vp8_signed_char_clamp(ps0 + Filter2)
+    vqsub.s8    q10, q7, q1                 ; u = vp8_signed_char_clamp(qs0 - Filter1)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+    vrshr.s8    q1, q1, #1                  ;round/shift:  vp8_filter += 1; vp8_filter >>= 1
+
+    sub         r0, r0, r1, lsl #4
+    add         r0, r0, #2
+    ;
+
+    vbic        q1, q1, q14                 ; vp8_filter &= ~hev
+    add         r2, r0, r1
+    ;
+
+    vqadd.s8    q13, q5, q1                 ; u = vp8_signed_char_clamp(ps1 + vp8_filter)
+    ;vqadd.s8   q11, q6, q11                ; u = vp8_signed_char_clamp(ps0 + u)
+    vqsub.s8    q12, q8, q1                 ; u = vp8_signed_char_clamp(qs1 - vp8_filter)
+
+    veor        q7, q10, q0                 ; *oq0 = u^0x80
+    veor        q5, q13, q0                 ; *op1 = u^0x80
+    veor        q6, q11, q0                 ; *op0 = u^0x80
+    veor        q8, q12, q0                 ; *oq1 = u^0x80
+    add         r3, r2, r1
+    ;
+    vswp        d12, d11
+    vswp        d16, d13
+    add         r12, r3, r1
+    vswp        d14, d12
+    vswp        d16, d15
+
+    ;store op1, op0, oq0, oq1
+    vst4.8      {d10[0], d11[0], d12[0], d13[0]}, [r0]
+    vst4.8      {d10[1], d11[1], d12[1], d13[1]}, [r2]
+    vst4.8      {d10[2], d11[2], d12[2], d13[2]}, [r3]
+    vst4.8      {d10[3], d11[3], d12[3], d13[3]}, [r12], r1
+    add         r0, r12, r1
+    vst4.8      {d10[4], d11[4], d12[4], d13[4]}, [r12]
+    vst4.8      {d10[5], d11[5], d12[5], d13[5]}, [r0], r1
+    add         r2, r0, r1
+    vst4.8      {d10[6], d11[6], d12[6], d13[6]}, [r0]
+    vst4.8      {d10[7], d11[7], d12[7], d13[7]}, [r2], r1
+    add         r3, r2, r1
+    vst4.8      {d14[0], d15[0], d16[0], d17[0]}, [r2]
+    vst4.8      {d14[1], d15[1], d16[1], d17[1]}, [r3], r1
+    add         r12, r3, r1
+    vst4.8      {d14[2], d15[2], d16[2], d17[2]}, [r3]
+    vst4.8      {d14[3], d15[3], d16[3], d17[3]}, [r12], r1
+    add         r0, r12, r1
+    vst4.8      {d14[4], d15[4], d16[4], d17[4]}, [r12]
+    vst4.8      {d14[5], d15[5], d16[5], d17[5]}, [r0], r1
+    add         r2, r0, r1
+    vst4.8      {d14[6], d15[6], d16[6], d17[6]}, [r0]
+    vst4.8      {d14[7], d15[7], d16[7], d17[7]}, [r2]
+
+    bx          lr
+    ENDP        ; |vp8_loop_filter_vertical_edge_y_neon|
+
+;-----------------
+    AREA    vloopfiltery_dat, DATA, READWRITE           ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_vlfy_coeff_
+    DCD     vlfy_coeff
+vlfy_coeff
+    DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
+    DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
+    DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
+    DCD     0x01010101, 0x01010101, 0x01010101, 0x01010101
+
+    END
diff --git a/vp8/common/arm/neon/mbloopfilterhorizontaledge_uv_neon.asm b/vp8/common/arm/neon/mbloopfilterhorizontaledge_uv_neon.asm
new file mode 100644
index 0000000..86eddaa
--- /dev/null
+++ b/vp8/common/arm/neon/mbloopfilterhorizontaledge_uv_neon.asm
@@ -0,0 +1,257 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_mbloop_filter_horizontal_edge_uv_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;Note: flimit, limit, and thresh shpuld be positive numbers. All 16 elements in flimit
+;are equal. So, in the code, only one load is needed
+;for flimit. Same way applies to limit and thresh.
+; r0    unsigned char *u,
+; r1    int p, //pitch
+; r2    const signed char *flimit,
+; r3    const signed char *limit,
+; stack(r4) const signed char *thresh,
+; stack(r5) unsigned char *v
+|vp8_mbloop_filter_horizontal_edge_uv_neon| PROC
+    sub         r0, r0, r1, lsl #2          ; move u pointer down by 4 lines
+    vld1.s8     {d2[], d3[]}, [r3]          ; limit
+    ldr         r3, [sp, #4]                ; load v ptr
+    ldr         r12, [sp, #0]               ; load thresh pointer
+    sub         r3, r3, r1, lsl #2          ; move v pointer down by 4 lines
+
+    vld1.u8     {d6}, [r0], r1              ; p3
+    vld1.u8     {d7}, [r3], r1              ; p3
+    vld1.u8     {d8}, [r0], r1              ; p2
+    vld1.u8     {d9}, [r3], r1              ; p2
+    vld1.u8     {d10}, [r0], r1             ; p1
+    vld1.u8     {d11}, [r3], r1             ; p1
+    vld1.u8     {d12}, [r0], r1             ; p0
+    vld1.u8     {d13}, [r3], r1             ; p0
+    vld1.u8     {d14}, [r0], r1             ; q0
+    vld1.u8     {d15}, [r3], r1             ; q0
+    vld1.u8     {d16}, [r0], r1             ; q1
+    vld1.u8     {d17}, [r3], r1             ; q1
+    vld1.u8     {d18}, [r0], r1             ; q2
+    vld1.u8     {d19}, [r3], r1             ; q2
+    vld1.u8     {d20}, [r0], r1             ; q3
+    vld1.u8     {d21}, [r3], r1             ; q3
+
+    vld1.s8     {d4[], d5[]}, [r12]         ; thresh
+
+    ldr         r12, _mbhlfuv_coeff_
+
+    ;vp8_filter_mask() function
+    ;vp8_hevmask() function
+    vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
+    vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
+    vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
+    vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
+    vabd.u8     q3, q9, q8                  ; abs(q2 - q1)
+    vabd.u8     q0, q10, q9                 ; abs(q3 - q2)
+
+    vcge.u8     q15, q1, q11                ; (abs(p3 - p2) > limit)*-1
+    vcge.u8     q12, q1, q12                ; (abs(p2 - p1) > limit)*-1
+    vcge.u8     q10, q1, q13                ; (abs(p1 - p0) > limit)*-1
+    vcge.u8     q11, q1, q14                ; (abs(q1 - q0) > limit)*-1
+    vcge.u8     q3, q1, q3                  ; (abs(q2 - q1) > limit)*-1
+    vcge.u8     q0, q1, q0                  ; (abs(q3 - q2) > limit)*-1
+
+    vand        q15, q15, q12
+
+    vabd.u8     q12, q6, q7                 ; abs(p0 - q0)
+
+    vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh)*-1
+    vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh)*-1
+
+    vld1.s8     {d4[], d5[]}, [r2]          ; flimit
+
+    vand        q10, q10, q11
+    vand        q3, q3, q0
+
+    vld1.u8     {q0}, [r12]!
+
+    vadd.u8     q2, q2, q2                  ; flimit * 2
+    vadd.u8     q2, q2, q1                  ; flimit * 2 +  limit
+
+    vabd.u8     q1, q5, q8                  ; abs(p1 - q1)
+    vqadd.u8    q12, q12, q12               ; abs(p0 - q0) * 2
+    vshr.u8     q1, q1, #1                  ; abs(p1 - q1) / 2
+    vqadd.u8    q12, q12, q1                ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+    vcge.u8     q12, q2, q12                ; (abs(p0 - q0)*2 + abs(p1 - q1)/2 > flimit*2 + limit)*-1
+
+    vand        q15, q15, q10
+
+    ;vp8_filter() function
+    veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
+    veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
+    veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
+    veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
+    veor        q4, q4, q0                  ; ps2: p2 offset to convert to a signed value
+    veor        q9, q9, q0                  ; qs2: q2 offset to convert to a signed value
+;;;;;;;;;;;;;
+    vorr        q14, q13, q14               ; q14: vp8_hevmask
+
+    ;vqsub.s8   q2, q7, q6                  ; ( qs0 - ps0)
+    vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
+    vsubl.s8    q13, d15, d13
+
+    vqsub.s8    q1, q5, q8                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
+
+    ;vadd.s8    q10, q2, q2                 ; 3 * ( qs0 - ps0)
+    vadd.s16    q10, q2, q2                 ; 3 * ( qs0 - ps0)
+    vadd.s16    q11, q13, q13
+
+    vand        q3, q3, q12
+
+    ;vadd.s8    q2, q2, q10
+    vadd.s16    q2, q2, q10
+    vadd.s16    q13, q13, q11
+
+    vld1.u8     {q12}, [r12]!               ;#3
+
+    ;vqadd.s8   q1, q1, q2                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q2, q2, d2                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q13, q13, d3
+
+    vand        q15, q15, q3                ; q15: vp8_filter_mask
+    vld1.u8     {q11}, [r12]!               ;#4
+
+    vqmovn.s16  d2, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d3, q13
+
+;;;;;;;;;;;;;;
+    vand        q1, q1, q15                 ; vp8_filter &= mask
+
+    vld1.u8     {q15}, [r12]!               ;#63
+    ;
+    vand        q13, q1, q14                ; Filter2: q13; Filter2 &= hev
+
+    vld1.u8     {d7}, [r12]!                ;#9
+    ;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Change for VP8 from VP7
+;   vand        q2, q13, q12                ; s = Filter2 & 7
+
+;   vqadd.s8    q13, q13, q11               ; Filter2 = vp8_signed_char_clamp(Filter2+4)
+;   vld1.u8     {d6}, [r12]!                ;#18
+
+;   sub         r0, r0, r1, lsl #3
+;   sub         r3, r3, r1, lsl #3
+
+;   vshr.s8     q13, q13, #3                ; Filter2 >>= 3
+;   vceq.i8     q2, q2, q11                 ; s = (s==4)*-1
+
+;   add         r0, r0, r1
+;   add         r3, r3, r1
+
+;   vqsub.s8    q7, q7, q13                 ; qs0 = vp8_signed_char_clamp(qs0 - Filter2)
+;   vqadd.s8    q11, q2, q13                ; u = vp8_signed_char_clamp(s + Filter2)
+
+;   vld1.u8     {d5}, [r12]!                ;#27
+;   vmov        q10, q15
+;   vmov        q12, q15
+
+;   vqadd.s8    q6, q6, q11                 ; ps0 = vp8_signed_char_clamp(ps0 + u)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    vqadd.s8    q2, q13, q11                ; Filter1 = vp8_signed_char_clamp(Filter2+4)
+    vqadd.s8    q13, q13, q12               ; Filter2 = vp8_signed_char_clamp(Filter2+3)
+
+    vld1.u8     {d6}, [r12]!                ;#18
+
+    sub         r0, r0, r1, lsl #3
+    sub         r3, r3, r1, lsl #3
+
+    vshr.s8     q2, q2, #3                  ; Filter1 >>= 3
+    vshr.s8     q13, q13, #3                ; Filter2 >>= 3
+
+    vmov        q10, q15
+    vmov        q12, q15
+
+    vqsub.s8    q7, q7, q2                  ; qs0 = vp8_signed_char_clamp(qs0 - Filter1)
+
+    vld1.u8     {d5}, [r12]!                ;#27
+
+    add         r0, r0, r1
+    add         r3, r3, r1
+
+    vqadd.s8    q6, q6, q13                 ; ps0 = vp8_signed_char_clamp(ps0 + Filter2)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+    vbic        q1, q1, q14                 ; Filter2: q1; vp8_filter &= ~hev; Filter2 = vp8_filter
+
+    ; roughly 1/7th difference across boundary
+    ; roughly 2/7th difference across boundary
+    ; roughly 3/7th difference across boundary
+    vmov        q11, q15
+    vmov        q13, q15
+    vmov        q14, q15
+
+    vmlal.s8    q10, d2, d7                 ; Filter2 * 9
+    vmlal.s8    q11, d3, d7
+    vmlal.s8    q12, d2, d6                 ; Filter2 * 18
+    vmlal.s8    q13, d3, d6
+    vmlal.s8    q14, d2, d5                 ; Filter2 * 27
+    vmlal.s8    q15, d3, d5
+    vqshrn.s16  d20, q10, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7)
+    vqshrn.s16  d21, q11, #7
+    vqshrn.s16  d24, q12, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7)
+    vqshrn.s16  d25, q13, #7
+    vqshrn.s16  d28, q14, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7)
+    vqshrn.s16  d29, q15, #7
+
+    vqsub.s8    q11, q9, q10                ; s = vp8_signed_char_clamp(qs2 - u)
+    vqadd.s8    q10, q4, q10                ; s = vp8_signed_char_clamp(ps2 + u)
+    vqsub.s8    q13, q8, q12                ; s = vp8_signed_char_clamp(qs1 - u)
+    vqadd.s8    q12, q5, q12                ; s = vp8_signed_char_clamp(ps1 + u)
+    vqsub.s8    q15, q7, q14                ; s = vp8_signed_char_clamp(qs0 - u)
+    vqadd.s8    q14, q6, q14                ; s = vp8_signed_char_clamp(ps0 + u)
+    veor        q9, q11, q0                 ; *oq2 = s^0x80
+    veor        q4, q10, q0                 ; *op2 = s^0x80
+    veor        q8, q13, q0                 ; *oq1 = s^0x80
+    veor        q5, q12, q0                 ; *op2 = s^0x80
+    veor        q7, q15, q0                 ; *oq0 = s^0x80
+    veor        q6, q14, q0                 ; *op0 = s^0x80
+
+    vst1.u8     {d8}, [r0], r1              ; store u op2
+    vst1.u8     {d9}, [r3], r1              ; store v op2
+    vst1.u8     {d10}, [r0], r1             ; store u op1
+    vst1.u8     {d11}, [r3], r1             ; store v op1
+    vst1.u8     {d12}, [r0], r1             ; store u op0
+    vst1.u8     {d13}, [r3], r1             ; store v op0
+    vst1.u8     {d14}, [r0], r1             ; store u oq0
+    vst1.u8     {d15}, [r3], r1             ; store v oq0
+    vst1.u8     {d16}, [r0], r1             ; store u oq1
+    vst1.u8     {d17}, [r3], r1             ; store v oq1
+    vst1.u8     {d18}, [r0], r1             ; store u oq2
+    vst1.u8     {d19}, [r3], r1             ; store v oq2
+
+    bx          lr
+    ENDP        ; |vp8_mbloop_filter_horizontal_edge_uv_neon|
+
+;-----------------
+    AREA    mbhloopfilteruv_dat, DATA, READWRITE            ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_mbhlfuv_coeff_
+    DCD     mbhlfuv_coeff
+mbhlfuv_coeff
+    DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
+    DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
+    DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
+    DCD     0x003f003f, 0x003f003f, 0x003f003f, 0x003f003f
+    DCD     0x09090909, 0x09090909, 0x12121212, 0x12121212
+    DCD     0x1b1b1b1b, 0x1b1b1b1b
+
+    END
diff --git a/vp8/common/arm/neon/mbloopfilterhorizontaledge_y_neon.asm b/vp8/common/arm/neon/mbloopfilterhorizontaledge_y_neon.asm
new file mode 100644
index 0000000..2ab0fc2
--- /dev/null
+++ b/vp8/common/arm/neon/mbloopfilterhorizontaledge_y_neon.asm
@@ -0,0 +1,236 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_mbloop_filter_horizontal_edge_y_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;Note: flimit, limit, and thresh shpuld be positive numbers. All 16 elements in flimit
+;are equal. So, in the code, only one load is needed
+;for flimit. Same way applies to limit and thresh.
+; r0    unsigned char *s,
+; r1    int p, //pitch
+; r2    const signed char *flimit,
+; r3    const signed char *limit,
+; stack(r4) const signed char *thresh,
+; //stack(r5)   int count --unused
+|vp8_mbloop_filter_horizontal_edge_y_neon| PROC
+    sub         r0, r0, r1, lsl #2          ; move src pointer down by 4 lines
+    ldr         r12, [sp, #0]               ; load thresh pointer
+
+    vld1.u8     {q3}, [r0], r1              ; p3
+    vld1.s8     {d2[], d3[]}, [r3]          ; limit
+    vld1.u8     {q4}, [r0], r1              ; p2
+    vld1.s8     {d4[], d5[]}, [r12]         ; thresh
+    vld1.u8     {q5}, [r0], r1              ; p1
+    ldr         r12, _mbhlfy_coeff_
+    vld1.u8     {q6}, [r0], r1              ; p0
+
+    ;vp8_filter_mask() function
+    ;vp8_hevmask() function
+    vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
+    vld1.u8     {q7}, [r0], r1              ; q0
+    vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
+    vld1.u8     {q8}, [r0], r1              ; q1
+    vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
+    vld1.u8     {q9}, [r0], r1              ; q2
+    vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
+    vld1.u8     {q10}, [r0], r1             ; q3
+    vabd.u8     q3, q9, q8                  ; abs(q2 - q1)
+    vabd.u8     q0, q10, q9                 ; abs(q3 - q2)
+
+    vcge.u8     q15, q1, q11                ; (abs(p3 - p2) > limit)*-1
+    vcge.u8     q12, q1, q12                ; (abs(p2 - p1) > limit)*-1
+    vcge.u8     q10, q1, q13                ; (abs(p1 - p0) > limit)*-1
+    vcge.u8     q11, q1, q14                ; (abs(q1 - q0) > limit)*-1
+    vcge.u8     q3, q1, q3                  ; (abs(q2 - q1) > limit)*-1
+    vcge.u8     q0, q1, q0                  ; (abs(q3 - q2) > limit)*-1
+
+    vand        q15, q15, q12
+
+    vabd.u8     q12, q6, q7                 ; abs(p0 - q0)
+
+    vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh)*-1
+    vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh)*-1
+
+    vld1.s8     {d4[], d5[]}, [r2]          ; flimit
+
+    vand        q10, q10, q11
+    vand        q3, q3, q0
+
+    vld1.u8     {q0}, [r12]!
+
+    vadd.u8     q2, q2, q2                  ; flimit * 2
+    vadd.u8     q2, q2, q1                  ; flimit * 2 + limit
+
+    vabd.u8     q1, q5, q8                  ; abs(p1 - q1)
+    vqadd.u8    q12, q12, q12               ; abs(p0 - q0) * 2
+    vshr.u8     q1, q1, #1                  ; abs(p1 - q1) / 2
+    vqadd.u8    q12, q12, q1                ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+    vcge.u8     q12, q2, q12                ; (abs(p0 - q0)*2 + abs(p1 - q1)/2 > flimit*2 + limit)*-1
+
+    vand        q15, q15, q10
+
+    ;vp8_filter() function
+    veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
+    veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
+    veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
+    veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
+    veor        q4, q4, q0                  ; ps2: p2 offset to convert to a signed value
+    veor        q9, q9, q0                  ; qs2: q2 offset to convert to a signed value
+;;;;;;;;;;;;;
+    vorr        q14, q13, q14               ; q14: vp8_hevmask
+
+    ;vqsub.s8   q2, q7, q6                  ; ( qs0 - ps0)
+    vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
+    vsubl.s8    q13, d15, d13
+
+    vqsub.s8    q1, q5, q8                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
+
+    ;vadd.s8    q10, q2, q2                 ; 3 * ( qs0 - ps0)
+    vadd.s16    q10, q2, q2                 ; 3 * ( qs0 - ps0)
+    vadd.s16    q11, q13, q13
+
+    vand        q3, q3, q12
+
+    ;vadd.s8    q2, q2, q10
+    vadd.s16    q2, q2, q10
+    vadd.s16    q13, q13, q11
+
+    vld1.u8     {q12}, [r12]!               ;#3
+
+    ;vqadd.s8   q1, q1, q2                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q2, q2, d2                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q13, q13, d3
+
+    vand        q15, q15, q3                ; q15: vp8_filter_mask
+    vld1.u8     {q11}, [r12]!               ;#4
+
+    vqmovn.s16  d2, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d3, q13
+
+;;;;;;;;;;;;;;
+    vand        q1, q1, q15                 ; vp8_filter &= mask
+
+    vld1.u8     {q15}, [r12]!               ;#63
+    ;
+    vand        q13, q1, q14                ; Filter2: q13; Filter2 &= hev
+
+    vld1.u8     {d7}, [r12]!                ;#9
+    sub         r0, r0, r1, lsl #3
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Change for VP8 from VP7
+;   vand        q2, q13, q12                ; s = Filter2 & 7
+
+;   vqadd.s8    q13, q13, q11               ; Filter2 = vp8_signed_char_clamp(Filter2+4)
+;   vld1.u8     {d6}, [r12]!                ;#18
+
+;   add         r0, r0, r1
+;   add         r2, r0, r1
+
+;   vshr.s8     q13, q13, #3                ; Filter2 >>= 3
+;   vceq.i8     q2, q2, q11                 ; s = (s==4)*-1
+
+;   add         r3, r2, r1
+
+;   vqsub.s8    q7, q7, q13                 ; qs0 = vp8_signed_char_clamp(qs0 - Filter2)
+;   vqadd.s8    q11, q2, q13                ; u = vp8_signed_char_clamp(s + Filter2)
+
+;   vld1.u8     {d5}, [r12]!                ;#27
+;   vmov        q10, q15
+;   vmov        q12, q15
+
+;   vqadd.s8    q6, q6, q11                 ; ps0 = vp8_signed_char_clamp(ps0 + u)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    vqadd.s8    q2, q13, q11                ; Filter1 = vp8_signed_char_clamp(Filter2+4)
+    vqadd.s8    q13, q13, q12               ; Filter2 = vp8_signed_char_clamp(Filter2+3)
+
+    vld1.u8     {d6}, [r12]!                ;#18
+    add         r0, r0, r1
+    add         r2, r0, r1
+
+    vshr.s8     q2, q2, #3                  ; Filter1 >>= 3
+    vshr.s8     q13, q13, #3                ; Filter2 >>= 3
+
+    vmov        q10, q15
+    vmov        q12, q15
+
+    vqsub.s8    q7, q7, q2                  ; qs0 = vp8_signed_char_clamp(qs0 - Filter1)
+
+    vld1.u8     {d5}, [r12]!                ;#27
+    add         r3, r2, r1
+
+    vqadd.s8    q6, q6, q13                 ; ps0 = vp8_signed_char_clamp(ps0 + Filter2)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+    vbic        q1, q1, q14                 ; Filter2: q1; vp8_filter &= ~hev; Filter2 = vp8_filter
+
+    ; roughly 1/7th difference across boundary
+    ; roughly 2/7th difference across boundary
+    ; roughly 3/7th difference across boundary
+    vmov        q11, q15
+    vmov        q13, q15
+    vmov        q14, q15
+
+    vmlal.s8    q10, d2, d7                 ; Filter2 * 9
+    vmlal.s8    q11, d3, d7
+    vmlal.s8    q12, d2, d6                 ; Filter2 * 18
+    vmlal.s8    q13, d3, d6
+    vmlal.s8    q14, d2, d5                 ; Filter2 * 27
+    vmlal.s8    q15, d3, d5
+    vqshrn.s16  d20, q10, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7)
+    vqshrn.s16  d21, q11, #7
+    vqshrn.s16  d24, q12, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7)
+    vqshrn.s16  d25, q13, #7
+    vqshrn.s16  d28, q14, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7)
+    vqshrn.s16  d29, q15, #7
+
+    vqsub.s8    q11, q9, q10                ; s = vp8_signed_char_clamp(qs2 - u)
+    vqadd.s8    q10, q4, q10                ; s = vp8_signed_char_clamp(ps2 + u)
+    vqsub.s8    q13, q8, q12                ; s = vp8_signed_char_clamp(qs1 - u)
+    vqadd.s8    q12, q5, q12                ; s = vp8_signed_char_clamp(ps1 + u)
+    vqsub.s8    q15, q7, q14                ; s = vp8_signed_char_clamp(qs0 - u)
+    vqadd.s8    q14, q6, q14                ; s = vp8_signed_char_clamp(ps0 + u)
+    veor        q9, q11, q0                 ; *oq2 = s^0x80
+    veor        q4, q10, q0                 ; *op2 = s^0x80
+    veor        q5, q12, q0                 ; *op2 = s^0x80
+    veor        q6, q14, q0                 ; *op0 = s^0x80
+    veor        q8, q13, q0                 ; *oq1 = s^0x80
+    veor        q7, q15, q0                 ; *oq0 = s^0x80
+
+    vst1.u8     {q4}, [r0]                  ; store op2
+    vst1.u8     {q5}, [r2]                  ; store op1
+    vst1.u8     {q6}, [r3], r1              ; store op0
+    add         r12, r3, r1
+    vst1.u8     {q7}, [r3]                  ; store oq0
+    vst1.u8     {q8}, [r12], r1             ; store oq1
+    vst1.u8     {q9}, [r12]             ; store oq2
+
+    bx          lr
+    ENDP        ; |vp8_mbloop_filter_horizontal_edge_y_neon|
+
+;-----------------
+    AREA    mbhloopfiltery_dat, DATA, READWRITE         ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_mbhlfy_coeff_
+    DCD     mbhlfy_coeff
+mbhlfy_coeff
+    DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
+    DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
+    DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
+    DCD     0x003f003f, 0x003f003f, 0x003f003f, 0x003f003f
+    DCD     0x09090909, 0x09090909, 0x12121212, 0x12121212
+    DCD     0x1b1b1b1b, 0x1b1b1b1b
+
+    END
diff --git a/vp8/common/arm/neon/mbloopfilterverticaledge_uv_neon.asm b/vp8/common/arm/neon/mbloopfilterverticaledge_uv_neon.asm
new file mode 100644
index 0000000..ad5afba
--- /dev/null
+++ b/vp8/common/arm/neon/mbloopfilterverticaledge_uv_neon.asm
@@ -0,0 +1,296 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_mbloop_filter_vertical_edge_uv_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;Note: flimit, limit, and thresh shpuld be positive numbers. All 16 elements in flimit
+;are equal. So, in the code, only one load is needed
+;for flimit. Same way applies to limit and thresh.
+; r0    unsigned char *u,
+; r1    int p, //pitch
+; r2    const signed char *flimit,
+; r3    const signed char *limit,
+; stack(r4) const signed char *thresh,
+; stack(r5) unsigned char *v
+|vp8_mbloop_filter_vertical_edge_uv_neon| PROC
+    sub         r0, r0, #4                  ; move src pointer down by 4 columns
+    vld1.s8     {d2[], d3[]}, [r3]          ; limit
+    ldr         r3, [sp, #4]                ; load v ptr
+    ldr         r12, [sp, #0]               ; load thresh pointer
+
+    sub         r3, r3, #4                  ; move v pointer down by 4 columns
+
+    vld1.u8     {d6}, [r0], r1              ;load u data
+    vld1.u8     {d7}, [r3], r1              ;load v data
+    vld1.u8     {d8}, [r0], r1
+    vld1.u8     {d9}, [r3], r1
+    vld1.u8     {d10}, [r0], r1
+    vld1.u8     {d11}, [r3], r1
+    vld1.u8     {d12}, [r0], r1
+    vld1.u8     {d13}, [r3], r1
+    vld1.u8     {d14}, [r0], r1
+    vld1.u8     {d15}, [r3], r1
+    vld1.u8     {d16}, [r0], r1
+    vld1.u8     {d17}, [r3], r1
+    vld1.u8     {d18}, [r0], r1
+    vld1.u8     {d19}, [r3], r1
+    vld1.u8     {d20}, [r0], r1
+    vld1.u8     {d21}, [r3], r1
+
+    ;transpose to 8x16 matrix
+    vtrn.32     q3, q7
+    vtrn.32     q4, q8
+    vtrn.32     q5, q9
+    vtrn.32     q6, q10
+
+    vtrn.16     q3, q5
+    vtrn.16     q4, q6
+    vtrn.16     q7, q9
+    vtrn.16     q8, q10
+
+    vtrn.8      q3, q4
+    vtrn.8      q5, q6
+    vtrn.8      q7, q8
+    vtrn.8      q9, q10
+
+    sub         sp, sp, #32
+    vld1.s8     {d4[], d5[]}, [r12]         ; thresh
+    vst1.u8     {q3}, [sp]!
+    ldr         r12, _mbvlfuv_coeff_
+    vst1.u8     {q10}, [sp]!
+
+    ;vp8_filter_mask() function
+    ;vp8_hevmask() function
+    vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
+    vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
+    vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
+    vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
+    vabd.u8     q3, q9, q8                  ; abs(q2 - q1)
+    vabd.u8     q0, q10, q9                 ; abs(q3 - q2)
+
+    vcge.u8     q15, q1, q11                ; (abs(p3 - p2) > limit)*-1
+    vcge.u8     q12, q1, q12                ; (abs(p2 - p1) > limit)*-1
+    vcge.u8     q10, q1, q13                ; (abs(p1 - p0) > limit)*-1
+    vcge.u8     q11, q1, q14                ; (abs(q1 - q0) > limit)*-1
+    vcge.u8     q3, q1, q3                  ; (abs(q2 - q1) > limit)*-1
+    vcge.u8     q0, q1, q0                  ; (abs(q3 - q2) > limit)*-1
+
+    vand        q15, q15, q12
+
+    vabd.u8     q12, q6, q7                 ; abs(p0 - q0)
+
+    vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh)*-1
+    vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh)*-1
+
+    vld1.s8     {d4[], d5[]}, [r2]          ; flimit
+
+    vand        q10, q10, q11
+    vand        q3, q3, q0
+
+    vld1.u8     {q0}, [r12]!
+
+    vadd.u8     q2, q2, q2                  ; flimit * 2
+    vadd.u8     q2, q2, q1                  ; flimit * 2 + limit
+
+    vabd.u8     q1, q5, q8                  ; abs(p1 - q1)
+    vqadd.u8    q12, q12, q12               ; abs(p0 - q0) * 2
+    vshr.u8     q1, q1, #1                  ; abs(p1 - q1) / 2
+    vqadd.u8    q12, q12, q1                ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+    vcge.u8     q12, q2, q12                ; (abs(p0 - q0)*2 + abs(p1 - q1)/2 > flimit*2 + limit)*-1
+
+    vand        q15, q15, q10
+
+    ;vp8_filter() function
+    veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
+    veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
+    veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
+    veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
+    veor        q4, q4, q0                  ; ps2: p2 offset to convert to a signed value
+    veor        q9, q9, q0                  ; qs2: q2 offset to convert to a signed value
+;;;;;;;;;;;;;
+    vorr        q14, q13, q14               ; q14: vp8_hevmask
+
+    ;vqsub.s8   q2, q7, q6                  ; ( qs0 - ps0)
+    vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
+    vsubl.s8    q13, d15, d13
+
+    vqsub.s8    q1, q5, q8                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
+
+    ;vadd.s8    q10, q2, q2                 ; 3 * ( qs0 - ps0)
+    vadd.s16    q10, q2, q2                 ; 3 * ( qs0 - ps0)
+    vadd.s16    q11, q13, q13
+
+    vand        q3, q3, q12
+
+    ;vadd.s8    q2, q2, q10
+    vadd.s16    q2, q2, q10
+    vadd.s16    q13, q13, q11
+
+    vld1.u8     {q12}, [r12]!               ;#3
+
+    ;vqadd.s8   q1, q1, q2                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q2, q2, d2                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q13, q13, d3
+
+    vand        q15, q15, q3                ; q15: vp8_filter_mask
+    vld1.u8     {q11}, [r12]!               ;#4
+
+    vqmovn.s16  d2, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d3, q13
+
+;;;;;;;;;;;;;;
+    vand        q1, q1, q15                 ; vp8_filter &= mask
+
+    vld1.u8     {q15}, [r12]!               ;#63
+    ;
+    vand        q13, q1, q14                ; Filter2: q13; Filter2 &= hev
+
+    vld1.u8     {d7}, [r12]!                ;#9
+    ;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Change for VP8 from VP7
+;   vand        q2, q13, q12                ; s = Filter2 & 7
+
+;   vqadd.s8    q13, q13, q11               ; Filter2 = vp8_signed_char_clamp(Filter2+4)
+;   vld1.u8     {d6}, [r12]!                ;#18
+
+;   sub         r0, r0, r1, lsl #3
+;   sub         r3, r3, r1, lsl #3
+;   sub         sp, sp, #32
+
+;   vshr.s8     q13, q13, #3                ; Filter2 >>= 3
+;   vceq.i8     q2, q2, q11                 ; s = (s==4)*-1
+
+;   vqsub.s8    q7, q7, q13                 ; qs0 = vp8_signed_char_clamp(qs0 - Filter2)
+;   vqadd.s8    q11, q2, q13                ; u = vp8_signed_char_clamp(s + Filter2)
+
+;   vld1.u8     {d5}, [r12]!                ;#27
+;   vmov        q10, q15
+;   vmov        q12, q15
+
+;   vqadd.s8    q6, q6, q11                 ; ps0 = vp8_signed_char_clamp(ps0 + u)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    vqadd.s8    q2, q13, q11                ; Filter1 = vp8_signed_char_clamp(Filter2+4)
+    vqadd.s8    q13, q13, q12               ; Filter2 = vp8_signed_char_clamp(Filter2+3)
+
+    vld1.u8     {d6}, [r12]!                ;#18
+
+    sub         r0, r0, r1, lsl #3
+    sub         r3, r3, r1, lsl #3
+
+    vshr.s8     q2, q2, #3                  ; Filter1 >>= 3
+    vshr.s8     q13, q13, #3                ; Filter2 >>= 3
+
+    vmov        q10, q15
+    vmov        q12, q15
+
+    vqsub.s8    q7, q7, q2                  ; qs0 = vp8_signed_char_clamp(qs0 - Filter1)
+
+    vld1.u8     {d5}, [r12]!                ;#27
+
+    sub         sp, sp, #32
+
+    vqadd.s8    q6, q6, q13                 ; ps0 = vp8_signed_char_clamp(ps0 + Filter2)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+    vbic        q1, q1, q14                 ; Filter2: q1; vp8_filter &= ~hev; Filter2 = vp8_filter
+
+    ; roughly 1/7th difference across boundary
+    ; roughly 2/7th difference across boundary
+    ; roughly 3/7th difference across boundary
+    vmov        q11, q15
+    vmov        q13, q15
+    vmov        q14, q15
+
+    vmlal.s8    q10, d2, d7                 ; Filter2 * 9
+    vmlal.s8    q11, d3, d7
+    vmlal.s8    q12, d2, d6                 ; Filter2 * 18
+    vmlal.s8    q13, d3, d6
+    vmlal.s8    q14, d2, d5                 ; Filter2 * 27
+    vmlal.s8    q15, d3, d5
+    vqshrn.s16  d20, q10, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7)
+    vqshrn.s16  d21, q11, #7
+    vqshrn.s16  d24, q12, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7)
+    vqshrn.s16  d25, q13, #7
+    vqshrn.s16  d28, q14, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7)
+    vqshrn.s16  d29, q15, #7
+
+    vqsub.s8    q11, q9, q10                ; s = vp8_signed_char_clamp(qs2 - u)
+    vqadd.s8    q10, q4, q10                ; s = vp8_signed_char_clamp(ps2 + u)
+    vqsub.s8    q13, q8, q12                ; s = vp8_signed_char_clamp(qs1 - u)
+    vqadd.s8    q12, q5, q12                ; s = vp8_signed_char_clamp(ps1 + u)
+    vqsub.s8    q15, q7, q14                ; s = vp8_signed_char_clamp(qs0 - u)
+    vqadd.s8    q14, q6, q14                ; s = vp8_signed_char_clamp(ps0 + u)
+    veor        q9, q11, q0                 ; *oq2 = s^0x80
+    veor        q4, q10, q0                 ; *op2 = s^0x80
+    veor        q8, q13, q0                 ; *oq1 = s^0x80
+    veor        q5, q12, q0                 ; *op2 = s^0x80
+    veor        q7, q15, q0                 ; *oq0 = s^0x80
+    vld1.u8     {q3}, [sp]!
+    veor        q6, q14, q0                 ; *op0 = s^0x80
+    vld1.u8     {q10}, [sp]!
+
+    ;transpose to 16x8 matrix
+    vtrn.32     q3, q7
+    vtrn.32     q4, q8
+    vtrn.32     q5, q9
+    vtrn.32     q6, q10
+
+    vtrn.16     q3, q5
+    vtrn.16     q4, q6
+    vtrn.16     q7, q9
+    vtrn.16     q8, q10
+
+    vtrn.8      q3, q4
+    vtrn.8      q5, q6
+    vtrn.8      q7, q8
+    vtrn.8      q9, q10
+
+    ;store op2, op1, op0, oq0, oq1, oq2
+    vst1.8      {d6}, [r0], r1
+    vst1.8      {d7}, [r3], r1
+    vst1.8      {d8}, [r0], r1
+    vst1.8      {d9}, [r3], r1
+    vst1.8      {d10}, [r0], r1
+    vst1.8      {d11}, [r3], r1
+    vst1.8      {d12}, [r0], r1
+    vst1.8      {d13}, [r3], r1
+    vst1.8      {d14}, [r0], r1
+    vst1.8      {d15}, [r3], r1
+    vst1.8      {d16}, [r0], r1
+    vst1.8      {d17}, [r3], r1
+    vst1.8      {d18}, [r0], r1
+    vst1.8      {d19}, [r3], r1
+    vst1.8      {d20}, [r0], r1
+    vst1.8      {d21}, [r3], r1
+
+    bx          lr
+    ENDP        ; |vp8_mbloop_filter_vertical_edge_uv_neon|
+
+;-----------------
+    AREA    mbvloopfilteruv_dat, DATA, READWRITE            ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_mbvlfuv_coeff_
+    DCD     mbvlfuv_coeff
+mbvlfuv_coeff
+    DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
+    DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
+    DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
+    DCD     0x003f003f, 0x003f003f, 0x003f003f, 0x003f003f
+    DCD     0x09090909, 0x09090909, 0x12121212, 0x12121212
+    DCD     0x1b1b1b1b, 0x1b1b1b1b
+
+    END
diff --git a/vp8/common/arm/neon/mbloopfilterverticaledge_y_neon.asm b/vp8/common/arm/neon/mbloopfilterverticaledge_y_neon.asm
new file mode 100644
index 0000000..60e5175
--- /dev/null
+++ b/vp8/common/arm/neon/mbloopfilterverticaledge_y_neon.asm
@@ -0,0 +1,303 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_mbloop_filter_vertical_edge_y_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;Note: flimit, limit, and thresh shpuld be positive numbers. All 16 elements in flimit
+;are equal. So, in the code, only one load is needed
+;for flimit. Same way applies to limit and thresh.
+; r0    unsigned char *s,
+; r1    int p, //pitch
+; r2    const signed char *flimit,
+; r3    const signed char *limit,
+; stack(r4) const signed char *thresh,
+; //stack(r5)   int count --unused
+|vp8_mbloop_filter_vertical_edge_y_neon| PROC
+    sub         r0, r0, #4                  ; move src pointer down by 4 columns
+
+    vld1.u8     {d6}, [r0], r1              ; load first 8-line src data
+    ldr         r12, [sp, #0]               ; load thresh pointer
+    vld1.u8     {d8}, [r0], r1
+    sub         sp, sp, #32
+    vld1.u8     {d10}, [r0], r1
+    vld1.u8     {d12}, [r0], r1
+    vld1.u8     {d14}, [r0], r1
+    vld1.u8     {d16}, [r0], r1
+    vld1.u8     {d18}, [r0], r1
+    vld1.u8     {d20}, [r0], r1
+
+    vld1.u8     {d7}, [r0], r1              ; load second 8-line src data
+    vld1.u8     {d9}, [r0], r1
+    vld1.u8     {d11}, [r0], r1
+    vld1.u8     {d13}, [r0], r1
+    vld1.u8     {d15}, [r0], r1
+    vld1.u8     {d17}, [r0], r1
+    vld1.u8     {d19}, [r0], r1
+    vld1.u8     {d21}, [r0], r1
+
+    ;transpose to 8x16 matrix
+    vtrn.32     q3, q7
+    vtrn.32     q4, q8
+    vtrn.32     q5, q9
+    vtrn.32     q6, q10
+
+    vtrn.16     q3, q5
+    vtrn.16     q4, q6
+    vtrn.16     q7, q9
+    vtrn.16     q8, q10
+
+    vtrn.8      q3, q4
+    vtrn.8      q5, q6
+    vtrn.8      q7, q8
+    vtrn.8      q9, q10
+
+    vld1.s8     {d2[], d3[]}, [r3]          ; limit
+    vst1.u8     {q3}, [sp]!
+    vld1.s8     {d4[], d5[]}, [r12]         ; thresh
+    ldr         r12, _mbvlfy_coeff_
+    vst1.u8     {q10}, [sp]!
+
+    ;vp8_filter_mask() function
+    ;vp8_hevmask() function
+    vabd.u8     q11, q3, q4                 ; abs(p3 - p2)
+    vabd.u8     q12, q4, q5                 ; abs(p2 - p1)
+    vabd.u8     q13, q5, q6                 ; abs(p1 - p0)
+    vabd.u8     q14, q8, q7                 ; abs(q1 - q0)
+    vabd.u8     q3, q9, q8                  ; abs(q2 - q1)
+    vabd.u8     q0, q10, q9                 ; abs(q3 - q2)
+
+    vcge.u8     q15, q1, q11                ; (abs(p3 - p2) > limit)*-1
+    vcge.u8     q12, q1, q12                ; (abs(p2 - p1) > limit)*-1
+    vcge.u8     q10, q1, q13                ; (abs(p1 - p0) > limit)*-1
+    vcge.u8     q11, q1, q14                ; (abs(q1 - q0) > limit)*-1
+    vcge.u8     q3, q1, q3                  ; (abs(q2 - q1) > limit)*-1
+    vcge.u8     q0, q1, q0                  ; (abs(q3 - q2) > limit)*-1
+
+    vand        q15, q15, q12
+
+    vabd.u8     q12, q6, q7                 ; abs(p0 - q0)
+
+    vcgt.u8     q13, q13, q2                ; (abs(p1 - p0) > thresh)*-1
+    vcgt.u8     q14, q14, q2                ; (abs(q1 - q0) > thresh)*-1
+
+    vld1.s8     {d4[], d5[]}, [r2]          ; flimit
+
+    vand        q10, q10, q11
+    vand        q3, q3, q0
+
+    vld1.u8     {q0}, [r12]!
+
+    vadd.u8     q2, q2, q2                  ; flimit * 2
+    vadd.u8     q2, q2, q1                  ; flimit * 2 + limit
+
+    vabd.u8     q1, q5, q8                  ; abs(p1 - q1)
+    vqadd.u8    q12, q12, q12               ; abs(p0 - q0) * 2
+    vshr.u8     q1, q1, #1                  ; abs(p1 - q1) / 2
+    vqadd.u8    q12, q12, q1                ; abs(p0 - q0) * 2 + abs(p1 - q1) / 2
+    vcge.u8     q12, q2, q12                ; (abs(p0 - q0)*2 + abs(p1 - q1)/2 > flimit*2 + limit)*-1
+
+    vand        q15, q15, q10
+
+    ;vp8_filter() function
+    veor        q7, q7, q0                  ; qs0: q0 offset to convert to a signed value
+    veor        q6, q6, q0                  ; ps0: p0 offset to convert to a signed value
+    veor        q5, q5, q0                  ; ps1: p1 offset to convert to a signed value
+    veor        q8, q8, q0                  ; qs1: q1 offset to convert to a signed value
+    veor        q4, q4, q0                  ; ps2: p2 offset to convert to a signed value
+    veor        q9, q9, q0                  ; qs2: q2 offset to convert to a signed value
+;;;;;;;;;;;;;
+    vorr        q14, q13, q14               ; q14: vp8_hevmask
+
+    ;vqsub.s8   q2, q7, q6                  ; ( qs0 - ps0)
+    vsubl.s8    q2, d14, d12                ; ( qs0 - ps0)
+    vsubl.s8    q13, d15, d13
+
+    vqsub.s8    q1, q5, q8                  ; vp8_filter = vp8_signed_char_clamp(ps1-qs1)
+
+    ;vadd.s8    q10, q2, q2                 ; 3 * ( qs0 - ps0)
+    vadd.s16    q10, q2, q2                 ; 3 * ( qs0 - ps0)
+    vadd.s16    q11, q13, q13
+
+    vand        q3, q3, q12
+
+    ;vadd.s8    q2, q2, q10
+    vadd.s16    q2, q2, q10
+    vadd.s16    q13, q13, q11
+
+    vld1.u8     {q12}, [r12]!               ;#3
+
+    ;vqadd.s8   q1, q1, q2                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q2, q2, d2                  ; vp8_filter + 3 * ( qs0 - ps0)
+    vaddw.s8    q13, q13, d3
+
+    vand        q15, q15, q3                ; q15: vp8_filter_mask
+    vld1.u8     {q11}, [r12]!               ;#4
+
+    vqmovn.s16  d2, q2                      ; vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0))
+    vqmovn.s16  d3, q13
+
+;;;;;;;;;;;;;;
+    vand        q1, q1, q15                 ; vp8_filter &= mask
+
+    vld1.u8     {q15}, [r12]!               ;#63
+    ;
+    vand        q13, q1, q14                ; Filter2: q13; Filter2 &= hev
+
+    vld1.u8     {d7}, [r12]!                ;#9
+    ;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Change for VP8 from VP7
+;   vand        q2, q13, q12                ; s = Filter2 & 7
+
+;   vqadd.s8    q13, q13, q11               ; Filter2 = vp8_signed_char_clamp(Filter2+4)
+;   vld1.u8     {d6}, [r12]!                ;#18
+
+;   sub         r0, r0, r1, lsl #4
+;   sub         sp, sp, #32
+;   add         r2, r0, r1
+
+;   vshr.s8     q13, q13, #3                ; Filter2 >>= 3
+;   vceq.i8     q2, q2, q11                 ; s = (s==4)*-1
+
+;   add         r3, r2, r1
+
+;   vqsub.s8    q7, q7, q13                 ; qs0 = vp8_signed_char_clamp(qs0 - Filter2)
+;   vqadd.s8    q11, q2, q13                ; u = vp8_signed_char_clamp(s + Filter2)
+
+;   vld1.u8     {d5}, [r12]!                ;#27
+;   vmov        q10, q15
+;   vmov        q12, q15
+
+;   vqadd.s8    q6, q6, q11                 ; ps0 = vp8_signed_char_clamp(ps0 + u)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+    vqadd.s8    q2, q13, q11                ; Filter1 = vp8_signed_char_clamp(Filter2+4)
+    vqadd.s8    q13, q13, q12               ; Filter2 = vp8_signed_char_clamp(Filter2+3)
+
+    vld1.u8     {d6}, [r12]!                ;#18
+    sub         r0, r0, r1, lsl #4
+    sub         sp, sp, #32
+
+    add         r2, r0, r1
+
+    vshr.s8     q2, q2, #3                  ; Filter1 >>= 3
+    vshr.s8     q13, q13, #3                ; Filter2 >>= 3
+
+    vmov        q10, q15
+    vmov        q12, q15
+
+    vqsub.s8    q7, q7, q2                  ; qs0 = vp8_signed_char_clamp(qs0 - Filter1)
+
+    vld1.u8     {d5}, [r12]!                ;#27
+    add         r3, r2, r1
+
+    vqadd.s8    q6, q6, q13                 ; ps0 = vp8_signed_char_clamp(ps0 + Filter2)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+    vbic        q1, q1, q14                 ; Filter2: q1; vp8_filter &= ~hev; Filter2 = vp8_filter
+
+    ; roughly 1/7th difference across boundary
+    ; roughly 2/7th difference across boundary
+    ; roughly 3/7th difference across boundary
+    vmov        q11, q15
+    vmov        q13, q15
+    vmov        q14, q15
+
+    vmlal.s8    q10, d2, d7                 ; Filter2 * 9
+    vmlal.s8    q11, d3, d7
+    vmlal.s8    q12, d2, d6                 ; Filter2 * 18
+    vmlal.s8    q13, d3, d6
+    vmlal.s8    q14, d2, d5                 ; Filter2 * 27
+    vmlal.s8    q15, d3, d5
+    vqshrn.s16  d20, q10, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7)
+    vqshrn.s16  d21, q11, #7
+    vqshrn.s16  d24, q12, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7)
+    vqshrn.s16  d25, q13, #7
+    vqshrn.s16  d28, q14, #7                ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7)
+    vqshrn.s16  d29, q15, #7
+
+    vqsub.s8    q11, q9, q10                ; s = vp8_signed_char_clamp(qs2 - u)
+    vqadd.s8    q10, q4, q10                ; s = vp8_signed_char_clamp(ps2 + u)
+    vqsub.s8    q13, q8, q12                ; s = vp8_signed_char_clamp(qs1 - u)
+    vqadd.s8    q12, q5, q12                ; s = vp8_signed_char_clamp(ps1 + u)
+    vqsub.s8    q15, q7, q14                ; s = vp8_signed_char_clamp(qs0 - u)
+    vqadd.s8    q14, q6, q14                ; s = vp8_signed_char_clamp(ps0 + u)
+    veor        q9, q11, q0                 ; *oq2 = s^0x80
+    veor        q4, q10, q0                 ; *op2 = s^0x80
+    veor        q8, q13, q0                 ; *oq1 = s^0x80
+    veor        q5, q12, q0                 ; *op2 = s^0x80
+    veor        q7, q15, q0                 ; *oq0 = s^0x80
+    vld1.u8     {q3}, [sp]!
+    veor        q6, q14, q0                 ; *op0 = s^0x80
+    vld1.u8     {q10}, [sp]!
+
+    ;transpose to 16x8 matrix
+    vtrn.32     q3, q7
+    vtrn.32     q4, q8
+    vtrn.32     q5, q9
+    vtrn.32     q6, q10
+    add         r12, r3, r1
+
+    vtrn.16     q3, q5
+    vtrn.16     q4, q6
+    vtrn.16     q7, q9
+    vtrn.16     q8, q10
+
+    vtrn.8      q3, q4
+    vtrn.8      q5, q6
+    vtrn.8      q7, q8
+    vtrn.8      q9, q10
+
+    ;store op2, op1, op0, oq0, oq1, oq2
+    vst1.8      {d6}, [r0]
+    vst1.8      {d8}, [r2]
+    vst1.8      {d10}, [r3]
+    vst1.8      {d12}, [r12], r1
+    add         r0, r12, r1
+    vst1.8      {d14}, [r12]
+    vst1.8      {d16}, [r0], r1
+    add         r2, r0, r1
+    vst1.8      {d18}, [r0]
+    vst1.8      {d20}, [r2], r1
+    add         r3, r2, r1
+    vst1.8      {d7}, [r2]
+    vst1.8      {d9}, [r3], r1
+    add         r12, r3, r1
+    vst1.8      {d11}, [r3]
+    vst1.8      {d13}, [r12], r1
+    add         r0, r12, r1
+    vst1.8      {d15}, [r12]
+    vst1.8      {d17}, [r0], r1
+    add         r2, r0, r1
+    vst1.8      {d19}, [r0]
+    vst1.8      {d21}, [r2]
+
+    bx          lr
+    ENDP        ; |vp8_mbloop_filter_vertical_edge_y_neon|
+
+;-----------------
+    AREA    mbvloopfiltery_dat, DATA, READWRITE         ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 16 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_mbvlfy_coeff_
+    DCD     mbvlfy_coeff
+mbvlfy_coeff
+    DCD     0x80808080, 0x80808080, 0x80808080, 0x80808080
+    DCD     0x03030303, 0x03030303, 0x03030303, 0x03030303
+    DCD     0x04040404, 0x04040404, 0x04040404, 0x04040404
+    DCD     0x003f003f, 0x003f003f, 0x003f003f, 0x003f003f
+    DCD     0x09090909, 0x09090909, 0x12121212, 0x12121212
+    DCD     0x1b1b1b1b, 0x1b1b1b1b
+
+    END
diff --git a/vp8/common/arm/neon/recon16x16mb_neon.asm b/vp8/common/arm/neon/recon16x16mb_neon.asm
new file mode 100644
index 0000000..b9ba1cb
--- /dev/null
+++ b/vp8/common/arm/neon/recon16x16mb_neon.asm
@@ -0,0 +1,130 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_recon16x16mb_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char  *pred_ptr,
+; r1    short *diff_ptr,
+; r2    unsigned char *dst_ptr,
+; r3    int ystride,
+; stack unsigned char *udst_ptr,
+; stack unsigned char *vdst_ptr
+
+|vp8_recon16x16mb_neon| PROC
+    mov             r12, #4             ;loop counter for Y loop
+
+recon16x16mb_loop_y
+    vld1.u8         {q12, q13}, [r0]!   ;load data from pred_ptr
+    vld1.16         {q8, q9}, [r1]!     ;load data from diff_ptr
+    vld1.u8         {q14, q15}, [r0]!
+    vld1.16         {q10, q11}, [r1]!
+
+    vmovl.u8        q0, d24             ;modify Pred data from 8 bits to 16 bits
+    vmovl.u8        q1, d25
+    vmovl.u8        q2, d26
+    vmovl.u8        q3, d27
+    vmovl.u8        q4, d28
+    vmovl.u8        q5, d29
+    vmovl.u8        q6, d30
+    vld1.16         {q12, q13}, [r1]!
+    vmovl.u8        q7, d31
+    vld1.16         {q14, q15}, [r1]!
+
+    pld             [r0]
+    pld             [r1]
+    pld             [r1, #64]
+
+    vadd.s16        q0, q0, q8          ;add Diff data and Pred data together
+    vadd.s16        q1, q1, q9
+    vadd.s16        q2, q2, q10
+    vadd.s16        q3, q3, q11
+    vadd.s16        q4, q4, q12
+    vadd.s16        q5, q5, q13
+    vadd.s16        q6, q6, q14
+    vadd.s16        q7, q7, q15
+
+    vqmovun.s16     d0, q0              ;CLAMP() saturation
+    vqmovun.s16     d1, q1
+    vqmovun.s16     d2, q2
+    vqmovun.s16     d3, q3
+    vqmovun.s16     d4, q4
+    vqmovun.s16     d5, q5
+    vst1.u8         {q0}, [r2], r3      ;store result
+    vqmovun.s16     d6, q6
+    vst1.u8         {q1}, [r2], r3
+    vqmovun.s16     d7, q7
+    vst1.u8         {q2}, [r2], r3
+    subs            r12, r12, #1
+
+    moveq           r12, #2             ;loop counter for UV loop
+
+    vst1.u8         {q3}, [r2], r3
+    bne             recon16x16mb_loop_y
+
+    mov             r3, r3, lsr #1      ;uv_stride = ystride>>1
+    ldr             r2, [sp]            ;load upred_ptr
+
+recon16x16mb_loop_uv
+    vld1.u8         {q12, q13}, [r0]!   ;load data from pred_ptr
+    vld1.16         {q8, q9}, [r1]!     ;load data from diff_ptr
+    vld1.u8         {q14, q15}, [r0]!
+    vld1.16         {q10, q11}, [r1]!
+
+    vmovl.u8        q0, d24             ;modify Pred data from 8 bits to 16 bits
+    vmovl.u8        q1, d25
+    vmovl.u8        q2, d26
+    vmovl.u8        q3, d27
+    vmovl.u8        q4, d28
+    vmovl.u8        q5, d29
+    vmovl.u8        q6, d30
+    vld1.16         {q12, q13}, [r1]!
+    vmovl.u8        q7, d31
+    vld1.16         {q14, q15}, [r1]!
+
+    vadd.s16        q0, q0, q8          ;add Diff data and Pred data together
+    vadd.s16        q1, q1, q9
+    vadd.s16        q2, q2, q10
+    vadd.s16        q3, q3, q11
+    vadd.s16        q4, q4, q12
+    vadd.s16        q5, q5, q13
+    vadd.s16        q6, q6, q14
+
+    vqmovun.s16     d0, q0              ;CLAMP() saturation
+    vadd.s16        q7, q7, q15
+    vqmovun.s16     d1, q1
+    vqmovun.s16     d2, q2
+    vqmovun.s16     d3, q3
+    vst1.u8         {d0}, [r2], r3      ;store result
+    vqmovun.s16     d4, q4
+    vst1.u8         {d1}, [r2], r3
+    vqmovun.s16     d5, q5
+    vst1.u8         {d2}, [r2], r3
+    vqmovun.s16     d6, q6
+    vst1.u8         {d3}, [r2], r3
+    vqmovun.s16     d7, q7
+    vst1.u8         {d4}, [r2], r3
+    subs            r12, r12, #1
+
+    vst1.u8         {d5}, [r2], r3
+    vst1.u8         {d6}, [r2], r3
+    vst1.u8         {d7}, [r2], r3
+
+    ldrne           r2, [sp, #4]        ;load vpred_ptr
+    bne             recon16x16mb_loop_uv
+
+    bx             lr
+
+    ENDP
+    END
diff --git a/vp8/common/arm/neon/recon2b_neon.asm b/vp8/common/arm/neon/recon2b_neon.asm
new file mode 100644
index 0000000..25aaf8c
--- /dev/null
+++ b/vp8/common/arm/neon/recon2b_neon.asm
@@ -0,0 +1,53 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_recon2b_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char  *pred_ptr,
+; r1    short *diff_ptr,
+; r2    unsigned char *dst_ptr,
+; r3    int stride
+
+|vp8_recon2b_neon| PROC
+    vld1.u8         {q8, q9}, [r0]      ;load data from pred_ptr
+    vld1.16         {q4, q5}, [r1]!     ;load data from diff_ptr
+
+    vmovl.u8        q0, d16             ;modify Pred data from 8 bits to 16 bits
+    vld1.16         {q6, q7}, [r1]!
+    vmovl.u8        q1, d17
+    vmovl.u8        q2, d18
+    vmovl.u8        q3, d19
+
+    vadd.s16        q0, q0, q4          ;add Diff data and Pred data together
+    vadd.s16        q1, q1, q5
+    vadd.s16        q2, q2, q6
+    vadd.s16        q3, q3, q7
+
+    vqmovun.s16     d0, q0              ;CLAMP() saturation
+    vqmovun.s16     d1, q1
+    vqmovun.s16     d2, q2
+    vqmovun.s16     d3, q3
+    add             r0, r2, r3
+
+    vst1.u8         {d0}, [r2]          ;store result
+    vst1.u8         {d1}, [r0], r3
+    add             r2, r0, r3
+    vst1.u8         {d2}, [r0]
+    vst1.u8         {d3}, [r2], r3
+
+    bx             lr
+
+    ENDP
+    END
diff --git a/vp8/common/arm/neon/recon4b_neon.asm b/vp8/common/arm/neon/recon4b_neon.asm
new file mode 100644
index 0000000..a4f5b80
--- /dev/null
+++ b/vp8/common/arm/neon/recon4b_neon.asm
@@ -0,0 +1,68 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_recon4b_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char  *pred_ptr,
+; r1    short *diff_ptr,
+; r2    unsigned char *dst_ptr,
+; r3    int stride
+
+|vp8_recon4b_neon| PROC
+    vld1.u8         {q12, q13}, [r0]!   ;load data from pred_ptr
+    vld1.16         {q8, q9}, [r1]!     ;load data from diff_ptr
+    vld1.u8         {q14, q15}, [r0]
+    vld1.16         {q10, q11}, [r1]!
+
+    vmovl.u8        q0, d24             ;modify Pred data from 8 bits to 16 bits
+    vmovl.u8        q1, d25
+    vmovl.u8        q2, d26
+    vmovl.u8        q3, d27
+    vmovl.u8        q4, d28
+    vmovl.u8        q5, d29
+    vmovl.u8        q6, d30
+    vld1.16         {q12, q13}, [r1]!
+    vmovl.u8        q7, d31
+    vld1.16         {q14, q15}, [r1]
+
+    vadd.s16        q0, q0, q8          ;add Diff data and Pred data together
+    vadd.s16        q1, q1, q9
+    vadd.s16        q2, q2, q10
+    vadd.s16        q3, q3, q11
+    vadd.s16        q4, q4, q12
+    vadd.s16        q5, q5, q13
+    vadd.s16        q6, q6, q14
+    vadd.s16        q7, q7, q15
+
+    vqmovun.s16     d0, q0              ;CLAMP() saturation
+    vqmovun.s16     d1, q1
+    vqmovun.s16     d2, q2
+    vqmovun.s16     d3, q3
+    vqmovun.s16     d4, q4
+    vqmovun.s16     d5, q5
+    vqmovun.s16     d6, q6
+    vqmovun.s16     d7, q7
+    add             r0, r2, r3
+
+    vst1.u8         {q0}, [r2]          ;store result
+    vst1.u8         {q1}, [r0], r3
+    add             r2, r0, r3
+    vst1.u8         {q2}, [r0]
+    vst1.u8         {q3}, [r2], r3
+
+    bx             lr
+
+    ENDP
+    END
diff --git a/vp8/common/arm/neon/reconb_neon.asm b/vp8/common/arm/neon/reconb_neon.asm
new file mode 100644
index 0000000..16d85a0
--- /dev/null
+++ b/vp8/common/arm/neon/reconb_neon.asm
@@ -0,0 +1,60 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_recon_b_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char  *pred_ptr,
+; r1    short *diff_ptr,
+; r2    unsigned char *dst_ptr,
+; r3    int stride
+
+|vp8_recon_b_neon| PROC
+    mov             r12, #16
+
+    vld1.u8         {d28}, [r0], r12    ;load 4 data/line from pred_ptr
+    vld1.16         {q10, q11}, [r1]!   ;load data from diff_ptr
+    vld1.u8         {d29}, [r0], r12
+    vld1.16         {q11, q12}, [r1]!
+    vld1.u8         {d30}, [r0], r12
+    vld1.16         {q12, q13}, [r1]!
+    vld1.u8         {d31}, [r0], r12
+    vld1.16         {q13}, [r1]
+
+    vmovl.u8        q0, d28             ;modify Pred data from 8 bits to 16 bits
+    vmovl.u8        q1, d29             ;Pred data in d0, d2, d4, d6
+    vmovl.u8        q2, d30
+    vmovl.u8        q3, d31
+
+    vadd.s16        d0, d0, d20         ;add Diff data and Pred data together
+    vadd.s16        d2, d2, d22
+    vadd.s16        d4, d4, d24
+    vadd.s16        d6, d6, d26
+
+    vqmovun.s16     d0, q0              ;CLAMP() saturation
+    vqmovun.s16     d1, q1
+    vqmovun.s16     d2, q2
+    vqmovun.s16     d3, q3
+    add             r1, r2, r3
+
+    vst1.32         {d0[0]}, [r2]       ;store result
+    vst1.32         {d1[0]}, [r1], r3
+    add             r2, r1, r3
+    vst1.32         {d2[0]}, [r1]
+    vst1.32         {d3[0]}, [r2], r3
+
+    bx             lr
+
+    ENDP
+    END
diff --git a/vp8/common/arm/neon/save_neon_reg.asm b/vp8/common/arm/neon/save_neon_reg.asm
new file mode 100644
index 0000000..4873e44
--- /dev/null
+++ b/vp8/common/arm/neon/save_neon_reg.asm
@@ -0,0 +1,35 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_push_neon|
+    EXPORT  |vp8_pop_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+|vp8_push_neon| PROC
+    vst1.i64            {d8, d9, d10, d11}, [r0]!
+    vst1.i64            {d12, d13, d14, d15}, [r0]!
+    bx              lr
+
+    ENDP
+
+|vp8_pop_neon| PROC
+    vld1.i64            {d8, d9, d10, d11}, [r0]!
+    vld1.i64            {d12, d13, d14, d15}, [r0]!
+    bx              lr
+
+    ENDP
+
+    END
+
diff --git a/vp8/common/arm/neon/shortidct4x4llm_1_neon.asm b/vp8/common/arm/neon/shortidct4x4llm_1_neon.asm
new file mode 100644
index 0000000..7d06ff9
--- /dev/null
+++ b/vp8/common/arm/neon/shortidct4x4llm_1_neon.asm
@@ -0,0 +1,66 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_short_idct4x4llm_1_neon|
+    EXPORT  |vp8_dc_only_idct_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;void vp8_short_idct4x4llm_1_c(short *input, short *output, int pitch);
+; r0    short *input;
+; r1    short *output;
+; r2    int pitch;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+|vp8_short_idct4x4llm_1_neon| PROC
+    vld1.16         {d0[]}, [r0]            ;load input[0]
+
+    add             r3, r1, r2
+    add             r12, r3, r2
+
+    vrshr.s16       d0, d0, #3
+
+    add             r0, r12, r2
+
+    vst1.16         {d0}, [r1]
+    vst1.16         {d0}, [r3]
+    vst1.16         {d0}, [r12]
+    vst1.16         {d0}, [r0]
+
+    bx             lr
+    ENDP
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;void vp8_dc_only_idct_c(short input_dc, short *output, int pitch);
+; r0    short input_dc;
+; r1    short *output;
+; r2    int pitch;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+|vp8_dc_only_idct_neon| PROC
+    vdup.16         d0, r0
+
+    add             r3, r1, r2
+    add             r12, r3, r2
+
+    vrshr.s16       d0, d0, #3
+
+    add             r0, r12, r2
+
+    vst1.16         {d0}, [r1]
+    vst1.16         {d0}, [r3]
+    vst1.16         {d0}, [r12]
+    vst1.16         {d0}, [r0]
+
+    bx             lr
+
+    ENDP
+    END
diff --git a/vp8/common/arm/neon/shortidct4x4llm_neon.asm b/vp8/common/arm/neon/shortidct4x4llm_neon.asm
new file mode 100644
index 0000000..ffecfbf
--- /dev/null
+++ b/vp8/common/arm/neon/shortidct4x4llm_neon.asm
@@ -0,0 +1,126 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_short_idct4x4llm_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+;*************************************************************
+;void vp8_short_idct4x4llm_c(short *input, short *output, int pitch)
+;r0 short * input
+;r1 short * output
+;r2 int pitch
+;*************************************************************
+;static const int cospi8sqrt2minus1=20091;
+;static const int sinpi8sqrt2      =35468;
+;static const int rounding = 0;
+;Optimization note: The resulted data from dequantization are signed 13-bit data that is
+;in the range of [-4096, 4095]. This allows to use "vqdmulh"(neon) instruction since
+;it won't go out of range (13+16+1=30bits<32bits). This instruction gives the high half
+;result of the multiplication that is needed in IDCT.
+
+|vp8_short_idct4x4llm_neon| PROC
+    ldr             r12, _idct_coeff_
+    vld1.16         {q1, q2}, [r0]
+    vld1.16         {d0}, [r12]
+
+    vswp            d3, d4                  ;q2(vp[4] vp[12])
+
+    vqdmulh.s16     q3, q2, d0[2]
+    vqdmulh.s16     q4, q2, d0[0]
+
+    vqadd.s16       d12, d2, d3             ;a1
+    vqsub.s16       d13, d2, d3             ;b1
+
+    vshr.s16        q3, q3, #1
+    vshr.s16        q4, q4, #1
+
+    vqadd.s16       q3, q3, q2              ;modify since sinpi8sqrt2 > 65536/2 (negtive number)
+    vqadd.s16       q4, q4, q2
+
+    ;d6 - c1:temp1
+    ;d7 - d1:temp2
+    ;d8 - d1:temp1
+    ;d9 - c1:temp2
+
+    vqsub.s16       d10, d6, d9             ;c1
+    vqadd.s16       d11, d7, d8             ;d1
+
+    vqadd.s16       d2, d12, d11
+    vqadd.s16       d3, d13, d10
+    vqsub.s16       d4, d13, d10
+    vqsub.s16       d5, d12, d11
+
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+    vswp            d3, d4
+
+    vqdmulh.s16     q3, q2, d0[2]
+    vqdmulh.s16     q4, q2, d0[0]
+
+    vqadd.s16       d12, d2, d3             ;a1
+    vqsub.s16       d13, d2, d3             ;b1
+
+    vshr.s16        q3, q3, #1
+    vshr.s16        q4, q4, #1
+
+    vqadd.s16       q3, q3, q2              ;modify since sinpi8sqrt2 > 65536/2 (negtive number)
+    vqadd.s16       q4, q4, q2
+
+    vqsub.s16       d10, d6, d9             ;c1
+    vqadd.s16       d11, d7, d8             ;d1
+
+    vqadd.s16       d2, d12, d11
+    vqadd.s16       d3, d13, d10
+    vqsub.s16       d4, d13, d10
+    vqsub.s16       d5, d12, d11
+
+    vrshr.s16       d2, d2, #3
+    vrshr.s16       d3, d3, #3
+    vrshr.s16       d4, d4, #3
+    vrshr.s16       d5, d5, #3
+
+    add             r3, r1, r2
+    add             r12, r3, r2
+    add             r0, r12, r2
+
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+    vst1.16         {d2}, [r1]
+    vst1.16         {d3}, [r3]
+    vst1.16         {d4}, [r12]
+    vst1.16         {d5}, [r0]
+
+    bx             lr
+
+    ENDP
+
+;-----------------
+    AREA    idct4x4_dat, DATA, READWRITE            ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_idct_coeff_
+    DCD     idct_coeff
+idct_coeff
+    DCD     0x4e7b4e7b, 0x8a8c8a8c
+
+;20091, 20091, 35468, 35468
+
+    END
diff --git a/vp8/common/arm/neon/sixtappredict16x16_neon.asm b/vp8/common/arm/neon/sixtappredict16x16_neon.asm
new file mode 100644
index 0000000..9f5f0d2
--- /dev/null
+++ b/vp8/common/arm/neon/sixtappredict16x16_neon.asm
@@ -0,0 +1,494 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_sixtap_predict16x16_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; r4    unsigned char *dst_ptr,
+; stack(r5) int  dst_pitch
+
+;Note: To take advantage of 8-bit mulplication instruction in NEON. First apply abs() to
+; filter coeffs to make them u8. Then, use vmlsl for negtive coeffs. After multiplication,
+; the result can be negtive. So, I treat the result as s16. But, since it is also possible
+; that the result can be a large positive number (> 2^15-1), which could be confused as a
+; negtive number. To avoid that error, apply filter coeffs in the order of 0, 1, 4 ,5 ,2,
+; which ensures that the result stays in s16 range. Finally, saturated add the result by
+; applying 3rd filter coeff. Same applys to other filter functions.
+
+|vp8_sixtap_predict16x16_neon| PROC
+    push            {r4-r5, lr}
+
+    ldr             r12, _filter16_coeff_
+    ldr             r4, [sp, #12]           ;load parameters from stack
+    ldr             r5, [sp, #16]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_filter16x16_only
+
+    add             r2, r12, r2, lsl #5     ;calculate filter location
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+
+    vld1.s32        {q14, q15}, [r2]        ;load first_pass filter
+
+    beq             firstpass_filter16x16_only
+
+    sub             sp, sp, #336            ;reserve space on stack for temporary storage
+    mov             lr, sp
+
+    vabs.s32        q12, q14
+    vabs.s32        q13, q15
+
+    mov             r2, #7                  ;loop counter
+    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
+    sub             r0, r0, r1, lsl #1
+
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vdup.8          d1, d24[4]
+    vdup.8          d2, d25[0]
+    vdup.8          d3, d25[4]
+    vdup.8          d4, d26[0]
+    vdup.8          d5, d26[4]
+
+;First Pass: output_height lines x output_width columns (21x16)
+filt_blk2d_fp16x16_loop_neon
+    vld1.u8         {d6, d7, d8}, [r0], r1      ;load src data
+    vld1.u8         {d9, d10, d11}, [r0], r1
+    vld1.u8         {d12, d13, d14}, [r0], r1
+
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q8, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q9, d7, d0
+    vmull.u8        q10, d9, d0
+    vmull.u8        q11, d10, d0
+    vmull.u8        q12, d12, d0
+    vmull.u8        q13, d13, d0
+
+    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d29, d9, d10, #1
+    vext.8          d30, d12, d13, #1
+
+    vmlsl.u8        q8, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q10, d29, d1
+    vmlsl.u8        q12, d30, d1
+
+    vext.8          d28, d7, d8, #1
+    vext.8          d29, d10, d11, #1
+    vext.8          d30, d13, d14, #1
+
+    vmlsl.u8        q9, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q11, d29, d1
+    vmlsl.u8        q13, d30, d1
+
+    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d29, d9, d10, #4
+    vext.8          d30, d12, d13, #4
+
+    vmlsl.u8        q8, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q10, d29, d4
+    vmlsl.u8        q12, d30, d4
+
+    vext.8          d28, d7, d8, #4
+    vext.8          d29, d10, d11, #4
+    vext.8          d30, d13, d14, #4
+
+    vmlsl.u8        q9, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q11, d29, d4
+    vmlsl.u8        q13, d30, d4
+
+    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d29, d9, d10, #5
+    vext.8          d30, d12, d13, #5
+
+    vmlal.u8        q8, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q10, d29, d5
+    vmlal.u8        q12, d30, d5
+
+    vext.8          d28, d7, d8, #5
+    vext.8          d29, d10, d11, #5
+    vext.8          d30, d13, d14, #5
+
+    vmlal.u8        q9, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q11, d29, d5
+    vmlal.u8        q13, d30, d5
+
+    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d29, d9, d10, #2
+    vext.8          d30, d12, d13, #2
+
+    vmlal.u8        q8, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q10, d29, d2
+    vmlal.u8        q12, d30, d2
+
+    vext.8          d28, d7, d8, #2
+    vext.8          d29, d10, d11, #2
+    vext.8          d30, d13, d14, #2
+
+    vmlal.u8        q9, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q11, d29, d2
+    vmlal.u8        q13, d30, d2
+
+    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d29, d9, d10, #3
+    vext.8          d30, d12, d13, #3
+
+    vext.8          d15, d7, d8, #3
+    vext.8          d31, d10, d11, #3
+    vext.8          d6, d13, d14, #3
+
+    vmull.u8        q4, d28, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q5, d29, d3
+    vmull.u8        q6, d30, d3
+
+    vqadd.s16       q8, q4                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q10, q5
+    vqadd.s16       q12, q6
+
+    vmull.u8        q6, d15, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q7, d31, d3
+    vmull.u8        q3, d6, d3
+
+    subs            r2, r2, #1
+
+    vqadd.s16       q9, q6
+    vqadd.s16       q11, q7
+    vqadd.s16       q13, q3
+
+    vqrshrun.s16    d6, q8, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q9, #7
+    vqrshrun.s16    d8, q10, #7
+    vqrshrun.s16    d9, q11, #7
+    vqrshrun.s16    d10, q12, #7
+    vqrshrun.s16    d11, q13, #7
+
+    vst1.u8         {d6, d7, d8}, [lr]!     ;store result
+    vst1.u8         {d9, d10, d11}, [lr]!
+
+    bne             filt_blk2d_fp16x16_loop_neon
+
+;Second pass: 16x16
+;secondpass_filter - do first 8-columns and then second 8-columns
+    add             r3, r12, r3, lsl #5
+    sub             lr, lr, #336
+
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+    mov             r3, #2                  ;loop counter
+
+    vabs.s32        q7, q5
+    vabs.s32        q8, q6
+
+    mov             r2, #16
+
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vdup.8          d1, d14[4]
+    vdup.8          d2, d15[0]
+    vdup.8          d3, d15[4]
+    vdup.8          d4, d16[0]
+    vdup.8          d5, d16[4]
+
+filt_blk2d_sp16x16_outloop_neon
+    vld1.u8         {d18}, [lr], r2         ;load src data
+    vld1.u8         {d19}, [lr], r2
+    vld1.u8         {d20}, [lr], r2
+    vld1.u8         {d21}, [lr], r2
+    mov             r12, #4                 ;loop counter
+    vld1.u8         {d22}, [lr], r2
+
+secondpass_inner_loop_neon
+    vld1.u8         {d23}, [lr], r2         ;load src data
+    vld1.u8         {d24}, [lr], r2
+    vld1.u8         {d25}, [lr], r2
+    vld1.u8         {d26}, [lr], r2
+
+    vmull.u8        q3, d18, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d19, d0
+    vmull.u8        q5, d20, d0
+    vmull.u8        q6, d21, d0
+
+    vmlsl.u8        q3, d19, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q4, d20, d1
+    vmlsl.u8        q5, d21, d1
+    vmlsl.u8        q6, d22, d1
+
+    vmlsl.u8        q3, d22, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d23, d4
+    vmlsl.u8        q5, d24, d4
+    vmlsl.u8        q6, d25, d4
+
+    vmlal.u8        q3, d20, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d21, d2
+    vmlal.u8        q5, d22, d2
+    vmlal.u8        q6, d23, d2
+
+    vmlal.u8        q3, d23, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q4, d24, d5
+    vmlal.u8        q5, d25, d5
+    vmlal.u8        q6, d26, d5
+
+    vmull.u8        q7, d21, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q8, d22, d3
+    vmull.u8        q9, d23, d3
+    vmull.u8        q10, d24, d3
+
+    subs            r12, r12, #1
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q8, #7
+    vqrshrun.s16    d8, q9, #7
+    vqrshrun.s16    d9, q10, #7
+
+    vst1.u8         {d6}, [r4], r5          ;store result
+    vmov            q9, q11
+    vst1.u8         {d7}, [r4], r5
+    vmov            q10, q12
+    vst1.u8         {d8}, [r4], r5
+    vmov            d22, d26
+    vst1.u8         {d9}, [r4], r5
+
+    bne             secondpass_inner_loop_neon
+
+    subs            r3, r3, #1
+    sub             lr, lr, #336
+    add             lr, lr, #8
+
+    sub             r4, r4, r5, lsl #4
+    add             r4, r4, #8
+
+    bne filt_blk2d_sp16x16_outloop_neon
+
+    add             sp, sp, #336
+    pop             {r4-r5,pc}
+
+;--------------------
+firstpass_filter16x16_only
+    vabs.s32        q12, q14
+    vabs.s32        q13, q15
+
+    mov             r2, #8                  ;loop counter
+    sub             r0, r0, #2              ;move srcptr back to (column-2)
+
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vdup.8          d1, d24[4]
+    vdup.8          d2, d25[0]
+    vdup.8          d3, d25[4]
+    vdup.8          d4, d26[0]
+    vdup.8          d5, d26[4]
+
+;First Pass: output_height lines x output_width columns (16x16)
+filt_blk2d_fpo16x16_loop_neon
+    vld1.u8         {d6, d7, d8}, [r0], r1      ;load src data
+    vld1.u8         {d9, d10, d11}, [r0], r1
+
+    pld             [r0]
+    pld             [r0, r1]
+
+    vmull.u8        q6, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q7, d7, d0
+    vmull.u8        q8, d9, d0
+    vmull.u8        q9, d10, d0
+
+    vext.8          d20, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d21, d9, d10, #1
+    vext.8          d22, d7, d8, #1
+    vext.8          d23, d10, d11, #1
+    vext.8          d24, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d25, d9, d10, #4
+    vext.8          d26, d7, d8, #4
+    vext.8          d27, d10, d11, #4
+    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d29, d9, d10, #5
+
+    vmlsl.u8        q6, d20, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d21, d1
+    vmlsl.u8        q7, d22, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q9, d23, d1
+    vmlsl.u8        q6, d24, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d25, d4
+    vmlsl.u8        q7, d26, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q9, d27, d4
+    vmlal.u8        q6, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q8, d29, d5
+
+    vext.8          d20, d7, d8, #5
+    vext.8          d21, d10, d11, #5
+    vext.8          d22, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d23, d9, d10, #2
+    vext.8          d24, d7, d8, #2
+    vext.8          d25, d10, d11, #2
+
+    vext.8          d26, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d27, d9, d10, #3
+    vext.8          d28, d7, d8, #3
+    vext.8          d29, d10, d11, #3
+
+    vmlal.u8        q7, d20, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q9, d21, d5
+    vmlal.u8        q6, d22, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d23, d2
+    vmlal.u8        q7, d24, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q9, d25, d2
+
+    vmull.u8        q10, d26, d3            ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q11, d27, d3
+    vmull.u8        q12, d28, d3            ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q15, d29, d3
+
+    vqadd.s16       q6, q10                 ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q11
+    vqadd.s16       q7, q12
+    vqadd.s16       q9, q15
+
+    subs            r2, r2, #1
+
+    vqrshrun.s16    d6, q6, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q7, #7
+    vqrshrun.s16    d8, q8, #7
+    vqrshrun.s16    d9, q9, #7
+
+    vst1.u8         {q3}, [r4], r5              ;store result
+    vst1.u8         {q4}, [r4], r5
+
+    bne             filt_blk2d_fpo16x16_loop_neon
+
+    pop             {r4-r5,pc}
+
+;--------------------
+secondpass_filter16x16_only
+;Second pass: 16x16
+    add             r3, r12, r3, lsl #5
+    sub             r0, r0, r1, lsl #1
+
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+    mov             r3, #2                  ;loop counter
+
+    vabs.s32        q7, q5
+    vabs.s32        q8, q6
+
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vdup.8          d1, d14[4]
+    vdup.8          d2, d15[0]
+    vdup.8          d3, d15[4]
+    vdup.8          d4, d16[0]
+    vdup.8          d5, d16[4]
+
+filt_blk2d_spo16x16_outloop_neon
+    vld1.u8         {d18}, [r0], r1         ;load src data
+    vld1.u8         {d19}, [r0], r1
+    vld1.u8         {d20}, [r0], r1
+    vld1.u8         {d21}, [r0], r1
+    mov             r12, #4                 ;loop counter
+    vld1.u8         {d22}, [r0], r1
+
+secondpass_only_inner_loop_neon
+    vld1.u8         {d23}, [r0], r1         ;load src data
+    vld1.u8         {d24}, [r0], r1
+    vld1.u8         {d25}, [r0], r1
+    vld1.u8         {d26}, [r0], r1
+
+    vmull.u8        q3, d18, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d19, d0
+    vmull.u8        q5, d20, d0
+    vmull.u8        q6, d21, d0
+
+    vmlsl.u8        q3, d19, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q4, d20, d1
+    vmlsl.u8        q5, d21, d1
+    vmlsl.u8        q6, d22, d1
+
+    vmlsl.u8        q3, d22, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d23, d4
+    vmlsl.u8        q5, d24, d4
+    vmlsl.u8        q6, d25, d4
+
+    vmlal.u8        q3, d20, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d21, d2
+    vmlal.u8        q5, d22, d2
+    vmlal.u8        q6, d23, d2
+
+    vmlal.u8        q3, d23, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q4, d24, d5
+    vmlal.u8        q5, d25, d5
+    vmlal.u8        q6, d26, d5
+
+    vmull.u8        q7, d21, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q8, d22, d3
+    vmull.u8        q9, d23, d3
+    vmull.u8        q10, d24, d3
+
+    subs            r12, r12, #1
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q8, #7
+    vqrshrun.s16    d8, q9, #7
+    vqrshrun.s16    d9, q10, #7
+
+    vst1.u8         {d6}, [r4], r5          ;store result
+    vmov            q9, q11
+    vst1.u8         {d7}, [r4], r5
+    vmov            q10, q12
+    vst1.u8         {d8}, [r4], r5
+    vmov            d22, d26
+    vst1.u8         {d9}, [r4], r5
+
+    bne             secondpass_only_inner_loop_neon
+
+    subs            r3, r3, #1
+    sub             r0, r0, r1, lsl #4
+    sub             r0, r0, r1, lsl #2
+    sub             r0, r0, r1
+    add             r0, r0, #8
+
+    sub             r4, r4, r5, lsl #4
+    add             r4, r4, #8
+
+    bne filt_blk2d_spo16x16_outloop_neon
+
+    pop             {r4-r5,pc}
+
+    ENDP
+
+;-----------------
+    AREA    subpelfilters16_dat, DATA, READWRITE            ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_filter16_coeff_
+    DCD     filter16_coeff
+filter16_coeff
+    DCD     0,  0,  128,    0,   0,  0,   0,  0
+    DCD     0, -6,  123,   12,  -1,  0,   0,  0
+    DCD     2, -11, 108,   36,  -8,  1,   0,  0
+    DCD     0, -9,   93,   50,  -6,  0,   0,  0
+    DCD     3, -16,  77,   77, -16,  3,   0,  0
+    DCD     0, -6,   50,   93,  -9,  0,   0,  0
+    DCD     1, -8,   36,  108, -11,  2,   0,  0
+    DCD     0, -1,   12,  123,  -6,   0,  0,  0
+
+    END
diff --git a/vp8/common/arm/neon/sixtappredict4x4_neon.asm b/vp8/common/arm/neon/sixtappredict4x4_neon.asm
new file mode 100644
index 0000000..c23a9db
--- /dev/null
+++ b/vp8/common/arm/neon/sixtappredict4x4_neon.asm
@@ -0,0 +1,425 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_sixtap_predict_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; stack(r4) unsigned char *dst_ptr,
+; stack(lr) int  dst_pitch
+
+|vp8_sixtap_predict_neon| PROC
+    push            {r4, lr}
+
+    ldr             r12, _filter4_coeff_
+    ldr             r4, [sp, #8]            ;load parameters from stack
+    ldr             lr, [sp, #12]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_filter4x4_only
+
+    add             r2, r12, r2, lsl #5     ;calculate filter location
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+    vld1.s32        {q14, q15}, [r2]        ;load first_pass filter
+
+    beq             firstpass_filter4x4_only
+
+    vabs.s32        q12, q14                ;get abs(filer_parameters)
+    vabs.s32        q13, q15
+
+    sub             r0, r0, #2              ;go back 2 columns of src data
+    sub             r0, r0, r1, lsl #1      ;go back 2 lines of src data
+
+;First pass: output_height lines x output_width columns (9x4)
+    vld1.u8         {q3}, [r0], r1          ;load first 4-line src data
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vld1.u8         {q4}, [r0], r1
+    vdup.8          d1, d24[4]
+    vld1.u8         {q5}, [r0], r1
+    vdup.8          d2, d25[0]
+    vld1.u8         {q6}, [r0], r1
+    vdup.8          d3, d25[4]
+    vdup.8          d4, d26[0]
+    vdup.8          d5, d26[4]
+
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vext.8          d18, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d19, d8, d9, #5
+    vext.8          d20, d10, d11, #5
+    vext.8          d21, d12, d13, #5
+
+    vswp            d7, d8                  ;discard 2nd half data after src_ptr[3] is done
+    vswp            d11, d12
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[3])
+    vzip.32         d20, d21
+    vmull.u8        q7, d18, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmull.u8        q8, d20, d5
+
+    vmov            q4, q3                  ;keep original src data in q4 q6
+    vmov            q6, q5
+
+    vzip.32         d6, d7                  ;construct src_ptr[-2], and put 2-line data together
+    vzip.32         d10, d11
+    vshr.u64        q9, q4, #8              ;construct src_ptr[-1]
+    vshr.u64        q10, q6, #8
+    vmlal.u8        q7, d6, d0              ;+(src_ptr[-2] * vp8_filter[0])
+    vmlal.u8        q8, d10, d0
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[-1])
+    vzip.32         d20, d21
+    vshr.u64        q3, q4, #32             ;construct src_ptr[2]
+    vshr.u64        q5, q6, #32
+    vmlsl.u8        q7, d18, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d20, d1
+
+    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[2])
+    vzip.32         d10, d11
+    vshr.u64        q9, q4, #16             ;construct src_ptr[0]
+    vshr.u64        q10, q6, #16
+    vmlsl.u8        q7, d6, d4              ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d10, d4
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[0])
+    vzip.32         d20, d21
+    vshr.u64        q3, q4, #24             ;construct src_ptr[1]
+    vshr.u64        q5, q6, #24
+    vmlal.u8        q7, d18, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d20, d2
+
+    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[1])
+    vzip.32         d10, d11
+    vmull.u8        q9, d6, d3              ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q10, d10, d3
+
+    vld1.u8         {q3}, [r0], r1          ;load rest 5-line src data
+    vld1.u8         {q4}, [r0], r1
+
+    vqadd.s16       q7, q9                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q10
+
+    vld1.u8         {q5}, [r0], r1
+    vld1.u8         {q6}, [r0], r1
+
+    vqrshrun.s16    d27, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d28, q8, #7
+
+    ;First Pass on rest 5-line data
+    vld1.u8         {q11}, [r0], r1
+
+    vext.8          d18, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d19, d8, d9, #5
+    vext.8          d20, d10, d11, #5
+    vext.8          d21, d12, d13, #5
+
+    vswp            d7, d8                  ;discard 2nd half data after src_ptr[3] is done
+    vswp            d11, d12
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[3])
+    vzip.32         d20, d21
+    vext.8          d31, d22, d23, #5       ;construct src_ptr[3]
+    vmull.u8        q7, d18, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmull.u8        q8, d20, d5
+    vmull.u8        q12, d31, d5            ;(src_ptr[3] * vp8_filter[5])
+
+    vmov            q4, q3                  ;keep original src data in q4 q6
+    vmov            q6, q5
+
+    vzip.32         d6, d7                  ;construct src_ptr[-2], and put 2-line data together
+    vzip.32         d10, d11
+    vshr.u64        q9, q4, #8              ;construct src_ptr[-1]
+    vshr.u64        q10, q6, #8
+
+    vmlal.u8        q7, d6, d0              ;+(src_ptr[-2] * vp8_filter[0])
+    vmlal.u8        q8, d10, d0
+    vmlal.u8        q12, d22, d0            ;(src_ptr[-2] * vp8_filter[0])
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[-1])
+    vzip.32         d20, d21
+    vshr.u64        q3, q4, #32             ;construct src_ptr[2]
+    vshr.u64        q5, q6, #32
+    vext.8          d31, d22, d23, #1       ;construct src_ptr[-1]
+
+    vmlsl.u8        q7, d18, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d20, d1
+    vmlsl.u8        q12, d31, d1            ;-(src_ptr[-1] * vp8_filter[1])
+
+    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[2])
+    vzip.32         d10, d11
+    vshr.u64        q9, q4, #16             ;construct src_ptr[0]
+    vshr.u64        q10, q6, #16
+    vext.8          d31, d22, d23, #4       ;construct src_ptr[2]
+
+    vmlsl.u8        q7, d6, d4              ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d10, d4
+    vmlsl.u8        q12, d31, d4            ;-(src_ptr[2] * vp8_filter[4])
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[0])
+    vzip.32         d20, d21
+    vshr.u64        q3, q4, #24             ;construct src_ptr[1]
+    vshr.u64        q5, q6, #24
+    vext.8          d31, d22, d23, #2       ;construct src_ptr[0]
+
+    vmlal.u8        q7, d18, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d20, d2
+    vmlal.u8        q12, d31, d2            ;(src_ptr[0] * vp8_filter[2])
+
+    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[1])
+    vzip.32         d10, d11
+    vext.8          d31, d22, d23, #3       ;construct src_ptr[1]
+    vmull.u8        q9, d6, d3              ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q10, d10, d3
+    vmull.u8        q11, d31, d3            ;(src_ptr[1] * vp8_filter[3])
+
+    add             r3, r12, r3, lsl #5
+
+    vqadd.s16       q7, q9                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q10
+    vqadd.s16       q12, q11
+
+    vext.8          d23, d27, d28, #4
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+
+    vqrshrun.s16    d29, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d30, q8, #7
+    vqrshrun.s16    d31, q12, #7
+
+;Second pass: 4x4
+    vabs.s32        q7, q5
+    vabs.s32        q8, q6
+
+    vext.8          d24, d28, d29, #4
+    vext.8          d25, d29, d30, #4
+    vext.8          d26, d30, d31, #4
+
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vdup.8          d1, d14[4]
+    vdup.8          d2, d15[0]
+    vdup.8          d3, d15[4]
+    vdup.8          d4, d16[0]
+    vdup.8          d5, d16[4]
+
+    vmull.u8        q3, d27, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d28, d0
+
+    vmull.u8        q5, d25, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmull.u8        q6, d26, d5
+
+    vmlsl.u8        q3, d29, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d30, d4
+
+    vmlsl.u8        q5, d23, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q6, d24, d1
+
+    vmlal.u8        q3, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d29, d2
+
+    vmlal.u8        q5, d24, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmlal.u8        q6, d25, d3
+
+    add             r0, r4, lr
+    add             r1, r0, lr
+    add             r2, r1, lr
+
+    vqadd.s16       q5, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q6, q4
+
+    vqrshrun.s16    d3, q5, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d4, q6, #7
+
+    vst1.32         {d3[0]}, [r4]           ;store result
+    vst1.32         {d3[1]}, [r0]
+    vst1.32         {d4[0]}, [r1]
+    vst1.32         {d4[1]}, [r2]
+
+    pop             {r4, pc}
+
+
+;---------------------
+firstpass_filter4x4_only
+    vabs.s32        q12, q14                ;get abs(filer_parameters)
+    vabs.s32        q13, q15
+
+    sub             r0, r0, #2              ;go back 2 columns of src data
+
+;First pass: output_height lines x output_width columns (4x4)
+    vld1.u8         {q3}, [r0], r1          ;load first 4-line src data
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vld1.u8         {q4}, [r0], r1
+    vdup.8          d1, d24[4]
+    vld1.u8         {q5}, [r0], r1
+    vdup.8          d2, d25[0]
+    vld1.u8         {q6}, [r0], r1
+
+    vdup.8          d3, d25[4]
+    vdup.8          d4, d26[0]
+    vdup.8          d5, d26[4]
+
+    vext.8          d18, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d19, d8, d9, #5
+    vext.8          d20, d10, d11, #5
+    vext.8          d21, d12, d13, #5
+
+    vswp            d7, d8                  ;discard 2nd half data after src_ptr[3] is done
+    vswp            d11, d12
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[3])
+    vzip.32         d20, d21
+    vmull.u8        q7, d18, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmull.u8        q8, d20, d5
+
+    vmov            q4, q3                  ;keep original src data in q4 q6
+    vmov            q6, q5
+
+    vzip.32         d6, d7                  ;construct src_ptr[-2], and put 2-line data together
+    vzip.32         d10, d11
+    vshr.u64        q9, q4, #8              ;construct src_ptr[-1]
+    vshr.u64        q10, q6, #8
+    vmlal.u8        q7, d6, d0              ;+(src_ptr[-2] * vp8_filter[0])
+    vmlal.u8        q8, d10, d0
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[-1])
+    vzip.32         d20, d21
+    vshr.u64        q3, q4, #32             ;construct src_ptr[2]
+    vshr.u64        q5, q6, #32
+    vmlsl.u8        q7, d18, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d20, d1
+
+    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[2])
+    vzip.32         d10, d11
+    vshr.u64        q9, q4, #16             ;construct src_ptr[0]
+    vshr.u64        q10, q6, #16
+    vmlsl.u8        q7, d6, d4              ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d10, d4
+
+    vzip.32         d18, d19                ;put 2-line data in 1 register (src_ptr[0])
+    vzip.32         d20, d21
+    vshr.u64        q3, q4, #24             ;construct src_ptr[1]
+    vshr.u64        q5, q6, #24
+    vmlal.u8        q7, d18, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d20, d2
+
+    vzip.32         d6, d7                  ;put 2-line data in 1 register (src_ptr[1])
+    vzip.32         d10, d11
+    vmull.u8        q9, d6, d3              ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q10, d10, d3
+
+    add             r0, r4, lr
+    add             r1, r0, lr
+    add             r2, r1, lr
+
+    vqadd.s16       q7, q9                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q10
+
+    vqrshrun.s16    d27, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d28, q8, #7
+
+    vst1.32         {d27[0]}, [r4]          ;store result
+    vst1.32         {d27[1]}, [r0]
+    vst1.32         {d28[0]}, [r1]
+    vst1.32         {d28[1]}, [r2]
+
+    pop             {r4, pc}
+
+
+;---------------------
+secondpass_filter4x4_only
+    sub             r0, r0, r1, lsl #1
+    add             r3, r12, r3, lsl #5
+
+    vld1.32         {d27[0]}, [r0], r1      ;load src data
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+    vld1.32         {d27[1]}, [r0], r1
+    vabs.s32        q7, q5
+    vld1.32         {d28[0]}, [r0], r1
+    vabs.s32        q8, q6
+    vld1.32         {d28[1]}, [r0], r1
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vld1.32         {d29[0]}, [r0], r1
+    vdup.8          d1, d14[4]
+    vld1.32         {d29[1]}, [r0], r1
+    vdup.8          d2, d15[0]
+    vld1.32         {d30[0]}, [r0], r1
+    vdup.8          d3, d15[4]
+    vld1.32         {d30[1]}, [r0], r1
+    vdup.8          d4, d16[0]
+    vld1.32         {d31[0]}, [r0], r1
+    vdup.8          d5, d16[4]
+
+    vext.8          d23, d27, d28, #4
+    vext.8          d24, d28, d29, #4
+    vext.8          d25, d29, d30, #4
+    vext.8          d26, d30, d31, #4
+
+    vmull.u8        q3, d27, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d28, d0
+
+    vmull.u8        q5, d25, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmull.u8        q6, d26, d5
+
+    vmlsl.u8        q3, d29, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d30, d4
+
+    vmlsl.u8        q5, d23, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q6, d24, d1
+
+    vmlal.u8        q3, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d29, d2
+
+    vmlal.u8        q5, d24, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmlal.u8        q6, d25, d3
+
+    add             r0, r4, lr
+    add             r1, r0, lr
+    add             r2, r1, lr
+
+    vqadd.s16       q5, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q6, q4
+
+    vqrshrun.s16    d3, q5, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d4, q6, #7
+
+    vst1.32         {d3[0]}, [r4]           ;store result
+    vst1.32         {d3[1]}, [r0]
+    vst1.32         {d4[0]}, [r1]
+    vst1.32         {d4[1]}, [r2]
+
+    pop             {r4, pc}
+
+    ENDP
+
+;-----------------
+    AREA    subpelfilters4_dat, DATA, READWRITE         ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_filter4_coeff_
+    DCD     filter4_coeff
+filter4_coeff
+    DCD     0,  0,  128,    0,   0,  0,   0,  0
+    DCD     0, -6,  123,   12,  -1,  0,   0,  0
+    DCD     2, -11, 108,   36,  -8,  1,   0,  0
+    DCD     0, -9,   93,   50,  -6,  0,   0,  0
+    DCD     3, -16,  77,   77, -16,  3,   0,  0
+    DCD     0, -6,   50,   93,  -9,  0,   0,  0
+    DCD     1, -8,   36,  108, -11,  2,   0,  0
+    DCD     0, -1,   12,  123,  -6,   0,  0,  0
+
+    END
diff --git a/vp8/common/arm/neon/sixtappredict8x4_neon.asm b/vp8/common/arm/neon/sixtappredict8x4_neon.asm
new file mode 100644
index 0000000..18e19f9
--- /dev/null
+++ b/vp8/common/arm/neon/sixtappredict8x4_neon.asm
@@ -0,0 +1,476 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_sixtap_predict8x4_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; r4    unsigned char *dst_ptr,
+; stack(r5) int  dst_pitch
+
+|vp8_sixtap_predict8x4_neon| PROC
+    push            {r4-r5, lr}
+
+    ldr             r12, _filter8_coeff_
+    ldr             r4, [sp, #12]           ;load parameters from stack
+    ldr             r5, [sp, #16]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_filter8x4_only
+
+    add             r2, r12, r2, lsl #5     ;calculate filter location
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+
+    vld1.s32        {q14, q15}, [r2]        ;load first_pass filter
+
+    beq             firstpass_filter8x4_only
+
+    sub             sp, sp, #32             ;reserve space on stack for temporary storage
+    vabs.s32        q12, q14
+    vabs.s32        q13, q15
+
+    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
+    mov             lr, sp
+    sub             r0, r0, r1, lsl #1
+
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vdup.8          d1, d24[4]
+    vdup.8          d2, d25[0]
+
+;First pass: output_height lines x output_width columns (9x8)
+    vld1.u8         {q3}, [r0], r1          ;load src data
+    vdup.8          d3, d25[4]
+    vld1.u8         {q4}, [r0], r1
+    vdup.8          d4, d26[0]
+    vld1.u8         {q5}, [r0], r1
+    vdup.8          d5, d26[4]
+    vld1.u8         {q6}, [r0], r1
+
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q8, d8, d0
+    vmull.u8        q9, d10, d0
+    vmull.u8        q10, d12, d0
+
+    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d29, d8, d9, #1
+    vext.8          d30, d10, d11, #1
+    vext.8          d31, d12, d13, #1
+
+    vmlsl.u8        q7, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d29, d1
+    vmlsl.u8        q9, d30, d1
+    vmlsl.u8        q10, d31, d1
+
+    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d29, d8, d9, #4
+    vext.8          d30, d10, d11, #4
+    vext.8          d31, d12, d13, #4
+
+    vmlsl.u8        q7, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d29, d4
+    vmlsl.u8        q9, d30, d4
+    vmlsl.u8        q10, d31, d4
+
+    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d29, d8, d9, #2
+    vext.8          d30, d10, d11, #2
+    vext.8          d31, d12, d13, #2
+
+    vmlal.u8        q7, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d29, d2
+    vmlal.u8        q9, d30, d2
+    vmlal.u8        q10, d31, d2
+
+    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d29, d8, d9, #5
+    vext.8          d30, d10, d11, #5
+    vext.8          d31, d12, d13, #5
+
+    vmlal.u8        q7, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q8, d29, d5
+    vmlal.u8        q9, d30, d5
+    vmlal.u8        q10, d31, d5
+
+    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d29, d8, d9, #3
+    vext.8          d30, d10, d11, #3
+    vext.8          d31, d12, d13, #3
+
+    vmull.u8        q3, d28, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q4, d29, d3
+    vmull.u8        q5, d30, d3
+    vmull.u8        q6, d31, d3
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vld1.u8         {q3}, [r0], r1          ;load src data
+
+    vqrshrun.s16    d22, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d23, q8, #7
+    vqrshrun.s16    d24, q9, #7
+    vqrshrun.s16    d25, q10, #7
+
+    vld1.u8         {q4}, [r0], r1
+    vst1.u8         {d22}, [lr]!            ;store result
+    vld1.u8         {q5}, [r0], r1
+    vst1.u8         {d23}, [lr]!
+    vld1.u8         {q6}, [r0], r1
+    vst1.u8         {d24}, [lr]!
+    vld1.u8         {q7}, [r0], r1
+    vst1.u8         {d25}, [lr]!
+
+    ;first_pass filtering on the rest 5-line data
+    vmull.u8        q8, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q9, d8, d0
+    vmull.u8        q10, d10, d0
+    vmull.u8        q11, d12, d0
+    vmull.u8        q12, d14, d0
+
+    vext.8          d27, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d28, d8, d9, #1
+    vext.8          d29, d10, d11, #1
+    vext.8          d30, d12, d13, #1
+    vext.8          d31, d14, d15, #1
+
+    vmlsl.u8        q8, d27, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q9, d28, d1
+    vmlsl.u8        q10, d29, d1
+    vmlsl.u8        q11, d30, d1
+    vmlsl.u8        q12, d31, d1
+
+    vext.8          d27, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d28, d8, d9, #4
+    vext.8          d29, d10, d11, #4
+    vext.8          d30, d12, d13, #4
+    vext.8          d31, d14, d15, #4
+
+    vmlsl.u8        q8, d27, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q9, d28, d4
+    vmlsl.u8        q10, d29, d4
+    vmlsl.u8        q11, d30, d4
+    vmlsl.u8        q12, d31, d4
+
+    vext.8          d27, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d28, d8, d9, #2
+    vext.8          d29, d10, d11, #2
+    vext.8          d30, d12, d13, #2
+    vext.8          d31, d14, d15, #2
+
+    vmlal.u8        q8, d27, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q9, d28, d2
+    vmlal.u8        q10, d29, d2
+    vmlal.u8        q11, d30, d2
+    vmlal.u8        q12, d31, d2
+
+    vext.8          d27, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d28, d8, d9, #5
+    vext.8          d29, d10, d11, #5
+    vext.8          d30, d12, d13, #5
+    vext.8          d31, d14, d15, #5
+
+    vmlal.u8        q8, d27, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q9, d28, d5
+    vmlal.u8        q10, d29, d5
+    vmlal.u8        q11, d30, d5
+    vmlal.u8        q12, d31, d5
+
+    vext.8          d27, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d28, d8, d9, #3
+    vext.8          d29, d10, d11, #3
+    vext.8          d30, d12, d13, #3
+    vext.8          d31, d14, d15, #3
+
+    vmull.u8        q3, d27, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q4, d28, d3
+    vmull.u8        q5, d29, d3
+    vmull.u8        q6, d30, d3
+    vmull.u8        q7, d31, d3
+
+    vqadd.s16       q8, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q9, q4
+    vqadd.s16       q10, q5
+    vqadd.s16       q11, q6
+    vqadd.s16       q12, q7
+
+    vqrshrun.s16    d26, q8, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d27, q9, #7
+    vqrshrun.s16    d28, q10, #7
+    vqrshrun.s16    d29, q11, #7                ;load intermediate data from stack
+    vqrshrun.s16    d30, q12, #7
+
+;Second pass: 8x4
+;secondpass_filter
+    add             r3, r12, r3, lsl #5
+    sub             lr, lr, #32
+
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+    vld1.u8         {q11}, [lr]!
+
+    vabs.s32        q7, q5
+    vabs.s32        q8, q6
+
+    vld1.u8         {q12}, [lr]!
+
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vdup.8          d1, d14[4]
+    vdup.8          d2, d15[0]
+    vdup.8          d3, d15[4]
+    vdup.8          d4, d16[0]
+    vdup.8          d5, d16[4]
+
+    vmull.u8        q3, d22, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d23, d0
+    vmull.u8        q5, d24, d0
+    vmull.u8        q6, d25, d0
+
+    vmlsl.u8        q3, d23, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q4, d24, d1
+    vmlsl.u8        q5, d25, d1
+    vmlsl.u8        q6, d26, d1
+
+    vmlsl.u8        q3, d26, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d27, d4
+    vmlsl.u8        q5, d28, d4
+    vmlsl.u8        q6, d29, d4
+
+    vmlal.u8        q3, d24, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d25, d2
+    vmlal.u8        q5, d26, d2
+    vmlal.u8        q6, d27, d2
+
+    vmlal.u8        q3, d27, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q4, d28, d5
+    vmlal.u8        q5, d29, d5
+    vmlal.u8        q6, d30, d5
+
+    vmull.u8        q7, d25, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q8, d26, d3
+    vmull.u8        q9, d27, d3
+    vmull.u8        q10, d28, d3
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q8, #7
+    vqrshrun.s16    d8, q9, #7
+    vqrshrun.s16    d9, q10, #7
+
+    vst1.u8         {d6}, [r4], r5          ;store result
+    vst1.u8         {d7}, [r4], r5
+    vst1.u8         {d8}, [r4], r5
+    vst1.u8         {d9}, [r4], r5
+
+    add             sp, sp, #32
+    pop             {r4-r5,pc}
+
+;--------------------
+firstpass_filter8x4_only
+    vabs.s32        q12, q14
+    vabs.s32        q13, q15
+
+    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
+    vld1.u8         {q3}, [r0], r1          ;load src data
+
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vld1.u8         {q4}, [r0], r1
+    vdup.8          d1, d24[4]
+    vld1.u8         {q5}, [r0], r1
+    vdup.8          d2, d25[0]
+    vld1.u8         {q6}, [r0], r1
+    vdup.8          d3, d25[4]
+    vdup.8          d4, d26[0]
+    vdup.8          d5, d26[4]
+
+;First pass: output_height lines x output_width columns (4x8)
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q8, d8, d0
+    vmull.u8        q9, d10, d0
+    vmull.u8        q10, d12, d0
+
+    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d29, d8, d9, #1
+    vext.8          d30, d10, d11, #1
+    vext.8          d31, d12, d13, #1
+
+    vmlsl.u8        q7, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d29, d1
+    vmlsl.u8        q9, d30, d1
+    vmlsl.u8        q10, d31, d1
+
+    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d29, d8, d9, #4
+    vext.8          d30, d10, d11, #4
+    vext.8          d31, d12, d13, #4
+
+    vmlsl.u8        q7, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d29, d4
+    vmlsl.u8        q9, d30, d4
+    vmlsl.u8        q10, d31, d4
+
+    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d29, d8, d9, #2
+    vext.8          d30, d10, d11, #2
+    vext.8          d31, d12, d13, #2
+
+    vmlal.u8        q7, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d29, d2
+    vmlal.u8        q9, d30, d2
+    vmlal.u8        q10, d31, d2
+
+    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d29, d8, d9, #5
+    vext.8          d30, d10, d11, #5
+    vext.8          d31, d12, d13, #5
+
+    vmlal.u8        q7, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q8, d29, d5
+    vmlal.u8        q9, d30, d5
+    vmlal.u8        q10, d31, d5
+
+    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d29, d8, d9, #3
+    vext.8          d30, d10, d11, #3
+    vext.8          d31, d12, d13, #3
+
+    vmull.u8        q3, d28, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q4, d29, d3
+    vmull.u8        q5, d30, d3
+    vmull.u8        q6, d31, d3
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d22, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d23, q8, #7
+    vqrshrun.s16    d24, q9, #7
+    vqrshrun.s16    d25, q10, #7
+
+    vst1.u8         {d22}, [r4], r5         ;store result
+    vst1.u8         {d23}, [r4], r5
+    vst1.u8         {d24}, [r4], r5
+    vst1.u8         {d25}, [r4], r5
+
+    pop             {r4-r5,pc}
+
+;---------------------
+secondpass_filter8x4_only
+;Second pass: 8x4
+    add             r3, r12, r3, lsl #5
+    sub             r0, r0, r1, lsl #1
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+    vabs.s32        q7, q5
+    vabs.s32        q8, q6
+
+    vld1.u8         {d22}, [r0], r1
+    vld1.u8         {d23}, [r0], r1
+    vld1.u8         {d24}, [r0], r1
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vld1.u8         {d25}, [r0], r1
+    vdup.8          d1, d14[4]
+    vld1.u8         {d26}, [r0], r1
+    vdup.8          d2, d15[0]
+    vld1.u8         {d27}, [r0], r1
+    vdup.8          d3, d15[4]
+    vld1.u8         {d28}, [r0], r1
+    vdup.8          d4, d16[0]
+    vld1.u8         {d29}, [r0], r1
+    vdup.8          d5, d16[4]
+    vld1.u8         {d30}, [r0], r1
+
+    vmull.u8        q3, d22, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d23, d0
+    vmull.u8        q5, d24, d0
+    vmull.u8        q6, d25, d0
+
+    vmlsl.u8        q3, d23, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q4, d24, d1
+    vmlsl.u8        q5, d25, d1
+    vmlsl.u8        q6, d26, d1
+
+    vmlsl.u8        q3, d26, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d27, d4
+    vmlsl.u8        q5, d28, d4
+    vmlsl.u8        q6, d29, d4
+
+    vmlal.u8        q3, d24, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d25, d2
+    vmlal.u8        q5, d26, d2
+    vmlal.u8        q6, d27, d2
+
+    vmlal.u8        q3, d27, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q4, d28, d5
+    vmlal.u8        q5, d29, d5
+    vmlal.u8        q6, d30, d5
+
+    vmull.u8        q7, d25, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q8, d26, d3
+    vmull.u8        q9, d27, d3
+    vmull.u8        q10, d28, d3
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q8, #7
+    vqrshrun.s16    d8, q9, #7
+    vqrshrun.s16    d9, q10, #7
+
+    vst1.u8         {d6}, [r4], r5          ;store result
+    vst1.u8         {d7}, [r4], r5
+    vst1.u8         {d8}, [r4], r5
+    vst1.u8         {d9}, [r4], r5
+
+    pop             {r4-r5,pc}
+
+    ENDP
+
+;-----------------
+    AREA    subpelfilters8_dat, DATA, READWRITE         ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_filter8_coeff_
+    DCD     filter8_coeff
+filter8_coeff
+    DCD     0,  0,  128,    0,   0,  0,   0,  0
+    DCD     0, -6,  123,   12,  -1,  0,   0,  0
+    DCD     2, -11, 108,   36,  -8,  1,   0,  0
+    DCD     0, -9,   93,   50,  -6,  0,   0,  0
+    DCD     3, -16,  77,   77, -16,  3,   0,  0
+    DCD     0, -6,   50,   93,  -9,  0,   0,  0
+    DCD     1, -8,   36,  108, -11,  2,   0,  0
+    DCD     0, -1,   12,  123,  -6,   0,  0,  0
+
+    END
diff --git a/vp8/common/arm/neon/sixtappredict8x8_neon.asm b/vp8/common/arm/neon/sixtappredict8x8_neon.asm
new file mode 100644
index 0000000..d27485e
--- /dev/null
+++ b/vp8/common/arm/neon/sixtappredict8x8_neon.asm
@@ -0,0 +1,527 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_sixtap_predict8x8_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; stack(r4) unsigned char *dst_ptr,
+; stack(r5) int  dst_pitch
+
+|vp8_sixtap_predict8x8_neon| PROC
+    push            {r4-r5, lr}
+
+    ldr             r12, _filter8_coeff_
+
+    ldr             r4, [sp, #12]           ;load parameters from stack
+    ldr             r5, [sp, #16]           ;load parameters from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_filter8x8_only
+
+    add             r2, r12, r2, lsl #5     ;calculate filter location
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+
+    vld1.s32        {q14, q15}, [r2]        ;load first_pass filter
+
+    beq             firstpass_filter8x8_only
+
+    sub             sp, sp, #64             ;reserve space on stack for temporary storage
+    mov             lr, sp
+
+    vabs.s32        q12, q14
+    vabs.s32        q13, q15
+
+    mov             r2, #2                  ;loop counter
+    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
+    sub             r0, r0, r1, lsl #1
+
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vdup.8          d1, d24[4]
+    vdup.8          d2, d25[0]
+
+;First pass: output_height lines x output_width columns (13x8)
+    vld1.u8         {q3}, [r0], r1          ;load src data
+    vdup.8          d3, d25[4]
+    vld1.u8         {q4}, [r0], r1
+    vdup.8          d4, d26[0]
+    vld1.u8         {q5}, [r0], r1
+    vdup.8          d5, d26[4]
+    vld1.u8         {q6}, [r0], r1
+
+filt_blk2d_fp8x8_loop_neon
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q8, d8, d0
+    vmull.u8        q9, d10, d0
+    vmull.u8        q10, d12, d0
+
+    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d29, d8, d9, #1
+    vext.8          d30, d10, d11, #1
+    vext.8          d31, d12, d13, #1
+
+    vmlsl.u8        q7, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d29, d1
+    vmlsl.u8        q9, d30, d1
+    vmlsl.u8        q10, d31, d1
+
+    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d29, d8, d9, #4
+    vext.8          d30, d10, d11, #4
+    vext.8          d31, d12, d13, #4
+
+    vmlsl.u8        q7, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d29, d4
+    vmlsl.u8        q9, d30, d4
+    vmlsl.u8        q10, d31, d4
+
+    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d29, d8, d9, #2
+    vext.8          d30, d10, d11, #2
+    vext.8          d31, d12, d13, #2
+
+    vmlal.u8        q7, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d29, d2
+    vmlal.u8        q9, d30, d2
+    vmlal.u8        q10, d31, d2
+
+    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d29, d8, d9, #5
+    vext.8          d30, d10, d11, #5
+    vext.8          d31, d12, d13, #5
+
+    vmlal.u8        q7, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q8, d29, d5
+    vmlal.u8        q9, d30, d5
+    vmlal.u8        q10, d31, d5
+
+    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d29, d8, d9, #3
+    vext.8          d30, d10, d11, #3
+    vext.8          d31, d12, d13, #3
+
+    vmull.u8        q3, d28, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q4, d29, d3
+    vmull.u8        q5, d30, d3
+    vmull.u8        q6, d31, d3
+
+    subs            r2, r2, #1
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vld1.u8         {q3}, [r0], r1          ;load src data
+
+    vqrshrun.s16    d22, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d23, q8, #7
+    vqrshrun.s16    d24, q9, #7
+    vqrshrun.s16    d25, q10, #7
+
+    vst1.u8         {d22}, [lr]!            ;store result
+    vld1.u8         {q4}, [r0], r1
+    vst1.u8         {d23}, [lr]!
+    vld1.u8         {q5}, [r0], r1
+    vst1.u8         {d24}, [lr]!
+    vld1.u8         {q6}, [r0], r1
+    vst1.u8         {d25}, [lr]!
+
+    bne             filt_blk2d_fp8x8_loop_neon
+
+    ;first_pass filtering on the rest 5-line data
+    ;vld1.u8            {q3}, [r0], r1          ;load src data
+    ;vld1.u8            {q4}, [r0], r1
+    ;vld1.u8            {q5}, [r0], r1
+    ;vld1.u8            {q6}, [r0], r1
+    vld1.u8         {q7}, [r0], r1
+
+    vmull.u8        q8, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q9, d8, d0
+    vmull.u8        q10, d10, d0
+    vmull.u8        q11, d12, d0
+    vmull.u8        q12, d14, d0
+
+    vext.8          d27, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d28, d8, d9, #1
+    vext.8          d29, d10, d11, #1
+    vext.8          d30, d12, d13, #1
+    vext.8          d31, d14, d15, #1
+
+    vmlsl.u8        q8, d27, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q9, d28, d1
+    vmlsl.u8        q10, d29, d1
+    vmlsl.u8        q11, d30, d1
+    vmlsl.u8        q12, d31, d1
+
+    vext.8          d27, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d28, d8, d9, #4
+    vext.8          d29, d10, d11, #4
+    vext.8          d30, d12, d13, #4
+    vext.8          d31, d14, d15, #4
+
+    vmlsl.u8        q8, d27, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q9, d28, d4
+    vmlsl.u8        q10, d29, d4
+    vmlsl.u8        q11, d30, d4
+    vmlsl.u8        q12, d31, d4
+
+    vext.8          d27, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d28, d8, d9, #2
+    vext.8          d29, d10, d11, #2
+    vext.8          d30, d12, d13, #2
+    vext.8          d31, d14, d15, #2
+
+    vmlal.u8        q8, d27, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q9, d28, d2
+    vmlal.u8        q10, d29, d2
+    vmlal.u8        q11, d30, d2
+    vmlal.u8        q12, d31, d2
+
+    vext.8          d27, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d28, d8, d9, #5
+    vext.8          d29, d10, d11, #5
+    vext.8          d30, d12, d13, #5
+    vext.8          d31, d14, d15, #5
+
+    vmlal.u8        q8, d27, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q9, d28, d5
+    vmlal.u8        q10, d29, d5
+    vmlal.u8        q11, d30, d5
+    vmlal.u8        q12, d31, d5
+
+    vext.8          d27, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d28, d8, d9, #3
+    vext.8          d29, d10, d11, #3
+    vext.8          d30, d12, d13, #3
+    vext.8          d31, d14, d15, #3
+
+    vmull.u8        q3, d27, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q4, d28, d3
+    vmull.u8        q5, d29, d3
+    vmull.u8        q6, d30, d3
+    vmull.u8        q7, d31, d3
+
+    vqadd.s16       q8, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q9, q4
+    vqadd.s16       q10, q5
+    vqadd.s16       q11, q6
+    vqadd.s16       q12, q7
+
+    add             r3, r12, r3, lsl #5
+
+    vqrshrun.s16    d26, q8, #7             ;shift/round/saturate to u8
+    sub             lr, lr, #64
+    vqrshrun.s16    d27, q9, #7
+    vld1.u8         {q9}, [lr]!             ;load intermediate data from stack
+    vqrshrun.s16    d28, q10, #7
+    vld1.u8         {q10}, [lr]!
+
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+
+    vqrshrun.s16    d29, q11, #7
+    vld1.u8         {q11}, [lr]!
+
+    vabs.s32        q7, q5
+    vabs.s32        q8, q6
+
+    vqrshrun.s16    d30, q12, #7
+    vld1.u8         {q12}, [lr]!
+
+;Second pass: 8x8
+    mov             r3, #2                  ;loop counter
+
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vdup.8          d1, d14[4]
+    vdup.8          d2, d15[0]
+    vdup.8          d3, d15[4]
+    vdup.8          d4, d16[0]
+    vdup.8          d5, d16[4]
+
+filt_blk2d_sp8x8_loop_neon
+    vmull.u8        q3, d18, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d19, d0
+    vmull.u8        q5, d20, d0
+    vmull.u8        q6, d21, d0
+
+    vmlsl.u8        q3, d19, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q4, d20, d1
+    vmlsl.u8        q5, d21, d1
+    vmlsl.u8        q6, d22, d1
+
+    vmlsl.u8        q3, d22, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d23, d4
+    vmlsl.u8        q5, d24, d4
+    vmlsl.u8        q6, d25, d4
+
+    vmlal.u8        q3, d20, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d21, d2
+    vmlal.u8        q5, d22, d2
+    vmlal.u8        q6, d23, d2
+
+    vmlal.u8        q3, d23, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q4, d24, d5
+    vmlal.u8        q5, d25, d5
+    vmlal.u8        q6, d26, d5
+
+    vmull.u8        q7, d21, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q8, d22, d3
+    vmull.u8        q9, d23, d3
+    vmull.u8        q10, d24, d3
+
+    subs            r3, r3, #1
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q8, #7
+    vqrshrun.s16    d8, q9, #7
+    vqrshrun.s16    d9, q10, #7
+
+    vmov            q9, q11
+    vst1.u8         {d6}, [r4], r5          ;store result
+    vmov            q10, q12
+    vst1.u8         {d7}, [r4], r5
+    vmov            q11, q13
+    vst1.u8         {d8}, [r4], r5
+    vmov            q12, q14
+    vst1.u8         {d9}, [r4], r5
+    vmov            d26, d30
+
+    bne filt_blk2d_sp8x8_loop_neon
+
+    add             sp, sp, #64
+    pop             {r4-r5,pc}
+
+;---------------------
+firstpass_filter8x8_only
+    ;add                r2, r12, r2, lsl #5     ;calculate filter location
+    ;vld1.s32       {q14, q15}, [r2]        ;load first_pass filter
+    vabs.s32        q12, q14
+    vabs.s32        q13, q15
+
+    mov             r2, #2                  ;loop counter
+    sub             r0, r0, #2              ;move srcptr back to (line-2) and (column-2)
+
+    vdup.8          d0, d24[0]              ;first_pass filter (d0-d5)
+    vdup.8          d1, d24[4]
+    vdup.8          d2, d25[0]
+    vdup.8          d3, d25[4]
+    vdup.8          d4, d26[0]
+    vdup.8          d5, d26[4]
+
+;First pass: output_height lines x output_width columns (8x8)
+filt_blk2d_fpo8x8_loop_neon
+    vld1.u8         {q3}, [r0], r1          ;load src data
+    vld1.u8         {q4}, [r0], r1
+    vld1.u8         {q5}, [r0], r1
+    vld1.u8         {q6}, [r0], r1
+
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d6, d0              ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q8, d8, d0
+    vmull.u8        q9, d10, d0
+    vmull.u8        q10, d12, d0
+
+    vext.8          d28, d6, d7, #1         ;construct src_ptr[-1]
+    vext.8          d29, d8, d9, #1
+    vext.8          d30, d10, d11, #1
+    vext.8          d31, d12, d13, #1
+
+    vmlsl.u8        q7, d28, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q8, d29, d1
+    vmlsl.u8        q9, d30, d1
+    vmlsl.u8        q10, d31, d1
+
+    vext.8          d28, d6, d7, #4         ;construct src_ptr[2]
+    vext.8          d29, d8, d9, #4
+    vext.8          d30, d10, d11, #4
+    vext.8          d31, d12, d13, #4
+
+    vmlsl.u8        q7, d28, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q8, d29, d4
+    vmlsl.u8        q9, d30, d4
+    vmlsl.u8        q10, d31, d4
+
+    vext.8          d28, d6, d7, #2         ;construct src_ptr[0]
+    vext.8          d29, d8, d9, #2
+    vext.8          d30, d10, d11, #2
+    vext.8          d31, d12, d13, #2
+
+    vmlal.u8        q7, d28, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q8, d29, d2
+    vmlal.u8        q9, d30, d2
+    vmlal.u8        q10, d31, d2
+
+    vext.8          d28, d6, d7, #5         ;construct src_ptr[3]
+    vext.8          d29, d8, d9, #5
+    vext.8          d30, d10, d11, #5
+    vext.8          d31, d12, d13, #5
+
+    vmlal.u8        q7, d28, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q8, d29, d5
+    vmlal.u8        q9, d30, d5
+    vmlal.u8        q10, d31, d5
+
+    vext.8          d28, d6, d7, #3         ;construct src_ptr[1]
+    vext.8          d29, d8, d9, #3
+    vext.8          d30, d10, d11, #3
+    vext.8          d31, d12, d13, #3
+
+    vmull.u8        q3, d28, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q4, d29, d3
+    vmull.u8        q5, d30, d3
+    vmull.u8        q6, d31, d3
+ ;
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    subs            r2, r2, #1
+
+    vqrshrun.s16    d22, q7, #7             ;shift/round/saturate to u8
+    vqrshrun.s16    d23, q8, #7
+    vqrshrun.s16    d24, q9, #7
+    vqrshrun.s16    d25, q10, #7
+
+    vst1.u8         {d22}, [r4], r5         ;store result
+    vst1.u8         {d23}, [r4], r5
+    vst1.u8         {d24}, [r4], r5
+    vst1.u8         {d25}, [r4], r5
+
+    bne             filt_blk2d_fpo8x8_loop_neon
+
+    pop             {r4-r5,pc}
+
+;---------------------
+secondpass_filter8x8_only
+    sub             r0, r0, r1, lsl #1
+    add             r3, r12, r3, lsl #5
+
+    vld1.u8         {d18}, [r0], r1         ;load src data
+    vld1.s32        {q5, q6}, [r3]          ;load second_pass filter
+    vld1.u8         {d19}, [r0], r1
+    vabs.s32        q7, q5
+    vld1.u8         {d20}, [r0], r1
+    vabs.s32        q8, q6
+    vld1.u8         {d21}, [r0], r1
+    mov             r3, #2                  ;loop counter
+    vld1.u8         {d22}, [r0], r1
+    vdup.8          d0, d14[0]              ;second_pass filter parameters (d0-d5)
+    vld1.u8         {d23}, [r0], r1
+    vdup.8          d1, d14[4]
+    vld1.u8         {d24}, [r0], r1
+    vdup.8          d2, d15[0]
+    vld1.u8         {d25}, [r0], r1
+    vdup.8          d3, d15[4]
+    vld1.u8         {d26}, [r0], r1
+    vdup.8          d4, d16[0]
+    vld1.u8         {d27}, [r0], r1
+    vdup.8          d5, d16[4]
+    vld1.u8         {d28}, [r0], r1
+    vld1.u8         {d29}, [r0], r1
+    vld1.u8         {d30}, [r0], r1
+
+;Second pass: 8x8
+filt_blk2d_spo8x8_loop_neon
+    vmull.u8        q3, d18, d0             ;(src_ptr[-2] * vp8_filter[0])
+    vmull.u8        q4, d19, d0
+    vmull.u8        q5, d20, d0
+    vmull.u8        q6, d21, d0
+
+    vmlsl.u8        q3, d19, d1             ;-(src_ptr[-1] * vp8_filter[1])
+    vmlsl.u8        q4, d20, d1
+    vmlsl.u8        q5, d21, d1
+    vmlsl.u8        q6, d22, d1
+
+    vmlsl.u8        q3, d22, d4             ;-(src_ptr[2] * vp8_filter[4])
+    vmlsl.u8        q4, d23, d4
+    vmlsl.u8        q5, d24, d4
+    vmlsl.u8        q6, d25, d4
+
+    vmlal.u8        q3, d20, d2             ;(src_ptr[0] * vp8_filter[2])
+    vmlal.u8        q4, d21, d2
+    vmlal.u8        q5, d22, d2
+    vmlal.u8        q6, d23, d2
+
+    vmlal.u8        q3, d23, d5             ;(src_ptr[3] * vp8_filter[5])
+    vmlal.u8        q4, d24, d5
+    vmlal.u8        q5, d25, d5
+    vmlal.u8        q6, d26, d5
+
+    vmull.u8        q7, d21, d3             ;(src_ptr[1] * vp8_filter[3])
+    vmull.u8        q8, d22, d3
+    vmull.u8        q9, d23, d3
+    vmull.u8        q10, d24, d3
+
+    subs            r3, r3, #1
+
+    vqadd.s16       q7, q3                  ;sum of all (src_data*filter_parameters)
+    vqadd.s16       q8, q4
+    vqadd.s16       q9, q5
+    vqadd.s16       q10, q6
+
+    vqrshrun.s16    d6, q7, #7              ;shift/round/saturate to u8
+    vqrshrun.s16    d7, q8, #7
+    vqrshrun.s16    d8, q9, #7
+    vqrshrun.s16    d9, q10, #7
+
+    vmov            q9, q11
+    vst1.u8         {d6}, [r4], r5          ;store result
+    vmov            q10, q12
+    vst1.u8         {d7}, [r4], r5
+    vmov            q11, q13
+    vst1.u8         {d8}, [r4], r5
+    vmov            q12, q14
+    vst1.u8         {d9}, [r4], r5
+    vmov            d26, d30
+
+    bne filt_blk2d_spo8x8_loop_neon
+
+    pop             {r4-r5,pc}
+
+    ENDP
+
+;-----------------
+    AREA    subpelfilters8_dat, DATA, READWRITE         ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_filter8_coeff_
+    DCD     filter8_coeff
+filter8_coeff
+    DCD     0,  0,  128,    0,   0,  0,   0,  0
+    DCD     0, -6,  123,   12,  -1,  0,   0,  0
+    DCD     2, -11, 108,   36,  -8,  1,   0,  0
+    DCD     0, -9,   93,   50,  -6,  0,   0,  0
+    DCD     3, -16,  77,   77, -16,  3,   0,  0
+    DCD     0, -6,   50,   93,  -9,  0,   0,  0
+    DCD     1, -8,   36,  108, -11,  2,   0,  0
+    DCD     0, -1,   12,  123,  -6,   0,  0,  0
+
+    END
diff --git a/vp8/common/arm/recon_arm.c b/vp8/common/arm/recon_arm.c
new file mode 100644
index 0000000..130059e
--- /dev/null
+++ b/vp8/common/arm/recon_arm.c
@@ -0,0 +1,108 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "recon.h"
+#include "blockd.h"
+
+extern void vp8_recon16x16mb_neon(unsigned char *pred_ptr, short *diff_ptr, unsigned char *dst_ptr, int ystride, unsigned char *udst_ptr, unsigned char *vdst_ptr);
+
+/*
+void vp8_recon16x16mby(MACROBLOCKD *x)
+{
+    int i;
+    for(i=0;i<16;i+=4)
+    {
+        //vp8_recon4b(&x->block[i]);
+        BLOCKD *b = &x->block[i];
+        vp8_recon4b (b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    }
+}
+*/
+void vp8_recon16x16mby(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+    BLOCKD *b = &x->block[0];
+    RECON_INVOKE(rtcd, recon4)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+
+    //b = &x->block[4];
+    b += 4;
+    RECON_INVOKE(rtcd, recon4)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+
+    //b = &x->block[8];
+    b += 4;
+    RECON_INVOKE(rtcd, recon4)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+
+    //b = &x->block[12];
+    b += 4;
+    RECON_INVOKE(rtcd, recon4)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+}
+
+#if HAVE_ARMV7
+void vp8_recon16x16mb(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+    unsigned char *pred_ptr = &x->predictor[0];
+    short *diff_ptr = &x->diff[0];
+    unsigned char *dst_ptr = x->dst.y_buffer;
+    unsigned char *udst_ptr = x->dst.u_buffer;
+    unsigned char *vdst_ptr = x->dst.v_buffer;
+    int ystride = x->dst.y_stride;
+    //int uv_stride = x->dst.uv_stride;
+
+    vp8_recon16x16mb_neon(pred_ptr, diff_ptr, dst_ptr, ystride, udst_ptr, vdst_ptr);
+}
+
+#else
+/*
+void vp8_recon16x16mb(MACROBLOCKD *x)
+{
+    int i;
+
+    for(i=0;i<16;i+=4)
+    {
+//      vp8_recon4b(&x->block[i]);
+        BLOCKD *b = &x->block[i];
+        vp8_recon4b (b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+
+    }
+    for(i=16;i<24;i+=2)
+    {
+//      vp8_recon2b(&x->block[i]);
+        BLOCKD *b = &x->block[i];
+        vp8_recon2b (b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    }
+}
+*/
+void vp8_recon16x16mb(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+    BLOCKD *b = &x->block[0];
+
+    RECON_INVOKE(rtcd, recon4)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    b += 4;
+    RECON_INVOKE(rtcd, recon4)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    b += 4;
+    RECON_INVOKE(rtcd, recon4)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    b += 4;
+    RECON_INVOKE(rtcd, recon4)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    b += 4;
+
+    //b = &x->block[16];
+
+    RECON_INVOKE(rtcd, recon2)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    b++;
+    b++;
+    RECON_INVOKE(rtcd, recon2)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    b++;
+    b++;
+    RECON_INVOKE(rtcd, recon2)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    b++;
+    b++;
+    RECON_INVOKE(rtcd, recon2)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+}
+#endif
diff --git a/vp8/common/arm/recon_arm.h b/vp8/common/arm/recon_arm.h
new file mode 100644
index 0000000..fd9f85e
--- /dev/null
+++ b/vp8/common/arm/recon_arm.h
@@ -0,0 +1,70 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef RECON_ARM_H
+#define RECON_ARM_H
+
+#if HAVE_ARMV6
+extern prototype_recon_block(vp8_recon_b_armv6);
+extern prototype_recon_block(vp8_recon2b_armv6);
+extern prototype_recon_block(vp8_recon4b_armv6);
+
+extern prototype_copy_block(vp8_copy_mem8x8_v6);
+extern prototype_copy_block(vp8_copy_mem8x4_v6);
+extern prototype_copy_block(vp8_copy_mem16x16_v6);
+
+#undef  vp8_recon_recon
+#define vp8_recon_recon vp8_recon_b_armv6
+
+#undef  vp8_recon_recon2
+#define vp8_recon_recon2 vp8_recon2b_armv6
+
+#undef  vp8_recon_recon4
+#define vp8_recon_recon4 vp8_recon4b_armv6
+
+#undef  vp8_recon_copy8x8
+#define vp8_recon_copy8x8 vp8_copy_mem8x8_v6
+
+#undef  vp8_recon_copy8x4
+#define vp8_recon_copy8x4 vp8_copy_mem8x4_v6
+
+#undef  vp8_recon_copy16x16
+#define vp8_recon_copy16x16 vp8_copy_mem16x16_v6
+#endif
+
+#if HAVE_ARMV7
+extern prototype_recon_block(vp8_recon_b_neon);
+extern prototype_recon_block(vp8_recon2b_neon);
+extern prototype_recon_block(vp8_recon4b_neon);
+
+extern prototype_copy_block(vp8_copy_mem8x8_neon);
+extern prototype_copy_block(vp8_copy_mem8x4_neon);
+extern prototype_copy_block(vp8_copy_mem16x16_neon);
+
+#undef  vp8_recon_recon
+#define vp8_recon_recon vp8_recon_b_neon
+
+#undef  vp8_recon_recon2
+#define vp8_recon_recon2 vp8_recon2b_neon
+
+#undef  vp8_recon_recon4
+#define vp8_recon_recon4 vp8_recon4b_neon
+
+#undef  vp8_recon_copy8x8
+#define vp8_recon_copy8x8 vp8_copy_mem8x8_neon
+
+#undef  vp8_recon_copy8x4
+#define vp8_recon_copy8x4 vp8_copy_mem8x4_neon
+
+#undef  vp8_recon_copy16x16
+#define vp8_recon_copy16x16 vp8_copy_mem16x16_neon
+#endif
+
+#endif
diff --git a/vp8/common/arm/reconintra4x4_arm.c b/vp8/common/arm/reconintra4x4_arm.c
new file mode 100644
index 0000000..334d352
--- /dev/null
+++ b/vp8/common/arm/reconintra4x4_arm.c
@@ -0,0 +1,408 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "recon.h"
+#include "vpx_mem/vpx_mem.h"
+#include "reconintra.h"
+
+void vp8_predict_intra4x4(BLOCKD *x,
+                          int b_mode,
+                          unsigned char *predictor)
+{
+    int i, r, c;
+
+    unsigned char *Above = *(x->base_dst) + x->dst - x->dst_stride;
+    unsigned char Left[4];
+    unsigned char top_left = Above[-1];
+
+    Left[0] = (*(x->base_dst))[x->dst - 1];
+    Left[1] = (*(x->base_dst))[x->dst - 1 + x->dst_stride];
+    Left[2] = (*(x->base_dst))[x->dst - 1 + 2 * x->dst_stride];
+    Left[3] = (*(x->base_dst))[x->dst - 1 + 3 * x->dst_stride];
+
+    switch (b_mode)
+    {
+    case B_DC_PRED:
+    {
+        int expected_dc = 0;
+
+        for (i = 0; i < 4; i++)
+        {
+            expected_dc += Above[i];
+            expected_dc += Left[i];
+        }
+
+        expected_dc = (expected_dc + 4) >> 3;
+
+        for (r = 0; r < 4; r++)
+        {
+            for (c = 0; c < 4; c++)
+            {
+                predictor[c] = expected_dc;
+            }
+
+            predictor += 16;
+        }
+    }
+    break;
+    case B_TM_PRED:
+    {
+        // prediction similar to true_motion prediction
+        for (r = 0; r < 4; r++)
+        {
+            for (c = 0; c < 4; c++)
+            {
+                int pred = Above[c] - top_left + Left[r];
+
+                if (pred < 0)
+                    pred = 0;
+
+                if (pred > 255)
+                    pred = 255;
+
+                predictor[c] = pred;
+            }
+
+            predictor += 16;
+        }
+    }
+    break;
+
+    case B_VE_PRED:
+    {
+
+        unsigned int ap[4];
+        ap[0] = (top_left  + 2 * Above[0] + Above[1] + 2) >> 2;
+        ap[1] = (Above[0] + 2 * Above[1] + Above[2] + 2) >> 2;
+        ap[2] = (Above[1] + 2 * Above[2] + Above[3] + 2) >> 2;
+        ap[3] = (Above[2] + 2 * Above[3] + Above[4] + 2) >> 2;
+
+        for (r = 0; r < 4; r++)
+        {
+            for (c = 0; c < 4; c++)
+            {
+
+                predictor[c] = ap[c];
+            }
+
+            predictor += 16;
+        }
+
+    }
+    break;
+
+
+    case B_HE_PRED:
+    {
+
+        unsigned int lp[4];
+        lp[0] = (top_left + 2 * Left[0] + Left[1] + 2) >> 2;
+        lp[1] = (Left[0] + 2 * Left[1] + Left[2] + 2) >> 2;
+        lp[2] = (Left[1] + 2 * Left[2] + Left[3] + 2) >> 2;
+        lp[3] = (Left[2] + 2 * Left[3] + Left[3] + 2) >> 2;
+
+        for (r = 0; r < 4; r++)
+        {
+            for (c = 0; c < 4; c++)
+            {
+                predictor[c] = lp[r];
+            }
+
+            predictor += 16;
+        }
+    }
+    break;
+    case B_LD_PRED:
+    {
+        unsigned char *ptr = Above;
+        predictor[0 * 16 + 0] = (ptr[0] + ptr[1] * 2 + ptr[2] + 2) >> 2;
+        predictor[0 * 16 + 1] =
+            predictor[1 * 16 + 0] = (ptr[1] + ptr[2] * 2 + ptr[3] + 2) >> 2;
+        predictor[0 * 16 + 2] =
+            predictor[1 * 16 + 1] =
+                predictor[2 * 16 + 0] = (ptr[2] + ptr[3] * 2 + ptr[4] + 2) >> 2;
+        predictor[0 * 16 + 3] =
+            predictor[1 * 16 + 2] =
+                predictor[2 * 16 + 1] =
+                    predictor[3 * 16 + 0] = (ptr[3] + ptr[4] * 2 + ptr[5] + 2) >> 2;
+        predictor[1 * 16 + 3] =
+            predictor[2 * 16 + 2] =
+                predictor[3 * 16 + 1] = (ptr[4] + ptr[5] * 2 + ptr[6] + 2) >> 2;
+        predictor[2 * 16 + 3] =
+            predictor[3 * 16 + 2] = (ptr[5] + ptr[6] * 2 + ptr[7] + 2) >> 2;
+        predictor[3 * 16 + 3] = (ptr[6] + ptr[7] * 2 + ptr[7] + 2) >> 2;
+
+    }
+    break;
+    case B_RD_PRED:
+    {
+
+        unsigned char pp[9];
+
+        pp[0] = Left[3];
+        pp[1] = Left[2];
+        pp[2] = Left[1];
+        pp[3] = Left[0];
+        pp[4] = top_left;
+        pp[5] = Above[0];
+        pp[6] = Above[1];
+        pp[7] = Above[2];
+        pp[8] = Above[3];
+
+        predictor[3 * 16 + 0] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
+        predictor[3 * 16 + 1] =
+            predictor[2 * 16 + 0] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        predictor[3 * 16 + 2] =
+            predictor[2 * 16 + 1] =
+                predictor[1 * 16 + 0] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
+        predictor[3 * 16 + 3] =
+            predictor[2 * 16 + 2] =
+                predictor[1 * 16 + 1] =
+                    predictor[0 * 16 + 0] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
+        predictor[2 * 16 + 3] =
+            predictor[1 * 16 + 2] =
+                predictor[0 * 16 + 1] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
+        predictor[1 * 16 + 3] =
+            predictor[0 * 16 + 2] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
+        predictor[0 * 16 + 3] = (pp[6] + pp[7] * 2 + pp[8] + 2) >> 2;
+
+    }
+    break;
+    case B_VR_PRED:
+    {
+
+        unsigned char pp[9];
+
+        pp[0] = Left[3];
+        pp[1] = Left[2];
+        pp[2] = Left[1];
+        pp[3] = Left[0];
+        pp[4] = top_left;
+        pp[5] = Above[0];
+        pp[6] = Above[1];
+        pp[7] = Above[2];
+        pp[8] = Above[3];
+
+
+        predictor[3 * 16 + 0] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        predictor[2 * 16 + 0] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
+        predictor[3 * 16 + 1] =
+            predictor[1 * 16 + 0] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
+        predictor[2 * 16 + 1] =
+            predictor[0 * 16 + 0] = (pp[4] + pp[5] + 1) >> 1;
+        predictor[3 * 16 + 2] =
+            predictor[1 * 16 + 1] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
+        predictor[2 * 16 + 2] =
+            predictor[0 * 16 + 1] = (pp[5] + pp[6] + 1) >> 1;
+        predictor[3 * 16 + 3] =
+            predictor[1 * 16 + 2] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
+        predictor[2 * 16 + 3] =
+            predictor[0 * 16 + 2] = (pp[6] + pp[7] + 1) >> 1;
+        predictor[1 * 16 + 3] = (pp[6] + pp[7] * 2 + pp[8] + 2) >> 2;
+        predictor[0 * 16 + 3] = (pp[7] + pp[8] + 1) >> 1;
+
+    }
+    break;
+    case B_VL_PRED:
+    {
+
+        unsigned char *pp = Above;
+
+        predictor[0 * 16 + 0] = (pp[0] + pp[1] + 1) >> 1;
+        predictor[1 * 16 + 0] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
+        predictor[2 * 16 + 0] =
+            predictor[0 * 16 + 1] = (pp[1] + pp[2] + 1) >> 1;
+        predictor[1 * 16 + 1] =
+            predictor[3 * 16 + 0] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        predictor[2 * 16 + 1] =
+            predictor[0 * 16 + 2] = (pp[2] + pp[3] + 1) >> 1;
+        predictor[3 * 16 + 1] =
+            predictor[1 * 16 + 2] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
+        predictor[0 * 16 + 3] =
+            predictor[2 * 16 + 2] = (pp[3] + pp[4] + 1) >> 1;
+        predictor[1 * 16 + 3] =
+            predictor[3 * 16 + 2] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
+        predictor[2 * 16 + 3] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
+        predictor[3 * 16 + 3] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
+    }
+    break;
+
+    case B_HD_PRED:
+    {
+        unsigned char pp[9];
+        pp[0] = Left[3];
+        pp[1] = Left[2];
+        pp[2] = Left[1];
+        pp[3] = Left[0];
+        pp[4] = top_left;
+        pp[5] = Above[0];
+        pp[6] = Above[1];
+        pp[7] = Above[2];
+        pp[8] = Above[3];
+
+
+        predictor[3 * 16 + 0] = (pp[0] + pp[1] + 1) >> 1;
+        predictor[3 * 16 + 1] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
+        predictor[2 * 16 + 0] =
+            predictor[3 * 16 + 2] = (pp[1] + pp[2] + 1) >> 1;
+        predictor[2 * 16 + 1] =
+            predictor[3 * 16 + 3] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        predictor[2 * 16 + 2] =
+            predictor[1 * 16 + 0] = (pp[2] + pp[3] + 1) >> 1;
+        predictor[2 * 16 + 3] =
+            predictor[1 * 16 + 1] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
+        predictor[1 * 16 + 2] =
+            predictor[0 * 16 + 0] = (pp[3] + pp[4] + 1) >> 1;
+        predictor[1 * 16 + 3] =
+            predictor[0 * 16 + 1] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
+        predictor[0 * 16 + 2] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
+        predictor[0 * 16 + 3] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
+    }
+    break;
+
+
+    case B_HU_PRED:
+    {
+        unsigned char *pp = Left;
+        predictor[0 * 16 + 0] = (pp[0] + pp[1] + 1) >> 1;
+        predictor[0 * 16 + 1] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
+        predictor[0 * 16 + 2] =
+            predictor[1 * 16 + 0] = (pp[1] + pp[2] + 1) >> 1;
+        predictor[0 * 16 + 3] =
+            predictor[1 * 16 + 1] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        predictor[1 * 16 + 2] =
+            predictor[2 * 16 + 0] = (pp[2] + pp[3] + 1) >> 1;
+        predictor[1 * 16 + 3] =
+            predictor[2 * 16 + 1] = (pp[2] + pp[3] * 2 + pp[3] + 2) >> 2;
+        predictor[2 * 16 + 2] =
+            predictor[2 * 16 + 3] =
+                predictor[3 * 16 + 0] =
+                    predictor[3 * 16 + 1] =
+                        predictor[3 * 16 + 2] =
+                            predictor[3 * 16 + 3] = pp[3];
+    }
+    break;
+
+
+    }
+}
+// copy 4 bytes from the above right down so that the 4x4 prediction modes using pixels above and
+// to the right prediction have filled in pixels to use.
+void vp8_intra_prediction_down_copy(MACROBLOCKD *x)
+{
+    unsigned char *above_right = *(x->block[0].base_dst) + x->block[0].dst - x->block[0].dst_stride + 16;
+
+    unsigned int *src_ptr = (unsigned int *)above_right;
+    unsigned int *dst_ptr0 = (unsigned int *)(above_right + 4 * x->block[0].dst_stride);
+    unsigned int *dst_ptr1 = (unsigned int *)(above_right + 8 * x->block[0].dst_stride);
+    unsigned int *dst_ptr2 = (unsigned int *)(above_right + 12 * x->block[0].dst_stride);
+
+    *dst_ptr0 = *src_ptr;
+    *dst_ptr1 = *src_ptr;
+    *dst_ptr2 = *src_ptr;
+}
+
+
+
+/*
+void vp8_recon_intra4x4mb(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+    int i;
+
+    vp8_intra_prediction_down_copy(x);
+
+    for(i=0;i<16;i++)
+    {
+        BLOCKD *b = &x->block[i];
+
+        vp8_predict_intra4x4(b, x->block[i].bmi.mode,x->block[i].predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    }
+
+    vp8_recon_intra_mbuv(x);
+
+}
+*/
+void vp8_recon_intra4x4mb(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+    int i;
+    BLOCKD *b = &x->block[0];
+
+    vp8_intra_prediction_down_copy(x);
+
+    {
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+        b += 1;
+
+        vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    }
+
+    vp8_recon_intra_mbuv(rtcd, x);
+
+}
diff --git a/vp8/common/arm/reconintra_arm.c b/vp8/common/arm/reconintra_arm.c
new file mode 100644
index 0000000..d7ee1dd
--- /dev/null
+++ b/vp8/common/arm/reconintra_arm.c
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "blockd.h"
+#include "reconintra.h"
+#include "vpx_mem/vpx_mem.h"
+#include "recon.h"
+
+#if HAVE_ARMV7
+extern void vp8_build_intra_predictors_mby_neon_func(
+    unsigned char *y_buffer,
+    unsigned char *ypred_ptr,
+    int y_stride,
+    int mode,
+    int Up,
+    int Left);
+
+void vp8_build_intra_predictors_mby_neon(MACROBLOCKD *x)
+{
+    unsigned char *y_buffer = x->dst.y_buffer;
+    unsigned char *ypred_ptr = x->predictor;
+    int y_stride = x->dst.y_stride;
+    int mode = x->mbmi.mode;
+    int Up = x->up_available;
+    int Left = x->left_available;
+
+    vp8_build_intra_predictors_mby_neon_func(y_buffer, ypred_ptr, y_stride, mode, Up, Left);
+}
+#endif
+
+
+#if HAVE_ARMV7
+extern void vp8_build_intra_predictors_mby_s_neon_func(
+    unsigned char *y_buffer,
+    unsigned char *ypred_ptr,
+    int y_stride,
+    int mode,
+    int Up,
+    int Left);
+
+void vp8_build_intra_predictors_mby_s_neon(MACROBLOCKD *x)
+{
+    unsigned char *y_buffer = x->dst.y_buffer;
+    unsigned char *ypred_ptr = x->predictor;
+    int y_stride = x->dst.y_stride;
+    int mode = x->mbmi.mode;
+    int Up = x->up_available;
+    int Left = x->left_available;
+
+    vp8_build_intra_predictors_mby_s_neon_func(y_buffer, ypred_ptr, y_stride, mode, Up, Left);
+}
+
+#endif
diff --git a/vp8/common/arm/subpixel_arm.h b/vp8/common/arm/subpixel_arm.h
new file mode 100644
index 0000000..56aec55
--- /dev/null
+++ b/vp8/common/arm/subpixel_arm.h
@@ -0,0 +1,84 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef SUBPIXEL_ARM_H
+#define SUBPIXEL_ARM_H
+
+#if HAVE_ARMV6
+extern prototype_subpixel_predict(vp8_sixtap_predict16x16_armv6);
+extern prototype_subpixel_predict(vp8_sixtap_predict8x8_armv6);
+extern prototype_subpixel_predict(vp8_sixtap_predict8x4_armv6);
+extern prototype_subpixel_predict(vp8_sixtap_predict_armv6);
+extern prototype_subpixel_predict(vp8_bilinear_predict16x16_armv6);
+extern prototype_subpixel_predict(vp8_bilinear_predict8x8_armv6);
+extern prototype_subpixel_predict(vp8_bilinear_predict8x4_armv6);
+extern prototype_subpixel_predict(vp8_bilinear_predict4x4_armv6);
+
+#undef  vp8_subpix_sixtap16x16
+#define vp8_subpix_sixtap16x16 vp8_sixtap_predict16x16_armv6
+
+#undef  vp8_subpix_sixtap8x8
+#define vp8_subpix_sixtap8x8 vp8_sixtap_predict8x8_armv6
+
+#undef  vp8_subpix_sixtap8x4
+#define vp8_subpix_sixtap8x4 vp8_sixtap_predict8x4_armv6
+
+#undef  vp8_subpix_sixtap4x4
+#define vp8_subpix_sixtap4x4 vp8_sixtap_predict_armv6
+
+#undef  vp8_subpix_bilinear16x16
+#define vp8_subpix_bilinear16x16 vp8_bilinear_predict16x16_armv6
+
+#undef  vp8_subpix_bilinear8x8
+#define vp8_subpix_bilinear8x8 vp8_bilinear_predict8x8_armv6
+
+#undef  vp8_subpix_bilinear8x4
+#define vp8_subpix_bilinear8x4 vp8_bilinear_predict8x4_armv6
+
+#undef  vp8_subpix_bilinear4x4
+#define vp8_subpix_bilinear4x4 vp8_bilinear_predict4x4_armv6
+#endif
+
+#if HAVE_ARMV7
+extern prototype_subpixel_predict(vp8_sixtap_predict16x16_neon);
+extern prototype_subpixel_predict(vp8_sixtap_predict8x8_neon);
+extern prototype_subpixel_predict(vp8_sixtap_predict8x4_neon);
+extern prototype_subpixel_predict(vp8_sixtap_predict_neon);
+extern prototype_subpixel_predict(vp8_bilinear_predict16x16_neon);
+extern prototype_subpixel_predict(vp8_bilinear_predict8x8_neon);
+extern prototype_subpixel_predict(vp8_bilinear_predict8x4_neon);
+extern prototype_subpixel_predict(vp8_bilinear_predict4x4_neon);
+
+#undef  vp8_subpix_sixtap16x16
+#define vp8_subpix_sixtap16x16 vp8_sixtap_predict16x16_neon
+
+#undef  vp8_subpix_sixtap8x8
+#define vp8_subpix_sixtap8x8 vp8_sixtap_predict8x8_neon
+
+#undef  vp8_subpix_sixtap8x4
+#define vp8_subpix_sixtap8x4 vp8_sixtap_predict8x4_neon
+
+#undef  vp8_subpix_sixtap4x4
+#define vp8_subpix_sixtap4x4 vp8_sixtap_predict_neon
+
+#undef  vp8_subpix_bilinear16x16
+#define vp8_subpix_bilinear16x16 vp8_bilinear_predict16x16_neon
+
+#undef  vp8_subpix_bilinear8x8
+#define vp8_subpix_bilinear8x8 vp8_bilinear_predict8x8_neon
+
+#undef  vp8_subpix_bilinear8x4
+#define vp8_subpix_bilinear8x4 vp8_bilinear_predict8x4_neon
+
+#undef  vp8_subpix_bilinear4x4
+#define vp8_subpix_bilinear4x4 vp8_bilinear_predict4x4_neon
+#endif
+
+#endif
diff --git a/vp8/common/arm/systemdependent.c b/vp8/common/arm/systemdependent.c
new file mode 100644
index 0000000..ecc6929
--- /dev/null
+++ b/vp8/common/arm/systemdependent.c
@@ -0,0 +1,148 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "g_common.h"
+#include "pragmas.h"
+#include "subpixel.h"
+#include "loopfilter.h"
+#include "recon.h"
+#include "idct.h"
+#include "onyxc_int.h"
+
+void (*vp8_build_intra_predictors_mby_ptr)(MACROBLOCKD *x);
+extern void vp8_build_intra_predictors_mby(MACROBLOCKD *x);
+extern void vp8_build_intra_predictors_mby_neon(MACROBLOCKD *x);
+
+void (*vp8_build_intra_predictors_mby_s_ptr)(MACROBLOCKD *x);
+extern void vp8_build_intra_predictors_mby_s(MACROBLOCKD *x);
+extern void vp8_build_intra_predictors_mby_s_neon(MACROBLOCKD *x);
+
+void vp8_machine_specific_config(VP8_COMMON *ctx)
+{
+#if CONFIG_RUNTIME_CPU_DETECT
+    VP8_COMMON_RTCD *rtcd = &ctx->rtcd;
+
+#if HAVE_ARMV7
+    rtcd->subpix.sixtap16x16   = vp8_sixtap_predict16x16_neon;
+    rtcd->subpix.sixtap8x8     = vp8_sixtap_predict8x8_neon;
+    rtcd->subpix.sixtap8x4     = vp8_sixtap_predict8x4_neon;
+    rtcd->subpix.sixtap4x4     = vp8_sixtap_predict_neon;
+    rtcd->subpix.bilinear16x16 = vp8_bilinear_predict16x16_neon;
+    rtcd->subpix.bilinear8x8   = vp8_bilinear_predict8x8_neon;
+    rtcd->subpix.bilinear8x4   = vp8_bilinear_predict8x4_neon;
+    rtcd->subpix.bilinear4x4   = vp8_bilinear_predict4x4_neon;
+
+    rtcd->idct.idct1        = vp8_short_idct4x4llm_1_neon;
+    rtcd->idct.idct16       = vp8_short_idct4x4llm_neon;
+    rtcd->idct.idct1_scalar = vp8_dc_only_idct_neon;
+    rtcd->idct.iwalsh1      = vp8_short_inv_walsh4x4_1_neon;
+    rtcd->idct.iwalsh16     = vp8_short_inv_walsh4x4_neon;
+
+    rtcd->loopfilter.normal_mb_v = vp8_loop_filter_mbv_neon;
+    rtcd->loopfilter.normal_b_v  = vp8_loop_filter_bv_neon;
+    rtcd->loopfilter.normal_mb_h = vp8_loop_filter_mbh_neon;
+    rtcd->loopfilter.normal_b_h  = vp8_loop_filter_bh_neon;
+    rtcd->loopfilter.simple_mb_v = vp8_loop_filter_mbvs_neon;
+    rtcd->loopfilter.simple_b_v  = vp8_loop_filter_bvs_neon;
+    rtcd->loopfilter.simple_mb_h = vp8_loop_filter_mbhs_neon;
+    rtcd->loopfilter.simple_b_h  = vp8_loop_filter_bhs_neon;
+
+    rtcd->recon.copy16x16   = vp8_copy_mem16x16_neon;
+    rtcd->recon.copy8x8     = vp8_copy_mem8x8_neon;
+    rtcd->recon.copy8x4     = vp8_copy_mem8x4_neon;
+    rtcd->recon.recon       = vp8_recon_b_neon;
+    rtcd->recon.recon2      = vp8_recon2b_neon;
+    rtcd->recon.recon4      = vp8_recon4b_neon;
+#elif HAVE_ARMV6
+
+    rtcd->subpix.sixtap16x16   = vp8_sixtap_predict16x16_armv6;
+    rtcd->subpix.sixtap8x8     = vp8_sixtap_predict8x8_armv6;
+    rtcd->subpix.sixtap8x4     = vp8_sixtap_predict8x4_armv6;
+    rtcd->subpix.sixtap4x4     = vp8_sixtap_predict_armv6;
+    rtcd->subpix.bilinear16x16 = vp8_bilinear_predict16x16_armv6;
+    rtcd->subpix.bilinear8x8   = vp8_bilinear_predict8x8_armv6;
+    rtcd->subpix.bilinear8x4   = vp8_bilinear_predict8x4_armv6;
+    rtcd->subpix.bilinear4x4   = vp8_bilinear_predict4x4_armv6;
+
+    rtcd->idct.idct1        = vp8_short_idct4x4llm_1_v6;
+    rtcd->idct.idct16       = vp8_short_idct4x4llm_v6_dual;
+    rtcd->idct.idct1_scalar = vp8_dc_only_idct_armv6;
+    rtcd->idct.iwalsh1      = vp8_short_inv_walsh4x4_1_armv6;
+    rtcd->idct.iwalsh16     = vp8_short_inv_walsh4x4_armv6;
+
+    rtcd->loopfilter.normal_mb_v = vp8_loop_filter_mbv_armv6;
+    rtcd->loopfilter.normal_b_v  = vp8_loop_filter_bv_armv6;
+    rtcd->loopfilter.normal_mb_h = vp8_loop_filter_mbh_armv6;
+    rtcd->loopfilter.normal_b_h  = vp8_loop_filter_bh_armv6;
+    rtcd->loopfilter.simple_mb_v = vp8_loop_filter_mbvs_armv6;
+    rtcd->loopfilter.simple_b_v  = vp8_loop_filter_bvs_armv6;
+    rtcd->loopfilter.simple_mb_h = vp8_loop_filter_mbhs_armv6;
+    rtcd->loopfilter.simple_b_h  = vp8_loop_filter_bhs_armv6;
+
+    rtcd->recon.copy16x16   = vp8_copy_mem16x16_v6;
+    rtcd->recon.copy8x8     = vp8_copy_mem8x8_v6;
+    rtcd->recon.copy8x4     = vp8_copy_mem8x4_v6;
+    rtcd->recon.recon       = vp8_recon_b_armv6;
+    rtcd->recon.recon2      = vp8_recon2b_armv6;
+    rtcd->recon.recon4      = vp8_recon4b_armv6;
+#else
+//pure c
+    rtcd->idct.idct1        = vp8_short_idct4x4llm_1_c;
+    rtcd->idct.idct16       = vp8_short_idct4x4llm_c;
+    rtcd->idct.idct1_scalar = vp8_dc_only_idct_c;
+    rtcd->idct.iwalsh1      = vp8_short_inv_walsh4x4_1_c;
+    rtcd->idct.iwalsh16     = vp8_short_inv_walsh4x4_c;
+
+    rtcd->recon.copy16x16   = vp8_copy_mem16x16_c;
+    rtcd->recon.copy8x8     = vp8_copy_mem8x8_c;
+    rtcd->recon.copy8x4     = vp8_copy_mem8x4_c;
+    rtcd->recon.recon      = vp8_recon_b_c;
+    rtcd->recon.recon2      = vp8_recon2b_c;
+    rtcd->recon.recon4     = vp8_recon4b_c;
+
+    rtcd->subpix.sixtap16x16   = vp8_sixtap_predict16x16_c;
+    rtcd->subpix.sixtap8x8     = vp8_sixtap_predict8x8_c;
+    rtcd->subpix.sixtap8x4     = vp8_sixtap_predict8x4_c;
+    rtcd->subpix.sixtap4x4     = vp8_sixtap_predict_c;
+    rtcd->subpix.bilinear16x16 = vp8_bilinear_predict16x16_c;
+    rtcd->subpix.bilinear8x8   = vp8_bilinear_predict8x8_c;
+    rtcd->subpix.bilinear8x4   = vp8_bilinear_predict8x4_c;
+    rtcd->subpix.bilinear4x4   = vp8_bilinear_predict4x4_c;
+
+    rtcd->loopfilter.normal_mb_v = vp8_loop_filter_mbv_c;
+    rtcd->loopfilter.normal_b_v  = vp8_loop_filter_bv_c;
+    rtcd->loopfilter.normal_mb_h = vp8_loop_filter_mbh_c;
+    rtcd->loopfilter.normal_b_h  = vp8_loop_filter_bh_c;
+    rtcd->loopfilter.simple_mb_v = vp8_loop_filter_mbvs_c;
+    rtcd->loopfilter.simple_b_v  = vp8_loop_filter_bvs_c;
+    rtcd->loopfilter.simple_mb_h = vp8_loop_filter_mbhs_c;
+    rtcd->loopfilter.simple_b_h  = vp8_loop_filter_bhs_c;
+#endif
+
+    rtcd->postproc.down        = vp8_mbpost_proc_down_c;
+    rtcd->postproc.across      = vp8_mbpost_proc_across_ip_c;
+    rtcd->postproc.downacross  = vp8_post_proc_down_and_across_c;
+    rtcd->postproc.addnoise    = vp8_plane_add_noise_c;
+#endif
+
+#if HAVE_ARMV7
+    vp8_build_intra_predictors_mby_ptr = vp8_build_intra_predictors_mby_neon;
+    vp8_build_intra_predictors_mby_s_ptr = vp8_build_intra_predictors_mby_s_neon;
+#elif HAVE_ARMV6
+    vp8_build_intra_predictors_mby_ptr = vp8_build_intra_predictors_mby;
+    vp8_build_intra_predictors_mby_s_ptr = vp8_build_intra_predictors_mby_s;
+#else
+    vp8_build_intra_predictors_mby_ptr = vp8_build_intra_predictors_mby;
+    vp8_build_intra_predictors_mby_s_ptr = vp8_build_intra_predictors_mby_s;
+
+#endif
+
+}
diff --git a/vp8/common/arm/vpx_asm_offsets.c b/vp8/common/arm/vpx_asm_offsets.c
new file mode 100644
index 0000000..68634bf
--- /dev/null
+++ b/vp8/common/arm/vpx_asm_offsets.c
@@ -0,0 +1,91 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include <stddef.h>
+
+#if CONFIG_VP8_ENCODER
+#include "vpx_scale/yv12config.h"
+#endif
+
+#if CONFIG_VP8_DECODER
+#include "onyxd_int.h"
+#endif
+
+#define DEFINE(sym, val) int sym = val;
+
+/*
+#define BLANK() asm volatile("\n->" : : )
+*/
+
+/*
+ * int main(void)
+ * {
+ */
+
+#if CONFIG_VP8_DECODER || CONFIG_VP8_ENCODER
+DEFINE(yv12_buffer_config_y_width,               offsetof(YV12_BUFFER_CONFIG, y_width));
+DEFINE(yv12_buffer_config_y_height,              offsetof(YV12_BUFFER_CONFIG, y_height));
+DEFINE(yv12_buffer_config_y_stride,              offsetof(YV12_BUFFER_CONFIG, y_stride));
+DEFINE(yv12_buffer_config_uv_width,               offsetof(YV12_BUFFER_CONFIG, uv_width));
+DEFINE(yv12_buffer_config_uv_height,              offsetof(YV12_BUFFER_CONFIG, uv_height));
+DEFINE(yv12_buffer_config_uv_stride,              offsetof(YV12_BUFFER_CONFIG, uv_stride));
+DEFINE(yv12_buffer_config_y_buffer,              offsetof(YV12_BUFFER_CONFIG, y_buffer));
+DEFINE(yv12_buffer_config_u_buffer,              offsetof(YV12_BUFFER_CONFIG, u_buffer));
+DEFINE(yv12_buffer_config_v_buffer,              offsetof(YV12_BUFFER_CONFIG, v_buffer));
+DEFINE(yv12_buffer_config_border,               offsetof(YV12_BUFFER_CONFIG, border));
+#endif
+
+#if CONFIG_VP8_DECODER
+DEFINE(mb_diff,                                 offsetof(MACROBLOCKD, diff));
+DEFINE(mb_predictor,                            offsetof(MACROBLOCKD, predictor));
+DEFINE(mb_dst_y_stride,                          offsetof(MACROBLOCKD, dst.y_stride));
+DEFINE(mb_dst_y_buffer,                          offsetof(MACROBLOCKD, dst.y_buffer));
+DEFINE(mb_dst_u_buffer,                          offsetof(MACROBLOCKD, dst.u_buffer));
+DEFINE(mb_dst_v_buffer,                          offsetof(MACROBLOCKD, dst.v_buffer));
+DEFINE(mb_mbmi_mode,                            offsetof(MACROBLOCKD, mbmi.mode));
+DEFINE(mb_up_available,                          offsetof(MACROBLOCKD, up_available));
+DEFINE(mb_left_available,                        offsetof(MACROBLOCKD, left_available));
+
+DEFINE(detok_scan,                              offsetof(DETOK, scan));
+DEFINE(detok_ptr_onyxblock2context_leftabove,    offsetof(DETOK, ptr_onyxblock2context_leftabove));
+DEFINE(detok_onyx_coef_tree_ptr,                  offsetof(DETOK, vp8_coef_tree_ptr));
+DEFINE(detok_teb_base_ptr,                        offsetof(DETOK, teb_base_ptr));
+DEFINE(detok_norm_ptr,                           offsetof(DETOK, norm_ptr));
+DEFINE(detok_ptr_onyx_coef_bands_x,                offsetof(DETOK, ptr_onyx_coef_bands_x));
+
+DEFINE(DETOK_A,                                 offsetof(DETOK, A));
+DEFINE(DETOK_L,                                 offsetof(DETOK, L));
+
+DEFINE(detok_qcoeff_start_ptr,                    offsetof(DETOK, qcoeff_start_ptr));
+DEFINE(detok_current_bc,                         offsetof(DETOK, current_bc));
+DEFINE(detok_coef_probs,                         offsetof(DETOK, coef_probs));
+DEFINE(detok_eob,                               offsetof(DETOK, eob));
+
+DEFINE(bool_decoder_lowvalue,                   offsetof(BOOL_DECODER, lowvalue));
+DEFINE(bool_decoder_range,                      offsetof(BOOL_DECODER, range));
+DEFINE(bool_decoder_value,                      offsetof(BOOL_DECODER, value));
+DEFINE(bool_decoder_count,                      offsetof(BOOL_DECODER, count));
+DEFINE(bool_decoder_user_buffer,                offsetof(BOOL_DECODER, user_buffer));
+DEFINE(bool_decoder_user_buffer_sz,             offsetof(BOOL_DECODER, user_buffer_sz));
+DEFINE(bool_decoder_decode_buffer,              offsetof(BOOL_DECODER, decode_buffer));
+DEFINE(bool_decoder_read_ptr,                   offsetof(BOOL_DECODER, read_ptr));
+DEFINE(bool_decoder_write_ptr,                  offsetof(BOOL_DECODER, write_ptr));
+
+DEFINE(tokenextrabits_min_val,                   offsetof(TOKENEXTRABITS, min_val));
+DEFINE(tokenextrabits_length,                   offsetof(TOKENEXTRABITS, Length));
+#endif
+
+//add asserts for any offset that is not supported by assembly code
+//add asserts for any size that is not supported by assembly code
+/*
+ * return 0;
+ * }
+ */
diff --git a/vp8/common/bigend.h b/vp8/common/bigend.h
new file mode 100644
index 0000000..6a91ba1
--- /dev/null
+++ b/vp8/common/bigend.h
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef _bigend_h
+#define _bigend_h
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define invert2(x) ( (((x)>>8)&0x00ff) | (((x)<<8)&0xff00) )
+#define invert4(x) ( ((invert2(x)&0x0000ffff)<<16) | (invert2((x>>16))&0x0000ffff) )
+
+#define high_byte(x) (unsigned char)x
+#define mid2Byte(x) (unsigned char)(x >> 8)
+#define mid1Byte(x) (unsigned char)(x >> 16)
+#define low_byte(x) (unsigned char)(x >> 24)
+
+#define SWAPENDS 1
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/vp8/common/blockd.c b/vp8/common/blockd.c
new file mode 100644
index 0000000..53f5e72
--- /dev/null
+++ b/vp8/common/blockd.c
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "blockd.h"
+#include "vpx_mem/vpx_mem.h"
+
+void vp8_setup_temp_context(TEMP_CONTEXT *t, ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l, int count)
+{
+    vpx_memcpy(t->l, l, sizeof(ENTROPY_CONTEXT) * count);
+    vpx_memcpy(t->a, a, sizeof(ENTROPY_CONTEXT) * count);
+}
+
+const int vp8_block2left[25] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 1, 1, 0, 0, 1, 1, 0};
+const int vp8_block2above[25] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 0, 1, 0, 1, 0, 1, 0};
+const int vp8_block2type[25] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1};
+const int vp8_block2context[25] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3};
diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h
new file mode 100644
index 0000000..84ed53a
--- /dev/null
+++ b/vp8/common/blockd.h
@@ -0,0 +1,299 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_BLOCKD_H
+#define __INC_BLOCKD_H
+
+void vpx_log(const char *format, ...);
+
+#include "vpx_ports/config.h"
+#include "vpx_scale/yv12config.h"
+#include "mv.h"
+#include "treecoder.h"
+#include "subpixel.h"
+#include "vpx_ports/mem.h"
+
+#define TRUE    1
+#define FALSE   0
+
+//#define DCPRED 1
+#define DCPREDSIMTHRESH 0
+#define DCPREDCNTTHRESH 3
+
+#define Y1CONTEXT 0
+#define UCONTEXT 1
+#define VCONTEXT 2
+#define Y2CONTEXT 3
+
+#define MB_FEATURE_TREE_PROBS   3
+#define MAX_MB_SEGMENTS         4
+
+#define MAX_REF_LF_DELTAS       4
+#define MAX_MODE_LF_DELTAS      4
+
+// Segment Feature Masks
+#define SEGMENT_DELTADATA   0
+#define SEGMENT_ABSDATA     1
+
+typedef struct
+{
+    int r, c;
+} POS;
+
+
+typedef int ENTROPY_CONTEXT;
+
+typedef struct
+{
+    ENTROPY_CONTEXT l[4];
+    ENTROPY_CONTEXT a[4];
+} TEMP_CONTEXT;
+
+extern void vp8_setup_temp_context(TEMP_CONTEXT *t, ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l, int count);
+extern const int vp8_block2left[25];
+extern const int vp8_block2above[25];
+extern const int vp8_block2type[25];
+extern const int vp8_block2context[25];
+
+#define VP8_COMBINEENTROPYCONTEXTS( Dest, A, B) \
+    Dest = ((A)!=0) + ((B)!=0);
+
+
+typedef enum
+{
+    KEY_FRAME = 0,
+    INTER_FRAME = 1
+} FRAME_TYPE;
+
+typedef enum
+{
+    DC_PRED,            // average of above and left pixels
+    V_PRED,             // vertical prediction
+    H_PRED,             // horizontal prediction
+    TM_PRED,            // Truemotion prediction
+    B_PRED,             // block based prediction, each block has its own prediction mode
+
+    NEARESTMV,
+    NEARMV,
+    ZEROMV,
+    NEWMV,
+    SPLITMV,
+
+    MB_MODE_COUNT
+} MB_PREDICTION_MODE;
+
+// Macroblock level features
+typedef enum
+{
+    MB_LVL_ALT_Q = 0,               // Use alternate Quantizer ....
+    MB_LVL_ALT_LF = 1,              // Use alternate loop filter value...
+    MB_LVL_MAX = 2,                 // Number of MB level features supported
+
+} MB_LVL_FEATURES;
+
+// Segment Feature Masks
+#define SEGMENT_ALTQ    0x01
+#define SEGMENT_ALT_LF  0x02
+
+#define VP8_YMODES  (B_PRED + 1)
+#define VP8_UV_MODES (TM_PRED + 1)
+
+#define VP8_MVREFS (1 + SPLITMV - NEARESTMV)
+
+typedef enum
+{
+    B_DC_PRED,          // average of above and left pixels
+    B_TM_PRED,
+
+    B_VE_PRED,           // vertical prediction
+    B_HE_PRED,           // horizontal prediction
+
+    B_LD_PRED,
+    B_RD_PRED,
+
+    B_VR_PRED,
+    B_VL_PRED,
+    B_HD_PRED,
+    B_HU_PRED,
+
+    LEFT4X4,
+    ABOVE4X4,
+    ZERO4X4,
+    NEW4X4,
+
+    B_MODE_COUNT
+} B_PREDICTION_MODE;
+
+#define VP8_BINTRAMODES (B_HU_PRED + 1)  /* 10 */
+#define VP8_SUBMVREFS (1 + NEW4X4 - LEFT4X4)
+
+/* For keyframes, intra block modes are predicted by the (already decoded)
+   modes for the Y blocks to the left and above us; for interframes, there
+   is a single probability table. */
+
+typedef struct
+{
+    B_PREDICTION_MODE mode;
+    union
+    {
+        int as_int;
+        MV  as_mv;
+    } mv;
+} B_MODE_INFO;
+
+
+typedef enum
+{
+    INTRA_FRAME = 0,
+    LAST_FRAME = 1,
+    GOLDEN_FRAME = 2,
+    ALTREF_FRAME = 3,
+    MAX_REF_FRAMES = 4
+} MV_REFERENCE_FRAME;
+
+typedef struct
+{
+    MB_PREDICTION_MODE mode, uv_mode;
+    MV_REFERENCE_FRAME ref_frame;
+    union
+    {
+        int as_int;
+        MV  as_mv;
+    } mv;
+    int partitioning;
+    int partition_count;
+    int mb_skip_coeff;                                //does this mb has coefficients at all, 1=no coefficients, 0=need decode tokens
+    int dc_diff;
+    unsigned char   segment_id;                  // Which set of segmentation parameters should be used for this MB
+    int force_no_skip;
+
+    B_MODE_INFO partition_bmi[16];
+
+} MB_MODE_INFO;
+
+
+typedef struct
+{
+    MB_MODE_INFO mbmi;
+    B_MODE_INFO bmi[16];
+} MODE_INFO;
+
+
+typedef struct
+{
+    short *qcoeff;
+    short *dqcoeff;
+    unsigned char  *predictor;
+    short *diff;
+    short *reference;
+
+    short(*dequant)[4];
+
+    // 16 Y blocks, 4 U blocks, 4 V blocks each with 16 entries
+    unsigned char **base_pre;
+    int pre;
+    int pre_stride;
+
+    unsigned char **base_dst;
+    int dst;
+    int dst_stride;
+
+    int eob;
+
+    B_MODE_INFO bmi;
+
+} BLOCKD;
+
+typedef struct
+{
+    DECLARE_ALIGNED(16, short, diff[400]);      // from idct diff
+    DECLARE_ALIGNED(16, unsigned char,  predictor[384]);
+    DECLARE_ALIGNED(16, short, reference[384]);
+    DECLARE_ALIGNED(16, short, qcoeff[400]);
+    DECLARE_ALIGNED(16, short, dqcoeff[400]);
+
+    // 16 Y blocks, 4 U, 4 V, 1 DC 2nd order block, each with 16 entries.
+    BLOCKD block[25];
+
+    YV12_BUFFER_CONFIG pre; // Filtered copy of previous frame reconstruction
+    YV12_BUFFER_CONFIG dst;
+
+    MODE_INFO *mode_info_context;
+    MODE_INFO *mode_info;
+
+    int mode_info_stride;
+
+    FRAME_TYPE frame_type;
+
+    MB_MODE_INFO mbmi;
+
+    int up_available;
+    int left_available;
+
+    // Y,U,V,Y2
+    ENTROPY_CONTEXT *above_context[4];   // row of context for each plane
+    ENTROPY_CONTEXT(*left_context)[4];   // (up to) 4 contexts ""
+
+    // 0 indicates segmentation at MB level is not enabled. Otherwise the individual bits indicate which features are active.
+    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_segement_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
+    vp8_prob mb_segment_tree_probs[MB_FEATURE_TREE_PROBS];         // Probability Tree used to code Segment number
+
+    signed char segment_feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];            // Segment parameters
+
+    // mode_based Loop filter adjustment
+    unsigned char mode_ref_lf_delta_enabled;
+    unsigned char mode_ref_lf_delta_update;
+
+    // Delta values have the range +/- MAX_LOOP_FILTER
+    //char ref_lf_deltas[MAX_REF_LF_DELTAS];                      // 0 = Intra, Last, GF, ARF
+    //char mode_lf_deltas[MAX_MODE_LF_DELTAS];                            // 0 = BPRED, ZERO_MV, MV, SPLIT
+    signed char ref_lf_deltas[MAX_REF_LF_DELTAS];                     // 0 = Intra, Last, GF, ARF
+    signed char mode_lf_deltas[MAX_MODE_LF_DELTAS];                           // 0 = BPRED, ZERO_MV, MV, SPLIT
+
+    // Distance of MB away from frame edges
+    int mb_to_left_edge;
+    int mb_to_right_edge;
+    int mb_to_top_edge;
+    int mb_to_bottom_edge;
+
+    //char * gf_active_ptr;
+    signed char *gf_active_ptr;
+
+    unsigned int frames_since_golden;
+    unsigned int frames_till_alt_ref_frame;
+    vp8_subpix_fn_t  subpixel_predict;
+    vp8_subpix_fn_t  subpixel_predict8x4;
+    vp8_subpix_fn_t  subpixel_predict8x8;
+    vp8_subpix_fn_t  subpixel_predict16x16;
+
+    void *current_bc;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+    struct VP8_COMMON_RTCD  *rtcd;
+#endif
+} MACROBLOCKD;
+
+
+extern void vp8_build_block_doffsets(MACROBLOCKD *x);
+extern void vp8_setup_block_dptrs(MACROBLOCKD *x);
+
+#endif  /* __INC_BLOCKD_H */
diff --git a/vp8/common/boolcoder.h b/vp8/common/boolcoder.h
new file mode 100644
index 0000000..0659d48
--- /dev/null
+++ b/vp8/common/boolcoder.h
@@ -0,0 +1,569 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef bool_coder_h
+#define bool_coder_h 1
+
+/* Arithmetic bool coder with largish probability range.
+   Timothy S Murphy  6 August 2004 */
+
+/* So as not to force users to drag in too much of my idiosyncratic C++ world,
+   I avoid fancy storage management. */
+
+#include <assert.h>
+
+#include <stddef.h>
+#include <stdio.h>
+
+typedef unsigned char vp8bc_index_t; // probability index
+
+/* There are a couple of slight variants in the details of finite-precision
+   arithmetic coding.  May be safely ignored by most users. */
+
+enum vp8bc_rounding
+{
+    vp8bc_down = 0,     // just like VP8
+    vp8bc_down_full = 1, // handles minimum probability correctly
+    vp8bc_up = 2
+};
+
+#if _MSC_VER
+
+/* Note that msvc by default does not inline _anything_ (regardless of the
+   setting of inline_depth) and that a command-line option (-Ob1 or -Ob2)
+   is required to inline even the smallest functions. */
+
+#   pragma inline_depth( 255)           // I mean it when I inline something
+#   pragma warning( disable : 4099)     // No class vs. struct harassment
+#   pragma warning( disable : 4250)     // dominance complaints
+#   pragma warning( disable : 4284)     // operator-> in templates
+#   pragma warning( disable : 4800)     // bool conversion
+
+// don't let prefix ++,-- stand in for postfix, disaster would ensue
+
+#   pragma warning( error : 4620 4621)
+
+#endif  // _MSC_VER
+
+
+#if __cplusplus
+
+// Sometimes one wishes to be definite about integer lengths.
+
+struct int_types
+{
+    typedef const bool cbool;
+    typedef const signed char cchar;
+    typedef const short cshort;
+    typedef const int cint;
+    typedef const int clong;
+
+    typedef const double cdouble;
+    typedef const size_t csize_t;
+
+    typedef unsigned char uchar;    // 8 bits
+    typedef const uchar cuchar;
+
+    typedef short int16;
+    typedef unsigned short uint16;
+    typedef const int16 cint16;
+    typedef const uint16 cuint16;
+
+    typedef int int32;
+    typedef unsigned int uint32;
+    typedef const int32 cint32;
+    typedef const uint32 cuint32;
+
+    typedef unsigned int uint;
+    typedef unsigned int ulong;
+    typedef const uint cuint;
+    typedef const ulong culong;
+
+
+    // All structs consume space, may as well have a vptr.
+
+    virtual ~int_types();
+};
+
+
+struct bool_coder_spec;
+struct bool_coder;
+struct bool_writer;
+struct bool_reader;
+
+
+struct bool_coder_namespace : int_types
+{
+    typedef vp8bc_index_t Index;
+    typedef bool_coder_spec Spec;
+    typedef const Spec c_spec;
+
+    enum Rounding
+    {
+        Down = vp8bc_down,
+        down_full = vp8bc_down_full,
+        Up = vp8bc_up
+    };
+};
+
+
+// Archivable specification of a bool coder includes rounding spec
+// and probability mapping table.  The latter replaces a uchar j
+// (0 <= j < 256) with an arbitrary uint16 tbl[j] = p.
+// p/65536 is then the probability of a zero.
+
+struct bool_coder_spec : bool_coder_namespace
+{
+    friend struct bool_coder;
+    friend struct bool_writer;
+    friend struct bool_reader;
+    friend struct bool_coder_spec_float;
+    friend struct bool_coder_spec_explicit_table;
+    friend struct bool_coder_spec_exponential_table;
+    friend struct BPsrc;
+private:
+    uint w;                 // precision
+    Rounding r;
+
+    uint ebits, mbits, ebias;
+    uint32 mmask;
+
+    Index max_index, half_index;
+
+    uint32 mantissa(Index i) const
+    {
+        assert(i < half_index);
+        return (1 << mbits) + (i & mmask);
+    }
+    uint exponent(Index i) const
+    {
+        assert(i < half_index);
+        return ebias - (i >> mbits);
+    }
+
+    uint16 Ptbl[256];       // kinda clunky, but so is storage management.
+
+    /* Cost in bits of encoding a zero at every probability, scaled by 2^20.
+       Assumes that index is at most 8 bits wide. */
+
+    uint32 Ctbl[256];
+
+    uint32 split(Index i, uint32 R) const    // 1 <= split <= max( 1, R-1)
+    {
+        if (!ebias)
+            return 1 + (((R - 1) * Ptbl[i]) >> 16);
+
+        if (i >= half_index)
+            return R - split(max_index - i, R);
+
+        return 1 + (((R - 1) * mantissa(i)) >> exponent(i));
+    }
+
+    uint32 max_range() const
+    {
+        return (1 << w) - (r == down_full ? 0 : 1);
+    }
+    uint32 min_range() const
+    {
+        return (1 << (w - 1)) + (r == down_full ? 1 : 0);
+    }
+    uint32 Rinc() const
+    {
+        return r == Up ? 1 : 0;
+    }
+
+    void check_prec() const;
+
+    bool float_init(uint Ebits, uint Mbits);
+
+    void cost_init();
+
+    bool_coder_spec(
+        uint prec, Rounding rr, uint Ebits = 0, uint Mbits = 0
+    )
+        : w(prec), r(rr)
+    {
+        float_init(Ebits, Mbits);
+    }
+public:
+    // Read complete spec from file.
+    bool_coder_spec(FILE *);
+
+    // Write spec to file.
+    void dump(FILE *) const;
+
+    // return probability index best approximating prob.
+    Index operator()(double prob) const;
+
+    // probability corresponding to index
+    double operator()(Index i) const;
+
+    Index complement(Index i) const
+    {
+        return max_index - i;
+    }
+
+    Index max_index() const
+    {
+        return max_index;
+    }
+    Index half_index() const
+    {
+        return half_index;
+    }
+
+    uint32 cost_zero(Index i) const
+    {
+        return Ctbl[i];
+    }
+    uint32 cost_one(Index i) const
+    {
+        return Ctbl[ max_index - i];
+    }
+    uint32 cost_bit(Index i, bool b) const
+    {
+        return Ctbl[b? max_index-i:i];
+    }
+};
+
+
+/* Pseudo floating-point probability specification.
+
+   At least one of Ebits and Mbits must be nonzero.
+
+   Since all arithmetic is done at 32 bits, Ebits is at most 5.
+
+   Total significant bits in index is Ebits + Mbits + 1.
+
+   Below the halfway point (i.e. when the top significant bit is 0),
+   the index is (e << Mbits) + m.
+
+   The exponent e is between 0 and (2**Ebits) - 1,
+   the mantissa m is between 0 and (2**Mbits) - 1.
+
+   Prepending an implicit 1 to the mantissa, the probability is then
+
+        (2**Mbits + m) >> (e - 2**Ebits - 1 - Mbits),
+
+   which has (1/2)**(2**Ebits + 1) as a minimum
+   and (1/2) * [1 - 2**(Mbits + 1)] as a maximum.
+
+   When the index is above the halfway point, the probability is the
+   complement of the probability associated to the complement of the index.
+
+   Note that the probability increases with the index and that, because of
+   the symmetry, we cannot encode probability exactly 1/2; though we
+   can get as close to 1/2 as we like, provided we have enough Mbits.
+
+   The latter is of course not a problem in practice, one never has
+   exact probabilities and entropy errors are second order, that is, the
+   "overcoding" of a zero will be largely compensated for by the
+   "undercoding" of a one (or vice-versa).
+
+   Compared to arithmetic probability specs (a la VP8), this will do better
+   at very high and low probabilities and worse at probabilities near 1/2,
+   as well as facilitating the usage of wider or narrower probability indices.
+*/
+
+struct bool_coder_spec_float : bool_coder_spec
+{
+    bool_coder_spec_float(
+        uint Ebits = 3, uint Mbits = 4, Rounding rr = down_full, uint prec = 12
+    )
+        : bool_coder_spec(prec, rr, Ebits, Mbits)
+    {
+        cost_init();
+    }
+};
+
+
+struct bool_coder_spec_explicit_table : bool_coder_spec
+{
+    bool_coder_spec_explicit_table(
+        cuint16 probability_table[256] = 0,  // default is tbl[i] = i << 8.
+        Rounding = down_full,
+        uint precision = 16
+    );
+};
+
+// Contruct table via multiplicative interpolation between
+// p[128] = 1/2  and p[0] = (1/2)^x.
+// Since we are working with 16-bit precision, x is at most 16.
+// For probabilities to increase with i, we must have x > 1.
+// For 0 <= i <= 128, p[i] = (1/2)^{ 1 + [1 - (i/128)]*[x-1] }.
+// Finally, p[128+i] = 1 - p[128 - i].
+
+struct bool_coder_spec_exponential_table : bool_coder_spec
+{
+    bool_coder_spec_exponential_table(uint x, Rounding = down_full, uint prec = 16);
+};
+
+
+// Commonalities between writer and reader.
+
+struct bool_coder : bool_coder_namespace
+{
+    friend struct bool_writer;
+    friend struct bool_reader;
+    friend struct BPsrc;
+private:
+    uint32 Low, Range;
+    cuint32 min_range;
+    cuint32 rinc;
+    c_spec spec;
+
+    void _reset()
+    {
+        Low = 0;
+        Range = spec.max_range();
+    }
+
+    bool_coder(c_spec &s)
+        :  min_range(s.min_range()),
+           rinc(s.Rinc()),
+           spec(s)
+    {
+        _reset();
+    }
+
+    uint32 half() const
+    {
+        return 1 + ((Range - 1) >> 1);
+    }
+public:
+    c_spec &Spec() const
+    {
+        return spec;
+    }
+};
+
+
+struct bool_writer : bool_coder
+{
+    friend struct BPsrc;
+private:
+    uchar *Bstart, *Bend, *B;
+    int bit_lag;
+    bool is_toast;
+    void carry();
+    void reset()
+    {
+        _reset();
+        bit_lag = 32 - spec.w;
+        is_toast = 0;
+    }
+    void raw(bool value, uint32 split);
+public:
+    bool_writer(c_spec &, uchar *Dest, size_t Len);
+    virtual ~bool_writer();
+
+    void operator()(Index p, bool v)
+    {
+        raw(v, spec.split(p, Range));
+    }
+
+    uchar *buf() const
+    {
+        return Bstart;
+    }
+    size_t bytes_written() const
+    {
+        return B - Bstart;
+    }
+
+    // Call when done with input, flushes internal state.
+    // DO NOT write any more data after calling this.
+
+    bool_writer &flush();
+
+    void write_bits(int n, uint val)
+    {
+        if (n)
+        {
+            uint m = 1 << (n - 1);
+
+            do
+            {
+                raw((bool)(val & m), half());
+            }
+            while (m >>= 1);
+        }
+    }
+
+#   if 0
+    // We are agnostic about storage management.
+    // By default, overflows throw an assert but user can
+    // override to provide an expanding buffer using ...
+
+    virtual void overflow(uint Len) const;
+
+    // ... this function copies already-written data into new buffer
+    // and retains new buffer location.
+
+    void new_buffer(uchar *dest, uint Len);
+
+    // Note that storage management is the user's responsibility.
+#   endif
+};
+
+
+// This could be adjusted to use a little less lookahead.
+
+struct bool_reader : bool_coder
+{
+    friend struct BPsrc;
+private:
+    cuchar *const Bstart;   // for debugging
+    cuchar *B;
+    cuchar *const Bend;
+    cuint shf;
+    uint bct;
+    bool raw(uint32 split);
+public:
+    bool_reader(c_spec &s, cuchar *src, size_t Len);
+
+    bool operator()(Index p)
+    {
+        return raw(spec.split(p, Range));
+    }
+
+    uint read_bits(int num_bits)
+    {
+        uint v = 0;
+
+        while (--num_bits >= 0)
+            v += v + (raw(half()) ? 1 : 0);
+
+        return v;
+    }
+};
+
+extern "C" {
+
+#endif /*  __cplusplus */
+
+
+    /* C interface */
+
+    typedef struct bool_coder_spec bool_coder_spec;
+    typedef struct bool_writer bool_writer;
+    typedef struct bool_reader bool_reader;
+
+    typedef const bool_coder_spec c_bool_coder_spec;
+    typedef const bool_writer c_bool_writer;
+    typedef const bool_reader c_bool_reader;
+
+
+    /* Optionally override default precision when constructing coder_specs.
+       Just pass a zero pointer if you don't care.
+       Precision is at most 16 bits for table specs, at most 23 otherwise. */
+
+    struct vp8bc_prec
+    {
+        enum vp8bc_rounding r;      /* see top header file for def */
+        unsigned int prec;          /* range precision in bits */
+    };
+
+    typedef const struct vp8bc_prec vp8bc_c_prec;
+
+    /* bool_coder_spec contains mapping of uchars to actual probabilities
+       (16 bit uints) as well as (usually immaterial) selection of
+       exact finite-precision algorithm used (for now, the latter can only
+       be overridden using the C++ interface).
+       See comments above the corresponding C++ constructors for discussion,
+       especially of exponential probability table generation. */
+
+    bool_coder_spec *vp8bc_vp8spec(); // just like vp8
+
+    bool_coder_spec *vp8bc_literal_spec(
+        const unsigned short prob_map[256],  // 0 is like vp8 w/more precision
+        vp8bc_c_prec*
+    );
+
+    bool_coder_spec *vp8bc_float_spec(
+        unsigned int exponent_bits, unsigned int mantissa_bits, vp8bc_c_prec*
+    );
+
+    bool_coder_spec *vp8bc_exponential_spec(unsigned int min_exp, vp8bc_c_prec *);
+
+    bool_coder_spec *vp8bc_spec_from_file(FILE *);
+
+
+    void vp8bc_destroy_spec(c_bool_coder_spec *);
+
+    void vp8bc_spec_to_file(c_bool_coder_spec *, FILE *);
+
+
+    /* Nearest index to supplied probability of zero, 0 <= prob <= 1. */
+
+    vp8bc_index_t vp8bc_index(c_bool_coder_spec *, double prob);
+
+    vp8bc_index_t vp8bc_index_from_counts(
+        c_bool_coder_spec *p, unsigned int zero_ct, unsigned int one_ct
+    );
+
+    /* In case you want to look */
+
+    double vp8bc_probability(c_bool_coder_spec *, vp8bc_index_t);
+
+    /* Opposite index */
+
+    vp8bc_index_t vp8bc_complement(c_bool_coder_spec *, vp8bc_index_t);
+
+    /* Cost in bits of encoding a zero at given probability, scaled by 2^20.
+       (assumes that an int holds at least 32 bits). */
+
+    unsigned int vp8bc_cost_zero(c_bool_coder_spec *, vp8bc_index_t);
+
+    unsigned int vp8bc_cost_one(c_bool_coder_spec *, vp8bc_index_t);
+    unsigned int vp8bc_cost_bit(c_bool_coder_spec *, vp8bc_index_t, int);
+
+
+    /* bool_writer interface */
+
+    /* Length = 0 disables checking for writes beyond buffer end. */
+
+    bool_writer *vp8bc_create_writer(
+        c_bool_coder_spec *, unsigned char *Destination, size_t Length
+    );
+
+    /* Flushes out any buffered data and returns total # of bytes written. */
+
+    size_t vp8bc_destroy_writer(bool_writer *);
+
+    void vp8bc_write_bool(bool_writer *, int boolean_val, vp8bc_index_t false_prob);
+
+    void vp8bc_write_bits(
+        bool_writer *, unsigned int integer_value, int number_of_bits
+    );
+
+    c_bool_coder_spec *vp8bc_writer_spec(c_bool_writer *);
+
+
+    /* bool_reader interface */
+
+    /* Length = 0 disables checking for reads beyond buffer end. */
+
+    bool_reader *vp8bc_create_reader(
+        c_bool_coder_spec *, const unsigned char *Source, size_t Length
+    );
+    void vp8bc_destroy_reader(bool_reader *);
+
+    int vp8bc_read_bool(bool_reader *, vp8bc_index_t false_prob);
+
+    unsigned int vp8bc_read_bits(bool_reader *, int number_of_bits);
+
+    c_bool_coder_spec *vp8bc_reader_spec(c_bool_reader *);
+
+#if __cplusplus
+}
+#endif
+
+#endif  /* bool_coder_h */
diff --git a/vp8/common/codec_common_interface.h b/vp8/common/codec_common_interface.h
new file mode 100644
index 0000000..7881b0a
--- /dev/null
+++ b/vp8/common/codec_common_interface.h
@@ -0,0 +1,92 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+#ifndef CODEC_COMMON_INTERFACE_H
+#define CODEC_COMMON_INTERFACE_H
+
+#define __export
+#define _export
+#define dll_export   __declspec( dllexport )
+#define dll_import   __declspec( dllimport )
+
+// Playback ERROR Codes.
+#define NO_DECODER_ERROR            0
+#define REMOTE_DECODER_ERROR        -1
+
+#define DFR_BAD_DCT_COEFF           -100
+#define DFR_ZERO_LENGTH_FRAME       -101
+#define DFR_FRAME_SIZE_INVALID      -102
+#define DFR_OUTPUT_BUFFER_OVERFLOW  -103
+#define DFR_INVALID_FRAME_HEADER    -104
+#define FR_INVALID_MODE_TOKEN       -110
+#define ETR_ALLOCATION_ERROR        -200
+#define ETR_INVALID_ROOT_PTR        -201
+#define SYNCH_ERROR                 -400
+#define BUFFER_UNDERFLOW_ERROR      -500
+#define PB_IB_OVERFLOW_ERROR        -501
+
+// External error triggers
+#define PB_HEADER_CHECKSUM_ERROR    -601
+#define PB_DATA_CHECKSUM_ERROR      -602
+
+// DCT Error Codes
+#define DDCT_EXPANSION_ERROR        -700
+#define DDCT_INVALID_TOKEN_ERROR    -701
+
+// exception_errors
+#define GEN_EXCEPTIONS              -800
+#define EX_UNQUAL_ERROR             -801
+
+// Unrecoverable error codes
+#define FATAL_PLAYBACK_ERROR        -1000
+#define GEN_ERROR_CREATING_CDC      -1001
+#define GEN_THREAD_CREATION_ERROR   -1002
+#define DFR_CREATE_BMP_FAILED       -1003
+
+// YUV buffer configuration structure
+typedef struct
+{
+    int     y_width;
+    int     y_height;
+    int     y_stride;
+
+    int     uv_width;
+    int     uv_height;
+    int     uv_stride;
+
+    unsigned char   *y_buffer;
+    unsigned char   *u_buffer;
+    unsigned char   *v_buffer;
+
+} YUV_BUFFER_CONFIG;
+typedef enum
+{
+    C_SET_KEY_FRAME,
+    C_SET_FIXED_Q,
+    C_SET_FIRSTPASS_FILE,
+    C_SET_EXPERIMENTAL_MIN,
+    C_SET_EXPERIMENTAL_MAX = C_SET_EXPERIMENTAL_MIN + 255,
+    C_SET_CHECKPROTECT,
+    C_SET_TESTMODE,
+    C_SET_INTERNAL_SIZE,
+    C_SET_RECOVERY_FRAME,
+    C_SET_REFERENCEFRAME,
+    C_SET_GOLDENFRAME
+
+#ifndef VP50_COMP_INTERFACE
+    // Specialist test facilities.
+//    C_VCAP_PARAMS,              // DO NOT USE FOR NOW WITH VFW CODEC
+#endif
+
+} C_SETTING;
+
+typedef unsigned long C_SET_VALUE;
+
+
+#endif
diff --git a/vp8/common/coefupdateprobs.h b/vp8/common/coefupdateprobs.h
new file mode 100644
index 0000000..99affd6
--- /dev/null
+++ b/vp8/common/coefupdateprobs.h
@@ -0,0 +1,184 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/* Update probabilities for the nodes in the token entropy tree.
+   Generated file included by entropy.c */
+
+const vp8_prob vp8_coef_update_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1] =
+{
+    {
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255, },
+            {250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+    {
+        {
+            {217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255, },
+            {234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255, },
+        },
+        {
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+    {
+        {
+            {186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+    {
+        {
+            {248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255, },
+            {248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+};
diff --git a/vp8/common/common.h b/vp8/common/common.h
new file mode 100644
index 0000000..29f6d37
--- /dev/null
+++ b/vp8/common/common.h
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef common_h
+#define common_h 1
+
+#include <assert.h>
+
+/* Interface header for common constant data structures and lookup tables */
+
+#include "vpx_mem/vpx_mem.h"
+
+#include "common_types.h"
+
+/* Only need this for fixed-size arrays, for structs just assign. */
+
+#define vp8_copy( Dest, Src) { \
+        assert( sizeof( Dest) == sizeof( Src)); \
+        vpx_memcpy( Dest, Src, sizeof( Src)); \
+    }
+
+/* Use this for variably-sized arrays. */
+
+#define vp8_copy_array( Dest, Src, N) { \
+        assert( sizeof( *Dest) == sizeof( *Src)); \
+        vpx_memcpy( Dest, Src, N * sizeof( *Src)); \
+    }
+
+#define vp8_zero( Dest)  vpx_memset( &Dest, 0, sizeof( Dest));
+
+#define vp8_zero_array( Dest, N)  vpx_memset( Dest, 0, N * sizeof( *Dest));
+
+
+#endif  /* common_h */
diff --git a/vp8/common/common_types.h b/vp8/common/common_types.h
new file mode 100644
index 0000000..deb5ed8
--- /dev/null
+++ b/vp8/common/common_types.h
@@ -0,0 +1,17 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_COMMON_TYPES
+#define __INC_COMMON_TYPES
+
+#define TRUE    1
+#define FALSE   0
+
+#endif
diff --git a/vp8/common/context.c b/vp8/common/context.c
new file mode 100644
index 0000000..17ee8c3
--- /dev/null
+++ b/vp8/common/context.c
@@ -0,0 +1,398 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "entropy.h"
+
+/* *** GENERATED FILE: DO NOT EDIT *** */
+
+#if 0
+int Contexts[vp8_coef_counter_dimen];
+
+const int default_contexts[vp8_coef_counter_dimen] =
+{
+    {
+        // Block Type ( 0 )
+        {
+            // Coeff Band ( 0 )
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+        },
+        {
+            // Coeff Band ( 1 )
+            {30190, 26544, 225,  24,   4,   0,   0,   0,   0,   0,   0, 4171593,},
+            {26846, 25157, 1241, 130,  26,   6,   1,   0,   0,   0,   0, 149987,},
+            {10484, 9538, 1006, 160,  36,  18,   0,   0,   0,   0,   0, 15104,},
+        },
+        {
+            // Coeff Band ( 2 )
+            {25842, 40456, 1126,  83,  11,   2,   0,   0,   0,   0,   0,   0,},
+            {9338, 8010, 512,  73,   7,   3,   2,   0,   0,   0,   0, 43294,},
+            {1047, 751, 149,  31,  13,   6,   1,   0,   0,   0,   0, 879,},
+        },
+        {
+            // Coeff Band ( 3 )
+            {26136, 9826, 252,  13,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {8134, 5574, 191,  14,   2,   0,   0,   0,   0,   0,   0, 35302,},
+            { 605, 677, 116,   9,   1,   0,   0,   0,   0,   0,   0, 611,},
+        },
+        {
+            // Coeff Band ( 4 )
+            {10263, 15463, 283,  17,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {2773, 2191, 128,   9,   2,   2,   0,   0,   0,   0,   0, 10073,},
+            { 134, 125,  32,   4,   0,   2,   0,   0,   0,   0,   0,  50,},
+        },
+        {
+            // Coeff Band ( 5 )
+            {10483, 2663,  23,   1,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {2137, 1251,  27,   1,   1,   0,   0,   0,   0,   0,   0, 14362,},
+            { 116, 156,  14,   2,   1,   0,   0,   0,   0,   0,   0, 190,},
+        },
+        {
+            // Coeff Band ( 6 )
+            {40977, 27614, 412,  28,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {6113, 5213, 261,  22,   3,   0,   0,   0,   0,   0,   0, 26164,},
+            { 382, 312,  50,  14,   2,   0,   0,   0,   0,   0,   0, 345,},
+        },
+        {
+            // Coeff Band ( 7 )
+            {   0,  26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,  13,   0,   0,   0,   0,   0,   0,   0,   0,   0, 319,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   8,},
+        },
+    },
+    {
+        // Block Type ( 1 )
+        {
+            // Coeff Band ( 0 )
+            {3268, 19382, 1043, 250,  93,  82,  49,  26,  17,   8,  25, 82289,},
+            {8758, 32110, 5436, 1832, 827, 668, 420, 153,  24,   0,   3, 52914,},
+            {9337, 23725, 8487, 3954, 2107, 1836, 1069, 399,  59,   0,   0, 18620,},
+        },
+        {
+            // Coeff Band ( 1 )
+            {12419, 8420, 452,  62,   9,   1,   0,   0,   0,   0,   0,   0,},
+            {11715, 8705, 693,  92,  15,   7,   2,   0,   0,   0,   0, 53988,},
+            {7603, 8585, 2306, 778, 270, 145,  39,   5,   0,   0,   0, 9136,},
+        },
+        {
+            // Coeff Band ( 2 )
+            {15938, 14335, 1207, 184,  55,  13,   4,   1,   0,   0,   0,   0,},
+            {7415, 6829, 1138, 244,  71,  26,   7,   0,   0,   0,   0, 9980,},
+            {1580, 1824, 655, 241,  89,  46,  10,   2,   0,   0,   0, 429,},
+        },
+        {
+            // Coeff Band ( 3 )
+            {19453, 5260, 201,  19,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {9173, 3758, 213,  22,   1,   1,   0,   0,   0,   0,   0, 9820,},
+            {1689, 1277, 276,  51,  17,   4,   0,   0,   0,   0,   0, 679,},
+        },
+        {
+            // Coeff Band ( 4 )
+            {12076, 10667, 620,  85,  19,   9,   5,   0,   0,   0,   0,   0,},
+            {4665, 3625, 423,  55,  19,   9,   0,   0,   0,   0,   0, 5127,},
+            { 415, 440, 143,  34,  20,   7,   2,   0,   0,   0,   0, 101,},
+        },
+        {
+            // Coeff Band ( 5 )
+            {12183, 4846, 115,  11,   1,   0,   0,   0,   0,   0,   0,   0,},
+            {4226, 3149, 177,  21,   2,   0,   0,   0,   0,   0,   0, 7157,},
+            { 375, 621, 189,  51,  11,   4,   1,   0,   0,   0,   0, 198,},
+        },
+        {
+            // Coeff Band ( 6 )
+            {61658, 37743, 1203,  94,  10,   3,   0,   0,   0,   0,   0,   0,},
+            {15514, 11563, 903, 111,  14,   5,   0,   0,   0,   0,   0, 25195,},
+            { 929, 1077, 291,  78,  14,   7,   1,   0,   0,   0,   0, 507,},
+        },
+        {
+            // Coeff Band ( 7 )
+            {   0, 990,  15,   3,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0, 412,  13,   0,   0,   0,   0,   0,   0,   0,   0, 1641,},
+            {   0,  18,   7,   1,   0,   0,   0,   0,   0,   0,   0,  30,},
+        },
+    },
+    {
+        // Block Type ( 2 )
+        {
+            // Coeff Band ( 0 )
+            { 953, 24519, 628, 120,  28,  12,   4,   0,   0,   0,   0, 2248798,},
+            {1525, 25654, 2647, 617, 239, 143,  42,   5,   0,   0,   0, 66837,},
+            {1180, 11011, 3001, 1237, 532, 448, 239,  54,   5,   0,   0, 7122,},
+        },
+        {
+            // Coeff Band ( 1 )
+            {1356, 2220,  67,  10,   4,   1,   0,   0,   0,   0,   0,   0,},
+            {1450, 2544, 102,  18,   4,   3,   0,   0,   0,   0,   0, 57063,},
+            {1182, 2110, 470, 130,  41,  21,   0,   0,   0,   0,   0, 6047,},
+        },
+        {
+            // Coeff Band ( 2 )
+            { 370, 3378, 200,  30,   5,   4,   1,   0,   0,   0,   0,   0,},
+            { 293, 1006, 131,  29,  11,   0,   0,   0,   0,   0,   0, 5404,},
+            { 114, 387,  98,  23,   4,   8,   1,   0,   0,   0,   0, 236,},
+        },
+        {
+            // Coeff Band ( 3 )
+            { 579, 194,   4,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            { 395, 213,   5,   1,   0,   0,   0,   0,   0,   0,   0, 4157,},
+            { 119, 122,   4,   0,   0,   0,   0,   0,   0,   0,   0, 300,},
+        },
+        {
+            // Coeff Band ( 4 )
+            {  38, 557,  19,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {  21, 114,  12,   1,   0,   0,   0,   0,   0,   0,   0, 427,},
+            {   0,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   7,},
+        },
+        {
+            // Coeff Band ( 5 )
+            {  52,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {  18,   6,   0,   0,   0,   0,   0,   0,   0,   0,   0, 652,},
+            {   1,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,  30,},
+        },
+        {
+            // Coeff Band ( 6 )
+            { 640, 569,  10,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {  25,  77,   2,   0,   0,   0,   0,   0,   0,   0,   0, 517,},
+            {   4,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,},
+        },
+        {
+            // Coeff Band ( 7 )
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+        },
+    },
+    {
+        // Block Type ( 3 )
+        {
+            // Coeff Band ( 0 )
+            {2506, 20161, 2707, 767, 261, 178, 107,  30,  14,   3,   0, 100694,},
+            {8806, 36478, 8817, 3268, 1280, 850, 401, 114,  42,   0,   0, 58572,},
+            {11003, 27214, 11798, 5716, 2482, 2072, 1048, 175,  32,   0,   0, 19284,},
+        },
+        {
+            // Coeff Band ( 1 )
+            {9738, 11313, 959, 205,  70,  18,  11,   1,   0,   0,   0,   0,},
+            {12628, 15085, 1507, 273,  52,  19,   9,   0,   0,   0,   0, 54280,},
+            {10701, 15846, 5561, 1926, 813, 570, 249,  36,   0,   0,   0, 6460,},
+        },
+        {
+            // Coeff Band ( 2 )
+            {6781, 22539, 2784, 634, 182, 123,  20,   4,   0,   0,   0,   0,},
+            {6263, 11544, 2649, 790, 259, 168,  27,   5,   0,   0,   0, 20539,},
+            {3109, 4075, 2031, 896, 457, 386, 158,  29,   0,   0,   0, 1138,},
+        },
+        {
+            // Coeff Band ( 3 )
+            {11515, 4079, 465,  73,   5,  14,   2,   0,   0,   0,   0,   0,},
+            {9361, 5834, 650,  96,  24,   8,   4,   0,   0,   0,   0, 22181,},
+            {4343, 3974, 1360, 415, 132,  96,  14,   1,   0,   0,   0, 1267,},
+        },
+        {
+            // Coeff Band ( 4 )
+            {4787, 9297, 823, 168,  44,  12,   4,   0,   0,   0,   0,   0,},
+            {3619, 4472, 719, 198,  60,  31,   3,   0,   0,   0,   0, 8401,},
+            {1157, 1175, 483, 182,  88,  31,   8,   0,   0,   0,   0, 268,},
+        },
+        {
+            // Coeff Band ( 5 )
+            {8299, 1226,  32,   5,   1,   0,   0,   0,   0,   0,   0,   0,},
+            {3502, 1568,  57,   4,   1,   1,   0,   0,   0,   0,   0, 9811,},
+            {1055, 1070, 166,  29,   6,   1,   0,   0,   0,   0,   0, 527,},
+        },
+        {
+            // Coeff Band ( 6 )
+            {27414, 27927, 1989, 347,  69,  26,   0,   0,   0,   0,   0,   0,},
+            {5876, 10074, 1574, 341,  91,  24,   4,   0,   0,   0,   0, 21954,},
+            {1571, 2171, 778, 324, 124,  65,  16,   0,   0,   0,   0, 979,},
+        },
+        {
+            // Coeff Band ( 7 )
+            {   0,  29,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,  23,   0,   0,   0,   0,   0,   0,   0,   0,   0, 459,},
+            {   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,  13,},
+        },
+    },
+};
+
+//Update probabilities for the nodes in the token entropy tree.
+const vp8_prob tree_update_probs[vp8_coef_tree_dimen] =
+{
+    {
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255, },
+            {250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+    {
+        {
+            {217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255, },
+            {234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255, },
+        },
+        {
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+    {
+        {
+            {186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+    {
+        {
+            {248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255, },
+            {248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, },
+        },
+    },
+};
+#endif
diff --git a/vp8/common/debugmodes.c b/vp8/common/debugmodes.c
new file mode 100644
index 0000000..e2d2d2c
--- /dev/null
+++ b/vp8/common/debugmodes.c
@@ -0,0 +1,156 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <stdio.h>
+#include "blockd.h"
+
+
+void vp8_print_modes_and_motion_vectors(MODE_INFO *mi, int rows, int cols, int frame)
+{
+
+    int mb_row;
+    int mb_col;
+    int mb_index = 0;
+    FILE *mvs = fopen("mvs.stt", "a");
+
+    // print out the macroblock Y modes
+    mb_index = 0;
+    fprintf(mvs, "Mb Modes for Frame %d\n", frame);
+
+    for (mb_row = 0; mb_row < rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < cols; mb_col++)
+        {
+
+            fprintf(mvs, "%2d ", mi[mb_index].mbmi.mode);
+
+            mb_index++;
+        }
+
+        fprintf(mvs, "\n");
+        mb_index++;
+    }
+
+    fprintf(mvs, "\n");
+
+    mb_index = 0;
+    fprintf(mvs, "Mb mv ref for Frame %d\n", frame);
+
+    for (mb_row = 0; mb_row < rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < cols; mb_col++)
+        {
+
+            fprintf(mvs, "%2d ", mi[mb_index].mbmi.ref_frame);
+
+            mb_index++;
+        }
+
+        fprintf(mvs, "\n");
+        mb_index++;
+    }
+
+    fprintf(mvs, "\n");
+
+    // print out the macroblock UV modes
+    mb_index = 0;
+    fprintf(mvs, "UV Modes for Frame %d\n", frame);
+
+    for (mb_row = 0; mb_row < rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < cols; mb_col++)
+        {
+
+            fprintf(mvs, "%2d ", mi[mb_index].mbmi.uv_mode);
+
+            mb_index++;
+        }
+
+        mb_index++;
+        fprintf(mvs, "\n");
+    }
+
+    fprintf(mvs, "\n");
+
+    // print out the block modes
+    mb_index = 0;
+    fprintf(mvs, "Mbs for Frame %d\n", frame);
+    {
+        int b_row;
+
+        for (b_row = 0; b_row < 4 * rows; b_row++)
+        {
+            int b_col;
+            int bindex;
+
+            for (b_col = 0; b_col < 4 * cols; b_col++)
+            {
+                mb_index = (b_row >> 2) * (cols + 1) + (b_col >> 2);
+                bindex = (b_row & 3) * 4 + (b_col & 3);
+
+                if (mi[mb_index].mbmi.mode == B_PRED)
+                    fprintf(mvs, "%2d ", mi[mb_index].bmi[bindex].mode);
+                else
+                    fprintf(mvs, "xx ");
+
+            }
+
+            fprintf(mvs, "\n");
+        }
+    }
+    fprintf(mvs, "\n");
+
+    // print out the macroblock mvs
+    mb_index = 0;
+    fprintf(mvs, "MVs for Frame %d\n", frame);
+
+    for (mb_row = 0; mb_row < rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < cols; mb_col++)
+        {
+            fprintf(mvs, "%5d:%-5d", mi[mb_index].mbmi.mv.as_mv.row / 2, mi[mb_index].mbmi.mv.as_mv.col / 2);
+
+            mb_index++;
+        }
+
+        mb_index++;
+        fprintf(mvs, "\n");
+    }
+
+    fprintf(mvs, "\n");
+
+
+    // print out the block modes
+    mb_index = 0;
+    fprintf(mvs, "MVs for Frame %d\n", frame);
+    {
+        int b_row;
+
+        for (b_row = 0; b_row < 4 * rows; b_row++)
+        {
+            int b_col;
+            int bindex;
+
+            for (b_col = 0; b_col < 4 * cols; b_col++)
+            {
+                mb_index = (b_row >> 2) * (cols + 1) + (b_col >> 2);
+                bindex = (b_row & 3) * 4 + (b_col & 3);
+                fprintf(mvs, "%3d:%-3d ", mi[mb_index].bmi[bindex].mv.as_mv.row, mi[mb_index].bmi[bindex].mv.as_mv.col);
+
+            }
+
+            fprintf(mvs, "\n");
+        }
+    }
+    fprintf(mvs, "\n");
+
+
+    fclose(mvs);
+}
diff --git a/vp8/common/defaultcoefcounts.h b/vp8/common/defaultcoefcounts.h
new file mode 100644
index 0000000..ccdf326
--- /dev/null
+++ b/vp8/common/defaultcoefcounts.h
@@ -0,0 +1,220 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/* Generated file, included by entropy.c */
+
+static const unsigned int default_coef_counts [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens] =
+{
+
+    {
+        // Block Type ( 0 )
+        {
+            // Coeff Band ( 0 )
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+        },
+        {
+            // Coeff Band ( 1 )
+            {30190, 26544, 225,  24,   4,   0,   0,   0,   0,   0,   0, 4171593,},
+            {26846, 25157, 1241, 130,  26,   6,   1,   0,   0,   0,   0, 149987,},
+            {10484, 9538, 1006, 160,  36,  18,   0,   0,   0,   0,   0, 15104,},
+        },
+        {
+            // Coeff Band ( 2 )
+            {25842, 40456, 1126,  83,  11,   2,   0,   0,   0,   0,   0,   0,},
+            {9338, 8010, 512,  73,   7,   3,   2,   0,   0,   0,   0, 43294,},
+            {1047, 751, 149,  31,  13,   6,   1,   0,   0,   0,   0, 879,},
+        },
+        {
+            // Coeff Band ( 3 )
+            {26136, 9826, 252,  13,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {8134, 5574, 191,  14,   2,   0,   0,   0,   0,   0,   0, 35302,},
+            { 605, 677, 116,   9,   1,   0,   0,   0,   0,   0,   0, 611,},
+        },
+        {
+            // Coeff Band ( 4 )
+            {10263, 15463, 283,  17,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {2773, 2191, 128,   9,   2,   2,   0,   0,   0,   0,   0, 10073,},
+            { 134, 125,  32,   4,   0,   2,   0,   0,   0,   0,   0,  50,},
+        },
+        {
+            // Coeff Band ( 5 )
+            {10483, 2663,  23,   1,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {2137, 1251,  27,   1,   1,   0,   0,   0,   0,   0,   0, 14362,},
+            { 116, 156,  14,   2,   1,   0,   0,   0,   0,   0,   0, 190,},
+        },
+        {
+            // Coeff Band ( 6 )
+            {40977, 27614, 412,  28,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {6113, 5213, 261,  22,   3,   0,   0,   0,   0,   0,   0, 26164,},
+            { 382, 312,  50,  14,   2,   0,   0,   0,   0,   0,   0, 345,},
+        },
+        {
+            // Coeff Band ( 7 )
+            {   0,  26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,  13,   0,   0,   0,   0,   0,   0,   0,   0,   0, 319,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   8,},
+        },
+    },
+    {
+        // Block Type ( 1 )
+        {
+            // Coeff Band ( 0 )
+            {3268, 19382, 1043, 250,  93,  82,  49,  26,  17,   8,  25, 82289,},
+            {8758, 32110, 5436, 1832, 827, 668, 420, 153,  24,   0,   3, 52914,},
+            {9337, 23725, 8487, 3954, 2107, 1836, 1069, 399,  59,   0,   0, 18620,},
+        },
+        {
+            // Coeff Band ( 1 )
+            {12419, 8420, 452,  62,   9,   1,   0,   0,   0,   0,   0,   0,},
+            {11715, 8705, 693,  92,  15,   7,   2,   0,   0,   0,   0, 53988,},
+            {7603, 8585, 2306, 778, 270, 145,  39,   5,   0,   0,   0, 9136,},
+        },
+        {
+            // Coeff Band ( 2 )
+            {15938, 14335, 1207, 184,  55,  13,   4,   1,   0,   0,   0,   0,},
+            {7415, 6829, 1138, 244,  71,  26,   7,   0,   0,   0,   0, 9980,},
+            {1580, 1824, 655, 241,  89,  46,  10,   2,   0,   0,   0, 429,},
+        },
+        {
+            // Coeff Band ( 3 )
+            {19453, 5260, 201,  19,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {9173, 3758, 213,  22,   1,   1,   0,   0,   0,   0,   0, 9820,},
+            {1689, 1277, 276,  51,  17,   4,   0,   0,   0,   0,   0, 679,},
+        },
+        {
+            // Coeff Band ( 4 )
+            {12076, 10667, 620,  85,  19,   9,   5,   0,   0,   0,   0,   0,},
+            {4665, 3625, 423,  55,  19,   9,   0,   0,   0,   0,   0, 5127,},
+            { 415, 440, 143,  34,  20,   7,   2,   0,   0,   0,   0, 101,},
+        },
+        {
+            // Coeff Band ( 5 )
+            {12183, 4846, 115,  11,   1,   0,   0,   0,   0,   0,   0,   0,},
+            {4226, 3149, 177,  21,   2,   0,   0,   0,   0,   0,   0, 7157,},
+            { 375, 621, 189,  51,  11,   4,   1,   0,   0,   0,   0, 198,},
+        },
+        {
+            // Coeff Band ( 6 )
+            {61658, 37743, 1203,  94,  10,   3,   0,   0,   0,   0,   0,   0,},
+            {15514, 11563, 903, 111,  14,   5,   0,   0,   0,   0,   0, 25195,},
+            { 929, 1077, 291,  78,  14,   7,   1,   0,   0,   0,   0, 507,},
+        },
+        {
+            // Coeff Band ( 7 )
+            {   0, 990,  15,   3,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0, 412,  13,   0,   0,   0,   0,   0,   0,   0,   0, 1641,},
+            {   0,  18,   7,   1,   0,   0,   0,   0,   0,   0,   0,  30,},
+        },
+    },
+    {
+        // Block Type ( 2 )
+        {
+            // Coeff Band ( 0 )
+            { 953, 24519, 628, 120,  28,  12,   4,   0,   0,   0,   0, 2248798,},
+            {1525, 25654, 2647, 617, 239, 143,  42,   5,   0,   0,   0, 66837,},
+            {1180, 11011, 3001, 1237, 532, 448, 239,  54,   5,   0,   0, 7122,},
+        },
+        {
+            // Coeff Band ( 1 )
+            {1356, 2220,  67,  10,   4,   1,   0,   0,   0,   0,   0,   0,},
+            {1450, 2544, 102,  18,   4,   3,   0,   0,   0,   0,   0, 57063,},
+            {1182, 2110, 470, 130,  41,  21,   0,   0,   0,   0,   0, 6047,},
+        },
+        {
+            // Coeff Band ( 2 )
+            { 370, 3378, 200,  30,   5,   4,   1,   0,   0,   0,   0,   0,},
+            { 293, 1006, 131,  29,  11,   0,   0,   0,   0,   0,   0, 5404,},
+            { 114, 387,  98,  23,   4,   8,   1,   0,   0,   0,   0, 236,},
+        },
+        {
+            // Coeff Band ( 3 )
+            { 579, 194,   4,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            { 395, 213,   5,   1,   0,   0,   0,   0,   0,   0,   0, 4157,},
+            { 119, 122,   4,   0,   0,   0,   0,   0,   0,   0,   0, 300,},
+        },
+        {
+            // Coeff Band ( 4 )
+            {  38, 557,  19,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {  21, 114,  12,   1,   0,   0,   0,   0,   0,   0,   0, 427,},
+            {   0,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   7,},
+        },
+        {
+            // Coeff Band ( 5 )
+            {  52,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {  18,   6,   0,   0,   0,   0,   0,   0,   0,   0,   0, 652,},
+            {   1,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,  30,},
+        },
+        {
+            // Coeff Band ( 6 )
+            { 640, 569,  10,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {  25,  77,   2,   0,   0,   0,   0,   0,   0,   0,   0, 517,},
+            {   4,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,},
+        },
+        {
+            // Coeff Band ( 7 )
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+        },
+    },
+    {
+        // Block Type ( 3 )
+        {
+            // Coeff Band ( 0 )
+            {2506, 20161, 2707, 767, 261, 178, 107,  30,  14,   3,   0, 100694,},
+            {8806, 36478, 8817, 3268, 1280, 850, 401, 114,  42,   0,   0, 58572,},
+            {11003, 27214, 11798, 5716, 2482, 2072, 1048, 175,  32,   0,   0, 19284,},
+        },
+        {
+            // Coeff Band ( 1 )
+            {9738, 11313, 959, 205,  70,  18,  11,   1,   0,   0,   0,   0,},
+            {12628, 15085, 1507, 273,  52,  19,   9,   0,   0,   0,   0, 54280,},
+            {10701, 15846, 5561, 1926, 813, 570, 249,  36,   0,   0,   0, 6460,},
+        },
+        {
+            // Coeff Band ( 2 )
+            {6781, 22539, 2784, 634, 182, 123,  20,   4,   0,   0,   0,   0,},
+            {6263, 11544, 2649, 790, 259, 168,  27,   5,   0,   0,   0, 20539,},
+            {3109, 4075, 2031, 896, 457, 386, 158,  29,   0,   0,   0, 1138,},
+        },
+        {
+            // Coeff Band ( 3 )
+            {11515, 4079, 465,  73,   5,  14,   2,   0,   0,   0,   0,   0,},
+            {9361, 5834, 650,  96,  24,   8,   4,   0,   0,   0,   0, 22181,},
+            {4343, 3974, 1360, 415, 132,  96,  14,   1,   0,   0,   0, 1267,},
+        },
+        {
+            // Coeff Band ( 4 )
+            {4787, 9297, 823, 168,  44,  12,   4,   0,   0,   0,   0,   0,},
+            {3619, 4472, 719, 198,  60,  31,   3,   0,   0,   0,   0, 8401,},
+            {1157, 1175, 483, 182,  88,  31,   8,   0,   0,   0,   0, 268,},
+        },
+        {
+            // Coeff Band ( 5 )
+            {8299, 1226,  32,   5,   1,   0,   0,   0,   0,   0,   0,   0,},
+            {3502, 1568,  57,   4,   1,   1,   0,   0,   0,   0,   0, 9811,},
+            {1055, 1070, 166,  29,   6,   1,   0,   0,   0,   0,   0, 527,},
+        },
+        {
+            // Coeff Band ( 6 )
+            {27414, 27927, 1989, 347,  69,  26,   0,   0,   0,   0,   0,   0,},
+            {5876, 10074, 1574, 341,  91,  24,   4,   0,   0,   0,   0, 21954,},
+            {1571, 2171, 778, 324, 124,  65,  16,   0,   0,   0,   0, 979,},
+        },
+        {
+            // Coeff Band ( 7 )
+            {   0,  29,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,},
+            {   0,  23,   0,   0,   0,   0,   0,   0,   0,   0,   0, 459,},
+            {   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,  13,},
+        },
+    },
+};
diff --git a/vp8/common/dma_desc.h b/vp8/common/dma_desc.h
new file mode 100644
index 0000000..5e6fa0c
--- /dev/null
+++ b/vp8/common/dma_desc.h
@@ -0,0 +1,124 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef _dma_desc_h
+#define _dma_desc_h
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#define NDSIZE_LG   0x00000900  // Next Descriptor Size
+#define NDSIZE_SM   0x00000800  // Next Descriptor Size
+#define NDSIZE_7    0x00000700  // Next Descriptor Size
+#define NDSIZE_6    0x00000600  // Next Descriptor Size
+#define NDSIZE_5    0x00000500  // Next Descriptor Size
+#define NDSIZE_4    0x00000400  // Next Descriptor Size
+#define NDSIZE_3    0x00000300  // Next Descriptor Size
+#define NDSIZE_2    0x00000200  // Next Descriptor Size
+#define NDSIZE_1    0x00000100  // Next Descriptor Size
+
+#define FLOW_STOP       0x0000
+#define FLOW_AUTO       0x1000
+#define FLOW_DESC_AR    0x4000
+#define FLOW_DESC_SM    0x6000
+#define FLOW_DESC_LG    0x7000
+
+    typedef struct
+    {
+        unsigned int ndp;
+        //unsigned short ndpl;
+        //unsigned short ndph;
+        unsigned int sa;
+        //unsigned short sal;
+        //unsigned short sah;
+
+        unsigned short dmacfg;
+        unsigned short xcnt;
+        unsigned short xmod;
+        unsigned short ycnt;
+        unsigned short ymod;
+
+    } LARGE_DESC;
+
+    typedef struct
+    {
+        unsigned short ndpl;
+        unsigned short sal;
+        unsigned short sah;
+        unsigned short dmacfg;
+        unsigned short xcnt;
+        unsigned short xmod;
+        unsigned short ycnt;
+        unsigned short ymod;
+    } SMALL_DESC;
+
+    typedef struct
+    {
+        unsigned short sal;
+        unsigned short sah;
+        unsigned short dmacfg;
+        unsigned short xcnt;
+        unsigned short xmod;
+        unsigned short ycnt;
+        unsigned short ymod;
+    } ARRAY_DESC_7;
+
+    typedef struct
+    {
+        unsigned short sal;
+        unsigned short sah;
+        unsigned short dmacfg;
+        unsigned short xcnt;
+        unsigned short xmod;
+        unsigned short ycnt;
+    } ARRAY_DESC_6;
+
+    typedef struct
+    {
+        unsigned short sal;
+        unsigned short sah;
+        unsigned short dmacfg;
+        unsigned short xcnt;
+        unsigned short xmod;
+    } ARRAY_DESC_5;
+
+    typedef struct
+    {
+        unsigned short sal;
+        unsigned short sah;
+        unsigned short dmacfg;
+        unsigned short xcnt;
+    } ARRAY_DESC_4;
+
+    typedef struct
+    {
+        unsigned short sal;
+        unsigned short sah;
+        unsigned short dmacfg;
+    } ARRAY_DESC_3;
+
+    typedef struct
+    {
+        unsigned short sal;
+        unsigned short sah;
+    } ARRAY_DESC_2;
+
+    typedef struct
+    {
+        unsigned short sal;
+    } ARRAY_DESC_1;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif //_dma_desc_h
diff --git a/vp8/common/duck_io.h b/vp8/common/duck_io.h
new file mode 100644
index 0000000..f63a5cd
--- /dev/null
+++ b/vp8/common/duck_io.h
@@ -0,0 +1,115 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef _duck_io_h
+#define _duck_io_h
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined (_WIN32)
+    typedef __int64 int64_t;
+#elif defined(__MWERKS__)
+    typedef long long int64_t;
+#elif defined(__APPLE__) || defined(__POWERPC)
+#include <ppc/types.h>
+#else
+    typedef long long int64_t;
+#endif
+
+    typedef struct
+    {
+        int64_t  offset;     // offset to start from
+        int    blocking;    // non-zero for blocking
+    } re_open_t;
+
+
+    typedef enum
+    {
+        SAL_ERR_MAX                 = -10,
+        SAL_ERROR                   = -11, // Default error
+        SAL_ERR_WSASTARTUP          = -12,
+        SAL_ERR_SOCKET_CREATE       = -13,
+        SAL_ERR_RESOLVING_HOSTNAME  = -14,
+        SAL_ERR_SERVER_CONNECTION   = -15,
+        SAL_ERR_SENDING_DATA        = -16,
+        SAL_ERR_RECEIVING_DATA      = -17,
+        SAL_ERR_404_FILE_NOT_FOUND  = -18,
+        SAL_ERR_PARSING_HTTP_HEADER = -19,
+        SAL_ERR_PARSING_CONTENT_LEN = -20,
+        SAL_ERR_CONNECTION_TIMEOUT  = -21,
+        SAL_ERR_FILE_OPEN_FAILED    = -22,
+        SAL_ERR_MIN                 = -23
+    } SAL_ERR; /* EMH 1-15-03 */
+
+
+    typedef struct sal_err_map_temp
+    {
+        SAL_ERR code;
+        const char *decode;
+
+    } sal_err_map_t;
+
+
+    static char *sal_err_text(SAL_ERR e)
+    {
+        int t;
+        const sal_err_map_t g_sal_err_map[] =
+        {
+            {   SAL_ERR_WSASTARTUP,             "Error with WSAStartup"         },
+            {   SAL_ERR_SOCKET_CREATE,          "Error creating socket"         },
+            {   SAL_ERR_RESOLVING_HOSTNAME,     "Error resolving hostname"      },
+            {   SAL_ERR_SERVER_CONNECTION,      "Error connecting to server"    },
+            {   SAL_ERR_SENDING_DATA,           "Error sending data"            },
+            {   SAL_ERR_RECEIVING_DATA,         "Error receiving data"          },
+            {   SAL_ERR_404_FILE_NOT_FOUND,     "Error file not found "         },
+            {   SAL_ERR_PARSING_HTTP_HEADER,    "Error parsing http header"     },
+            {   SAL_ERR_PARSING_CONTENT_LEN,    "Error parsing content length"  },
+            {   SAL_ERR_CONNECTION_TIMEOUT,     "Error Connection timed out"    },
+            {   SAL_ERR_FILE_OPEN_FAILED,       "Error opening file"            }
+        };
+
+        for (t = 0; t < sizeof(g_sal_err_map) / sizeof(sal_err_map_t); t++)
+        {
+            if (e == g_sal_err_map[t].code)
+                return (char *) g_sal_err_map[t].decode;
+        }
+
+        return 0;
+    }
+
+
+
+
+
+
+
+    int duck_open(const char *fname, unsigned long user_data);
+
+    void duck_close(int ghndl);
+
+    int duck_read(int ghndl, unsigned char *buf, int nbytes);
+
+    int64_t duck_seek(int g_hndl, int64_t offs, int origin);
+
+    int duck_read_finished(int han, int flag); /* FWG 7-9-99 */
+
+    int duck_name(int handle, char name[], size_t max_len); /* EMH 9-23-03 */
+
+    int duck_read_blocking(int handle, unsigned char *buffer, int bytes); /* EMH 9-23-03 */
+
+    int64_t duck_available_data(int handle); /* EMH 10-23-03 */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/vp8/common/entropy.c b/vp8/common/entropy.c
new file mode 100644
index 0000000..e524c2a
--- /dev/null
+++ b/vp8/common/entropy.c
@@ -0,0 +1,161 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <stdio.h>
+
+#include "entropy.h"
+#include "string.h"
+#include "blockd.h"
+#include "onyxc_int.h"
+
+#define uchar unsigned char     /* typedefs can clash */
+#define uint  unsigned int
+
+typedef const uchar cuchar;
+typedef const uint cuint;
+
+typedef vp8_prob Prob;
+
+#include "coefupdateprobs.h"
+
+DECLARE_ALIGNED(16, cuchar, vp8_coef_bands[16]) = { 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7};
+DECLARE_ALIGNED(16, cuchar, vp8_prev_token_class[MAX_ENTROPY_TOKENS]) = { 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0};
+DECLARE_ALIGNED(16, const int, vp8_default_zig_zag1d[16]) =
+{
+    0,  1,  4,  8,
+    5,  2,  3,  6,
+    9, 12, 13, 10,
+    7, 11, 14, 15,
+};
+
+DECLARE_ALIGNED(16, short, vp8_default_zig_zag_mask[16]);
+
+const int vp8_mb_feature_data_bits[MB_LVL_MAX] = {7, 6};
+
+/* Array indices are identical to previously-existing CONTEXT_NODE indices */
+
+const vp8_tree_index vp8_coef_tree[ 22] =     /* corresponding _CONTEXT_NODEs */
+{
+    -DCT_EOB_TOKEN, 2,                             /* 0 = EOB */
+    -ZERO_TOKEN, 4,                               /* 1 = ZERO */
+    -ONE_TOKEN, 6,                               /* 2 = ONE */
+    8, 12,                                      /* 3 = LOW_VAL */
+    -TWO_TOKEN, 10,                            /* 4 = TWO */
+    -THREE_TOKEN, -FOUR_TOKEN,                /* 5 = THREE */
+    14, 16,                                    /* 6 = HIGH_LOW */
+    -DCT_VAL_CATEGORY1, -DCT_VAL_CATEGORY2,   /* 7 = CAT_ONE */
+    18, 20,                                   /* 8 = CAT_THREEFOUR */
+    -DCT_VAL_CATEGORY3, -DCT_VAL_CATEGORY4,  /* 9 = CAT_THREE */
+    -DCT_VAL_CATEGORY5, -DCT_VAL_CATEGORY6   /* 10 = CAT_FIVE */
+};
+
+struct vp8_token_struct vp8_coef_encodings[vp8_coef_tokens];
+
+/* Trees for extra bits.  Probabilities are constant and
+   do not depend on previously encoded bits */
+
+static const Prob Pcat1[] = { 159};
+static const Prob Pcat2[] = { 165, 145};
+static const Prob Pcat3[] = { 173, 148, 140};
+static const Prob Pcat4[] = { 176, 155, 140, 135};
+static const Prob Pcat5[] = { 180, 157, 141, 134, 130};
+static const Prob Pcat6[] =
+{ 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129};
+
+static vp8_tree_index cat1[2], cat2[4], cat3[6], cat4[8], cat5[10], cat6[22];
+
+void vp8_init_scan_order_mask()
+{
+    int i;
+
+    for (i = 0; i < 16; i++)
+    {
+        vp8_default_zig_zag_mask[vp8_default_zig_zag1d[i]] = 1 << i;
+    }
+
+}
+
+static void init_bit_tree(vp8_tree_index *p, int n)
+{
+    int i = 0;
+
+    while (++i < n)
+    {
+        p[0] = p[1] = i << 1;
+        p += 2;
+    }
+
+    p[0] = p[1] = 0;
+}
+
+static void init_bit_trees()
+{
+    init_bit_tree(cat1, 1);
+    init_bit_tree(cat2, 2);
+    init_bit_tree(cat3, 3);
+    init_bit_tree(cat4, 4);
+    init_bit_tree(cat5, 5);
+    init_bit_tree(cat6, 11);
+}
+
+
+static vp8bc_index_t bcc1[1], bcc2[2], bcc3[3], bcc4[4], bcc5[5], bcc6[11];
+
+vp8_extra_bit_struct vp8_extra_bits[12] =
+{
+    { 0, 0, 0, 0, 0},
+    { 0, 0, 0, 0, 1},
+    { 0, 0, 0, 0, 2},
+    { 0, 0, 0, 0, 3},
+    { 0, 0, 0, 0, 4},
+    { cat1, Pcat1, bcc1, 1, 5},
+    { cat2, Pcat2, bcc2, 2, 7},
+    { cat3, Pcat3, bcc3, 3, 11},
+    { cat4, Pcat4, bcc4, 4, 19},
+    { cat5, Pcat5, bcc5, 5, 35},
+    { cat6, Pcat6, bcc6, 11, 67},
+    { 0, 0, 0, 0, 0}
+};
+#include "defaultcoefcounts.h"
+
+void vp8_default_coef_probs(VP8_COMMON *pc)
+{
+    int h = 0;
+
+    do
+    {
+        int i = 0;
+
+        do
+        {
+            int k = 0;
+
+            do
+            {
+                unsigned int branch_ct [vp8_coef_tokens-1] [2];
+                vp8_tree_probs_from_distribution(
+                    vp8_coef_tokens, vp8_coef_encodings, vp8_coef_tree,
+                    pc->fc.coef_probs [h][i][k], branch_ct, default_coef_counts [h][i][k],
+                    256, 1);
+
+            }
+            while (++k < PREV_COEF_CONTEXTS);
+        }
+        while (++i < COEF_BANDS);
+    }
+    while (++h < BLOCK_TYPES);
+}
+
+
+void vp8_coef_tree_initialize()
+{
+    init_bit_trees();
+    vp8_tokens_from_tree(vp8_coef_encodings, vp8_coef_tree);
+}
diff --git a/vp8/common/entropy.h b/vp8/common/entropy.h
new file mode 100644
index 0000000..1415832
--- /dev/null
+++ b/vp8/common/entropy.h
@@ -0,0 +1,101 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_ENTROPY_H
+#define __INC_ENTROPY_H
+
+#include "treecoder.h"
+#include "blockd.h"
+
+/* Coefficient token alphabet */
+
+#define ZERO_TOKEN              0       //0         Extra Bits 0+0
+#define ONE_TOKEN               1       //1         Extra Bits 0+1
+#define TWO_TOKEN               2       //2         Extra Bits 0+1
+#define THREE_TOKEN             3       //3         Extra Bits 0+1
+#define FOUR_TOKEN              4       //4         Extra Bits 0+1
+#define DCT_VAL_CATEGORY1       5       //5-6       Extra Bits 1+1
+#define DCT_VAL_CATEGORY2       6       //7-10      Extra Bits 2+1
+#define DCT_VAL_CATEGORY3       7       //11-26     Extra Bits 4+1
+#define DCT_VAL_CATEGORY4       8       //11-26     Extra Bits 5+1
+#define DCT_VAL_CATEGORY5       9       //27-58     Extra Bits 5+1
+#define DCT_VAL_CATEGORY6       10      //59+       Extra Bits 11+1
+#define DCT_EOB_TOKEN           11      //EOB       Extra Bits 0+0
+
+#define vp8_coef_tokens 12
+#define MAX_ENTROPY_TOKENS vp8_coef_tokens
+#define ENTROPY_NODES 11
+
+extern const vp8_tree_index vp8_coef_tree[];
+
+extern struct vp8_token_struct vp8_coef_encodings[vp8_coef_tokens];
+
+typedef struct
+{
+    vp8_tree_p tree;
+    const vp8_prob *prob;
+    vp8bc_index_t *prob_bc;
+    int Len;
+    int base_val;
+} vp8_extra_bit_struct;
+
+extern vp8_extra_bit_struct vp8_extra_bits[12];    /* indexed by token value */
+
+#define PROB_UPDATE_BASELINE_COST   7
+
+#define MAX_PROB                255
+#define DCT_MAX_VALUE           2048
+
+
+/* Coefficients are predicted via a 3-dimensional probability table. */
+
+/* Outside dimension.  0 = Y no DC, 1 = Y2, 2 = UV, 3 = Y with DC */
+
+#define BLOCK_TYPES 4
+
+/* Middle dimension is a coarsening of the coefficient's
+   position within the 4x4 DCT. */
+
+#define COEF_BANDS 8
+extern DECLARE_ALIGNED(16, const unsigned char, vp8_coef_bands[16]);
+
+/* Inside dimension is 3-valued measure of nearby complexity, that is,
+   the extent to which nearby coefficients are nonzero.  For the first
+   coefficient (DC, unless block type is 0), we look at the (already encoded)
+   blocks above and to the left of the current block.  The context index is
+   then the number (0,1,or 2) of these blocks having nonzero coefficients.
+   After decoding a coefficient, the measure is roughly the size of the
+   most recently decoded coefficient (0 for 0, 1 for 1, 2 for >1).
+   Note that the intuitive meaning of this measure changes as coefficients
+   are decoded, e.g., prior to the first token, a zero means that my neighbors
+   are empty while, after the first token, because of the use of end-of-block,
+   a zero means we just decoded a zero and hence guarantees that a non-zero
+   coefficient will appear later in this block.  However, this shift
+   in meaning is perfectly OK because our context depends also on the
+   coefficient band (and since zigzag positions 0, 1, and 2 are in
+   distinct bands). */
+
+/*# define DC_TOKEN_CONTEXTS        3 // 00, 0!0, !0!0 */
+#   define PREV_COEF_CONTEXTS       3
+
+extern DECLARE_ALIGNED(16, const unsigned char, vp8_prev_token_class[vp8_coef_tokens]);
+
+extern const vp8_prob vp8_coef_update_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1];
+
+
+struct VP8Common;
+void vp8_default_coef_probs(struct VP8Common *);
+
+extern DECLARE_ALIGNED(16, const int, vp8_default_zig_zag1d[16]);
+extern short vp8_default_zig_zag_mask[16];
+extern const int vp8_mb_feature_data_bits[MB_LVL_MAX];
+
+void vp8_coef_tree_initialize(void);
+#endif
diff --git a/vp8/common/entropymode.c b/vp8/common/entropymode.c
new file mode 100644
index 0000000..7dc1acd
--- /dev/null
+++ b/vp8/common/entropymode.c
@@ -0,0 +1,270 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "entropymode.h"
+#include "entropy.h"
+#include "vpx_mem/vpx_mem.h"
+
+static const unsigned int kf_y_mode_cts[VP8_YMODES] = { 1607, 915, 812, 811, 5455};
+static const unsigned int y_mode_cts  [VP8_YMODES] = { 8080, 1908, 1582, 1007, 5874};
+
+static const unsigned int uv_mode_cts  [VP8_UV_MODES] = { 59483, 13605, 16492, 4230};
+static const unsigned int kf_uv_mode_cts[VP8_UV_MODES] = { 5319, 1904, 1703, 674};
+
+static const unsigned int bmode_cts[VP8_BINTRAMODES] =
+{
+    43891, 17694, 10036, 3920, 3363, 2546, 5119, 3221, 2471, 1723
+};
+
+typedef enum
+{
+    SUBMVREF_NORMAL,
+    SUBMVREF_LEFT_ZED,
+    SUBMVREF_ABOVE_ZED,
+    SUBMVREF_LEFT_ABOVE_SAME,
+    SUBMVREF_LEFT_ABOVE_ZED
+} sumvfref_t;
+
+int vp8_mv_cont(const MV *l, const MV *a)
+{
+    int lez = (l->row == 0 && l->col == 0);
+    int aez = (a->row == 0 && a->col == 0);
+    int lea = (l->row == a->row && l->col == a->col);
+
+    if (lea && lez)
+        return SUBMVREF_LEFT_ABOVE_ZED;
+
+    if (lea)
+        return SUBMVREF_LEFT_ABOVE_SAME;
+
+    if (aez)
+        return SUBMVREF_ABOVE_ZED;
+
+    if (lez)
+        return SUBMVREF_LEFT_ZED;
+
+    return SUBMVREF_NORMAL;
+}
+
+static const vp8_prob sub_mv_ref_prob [VP8_SUBMVREFS-1] = { 180, 162, 25};
+
+const vp8_prob vp8_sub_mv_ref_prob2 [SUBMVREF_COUNT][VP8_SUBMVREFS-1] =
+{
+    { 147, 136, 18 },
+    { 106, 145, 1  },
+    { 179, 121, 1  },
+    { 223, 1  , 34 },
+    { 208, 1  , 1  }
+};
+
+
+
+vp8_mbsplit vp8_mbsplits [VP8_NUMMBSPLITS] =
+{
+    {
+        0,  0,  0,  0,
+        0,  0,  0,  0,
+        1,  1,  1,  1,
+        1,  1,  1,  1,
+    },
+    {
+        0,  0,  1,  1,
+        0,  0,  1,  1,
+        0,  0,  1,  1,
+        0,  0,  1,  1,
+    },
+    {
+        0,  0,  1,  1,
+        0,  0,  1,  1,
+        2,  2,  3,  3,
+        2,  2,  3,  3,
+    },
+    {
+        0,  1,  2,  3,
+        4,  5,  6,  7,
+        8,  9,  10, 11,
+        12, 13, 14, 15,
+    },
+};
+
+const int vp8_mbsplit_count [VP8_NUMMBSPLITS] = { 2, 2, 4, 16};
+
+const vp8_prob vp8_mbsplit_probs [VP8_NUMMBSPLITS-1] = { 110, 111, 150};
+
+
+/* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
+
+const vp8_tree_index vp8_bmode_tree[18] =     /* INTRAMODECONTEXTNODE value */
+{
+    -B_DC_PRED, 2,                             /* 0 = DC_NODE */
+    -B_TM_PRED, 4,                            /* 1 = TM_NODE */
+    -B_VE_PRED, 6,                           /* 2 = VE_NODE */
+    8, 12,                                  /* 3 = COM_NODE */
+    -B_HE_PRED, 10,                        /* 4 = HE_NODE */
+    -B_RD_PRED, -B_VR_PRED,               /* 5 = RD_NODE */
+    -B_LD_PRED, 14,                        /* 6 = LD_NODE */
+    -B_VL_PRED, 16,                      /* 7 = VL_NODE */
+    -B_HD_PRED, -B_HU_PRED             /* 8 = HD_NODE */
+};
+
+/* Again, these trees use the same probability indices as their
+   explicitly-programmed predecessors. */
+
+const vp8_tree_index vp8_ymode_tree[8] =
+{
+    -DC_PRED, 2,
+    4, 6,
+    -V_PRED, -H_PRED,
+    -TM_PRED, -B_PRED
+};
+
+const vp8_tree_index vp8_kf_ymode_tree[8] =
+{
+    -B_PRED, 2,
+    4, 6,
+    -DC_PRED, -V_PRED,
+    -H_PRED, -TM_PRED
+};
+
+const vp8_tree_index vp8_uv_mode_tree[6] =
+{
+    -DC_PRED, 2,
+    -V_PRED, 4,
+    -H_PRED, -TM_PRED
+};
+
+const vp8_tree_index vp8_mbsplit_tree[6] =
+{
+    -3, 2,
+    -2, 4,
+    -0, -1
+};
+
+const vp8_tree_index vp8_mv_ref_tree[8] =
+{
+    -ZEROMV, 2,
+    -NEARESTMV, 4,
+    -NEARMV, 6,
+    -NEWMV, -SPLITMV
+};
+
+const vp8_tree_index vp8_sub_mv_ref_tree[6] =
+{
+    -LEFT4X4, 2,
+    -ABOVE4X4, 4,
+    -ZERO4X4, -NEW4X4
+};
+
+
+struct vp8_token_struct vp8_bmode_encodings   [VP8_BINTRAMODES];
+struct vp8_token_struct vp8_ymode_encodings   [VP8_YMODES];
+struct vp8_token_struct vp8_kf_ymode_encodings [VP8_YMODES];
+struct vp8_token_struct vp8_uv_mode_encodings  [VP8_UV_MODES];
+struct vp8_token_struct vp8_mbsplit_encodings [VP8_NUMMBSPLITS];
+
+struct vp8_token_struct vp8_mv_ref_encoding_array    [VP8_MVREFS];
+struct vp8_token_struct vp8_sub_mv_ref_encoding_array [VP8_SUBMVREFS];
+
+
+const vp8_tree_index vp8_small_mvtree [14] =
+{
+    2, 8,
+    4, 6,
+    -0, -1,
+    -2, -3,
+    10, 12,
+    -4, -5,
+    -6, -7
+};
+
+struct vp8_token_struct vp8_small_mvencodings [8];
+
+void vp8_init_mbmode_probs(VP8_COMMON *x)
+{
+    unsigned int bct [VP8_YMODES] [2];      /* num Ymodes > num UV modes */
+
+    vp8_tree_probs_from_distribution(
+        VP8_YMODES, vp8_ymode_encodings, vp8_ymode_tree,
+        x->fc.ymode_prob, bct, y_mode_cts,
+        256, 1
+    );
+    vp8_tree_probs_from_distribution(
+        VP8_YMODES, vp8_kf_ymode_encodings, vp8_kf_ymode_tree,
+        x->kf_ymode_prob, bct, kf_y_mode_cts,
+        256, 1
+    );
+    vp8_tree_probs_from_distribution(
+        VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree,
+        x->fc.uv_mode_prob, bct, uv_mode_cts,
+        256, 1
+    );
+    vp8_tree_probs_from_distribution(
+        VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree,
+        x->kf_uv_mode_prob, bct, kf_uv_mode_cts,
+        256, 1
+    );
+    vpx_memcpy(x->fc.sub_mv_ref_prob, sub_mv_ref_prob, sizeof(sub_mv_ref_prob));
+}
+
+
+static void intra_bmode_probs_from_distribution(
+    vp8_prob p [VP8_BINTRAMODES-1],
+    unsigned int branch_ct [VP8_BINTRAMODES-1] [2],
+    const unsigned int events [VP8_BINTRAMODES]
+)
+{
+    vp8_tree_probs_from_distribution(
+        VP8_BINTRAMODES, vp8_bmode_encodings, vp8_bmode_tree,
+        p, branch_ct, events,
+        256, 1
+    );
+}
+
+void vp8_default_bmode_probs(vp8_prob p [VP8_BINTRAMODES-1])
+{
+    unsigned int branch_ct [VP8_BINTRAMODES-1] [2];
+    intra_bmode_probs_from_distribution(p, branch_ct, bmode_cts);
+}
+
+void vp8_kf_default_bmode_probs(vp8_prob p [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES-1])
+{
+    unsigned int branch_ct [VP8_BINTRAMODES-1] [2];
+
+    int i = 0;
+
+    do
+    {
+        int j = 0;
+
+        do
+        {
+            intra_bmode_probs_from_distribution(
+                p[i][j], branch_ct, vp8_kf_default_bmode_counts[i][j]);
+
+        }
+        while (++j < VP8_BINTRAMODES);
+    }
+    while (++i < VP8_BINTRAMODES);
+}
+
+
+void vp8_entropy_mode_init()
+{
+    vp8_tokens_from_tree(vp8_bmode_encodings,   vp8_bmode_tree);
+    vp8_tokens_from_tree(vp8_ymode_encodings,   vp8_ymode_tree);
+    vp8_tokens_from_tree(vp8_kf_ymode_encodings, vp8_kf_ymode_tree);
+    vp8_tokens_from_tree(vp8_uv_mode_encodings,  vp8_uv_mode_tree);
+    vp8_tokens_from_tree(vp8_mbsplit_encodings, vp8_mbsplit_tree);
+
+    vp8_tokens_from_tree(VP8_MVREFENCODINGS,   vp8_mv_ref_tree);
+    vp8_tokens_from_tree(VP8_SUBMVREFENCODINGS, vp8_sub_mv_ref_tree);
+
+    vp8_tokens_from_tree(vp8_small_mvencodings, vp8_small_mvtree);
+}
diff --git a/vp8/common/entropymode.h b/vp8/common/entropymode.h
new file mode 100644
index 0000000..ff630a4
--- /dev/null
+++ b/vp8/common/entropymode.h
@@ -0,0 +1,71 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_ENTROPYMODE_H
+#define __INC_ENTROPYMODE_H
+
+#include "onyxc_int.h"
+#include "treecoder.h"
+
+typedef const int vp8_mbsplit[16];
+
+#define VP8_NUMMBSPLITS 4
+
+extern vp8_mbsplit vp8_mbsplits [VP8_NUMMBSPLITS];
+
+extern const int vp8_mbsplit_count [VP8_NUMMBSPLITS];    /* # of subsets */
+
+extern const vp8_prob vp8_mbsplit_probs [VP8_NUMMBSPLITS-1];
+
+extern int vp8_mv_cont(const MV *l, const MV *a);
+#define SUBMVREF_COUNT 5
+extern const vp8_prob vp8_sub_mv_ref_prob2 [SUBMVREF_COUNT][VP8_SUBMVREFS-1];
+
+
+extern const unsigned int vp8_kf_default_bmode_counts [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES];
+
+
+extern const vp8_tree_index vp8_bmode_tree[];
+
+extern const vp8_tree_index  vp8_ymode_tree[];
+extern const vp8_tree_index  vp8_kf_ymode_tree[];
+extern const vp8_tree_index  vp8_uv_mode_tree[];
+
+extern const vp8_tree_index  vp8_mbsplit_tree[];
+extern const vp8_tree_index  vp8_mv_ref_tree[];
+extern const vp8_tree_index  vp8_sub_mv_ref_tree[];
+
+extern struct vp8_token_struct vp8_bmode_encodings   [VP8_BINTRAMODES];
+extern struct vp8_token_struct vp8_ymode_encodings   [VP8_YMODES];
+extern struct vp8_token_struct vp8_kf_ymode_encodings [VP8_YMODES];
+extern struct vp8_token_struct vp8_uv_mode_encodings  [VP8_UV_MODES];
+extern struct vp8_token_struct vp8_mbsplit_encodings  [VP8_NUMMBSPLITS];
+
+/* Inter mode values do not start at zero */
+
+extern struct vp8_token_struct vp8_mv_ref_encoding_array    [VP8_MVREFS];
+extern struct vp8_token_struct vp8_sub_mv_ref_encoding_array [VP8_SUBMVREFS];
+
+#define VP8_MVREFENCODINGS      (vp8_mv_ref_encoding_array - NEARESTMV)
+#define VP8_SUBMVREFENCODINGS   (vp8_sub_mv_ref_encoding_array - LEFT4X4)
+
+
+extern const vp8_tree_index vp8_small_mvtree[];
+
+extern struct vp8_token_struct vp8_small_mvencodings [8];
+
+void vp8_entropy_mode_init(void);
+
+void vp8_init_mbmode_probs(VP8_COMMON *x);
+
+void   vp8_default_bmode_probs(vp8_prob dest [VP8_BINTRAMODES-1]);
+void vp8_kf_default_bmode_probs(vp8_prob dest [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES-1]);
+
+#endif
diff --git a/vp8/common/entropymv.c b/vp8/common/entropymv.c
new file mode 100644
index 0000000..2b00c17
--- /dev/null
+++ b/vp8/common/entropymv.c
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "entropymv.h"
+
+const MV_CONTEXT vp8_mv_update_probs[2] =
+{
+    {{
+        237,
+        246,
+        253, 253, 254, 254, 254, 254, 254,
+        254, 254, 254, 254, 254, 250, 250, 252, 254, 254
+    }},
+    {{
+        231,
+        243,
+        245, 253, 254, 254, 254, 254, 254,
+        254, 254, 254, 254, 254, 251, 251, 254, 254, 254
+    }}
+};
+const MV_CONTEXT vp8_default_mv_context[2] =
+{
+    {{
+        // row
+        162,                                        // is short
+        128,                                        // sign
+        225, 146, 172, 147, 214,  39, 156,          // short tree
+        128, 129, 132,  75, 145, 178, 206, 239, 254, 254 // long bits
+    }},
+
+
+
+    {{
+        // same for column
+        164,                                        // is short
+        128,
+        204, 170, 119, 235, 140, 230, 228,
+        128, 130, 130,  74, 148, 180, 203, 236, 254, 254 // long bits
+
+    }}
+};
diff --git a/vp8/common/entropymv.h b/vp8/common/entropymv.h
new file mode 100644
index 0000000..d940c59
--- /dev/null
+++ b/vp8/common/entropymv.h
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_ENTROPYMV_H
+#define __INC_ENTROPYMV_H
+
+#include "treecoder.h"
+
+enum
+{
+    mv_max  = 1023,              /* max absolute value of a MV component */
+    MVvals = (2 * mv_max) + 1,   /* # possible values "" */
+
+    mvlong_width = 10,       /* Large MVs have 9 bit magnitudes */
+    mvnum_short = 8,         /* magnitudes 0 through 7 */
+
+    /* probability offsets for coding each MV component */
+
+    mvpis_short = 0,         /* short (<= 7) vs long (>= 8) */
+    MVPsign,                /* sign for non-zero */
+    MVPshort,               /* 8 short values = 7-position tree */
+
+    MVPbits = MVPshort + mvnum_short - 1, /* mvlong_width long value bits */
+    MVPcount = MVPbits + mvlong_width    /* (with independent probabilities) */
+};
+
+typedef struct mv_context
+{
+    vp8_prob prob[MVPcount];  /* often come in row, col pairs */
+} MV_CONTEXT;
+
+extern const MV_CONTEXT vp8_mv_update_probs[2], vp8_default_mv_context[2];
+
+#endif
diff --git a/vp8/common/extend.c b/vp8/common/extend.c
new file mode 100644
index 0000000..7407952
--- /dev/null
+++ b/vp8/common/extend.c
@@ -0,0 +1,120 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "extend.h"
+#include "vpx_mem/vpx_mem.h"
+
+
+static void extend_plane_borders
+(
+    unsigned char *s, // source
+    int sp,           // pitch
+    int h,            // height
+    int w,            // width
+    int et,           // extend top border
+    int el,           // extend left border
+    int eb,           // extend bottom border
+    int er            // extend right border
+)
+{
+
+    int i;
+    unsigned char *src_ptr1, *src_ptr2;
+    unsigned char *dest_ptr1, *dest_ptr2;
+    int linesize;
+
+    // copy the left and right most columns out
+    src_ptr1 = s;
+    src_ptr2 = s + w - 1;
+    dest_ptr1 = s - el;
+    dest_ptr2 = s + w;
+
+    for (i = 0; i < h - 0 + 1; i++)
+    {
+        vpx_memset(dest_ptr1, src_ptr1[0], el);
+        vpx_memset(dest_ptr2, src_ptr2[0], er);
+        src_ptr1  += sp;
+        src_ptr2  += sp;
+        dest_ptr1 += sp;
+        dest_ptr2 += sp;
+    }
+
+    // Now copy the top and bottom source lines into each line of the respective borders
+    src_ptr1 = s - el;
+    src_ptr2 = s + sp * (h - 1) - el;
+    dest_ptr1 = s + sp * (-et) - el;
+    dest_ptr2 = s + sp * (h) - el;
+    linesize = el + er + w + 1;
+
+    for (i = 0; i < (int)et; i++)
+    {
+        vpx_memcpy(dest_ptr1, src_ptr1, linesize);
+        dest_ptr1 += sp;
+    }
+
+    for (i = 0; i < (int)eb; i++)
+    {
+        vpx_memcpy(dest_ptr2, src_ptr2, linesize);
+        dest_ptr2 += sp;
+    }
+}
+
+
+void vp8_extend_to_multiple_of16(YV12_BUFFER_CONFIG *ybf, int width, int height)
+{
+    int er = 0xf & (16 - (width & 0xf));
+    int eb = 0xf & (16 - (height & 0xf));
+
+    // check for non multiples of 16
+    if (er != 0 || eb != 0)
+    {
+        extend_plane_borders(ybf->y_buffer, ybf->y_stride, height, width, 0, 0, eb, er);
+
+        //adjust for uv
+        height = (height + 1) >> 1;
+        width  = (width  + 1) >> 1;
+        er = 0x7 & (8 - (width  & 0x7));
+        eb = 0x7 & (8 - (height & 0x7));
+
+        if (er || eb)
+        {
+            extend_plane_borders(ybf->u_buffer, ybf->uv_stride, height, width, 0, 0, eb, er);
+            extend_plane_borders(ybf->v_buffer, ybf->uv_stride, height, width, 0, 0, eb, er);
+        }
+    }
+}
+
+// note the extension is only for the last row, for intra prediction purpose
+void vp8_extend_mb_row(YV12_BUFFER_CONFIG *ybf, unsigned char *YPtr, unsigned char *UPtr, unsigned char *VPtr)
+{
+    int i;
+
+    YPtr += ybf->y_stride * 14;
+    UPtr += ybf->uv_stride * 6;
+    VPtr += ybf->uv_stride * 6;
+
+    for (i = 0; i < 4; i++)
+    {
+        YPtr[i] = YPtr[-1];
+        UPtr[i] = UPtr[-1];
+        VPtr[i] = VPtr[-1];
+    }
+
+    YPtr += ybf->y_stride;
+    UPtr += ybf->uv_stride;
+    VPtr += ybf->uv_stride;
+
+    for (i = 0; i < 4; i++)
+    {
+        YPtr[i] = YPtr[-1];
+        UPtr[i] = UPtr[-1];
+        VPtr[i] = VPtr[-1];
+    }
+}
diff --git a/vp8/common/extend.h b/vp8/common/extend.h
new file mode 100644
index 0000000..6809ae7
--- /dev/null
+++ b/vp8/common/extend.h
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_EXTEND_H
+#define __INC_EXTEND_H
+
+#include "vpx_scale/yv12config.h"
+
+void Extend(YV12_BUFFER_CONFIG *ybf);
+void vp8_extend_mb_row(YV12_BUFFER_CONFIG *ybf, unsigned char *YPtr, unsigned char *UPtr, unsigned char *VPtr);
+void vp8_extend_to_multiple_of16(YV12_BUFFER_CONFIG *ybf, int width, int height);
+
+#endif
diff --git a/vp8/common/filter_c.c b/vp8/common/filter_c.c
new file mode 100644
index 0000000..38991cb
--- /dev/null
+++ b/vp8/common/filter_c.c
@@ -0,0 +1,539 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <stdlib.h>
+
+#define BLOCK_HEIGHT_WIDTH 4
+#define VP8_FILTER_WEIGHT 128
+#define VP8_FILTER_SHIFT  7
+
+
+static const int bilinear_filters[8][2] =
+{
+    { 128,   0 },
+    { 112,  16 },
+    {  96,  32 },
+    {  80,  48 },
+    {  64,  64 },
+    {  48,  80 },
+    {  32,  96 },
+    {  16, 112 }
+};
+
+
+static const short sub_pel_filters[8][6] =
+{
+
+    { 0,  0,  128,    0,   0,  0 },         // note that 1/8 pel positions are just as per alpha -0.5 bicubic
+    { 0, -6,  123,   12,  -1,  0 },
+    { 2, -11, 108,   36,  -8,  1 },         // New 1/4 pel 6 tap filter
+    { 0, -9,   93,   50,  -6,  0 },
+    { 3, -16,  77,   77, -16,  3 },         // New 1/2 pel 6 tap filter
+    { 0, -6,   50,   93,  -9,  0 },
+    { 1, -8,   36,  108, -11,  2 },         // New 1/4 pel 6 tap filter
+    { 0, -1,   12,  123,  -6,  0 },
+
+
+
+};
+
+void vp8_filter_block2d_first_pass
+(
+    unsigned char *src_ptr,
+    int *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short *vp8_filter
+)
+{
+    unsigned int i, j;
+    int  Temp;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+            Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
+                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
+                   ((int)src_ptr[0]                 * vp8_filter[2]) +
+                   ((int)src_ptr[pixel_step]         * vp8_filter[3]) +
+                   ((int)src_ptr[2*pixel_step]       * vp8_filter[4]) +
+                   ((int)src_ptr[3*pixel_step]       * vp8_filter[5]) +
+                   (VP8_FILTER_WEIGHT >> 1);      // Rounding
+
+            // Normalize back to 0-255
+            Temp = Temp >> VP8_FILTER_SHIFT;
+
+            if (Temp < 0)
+                Temp = 0;
+            else if (Temp > 255)
+                Temp = 255;
+
+            output_ptr[j] = Temp;
+            src_ptr++;
+        }
+
+        // Next row...
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_width;
+    }
+}
+
+void vp8_filter_block2d_second_pass
+(
+    int *src_ptr,
+    unsigned char *output_ptr,
+    int output_pitch,
+    unsigned int src_pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short *vp8_filter
+)
+{
+    unsigned int i, j;
+    int  Temp;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+            // Apply filter
+            Temp = ((int)src_ptr[-2 * (int)pixel_step] * vp8_filter[0]) +
+                   ((int)src_ptr[-1 * (int)pixel_step] * vp8_filter[1]) +
+                   ((int)src_ptr[0]                 * vp8_filter[2]) +
+                   ((int)src_ptr[pixel_step]         * vp8_filter[3]) +
+                   ((int)src_ptr[2*pixel_step]       * vp8_filter[4]) +
+                   ((int)src_ptr[3*pixel_step]       * vp8_filter[5]) +
+                   (VP8_FILTER_WEIGHT >> 1);   // Rounding
+
+            // Normalize back to 0-255
+            Temp = Temp >> VP8_FILTER_SHIFT;
+
+            if (Temp < 0)
+                Temp = 0;
+            else if (Temp > 255)
+                Temp = 255;
+
+            output_ptr[j] = (unsigned char)Temp;
+            src_ptr++;
+        }
+
+        // Start next row
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_pitch;
+    }
+}
+
+
+void vp8_filter_block2d
+(
+    unsigned char  *src_ptr,
+    unsigned char  *output_ptr,
+    unsigned int src_pixels_per_line,
+    int output_pitch,
+    const short  *HFilter,
+    const short  *VFilter
+)
+{
+    int FData[9*4]; // Temp data bufffer used in filtering
+
+    // First filter 1-D horizontally...
+    vp8_filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 9, 4, HFilter);
+
+    // then filter verticaly...
+    vp8_filter_block2d_second_pass(FData + 8, output_ptr, output_pitch, 4, 4, 4, 4, VFilter);
+}
+
+
+void vp8_block_variation_c
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int *HVar,
+    int *VVar
+)
+{
+    int i, j;
+    unsigned char *Ptr = src_ptr;
+
+    for (i = 0; i < 4; i++)
+    {
+        for (j = 0; j < 4; j++)
+        {
+            *HVar += abs((int)Ptr[j] - (int)Ptr[j+1]);
+            *VVar += abs((int)Ptr[j] - (int)Ptr[j+src_pixels_per_line]);
+        }
+
+        Ptr += src_pixels_per_line;
+    }
+}
+
+
+
+
+void vp8_sixtap_predict_c
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+
+    HFilter = sub_pel_filters[xoffset];   // 6 tap
+    VFilter = sub_pel_filters[yoffset];   // 6 tap
+
+    vp8_filter_block2d(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter);
+}
+void vp8_sixtap_predict8x8_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    int FData[13*16];   // Temp data bufffer used in filtering
+
+    HFilter = sub_pel_filters[xoffset];   // 6 tap
+    VFilter = sub_pel_filters[yoffset];   // 6 tap
+
+    // First filter 1-D horizontally...
+    vp8_filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 13, 8, HFilter);
+
+
+    // then filter verticaly...
+    vp8_filter_block2d_second_pass(FData + 16, dst_ptr, dst_pitch, 8, 8, 8, 8, VFilter);
+
+}
+
+void vp8_sixtap_predict8x4_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    int FData[13*16];   // Temp data bufffer used in filtering
+
+    HFilter = sub_pel_filters[xoffset];   // 6 tap
+    VFilter = sub_pel_filters[yoffset];   // 6 tap
+
+    // First filter 1-D horizontally...
+    vp8_filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 9, 8, HFilter);
+
+
+    // then filter verticaly...
+    vp8_filter_block2d_second_pass(FData + 16, dst_ptr, dst_pitch, 8, 8, 4, 8, VFilter);
+
+}
+
+void vp8_sixtap_predict16x16_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const short  *HFilter;
+    const short  *VFilter;
+    int FData[21*24];   // Temp data bufffer used in filtering
+
+
+    HFilter = sub_pel_filters[xoffset];   // 6 tap
+    VFilter = sub_pel_filters[yoffset];   // 6 tap
+
+    // First filter 1-D horizontally...
+    vp8_filter_block2d_first_pass(src_ptr - (2 * src_pixels_per_line), FData, src_pixels_per_line, 1, 21, 16, HFilter);
+
+    // then filter verticaly...
+    vp8_filter_block2d_second_pass(FData + 32, dst_ptr, dst_pitch, 16, 16, 16, 16, VFilter);
+
+}
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : filter_block2d_bil_first_pass
+ *
+ *  INPUTS        : UINT8  *src_ptr          : Pointer to source block.
+ *                  UINT32 src_pixels_per_line : Stride of input block.
+ *                  UINT32 pixel_step        : Offset between filter input samples (see notes).
+ *                  UINT32 output_height     : Input block height.
+ *                  UINT32 output_width      : Input block width.
+ *                  INT32  *vp8_filter          : Array of 2 bi-linear filter taps.
+ *
+ *  OUTPUTS       : INT32 *output_ptr        : Pointer to filtered block.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block in
+ *                  either horizontal or vertical direction to produce the
+ *                  filtered output block. Used to implement first-pass
+ *                  of 2-D separable filter.
+ *
+ *  SPECIAL NOTES : Produces INT32 output to retain precision for next pass.
+ *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
+ *                  pixel_step defines whether the filter is applied
+ *                  horizontally (pixel_step=1) or vertically (pixel_step=stride).
+ *                  It defines the offset required to move from one input
+ *                  to the next.
+ *
+ ****************************************************************************/
+void vp8_filter_block2d_bil_first_pass
+(
+    unsigned char *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int src_pixels_per_line,
+    int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const int *vp8_filter
+)
+{
+    unsigned int i, j;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+            // Apply bilinear filter
+            output_ptr[j] = (((int)src_ptr[0]          * vp8_filter[0]) +
+                             ((int)src_ptr[pixel_step] * vp8_filter[1]) +
+                             (VP8_FILTER_WEIGHT / 2)) >> VP8_FILTER_SHIFT;
+            src_ptr++;
+        }
+
+        // Next row...
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_width;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : filter_block2d_bil_second_pass
+ *
+ *  INPUTS        : INT32  *src_ptr          : Pointer to source block.
+ *                  UINT32 src_pixels_per_line : Stride of input block.
+ *                  UINT32 pixel_step        : Offset between filter input samples (see notes).
+ *                  UINT32 output_height     : Input block height.
+ *                  UINT32 output_width      : Input block width.
+ *                  INT32  *vp8_filter          : Array of 2 bi-linear filter taps.
+ *
+ *  OUTPUTS       : UINT16 *output_ptr       : Pointer to filtered block.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block in
+ *                  either horizontal or vertical direction to produce the
+ *                  filtered output block. Used to implement second-pass
+ *                  of 2-D separable filter.
+ *
+ *  SPECIAL NOTES : Requires 32-bit input as produced by filter_block2d_bil_first_pass.
+ *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
+ *                  pixel_step defines whether the filter is applied
+ *                  horizontally (pixel_step=1) or vertically (pixel_step=stride).
+ *                  It defines the offset required to move from one input
+ *                  to the next.
+ *
+ ****************************************************************************/
+void vp8_filter_block2d_bil_second_pass
+(
+    unsigned short *src_ptr,
+    unsigned char  *output_ptr,
+    int output_pitch,
+    unsigned int  src_pixels_per_line,
+    unsigned int  pixel_step,
+    unsigned int  output_height,
+    unsigned int  output_width,
+    const int *vp8_filter
+)
+{
+    unsigned int  i, j;
+    int  Temp;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+            // Apply filter
+            Temp = ((int)src_ptr[0]         * vp8_filter[0]) +
+                   ((int)src_ptr[pixel_step] * vp8_filter[1]) +
+                   (VP8_FILTER_WEIGHT / 2);
+            output_ptr[j] = (unsigned int)(Temp >> VP8_FILTER_SHIFT);
+            src_ptr++;
+        }
+
+        // Next row...
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_pitch;
+    }
+}
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : filter_block2d_bil
+ *
+ *  INPUTS        : UINT8  *src_ptr          : Pointer to source block.
+ *                  UINT32 src_pixels_per_line : Stride of input block.
+ *                  INT32  *HFilter         : Array of 2 horizontal filter taps.
+ *                  INT32  *VFilter         : Array of 2 vertical filter taps.
+ *
+ *  OUTPUTS       : UINT16 *output_ptr       : Pointer to filtered block.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : 2-D filters an input block by applying a 2-tap
+ *                  bi-linear filter horizontally followed by a 2-tap
+ *                  bi-linear filter vertically on the result.
+ *
+ *  SPECIAL NOTES : The largest block size can be handled here is 16x16
+ *
+ ****************************************************************************/
+void vp8_filter_block2d_bil
+(
+    unsigned char *src_ptr,
+    unsigned char *output_ptr,
+    unsigned int   src_pixels_per_line,
+    unsigned int   dst_pitch,
+    const int      *HFilter,
+    const int      *VFilter,
+    int            Width,
+    int            Height
+)
+{
+
+    unsigned short FData[17*16];    // Temp data bufffer used in filtering
+
+    // First filter 1-D horizontally...
+    vp8_filter_block2d_bil_first_pass(src_ptr, FData, src_pixels_per_line, 1, Height + 1, Width, HFilter);
+
+    // then 1-D vertically...
+    vp8_filter_block2d_bil_second_pass(FData, output_ptr, dst_pitch, Width, Width, Height, Width, VFilter);
+}
+
+
+void vp8_bilinear_predict4x4_c
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    const int  *HFilter;
+    const int  *VFilter;
+
+    HFilter = bilinear_filters[xoffset];
+    VFilter = bilinear_filters[yoffset];
+#if 0
+    {
+        int i;
+        unsigned char temp1[16];
+        unsigned char temp2[16];
+
+        bilinear_predict4x4_mmx(src_ptr, src_pixels_per_line, xoffset, yoffset, temp1, 4);
+        vp8_filter_block2d_bil(src_ptr, temp2, src_pixels_per_line, 4, HFilter, VFilter, 4, 4);
+
+        for (i = 0; i < 16; i++)
+        {
+            if (temp1[i] != temp2[i])
+            {
+                bilinear_predict4x4_mmx(src_ptr, src_pixels_per_line, xoffset, yoffset, temp1, 4);
+                vp8_filter_block2d_bil(src_ptr, temp2, src_pixels_per_line, 4, HFilter, VFilter, 4, 4);
+            }
+        }
+    }
+#endif
+    vp8_filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 4, 4);
+
+}
+
+void vp8_bilinear_predict8x8_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const int  *HFilter;
+    const int  *VFilter;
+
+    HFilter = bilinear_filters[xoffset];
+    VFilter = bilinear_filters[yoffset];
+
+    vp8_filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 8);
+
+}
+
+void vp8_bilinear_predict8x4_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const int  *HFilter;
+    const int  *VFilter;
+
+    HFilter = bilinear_filters[xoffset];
+    VFilter = bilinear_filters[yoffset];
+
+    vp8_filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 8, 4);
+
+}
+
+void vp8_bilinear_predict16x16_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int  dst_pitch
+)
+{
+    const int  *HFilter;
+    const int  *VFilter;
+
+    HFilter = bilinear_filters[xoffset];
+    VFilter = bilinear_filters[yoffset];
+
+    vp8_filter_block2d_bil(src_ptr, dst_ptr, src_pixels_per_line, dst_pitch, HFilter, VFilter, 16, 16);
+}
diff --git a/vp8/common/findnearmv.c b/vp8/common/findnearmv.c
new file mode 100644
index 0000000..fcb1f20
--- /dev/null
+++ b/vp8/common/findnearmv.c
@@ -0,0 +1,207 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "findnearmv.h"
+
+#define FINDNEAR_SEARCH_SITES   3
+
+/* Predict motion vectors using those from already-decoded nearby blocks.
+   Note that we only consider one 4x4 subblock from each candidate 16x16
+   macroblock.   */
+
+typedef union
+{
+    unsigned int as_int;
+    MV           as_mv;
+} int_mv;        /* facilitates rapid equality tests */
+
+static void mv_bias(const MODE_INFO *x, int refframe, int_mv *mvp, const int *ref_frame_sign_bias)
+{
+    MV xmv;
+    xmv = x->mbmi.mv.as_mv;
+
+    if (ref_frame_sign_bias[x->mbmi.ref_frame] != ref_frame_sign_bias[refframe])
+    {
+        xmv.row *= -1;
+        xmv.col *= -1;
+    }
+
+    mvp->as_mv = xmv;
+}
+
+
+void vp8_clamp_mv(MV *mv, const MACROBLOCKD *xd)
+{
+    if (mv->col < (xd->mb_to_left_edge - LEFT_TOP_MARGIN))
+        mv->col = xd->mb_to_left_edge - LEFT_TOP_MARGIN;
+    else if (mv->col > xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN)
+        mv->col = xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN;
+
+    if (mv->row < (xd->mb_to_top_edge - LEFT_TOP_MARGIN))
+        mv->row = xd->mb_to_top_edge - LEFT_TOP_MARGIN;
+    else if (mv->row > xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN)
+        mv->row = xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN;
+}
+
+
+void vp8_find_near_mvs
+(
+    MACROBLOCKD *xd,
+    const MODE_INFO *here,
+    MV *nearest,
+    MV *nearby,
+    MV *best_mv,
+    int cnt[4],
+    int refframe,
+    int *ref_frame_sign_bias
+)
+{
+    const MODE_INFO *above = here - xd->mode_info_stride;
+    const MODE_INFO *left = here - 1;
+    const MODE_INFO *aboveleft = above - 1;
+    int_mv            near_mvs[4];
+    int_mv           *mv = near_mvs;
+    int             *cntx = cnt;
+    enum {CNT_INTRA, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV};
+
+    /* Zero accumulators */
+    mv[0].as_int = mv[1].as_int = mv[2].as_int = 0;
+    cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;
+
+    /* Process above */
+    if (above->mbmi.ref_frame != INTRA_FRAME)
+    {
+        if (above->mbmi.mv.as_int)
+        {
+            (++mv)->as_int = above->mbmi.mv.as_int;
+            mv_bias(above, refframe, mv, ref_frame_sign_bias);
+            ++cntx;
+        }
+
+        *cntx += 2;
+    }
+
+    /* Process left */
+    if (left->mbmi.ref_frame != INTRA_FRAME)
+    {
+        if (left->mbmi.mv.as_int)
+        {
+            int_mv this_mv;
+
+            this_mv.as_int = left->mbmi.mv.as_int;
+            mv_bias(left, refframe, &this_mv, ref_frame_sign_bias);
+
+            if (this_mv.as_int != mv->as_int)
+            {
+                (++mv)->as_int = this_mv.as_int;
+                ++cntx;
+            }
+
+            *cntx += 2;
+        }
+        else
+            cnt[CNT_INTRA] += 2;
+    }
+
+    /* Process above left */
+    if (aboveleft->mbmi.ref_frame != INTRA_FRAME)
+    {
+        if (aboveleft->mbmi.mv.as_int)
+        {
+            int_mv this_mv;
+
+            this_mv.as_int = aboveleft->mbmi.mv.as_int;
+            mv_bias(aboveleft, refframe, &this_mv, ref_frame_sign_bias);
+
+            if (this_mv.as_int != mv->as_int)
+            {
+                (++mv)->as_int = this_mv.as_int;
+                ++cntx;
+            }
+
+            *cntx += 1;
+        }
+        else
+            cnt[CNT_INTRA] += 1;
+    }
+
+    /* If we have three distinct MV's ... */
+    if (cnt[CNT_SPLITMV])
+    {
+        /* See if above-left MV can be merged with NEAREST */
+        if (mv->as_int == near_mvs[CNT_NEAREST].as_int)
+            cnt[CNT_NEAREST] += 1;
+    }
+
+    cnt[CNT_SPLITMV] = ((above->mbmi.mode == SPLITMV)
+                        + (left->mbmi.mode == SPLITMV)) * 2
+                       + (aboveleft->mbmi.mode == SPLITMV);
+
+    /* Swap near and nearest if necessary */
+    if (cnt[CNT_NEAR] > cnt[CNT_NEAREST])
+    {
+        int tmp;
+        tmp = cnt[CNT_NEAREST];
+        cnt[CNT_NEAREST] = cnt[CNT_NEAR];
+        cnt[CNT_NEAR] = tmp;
+        tmp = near_mvs[CNT_NEAREST].as_int;
+        near_mvs[CNT_NEAREST].as_int = near_mvs[CNT_NEAR].as_int;
+        near_mvs[CNT_NEAR].as_int = tmp;
+    }
+
+    /* Use near_mvs[0] to store the "best" MV */
+    if (cnt[CNT_NEAREST] >= cnt[CNT_INTRA])
+        near_mvs[CNT_INTRA] = near_mvs[CNT_NEAREST];
+
+    /* Set up return values */
+    *best_mv = near_mvs[0].as_mv;
+    *nearest = near_mvs[CNT_NEAREST].as_mv;
+    *nearby = near_mvs[CNT_NEAR].as_mv;
+
+    vp8_clamp_mv(nearest, xd);
+    vp8_clamp_mv(nearby, xd);
+    vp8_clamp_mv(best_mv, xd); //TODO: move this up before the copy
+}
+
+vp8_prob *vp8_mv_ref_probs(
+    vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4]
+)
+{
+    p[0] = vp8_mode_contexts [near_mv_ref_ct[0]] [0];
+    p[1] = vp8_mode_contexts [near_mv_ref_ct[1]] [1];
+    p[2] = vp8_mode_contexts [near_mv_ref_ct[2]] [2];
+    p[3] = vp8_mode_contexts [near_mv_ref_ct[3]] [3];
+    //p[3] = vp8_mode_contexts [near_mv_ref_ct[1] + near_mv_ref_ct[2] + near_mv_ref_ct[3]] [3];
+    return p;
+}
+
+const B_MODE_INFO *vp8_left_bmi(const MODE_INFO *cur_mb, int b)
+{
+    if (!(b & 3))
+    {
+        /* On L edge, get from MB to left of us */
+        --cur_mb;
+        b += 4;
+    }
+
+    return cur_mb->bmi + b - 1;
+}
+
+const B_MODE_INFO *vp8_above_bmi(const MODE_INFO *cur_mb, int b, int mi_stride)
+{
+    if (!(b >> 2))
+    {
+        /* On top edge, get from MB above us */
+        cur_mb -= mi_stride;
+        b += 16;
+    }
+
+    return cur_mb->bmi + b - 4;
+}
diff --git a/vp8/common/findnearmv.h b/vp8/common/findnearmv.h
new file mode 100644
index 0000000..2c02033
--- /dev/null
+++ b/vp8/common/findnearmv.h
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_FINDNEARMV_H
+#define __INC_FINDNEARMV_H
+
+#include "mv.h"
+#include "blockd.h"
+#include "modecont.h"
+#include "treecoder.h"
+
+void vp8_find_near_mvs
+(
+    MACROBLOCKD *xd,
+    const MODE_INFO *here,
+    MV *nearest, MV *nearby, MV *best,
+    int near_mv_ref_cts[4],
+    int refframe,
+    int *ref_frame_sign_bias
+);
+
+vp8_prob *vp8_mv_ref_probs(
+    vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4]
+);
+
+const B_MODE_INFO *vp8_left_bmi(const MODE_INFO *cur_mb, int b);
+
+const B_MODE_INFO *vp8_above_bmi(const MODE_INFO *cur_mb, int b, int mi_stride);
+
+#define LEFT_TOP_MARGIN (16 << 3)
+#define RIGHT_BOTTOM_MARGIN (16 << 3)
+
+
+#endif
diff --git a/vp8/common/fourcc.hpp b/vp8/common/fourcc.hpp
new file mode 100644
index 0000000..5f1faed
--- /dev/null
+++ b/vp8/common/fourcc.hpp
@@ -0,0 +1,120 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef FOURCC_HPP
+#define FOURCC_HPP
+
+#include <iosfwd>
+#include <cstring>
+
+
+#if defined(__POWERPC__) || defined(__APPLE__) || defined(__MERKS__)
+using namespace std;
+#endif
+
+class four_cc
+{
+public:
+
+    four_cc();
+    four_cc(const char*);
+    explicit four_cc(unsigned long);
+
+    bool operator==(const four_cc&) const;
+    bool operator!=(const four_cc&) const;
+
+    bool operator==(const char*) const;
+    bool operator!=(const char*) const;
+
+    operator unsigned long() const;
+    unsigned long as_long() const;
+
+    four_cc& operator=(unsigned long);
+
+    char operator[](int) const;
+
+    std::ostream& put(std::ostream&) const;
+
+    bool printable() const;
+
+private:
+
+    union
+    {
+        char code[4];
+        unsigned long code_as_long;
+    };
+
+};
+
+
+inline four_cc::four_cc()
+{
+}
+
+inline four_cc::four_cc(unsigned long x)
+    : code_as_long(x)
+{
+}
+
+inline four_cc::four_cc(const char* str)
+{
+    memcpy(code, str, 4);
+}
+
+
+inline bool four_cc::operator==(const four_cc& rhs) const
+{
+    return code_as_long == rhs.code_as_long;
+}
+
+inline bool four_cc::operator!=(const four_cc& rhs) const
+{
+    return !operator==(rhs);
+}
+
+inline bool four_cc::operator==(const char* rhs) const
+{
+    return (memcmp(code, rhs, 4) == 0);
+}
+
+inline bool four_cc::operator!=(const char* rhs) const
+{
+    return !operator==(rhs);
+}
+
+
+inline four_cc::operator unsigned long() const
+{
+    return code_as_long;
+}
+
+inline unsigned long four_cc::as_long() const
+{
+    return code_as_long;
+}
+
+inline char four_cc::operator[](int i) const
+{
+    return code[i];
+}
+
+inline four_cc& four_cc::operator=(unsigned long val)
+{
+    code_as_long = val;
+    return *this;
+}
+
+inline std::ostream& operator<<(std::ostream& os, const four_cc& rhs)
+{
+    return rhs.put(os);
+}
+
+#endif
diff --git a/vp8/common/g_common.h b/vp8/common/g_common.h
new file mode 100644
index 0000000..e68c53e
--- /dev/null
+++ b/vp8/common/g_common.h
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+extern void (*vp8_clear_system_state)(void);
+extern void (*vp8_plane_add_noise)(unsigned char *Start, unsigned int Width, unsigned int Height, int Pitch, int DPitch, int q);
+extern void (*de_interlace)
+(
+    unsigned char *src_ptr,
+    unsigned char *dst_ptr,
+    int Width,
+    int Height,
+    int Stride
+);
diff --git a/vp8/common/generic/systemdependent.c b/vp8/common/generic/systemdependent.c
new file mode 100644
index 0000000..0011ae0
--- /dev/null
+++ b/vp8/common/generic/systemdependent.c
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "g_common.h"
+#include "subpixel.h"
+#include "loopfilter.h"
+#include "recon.h"
+#include "idct.h"
+#include "onyxc_int.h"
+
+extern void vp8_arch_x86_common_init(VP8_COMMON *ctx);
+
+void (*vp8_build_intra_predictors_mby_ptr)(MACROBLOCKD *x);
+extern void vp8_build_intra_predictors_mby(MACROBLOCKD *x);
+
+void (*vp8_build_intra_predictors_mby_s_ptr)(MACROBLOCKD *x);
+extern void vp8_build_intra_predictors_mby_s(MACROBLOCKD *x);
+
+void vp8_machine_specific_config(VP8_COMMON *ctx)
+{
+#if CONFIG_RUNTIME_CPU_DETECT
+    VP8_COMMON_RTCD *rtcd = &ctx->rtcd;
+
+    rtcd->idct.idct1        = vp8_short_idct4x4llm_1_c;
+    rtcd->idct.idct16       = vp8_short_idct4x4llm_c;
+    rtcd->idct.idct1_scalar = vp8_dc_only_idct_c;
+    rtcd->idct.iwalsh1      = vp8_short_inv_walsh4x4_1_c;
+    rtcd->idct.iwalsh16     = vp8_short_inv_walsh4x4_c;
+
+    rtcd->recon.copy16x16   = vp8_copy_mem16x16_c;
+    rtcd->recon.copy8x8     = vp8_copy_mem8x8_c;
+    rtcd->recon.copy8x4     = vp8_copy_mem8x4_c;
+    rtcd->recon.recon      = vp8_recon_b_c;
+    rtcd->recon.recon2      = vp8_recon2b_c;
+    rtcd->recon.recon4     = vp8_recon4b_c;
+
+    rtcd->subpix.sixtap16x16   = vp8_sixtap_predict16x16_c;
+    rtcd->subpix.sixtap8x8     = vp8_sixtap_predict8x8_c;
+    rtcd->subpix.sixtap8x4     = vp8_sixtap_predict8x4_c;
+    rtcd->subpix.sixtap4x4     = vp8_sixtap_predict_c;
+    rtcd->subpix.bilinear16x16 = vp8_bilinear_predict16x16_c;
+    rtcd->subpix.bilinear8x8   = vp8_bilinear_predict8x8_c;
+    rtcd->subpix.bilinear8x4   = vp8_bilinear_predict8x4_c;
+    rtcd->subpix.bilinear4x4   = vp8_bilinear_predict4x4_c;
+
+    rtcd->loopfilter.normal_mb_v = vp8_loop_filter_mbv_c;
+    rtcd->loopfilter.normal_b_v  = vp8_loop_filter_bv_c;
+    rtcd->loopfilter.normal_mb_h = vp8_loop_filter_mbh_c;
+    rtcd->loopfilter.normal_b_h  = vp8_loop_filter_bh_c;
+    rtcd->loopfilter.simple_mb_v = vp8_loop_filter_mbvs_c;
+    rtcd->loopfilter.simple_b_v  = vp8_loop_filter_bvs_c;
+    rtcd->loopfilter.simple_mb_h = vp8_loop_filter_mbhs_c;
+    rtcd->loopfilter.simple_b_h  = vp8_loop_filter_bhs_c;
+
+#if CONFIG_POSTPROC || CONFIG_VP8_ENCODER
+    rtcd->postproc.down        = vp8_mbpost_proc_down_c;
+    rtcd->postproc.across      = vp8_mbpost_proc_across_ip_c;
+    rtcd->postproc.downacross  = vp8_post_proc_down_and_across_c;
+    rtcd->postproc.addnoise    = vp8_plane_add_noise_c;
+#endif
+
+#endif
+    // Pure C:
+    vp8_build_intra_predictors_mby_ptr = vp8_build_intra_predictors_mby;
+    vp8_build_intra_predictors_mby_s_ptr = vp8_build_intra_predictors_mby_s;
+
+#if ARCH_X86 || ARCH_X86_64
+    vp8_arch_x86_common_init(ctx);
+#endif
+
+}
diff --git a/vp8/common/header.h b/vp8/common/header.h
new file mode 100644
index 0000000..8b2b009
--- /dev/null
+++ b/vp8/common/header.h
@@ -0,0 +1,42 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_HEADER_H
+#define __INC_HEADER_H
+
+/* 24 bits total */
+typedef struct
+{
+    unsigned int type: 1;
+    unsigned int version: 3;
+    unsigned int show_frame: 1;
+
+    /* Allow 2^20 bytes = 8 megabits for first partition */
+
+    unsigned int first_partition_length_in_bytes: 19;
+
+#ifdef PACKET_TESTING
+    unsigned int frame_number;
+    unsigned int update_gold: 1;
+    unsigned int uses_gold: 1;
+    unsigned int update_last: 1;
+    unsigned int uses_last: 1;
+#endif
+
+} VP8_HEADER;
+
+#ifdef PACKET_TESTING
+#define VP8_HEADER_SIZE 8
+#else
+#define VP8_HEADER_SIZE 3
+#endif
+
+
+#endif
diff --git a/vp8/common/idct.h b/vp8/common/idct.h
new file mode 100644
index 0000000..47b5f05
--- /dev/null
+++ b/vp8/common/idct.h
@@ -0,0 +1,77 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_IDCT_H
+#define __INC_IDCT_H
+
+#define prototype_second_order(sym) \
+    void sym(short *input, short *output)
+
+#define prototype_idct(sym) \
+    void sym(short *input, short *output, int pitch)
+
+#define prototype_idct_scalar(sym) \
+    void sym(short input, short *output, int pitch)
+
+#if ARCH_X86 || ARCH_X86_64
+#include "x86/idct_x86.h"
+#endif
+
+#if ARCH_ARM
+#include "arm/idct_arm.h"
+#endif
+
+#ifndef vp8_idct_idct1
+#define vp8_idct_idct1 vp8_short_idct4x4llm_1_c
+#endif
+extern prototype_idct(vp8_idct_idct1);
+
+#ifndef vp8_idct_idct16
+#define vp8_idct_idct16 vp8_short_idct4x4llm_c
+#endif
+extern prototype_idct(vp8_idct_idct16);
+
+#ifndef vp8_idct_idct1_scalar
+#define vp8_idct_idct1_scalar vp8_dc_only_idct_c
+#endif
+extern prototype_idct_scalar(vp8_idct_idct1_scalar);
+
+
+#ifndef vp8_idct_iwalsh1
+#define vp8_idct_iwalsh1 vp8_short_inv_walsh4x4_1_c
+#endif
+extern prototype_second_order(vp8_idct_iwalsh1);
+
+#ifndef vp8_idct_iwalsh16
+#define vp8_idct_iwalsh16 vp8_short_inv_walsh4x4_c
+#endif
+extern prototype_second_order(vp8_idct_iwalsh16);
+
+typedef prototype_idct((*vp8_idct_fn_t));
+typedef prototype_idct_scalar((*vp8_idct_scalar_fn_t));
+typedef prototype_second_order((*vp8_second_order_fn_t));
+
+typedef struct
+{
+    vp8_idct_fn_t         idct1;
+    vp8_idct_fn_t         idct16;
+    vp8_idct_scalar_fn_t  idct1_scalar;
+
+    vp8_second_order_fn_t iwalsh1;
+    vp8_second_order_fn_t iwalsh16;
+} vp8_idct_rtcd_vtable_t;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define IDCT_INVOKE(ctx,fn) (ctx)->fn
+#else
+#define IDCT_INVOKE(ctx,fn) vp8_idct_##fn
+#endif
+
+#endif
diff --git a/vp8/common/idctllm.c b/vp8/common/idctllm.c
new file mode 100644
index 0000000..57cf858
--- /dev/null
+++ b/vp8/common/idctllm.c
@@ -0,0 +1,189 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/****************************************************************************
+ * Notes:
+ *
+ * This implementation makes use of 16 bit fixed point verio of two multiply
+ * constants:
+ *         1.   sqrt(2) * cos (pi/8)
+ *         2.   sqrt(2) * sin (pi/8)
+ * Becuase the first constant is bigger than 1, to maintain the same 16 bit
+ * fixed point precision as the second one, we use a trick of
+ *         x * a = x + x*(a-1)
+ * so
+ *         x * sqrt(2) * cos (pi/8) = x + x * (sqrt(2) *cos(pi/8)-1).
+ **************************************************************************/
+static const int cospi8sqrt2minus1 = 20091;
+static const int sinpi8sqrt2      = 35468;
+static const int rounding = 0;
+void vp8_short_idct4x4llm_c(short *input, short *output, int pitch)
+{
+    int i;
+    int a1, b1, c1, d1;
+
+    short *ip = input;
+    short *op = output;
+    int temp1, temp2;
+    int shortpitch = pitch >> 1;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ip[0] + ip[8];
+        b1 = ip[0] - ip[8];
+
+        temp1 = (ip[4] * sinpi8sqrt2 + rounding) >> 16;
+        temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1 + rounding) >> 16);
+        c1 = temp1 - temp2;
+
+        temp1 = ip[4] + ((ip[4] * cospi8sqrt2minus1 + rounding) >> 16);
+        temp2 = (ip[12] * sinpi8sqrt2 + rounding) >> 16;
+        d1 = temp1 + temp2;
+
+        op[shortpitch*0] = a1 + d1;
+        op[shortpitch*3] = a1 - d1;
+
+        op[shortpitch*1] = b1 + c1;
+        op[shortpitch*2] = b1 - c1;
+
+        ip++;
+        op++;
+    }
+
+    ip = output;
+    op = output;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ip[0] + ip[2];
+        b1 = ip[0] - ip[2];
+
+        temp1 = (ip[1] * sinpi8sqrt2 + rounding) >> 16;
+        temp2 = ip[3] + ((ip[3] * cospi8sqrt2minus1 + rounding) >> 16);
+        c1 = temp1 - temp2;
+
+        temp1 = ip[1] + ((ip[1] * cospi8sqrt2minus1 + rounding) >> 16);
+        temp2 = (ip[3] * sinpi8sqrt2 + rounding) >> 16;
+        d1 = temp1 + temp2;
+
+
+        op[0] = (a1 + d1 + 4) >> 3;
+        op[3] = (a1 - d1 + 4) >> 3;
+
+        op[1] = (b1 + c1 + 4) >> 3;
+        op[2] = (b1 - c1 + 4) >> 3;
+
+        ip += shortpitch;
+        op += shortpitch;
+    }
+}
+
+void vp8_short_idct4x4llm_1_c(short *input, short *output, int pitch)
+{
+    int i;
+    int a1;
+    short *op = output;
+    int shortpitch = pitch >> 1;
+    a1 = ((input[0] + 4) >> 3);
+
+    for (i = 0; i < 4; i++)
+    {
+        op[0] = a1;
+        op[1] = a1;
+        op[2] = a1;
+        op[3] = a1;
+        op += shortpitch;
+    }
+}
+
+
+void vp8_dc_only_idct_c(short input_dc, short *output, int pitch)
+{
+    int i;
+    int a1;
+    short *op = output;
+    int shortpitch = pitch >> 1;
+    a1 = ((input_dc + 4) >> 3);
+
+    for (i = 0; i < 4; i++)
+    {
+        op[0] = a1;
+        op[1] = a1;
+        op[2] = a1;
+        op[3] = a1;
+        op += shortpitch;
+    }
+}
+
+void vp8_short_inv_walsh4x4_c(short *input, short *output)
+{
+    int i;
+    int a1, b1, c1, d1;
+    int a2, b2, c2, d2;
+    short *ip = input;
+    short *op = output;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ip[0] + ip[12];
+        b1 = ip[4] + ip[8];
+        c1 = ip[4] - ip[8];
+        d1 = ip[0] - ip[12];
+
+        op[0] = a1 + b1;
+        op[4] = c1 + d1;
+        op[8] = a1 - b1;
+        op[12] = d1 - c1;
+        ip++;
+        op++;
+    }
+
+    ip = output;
+    op = output;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ip[0] + ip[3];
+        b1 = ip[1] + ip[2];
+        c1 = ip[1] - ip[2];
+        d1 = ip[0] - ip[3];
+
+        a2 = a1 + b1;
+        b2 = c1 + d1;
+        c2 = a1 - b1;
+        d2 = d1 - c1;
+
+        op[0] = (a2 + 3) >> 3;
+        op[1] = (b2 + 3) >> 3;
+        op[2] = (c2 + 3) >> 3;
+        op[3] = (d2 + 3) >> 3;
+
+        ip += 4;
+        op += 4;
+    }
+}
+
+void vp8_short_inv_walsh4x4_1_c(short *input, short *output)
+{
+    int i;
+    int a1;
+    short *op = output;
+
+    a1 = ((input[0] + 3) >> 3);
+
+    for (i = 0; i < 4; i++)
+    {
+        op[0] = a1;
+        op[1] = a1;
+        op[2] = a1;
+        op[3] = a1;
+        op += 4;
+    }
+}
diff --git a/vp8/common/invtrans.c b/vp8/common/invtrans.c
new file mode 100644
index 0000000..1ff596e
--- /dev/null
+++ b/vp8/common/invtrans.c
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "invtrans.h"
+
+
+
+static void recon_dcblock(MACROBLOCKD *x)
+{
+    BLOCKD *b = &x->block[24];
+    int i;
+
+    for (i = 0; i < 16; i++)
+    {
+        x->block[i].dqcoeff[0] = b->diff[i];
+    }
+
+}
+
+void vp8_inverse_transform_b(const vp8_idct_rtcd_vtable_t *rtcd, BLOCKD *b, int pitch)
+{
+    if (b->eob > 1)
+        IDCT_INVOKE(rtcd, idct16)(b->dqcoeff, b->diff, pitch);
+    else
+        IDCT_INVOKE(rtcd, idct1)(b->dqcoeff, b->diff, pitch);
+}
+
+
+void vp8_inverse_transform_mby(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+    int i;
+
+    // do 2nd order transform on the dc block
+    IDCT_INVOKE(rtcd, iwalsh16)(x->block[24].dqcoeff, x->block[24].diff);
+
+    recon_dcblock(x);
+
+    for (i = 0; i < 16; i++)
+    {
+        vp8_inverse_transform_b(rtcd, &x->block[i], 32);
+    }
+
+}
+void vp8_inverse_transform_mbuv(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+    int i;
+
+    for (i = 16; i < 24; i++)
+    {
+        vp8_inverse_transform_b(rtcd, &x->block[i], 16);
+    }
+
+}
+
+
+void vp8_inverse_transform_mb(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+    int i;
+
+    if (x->mbmi.mode != B_PRED && x->mbmi.mode != SPLITMV)
+    {
+        // do 2nd order transform on the dc block
+
+        IDCT_INVOKE(rtcd, iwalsh16)(&x->block[24].dqcoeff[0], x->block[24].diff);
+        recon_dcblock(x);
+    }
+
+    for (i = 0; i < 16; i++)
+    {
+        vp8_inverse_transform_b(rtcd, &x->block[i], 32);
+    }
+
+
+    for (i = 16; i < 24; i++)
+    {
+        vp8_inverse_transform_b(rtcd, &x->block[i], 16);
+    }
+
+}
diff --git a/vp8/common/invtrans.h b/vp8/common/invtrans.h
new file mode 100644
index 0000000..93a40f9
--- /dev/null
+++ b/vp8/common/invtrans.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_INVTRANS_H
+#define __INC_INVTRANS_H
+
+#include "vpx_ports/config.h"
+#include "idct.h"
+#include "blockd.h"
+extern void vp8_inverse_transform_b(const vp8_idct_rtcd_vtable_t *rtcd, BLOCKD *b, int pitch);
+extern void vp8_inverse_transform_mb(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x);
+extern void vp8_inverse_transform_mby(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x);
+extern void vp8_inverse_transform_mbuv(const vp8_idct_rtcd_vtable_t *rtcd, MACROBLOCKD *x);
+
+#endif
diff --git a/vp8/common/littlend.h b/vp8/common/littlend.h
new file mode 100644
index 0000000..08c525c
--- /dev/null
+++ b/vp8/common/littlend.h
@@ -0,0 +1,32 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef _littlend_h
+#define _littlend_h
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define invert2(x) (x)
+#define invert4(x) (x)
+
+#define low_byte(x) (unsigned char)x
+#define mid1Byte(x) (unsigned char)(x >> 8)
+#define mid2Byte(x) (unsigned char)(x >> 16)
+#define high_byte(x) (unsigned char)(x >> 24)
+
+#define SWAPENDS 0
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/vp8/common/loopfilter.c b/vp8/common/loopfilter.c
new file mode 100644
index 0000000..79e6177
--- /dev/null
+++ b/vp8/common/loopfilter.c
@@ -0,0 +1,601 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "loopfilter.h"
+#include "onyxc_int.h"
+
+typedef unsigned char uc;
+
+
+prototype_loopfilter(vp8_loop_filter_horizontal_edge_c);
+prototype_loopfilter(vp8_loop_filter_vertical_edge_c);
+prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_c);
+prototype_loopfilter(vp8_mbloop_filter_vertical_edge_c);
+prototype_loopfilter(vp8_loop_filter_simple_horizontal_edge_c);
+prototype_loopfilter(vp8_loop_filter_simple_vertical_edge_c);
+
+// Horizontal MB filtering
+void vp8_loop_filter_mbh_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                           int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_mbloop_filter_horizontal_edge_c(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_horizontal_edge_c(u_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_horizontal_edge_c(v_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+}
+
+void vp8_loop_filter_mbhs_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                            int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_horizontal_edge_c(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+}
+
+// Vertical MB Filtering
+void vp8_loop_filter_mbv_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                           int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_mbloop_filter_vertical_edge_c(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_vertical_edge_c(u_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_vertical_edge_c(v_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+}
+
+void vp8_loop_filter_mbvs_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                            int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_vertical_edge_c(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+}
+
+// Horizontal B Filtering
+void vp8_loop_filter_bh_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                          int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_loop_filter_horizontal_edge_c(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_horizontal_edge_c(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_horizontal_edge_c(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_horizontal_edge_c(u_ptr + 4 * uv_stride, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_horizontal_edge_c(v_ptr + 4 * uv_stride, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+}
+
+void vp8_loop_filter_bhs_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                           int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+}
+
+// Vertical B Filtering
+void vp8_loop_filter_bv_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                          int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_loop_filter_vertical_edge_c(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_vertical_edge_c(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_vertical_edge_c(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_vertical_edge_c(u_ptr + 4, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_vertical_edge_c(v_ptr + 4, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+}
+
+void vp8_loop_filter_bvs_c(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                           int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_vertical_edge_c(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_vertical_edge_c(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_vertical_edge_c(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+}
+
+void vp8_init_loop_filter(VP8_COMMON *cm)
+{
+    loop_filter_info *lfi = cm->lf_info;
+    LOOPFILTERTYPE lft = cm->filter_type;
+    int sharpness_lvl = cm->sharpness_level;
+    int frame_type = cm->frame_type;
+    int i, j;
+
+    int block_inside_limit = 0;
+    int HEVThresh;
+    const int yhedge_boost  = 2;
+    const int uvhedge_boost = 2;
+
+    // For each possible value for the loop filter fill out a "loop_filter_info" entry.
+    for (i = 0; i <= MAX_LOOP_FILTER; i++)
+    {
+        int filt_lvl = i;
+
+        if (frame_type == KEY_FRAME)
+        {
+            if (filt_lvl >= 40)
+                HEVThresh = 2;
+            else if (filt_lvl >= 15)
+                HEVThresh = 1;
+            else
+                HEVThresh = 0;
+        }
+        else
+        {
+            if (filt_lvl >= 40)
+                HEVThresh = 3;
+            else if (filt_lvl >= 20)
+                HEVThresh = 2;
+            else if (filt_lvl >= 15)
+                HEVThresh = 1;
+            else
+                HEVThresh = 0;
+        }
+
+        // Set loop filter paramaeters that control sharpness.
+        block_inside_limit = filt_lvl >> (sharpness_lvl > 0);
+        block_inside_limit = block_inside_limit >> (sharpness_lvl > 4);
+
+        if (sharpness_lvl > 0)
+        {
+            if (block_inside_limit > (9 - sharpness_lvl))
+                block_inside_limit = (9 - sharpness_lvl);
+        }
+
+        if (block_inside_limit < 1)
+            block_inside_limit = 1;
+
+        for (j = 0; j < 16; j++)
+        {
+            lfi[i].lim[j] = block_inside_limit;
+            lfi[i].mbflim[j] = filt_lvl + yhedge_boost;
+            lfi[i].mbthr[j] = HEVThresh;
+            lfi[i].flim[j] = filt_lvl;
+            lfi[i].thr[j] = HEVThresh;
+            lfi[i].uvlim[j] = block_inside_limit;
+            lfi[i].uvmbflim[j] = filt_lvl + uvhedge_boost;
+            lfi[i].uvmbthr[j] = HEVThresh;
+            lfi[i].uvflim[j] = filt_lvl;
+            lfi[i].uvthr[j] = HEVThresh;
+        }
+
+    }
+
+    // Set up the function pointers depending on the type of loop filtering selected
+    if (lft == NORMAL_LOOPFILTER)
+    {
+        cm->lf_mbv = LF_INVOKE(&cm->rtcd.loopfilter, normal_mb_v);
+        cm->lf_bv  = LF_INVOKE(&cm->rtcd.loopfilter, normal_b_v);
+        cm->lf_mbh = LF_INVOKE(&cm->rtcd.loopfilter, normal_mb_h);
+        cm->lf_bh  = LF_INVOKE(&cm->rtcd.loopfilter, normal_b_h);
+    }
+    else
+    {
+        cm->lf_mbv = LF_INVOKE(&cm->rtcd.loopfilter, simple_mb_v);
+        cm->lf_bv  = LF_INVOKE(&cm->rtcd.loopfilter, simple_b_v);
+        cm->lf_mbh = LF_INVOKE(&cm->rtcd.loopfilter, simple_mb_h);
+        cm->lf_bh  = LF_INVOKE(&cm->rtcd.loopfilter, simple_b_h);
+    }
+}
+
+// Put vp8_init_loop_filter() in vp8dx_create_decompressor(). Only call vp8_frame_init_loop_filter() while decoding
+// each frame. Check last_frame_type to skip the function most of times.
+void vp8_frame_init_loop_filter(loop_filter_info *lfi, int frame_type)
+{
+    int HEVThresh;
+    int i, j;
+
+    // For each possible value for the loop filter fill out a "loop_filter_info" entry.
+    for (i = 0; i <= MAX_LOOP_FILTER; i++)
+    {
+        int filt_lvl = i;
+
+        if (frame_type == KEY_FRAME)
+        {
+            if (filt_lvl >= 40)
+                HEVThresh = 2;
+            else if (filt_lvl >= 15)
+                HEVThresh = 1;
+            else
+                HEVThresh = 0;
+        }
+        else
+        {
+            if (filt_lvl >= 40)
+                HEVThresh = 3;
+            else if (filt_lvl >= 20)
+                HEVThresh = 2;
+            else if (filt_lvl >= 15)
+                HEVThresh = 1;
+            else
+                HEVThresh = 0;
+        }
+
+        for (j = 0; j < 16; j++)
+        {
+            //lfi[i].lim[j] = block_inside_limit;
+            //lfi[i].mbflim[j] = filt_lvl+yhedge_boost;
+            lfi[i].mbthr[j] = HEVThresh;
+            //lfi[i].flim[j] = filt_lvl;
+            lfi[i].thr[j] = HEVThresh;
+            //lfi[i].uvlim[j] = block_inside_limit;
+            //lfi[i].uvmbflim[j] = filt_lvl+uvhedge_boost;
+            lfi[i].uvmbthr[j] = HEVThresh;
+            //lfi[i].uvflim[j] = filt_lvl;
+            lfi[i].uvthr[j] = HEVThresh;
+        }
+    }
+}
+
+
+void vp8_adjust_mb_lf_value(MACROBLOCKD *mbd, int *filter_level)
+{
+    MB_MODE_INFO *mbmi = &mbd->mode_info_context->mbmi;
+
+    if (mbd->mode_ref_lf_delta_enabled)
+    {
+        // Aplly delta for reference frame
+        *filter_level += mbd->ref_lf_deltas[mbmi->ref_frame];
+
+        // Apply delta for mode
+        if (mbmi->ref_frame == INTRA_FRAME)
+        {
+            // Only the split mode BPRED has a further special case
+            if (mbmi->mode == B_PRED)
+                *filter_level +=  mbd->mode_lf_deltas[0];
+        }
+        else
+        {
+            // Zero motion mode
+            if (mbmi->mode == ZEROMV)
+                *filter_level +=  mbd->mode_lf_deltas[1];
+
+            // Split MB motion mode
+            else if (mbmi->mode == SPLITMV)
+                *filter_level +=  mbd->mode_lf_deltas[3];
+
+            // All other inter motion modes (Nearest, Near, New)
+            else
+                *filter_level +=  mbd->mode_lf_deltas[2];
+        }
+
+        // Range check
+        if (*filter_level > MAX_LOOP_FILTER)
+            *filter_level = MAX_LOOP_FILTER;
+        else if (*filter_level < 0)
+            *filter_level = 0;
+    }
+}
+
+
+void vp8_loop_filter_frame
+(
+    VP8_COMMON *cm,
+    MACROBLOCKD *mbd,
+    int default_filt_lvl
+)
+{
+    YV12_BUFFER_CONFIG *post = cm->frame_to_show;
+    loop_filter_info *lfi = cm->lf_info;
+    int frame_type = cm->frame_type;
+
+    int mb_row;
+    int mb_col;
+
+
+    int baseline_filter_level[MAX_MB_SEGMENTS];
+    int filter_level;
+    int alt_flt_enabled = mbd->segmentation_enabled;
+
+    int i;
+    unsigned char *y_ptr, *u_ptr, *v_ptr;
+
+    mbd->mode_info_context = cm->mi;          // Point at base of Mb MODE_INFO list
+
+    // Note the baseline filter values for each segment
+    if (alt_flt_enabled)
+    {
+        for (i = 0; i < MAX_MB_SEGMENTS; i++)
+        {
+            // Abs value
+            if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+                baseline_filter_level[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
+            // Delta Value
+            else
+            {
+                baseline_filter_level[i] = default_filt_lvl + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
+                baseline_filter_level[i] = (baseline_filter_level[i] >= 0) ? ((baseline_filter_level[i] <= MAX_LOOP_FILTER) ? baseline_filter_level[i] : MAX_LOOP_FILTER) : 0;  // Clamp to valid range
+            }
+        }
+    }
+    else
+    {
+        for (i = 0; i < MAX_MB_SEGMENTS; i++)
+            baseline_filter_level[i] = default_filt_lvl;
+    }
+
+    // Initialize the loop filter for this frame.
+    if ((cm->last_filter_type != cm->filter_type) || (cm->last_sharpness_level != cm->sharpness_level))
+        vp8_init_loop_filter(cm);
+    else if (frame_type != cm->last_frame_type)
+        vp8_frame_init_loop_filter(lfi, frame_type);
+
+    // Set up the buffer pointers
+    y_ptr = post->y_buffer;
+    u_ptr = post->u_buffer;
+    v_ptr = post->v_buffer;
+
+    // vp8_filter each macro block
+    for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+        {
+            int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;
+
+            filter_level = baseline_filter_level[Segment];
+
+            // Distance of Mb to the various image edges.
+            // These specified to 8th pel as they are always compared to values that are in 1/8th pel units
+            // Apply any context driven MB level adjustment
+            vp8_adjust_mb_lf_value(mbd, &filter_level);
+
+            if (filter_level)
+            {
+                if (mb_col > 0)
+                    cm->lf_mbv(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
+
+                if (mbd->mode_info_context->mbmi.dc_diff > 0)
+                    cm->lf_bv(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
+
+                // don't apply across umv border
+                if (mb_row > 0)
+                    cm->lf_mbh(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
+
+                if (mbd->mode_info_context->mbmi.dc_diff > 0)
+                    cm->lf_bh(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
+            }
+
+            y_ptr += 16;
+            u_ptr += 8;
+            v_ptr += 8;
+
+            mbd->mode_info_context++;     // step to next MB
+        }
+
+        y_ptr += post->y_stride  * 16 - post->y_width;
+        u_ptr += post->uv_stride *  8 - post->uv_width;
+        v_ptr += post->uv_stride *  8 - post->uv_width;
+
+        mbd->mode_info_context++;         // Skip border mb
+    }
+}
+
+
+void vp8_loop_filter_frame_yonly
+(
+    VP8_COMMON *cm,
+    MACROBLOCKD *mbd,
+    int default_filt_lvl,
+    int sharpness_lvl
+)
+{
+    YV12_BUFFER_CONFIG *post = cm->frame_to_show;
+
+    int i;
+    unsigned char *y_ptr;
+    int mb_row;
+    int mb_col;
+
+    loop_filter_info *lfi = cm->lf_info;
+    int baseline_filter_level[MAX_MB_SEGMENTS];
+    int filter_level;
+    int alt_flt_enabled = mbd->segmentation_enabled;
+    int frame_type = cm->frame_type;
+
+    (void) sharpness_lvl;
+
+    //MODE_INFO * this_mb_mode_info = cm->mi;  // Point at base of Mb MODE_INFO list
+    mbd->mode_info_context = cm->mi;          // Point at base of Mb MODE_INFO list
+
+    // Note the baseline filter values for each segment
+    if (alt_flt_enabled)
+    {
+        for (i = 0; i < MAX_MB_SEGMENTS; i++)
+        {
+            // Abs value
+            if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+                baseline_filter_level[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
+            // Delta Value
+            else
+            {
+                baseline_filter_level[i] = default_filt_lvl + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
+                baseline_filter_level[i] = (baseline_filter_level[i] >= 0) ? ((baseline_filter_level[i] <= MAX_LOOP_FILTER) ? baseline_filter_level[i] : MAX_LOOP_FILTER) : 0;  // Clamp to valid range
+            }
+        }
+    }
+    else
+    {
+        for (i = 0; i < MAX_MB_SEGMENTS; i++)
+            baseline_filter_level[i] = default_filt_lvl;
+    }
+
+    // Initialize the loop filter for this frame.
+    if ((cm->last_filter_type != cm->filter_type) || (cm->last_sharpness_level != cm->sharpness_level))
+        vp8_init_loop_filter(cm);
+    else if (frame_type != cm->last_frame_type)
+        vp8_frame_init_loop_filter(lfi, frame_type);
+
+    // Set up the buffer pointers
+    y_ptr = post->y_buffer;
+
+    // vp8_filter each macro block
+    for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+    {
+        for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+        {
+            int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;
+            filter_level = baseline_filter_level[Segment];
+
+            // Apply any context driven MB level adjustment
+            vp8_adjust_mb_lf_value(mbd, &filter_level);
+
+            if (filter_level)
+            {
+                if (mb_col > 0)
+                    cm->lf_mbv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
+
+                if (mbd->mode_info_context->mbmi.dc_diff > 0)
+                    cm->lf_bv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
+
+                // don't apply across umv border
+                if (mb_row > 0)
+                    cm->lf_mbh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
+
+                if (mbd->mode_info_context->mbmi.dc_diff > 0)
+                    cm->lf_bh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
+            }
+
+            y_ptr += 16;
+            mbd->mode_info_context ++;        // step to next MB
+
+        }
+
+        y_ptr += post->y_stride  * 16 - post->y_width;
+        mbd->mode_info_context ++;            // Skip border mb
+    }
+
+}
+
+
+void vp8_loop_filter_partial_frame
+(
+    VP8_COMMON *cm,
+    MACROBLOCKD *mbd,
+    int default_filt_lvl,
+    int sharpness_lvl,
+    int Fraction
+)
+{
+    YV12_BUFFER_CONFIG *post = cm->frame_to_show;
+
+    int i;
+    unsigned char *y_ptr;
+    int mb_row;
+    int mb_col;
+    //int mb_rows = post->y_height >> 4;
+    int mb_cols = post->y_width  >> 4;
+
+    int linestocopy;
+
+    loop_filter_info *lfi = cm->lf_info;
+    int baseline_filter_level[MAX_MB_SEGMENTS];
+    int filter_level;
+    int alt_flt_enabled = mbd->segmentation_enabled;
+    int frame_type = cm->frame_type;
+
+    (void) sharpness_lvl;
+
+    //MODE_INFO * this_mb_mode_info = cm->mi + (post->y_height>>5) * (mb_cols + 1);  // Point at base of Mb MODE_INFO list
+    mbd->mode_info_context = cm->mi + (post->y_height >> 5) * (mb_cols + 1);        // Point at base of Mb MODE_INFO list
+
+    linestocopy = (post->y_height >> (4 + Fraction));
+
+    if (linestocopy < 1)
+        linestocopy = 1;
+
+    linestocopy <<= 4;
+
+    // Note the baseline filter values for each segment
+    if (alt_flt_enabled)
+    {
+        for (i = 0; i < MAX_MB_SEGMENTS; i++)
+        {
+            // Abs value
+            if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+                baseline_filter_level[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
+            // Delta Value
+            else
+            {
+                baseline_filter_level[i] = default_filt_lvl + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
+                baseline_filter_level[i] = (baseline_filter_level[i] >= 0) ? ((baseline_filter_level[i] <= MAX_LOOP_FILTER) ? baseline_filter_level[i] : MAX_LOOP_FILTER) : 0;  // Clamp to valid range
+            }
+        }
+    }
+    else
+    {
+        for (i = 0; i < MAX_MB_SEGMENTS; i++)
+            baseline_filter_level[i] = default_filt_lvl;
+    }
+
+    // Initialize the loop filter for this frame.
+    if ((cm->last_filter_type != cm->filter_type) || (cm->last_sharpness_level != cm->sharpness_level))
+        vp8_init_loop_filter(cm);
+    else if (frame_type != cm->last_frame_type)
+        vp8_frame_init_loop_filter(lfi, frame_type);
+
+    // Set up the buffer pointers
+    y_ptr = post->y_buffer + (post->y_height >> 5) * 16 * post->y_stride;
+
+    // vp8_filter each macro block
+    for (mb_row = 0; mb_row<(linestocopy >> 4); mb_row++)
+    {
+        for (mb_col = 0; mb_col < mb_cols; mb_col++)
+        {
+            int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;
+            filter_level = baseline_filter_level[Segment];
+
+            if (filter_level)
+            {
+                if (mb_col > 0)
+                    cm->lf_mbv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
+
+                if (mbd->mode_info_context->mbmi.dc_diff > 0)
+                    cm->lf_bv(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
+
+                cm->lf_mbh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
+
+                if (mbd->mode_info_context->mbmi.dc_diff > 0)
+                    cm->lf_bh(y_ptr, 0, 0, post->y_stride, 0, &lfi[filter_level], 0);
+            }
+
+            y_ptr += 16;
+            mbd->mode_info_context += 1;      // step to next MB
+        }
+
+        y_ptr += post->y_stride  * 16 - post->y_width;
+        mbd->mode_info_context += 1;          // Skip border mb
+    }
+}
diff --git a/vp8/common/loopfilter.h b/vp8/common/loopfilter.h
new file mode 100644
index 0000000..c6ce508
--- /dev/null
+++ b/vp8/common/loopfilter.h
@@ -0,0 +1,120 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef loopfilter_h
+#define loopfilter_h
+
+#include "vpx_ports/mem.h"
+
+#define MAX_LOOP_FILTER 63
+
+typedef enum
+{
+    NORMAL_LOOPFILTER = 0,
+    SIMPLE_LOOPFILTER = 1
+} LOOPFILTERTYPE;
+
+// FRK
+// Need to align this structure so when it is declared and
+// passed it can be loaded into vector registers.
+// FRK
+typedef struct
+{
+    DECLARE_ALIGNED(16, signed char, lim[16]);
+    DECLARE_ALIGNED(16, signed char, flim[16]);
+    DECLARE_ALIGNED(16, signed char, thr[16]);
+    DECLARE_ALIGNED(16, signed char, mbflim[16]);
+    DECLARE_ALIGNED(16, signed char, mbthr[16]);
+    DECLARE_ALIGNED(16, signed char, uvlim[16]);
+    DECLARE_ALIGNED(16, signed char, uvflim[16]);
+    DECLARE_ALIGNED(16, signed char, uvthr[16]);
+    DECLARE_ALIGNED(16, signed char, uvmbflim[16]);
+    DECLARE_ALIGNED(16, signed char, uvmbthr[16]);
+} loop_filter_info;
+
+
+#define prototype_loopfilter(sym) \
+    void sym(unsigned char *src, int pitch, const signed char *flimit,\
+             const signed char *limit, const signed char *thresh, int count)
+
+#define prototype_loopfilter_block(sym) \
+    void sym(unsigned char *y, unsigned char *u, unsigned char *v,\
+             int ystride, int uv_stride, loop_filter_info *lfi, int simpler)
+
+#if ARCH_X86 || ARCH_X86_64
+#include "x86/loopfilter_x86.h"
+#endif
+
+#if ARCH_ARM
+#include "arm/loopfilter_arm.h"
+#endif
+
+#ifndef vp8_lf_normal_mb_v
+#define vp8_lf_normal_mb_v vp8_loop_filter_mbv_c
+#endif
+extern prototype_loopfilter_block(vp8_lf_normal_mb_v);
+
+#ifndef vp8_lf_normal_b_v
+#define vp8_lf_normal_b_v vp8_loop_filter_bv_c
+#endif
+extern prototype_loopfilter_block(vp8_lf_normal_b_v);
+
+#ifndef vp8_lf_normal_mb_h
+#define vp8_lf_normal_mb_h vp8_loop_filter_mbh_c
+#endif
+extern prototype_loopfilter_block(vp8_lf_normal_mb_h);
+
+#ifndef vp8_lf_normal_b_h
+#define vp8_lf_normal_b_h vp8_loop_filter_bh_c
+#endif
+extern prototype_loopfilter_block(vp8_lf_normal_b_h);
+
+
+#ifndef vp8_lf_simple_mb_v
+#define vp8_lf_simple_mb_v vp8_loop_filter_mbvs_c
+#endif
+extern prototype_loopfilter_block(vp8_lf_simple_mb_v);
+
+#ifndef vp8_lf_simple_b_v
+#define vp8_lf_simple_b_v vp8_loop_filter_bvs_c
+#endif
+extern prototype_loopfilter_block(vp8_lf_simple_b_v);
+
+#ifndef vp8_lf_simple_mb_h
+#define vp8_lf_simple_mb_h vp8_loop_filter_mbhs_c
+#endif
+extern prototype_loopfilter_block(vp8_lf_simple_mb_h);
+
+#ifndef vp8_lf_simple_b_h
+#define vp8_lf_simple_b_h vp8_loop_filter_bhs_c
+#endif
+extern prototype_loopfilter_block(vp8_lf_simple_b_h);
+
+typedef prototype_loopfilter_block((*vp8_lf_block_fn_t));
+typedef struct
+{
+    vp8_lf_block_fn_t  normal_mb_v;
+    vp8_lf_block_fn_t  normal_b_v;
+    vp8_lf_block_fn_t  normal_mb_h;
+    vp8_lf_block_fn_t  normal_b_h;
+    vp8_lf_block_fn_t  simple_mb_v;
+    vp8_lf_block_fn_t  simple_b_v;
+    vp8_lf_block_fn_t  simple_mb_h;
+    vp8_lf_block_fn_t  simple_b_h;
+} vp8_loopfilter_rtcd_vtable_t;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define LF_INVOKE(ctx,fn) (ctx)->fn
+#else
+#define LF_INVOKE(ctx,fn) vp8_lf_##fn
+#endif
+
+
+#endif
diff --git a/vp8/common/loopfilter_filters.c b/vp8/common/loopfilter_filters.c
new file mode 100644
index 0000000..7d16e48
--- /dev/null
+++ b/vp8/common/loopfilter_filters.c
@@ -0,0 +1,368 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <stdlib.h>
+#include "loopfilter.h"
+#include "onyxc_int.h"
+
+
+#define NEW_LOOPFILTER_MASK
+
+typedef unsigned char uc;
+
+__inline signed char vp8_signed_char_clamp(int t)
+{
+    t = (t < -128 ? -128 : t);
+    t = (t > 127 ? 127 : t);
+    return (signed char) t;
+}
+
+
+// should we apply any filter at all ( 11111111 yes, 00000000 no)
+__inline signed char vp8_filter_mask(signed char limit, signed char flimit,
+                                     uc p3, uc p2, uc p1, uc p0, uc q0, uc q1, uc q2, uc q3)
+{
+    signed char mask = 0;
+    mask |= (abs(p3 - p2) > limit) * -1;
+    mask |= (abs(p2 - p1) > limit) * -1;
+    mask |= (abs(p1 - p0) > limit) * -1;
+    mask |= (abs(q1 - q0) > limit) * -1;
+    mask |= (abs(q2 - q1) > limit) * -1;
+    mask |= (abs(q3 - q2) > limit) * -1;
+#ifndef NEW_LOOPFILTER_MASK
+    mask |= (abs(p0 - q0) > flimit) * -1;
+#else
+    mask |= (abs(p0 - q0) * 2 + abs(p1 - q1) / 2  > flimit * 2 + limit) * -1;
+#endif
+    mask = ~mask;
+    return mask;
+}
+
+// is there high variance internal edge ( 11111111 yes, 00000000 no)
+__inline signed char vp8_hevmask(signed char thresh, uc p1, uc p0, uc q0, uc q1)
+{
+    signed char hev = 0;
+    hev  |= (abs(p1 - p0) > thresh) * -1;
+    hev  |= (abs(q1 - q0) > thresh) * -1;
+    return hev;
+}
+
+__inline void vp8_filter(signed char mask, signed char hev, uc *op1, uc *op0, uc *oq0, uc *oq1)
+
+{
+    signed char ps0, qs0;
+    signed char ps1, qs1;
+    signed char vp8_filter, Filter1, Filter2;
+    signed char u;
+
+    ps1 = (signed char) * op1 ^ 0x80;
+    ps0 = (signed char) * op0 ^ 0x80;
+    qs0 = (signed char) * oq0 ^ 0x80;
+    qs1 = (signed char) * oq1 ^ 0x80;
+
+    // add outer taps if we have high edge variance
+    vp8_filter = vp8_signed_char_clamp(ps1 - qs1);
+    vp8_filter &= hev;
+
+    // inner taps
+    vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (qs0 - ps0));
+    vp8_filter &= mask;
+
+    // save bottom 3 bits so that we round one side +4 and the other +3
+    // if it equals 4 we'll set to adjust by -1 to account for the fact
+    // we'd round 3 the other way
+    Filter1 = vp8_signed_char_clamp(vp8_filter + 4);
+    Filter2 = vp8_signed_char_clamp(vp8_filter + 3);
+    Filter1 >>= 3;
+    Filter2 >>= 3;
+    u = vp8_signed_char_clamp(qs0 - Filter1);
+    *oq0 = u ^ 0x80;
+    u = vp8_signed_char_clamp(ps0 + Filter2);
+    *op0 = u ^ 0x80;
+    vp8_filter = Filter1;
+
+    // outer tap adjustments
+    vp8_filter += 1;
+    vp8_filter >>= 1;
+    vp8_filter &= ~hev;
+
+    u = vp8_signed_char_clamp(qs1 - vp8_filter);
+    *oq1 = u ^ 0x80;
+    u = vp8_signed_char_clamp(ps1 + vp8_filter);
+    *op1 = u ^ 0x80;
+
+}
+void vp8_loop_filter_horizontal_edge_c
+(
+    unsigned char *s,
+    int p, //pitch
+    const signed char *flimit,
+    const signed char *limit,
+    const signed char *thresh,
+    int count
+)
+{
+    int  hev = 0; // high edge variance
+    signed char mask = 0;
+    int i = 0;
+
+    // loop filter designed to work using chars so that we can make maximum use
+    // of 8 bit simd instructions.
+    do
+    {
+        mask = vp8_filter_mask(limit[i], flimit[i],
+                               s[-4*p], s[-3*p], s[-2*p], s[-1*p],
+                               s[0*p], s[1*p], s[2*p], s[3*p]);
+
+        hev = vp8_hevmask(thresh[i], s[-2*p], s[-1*p], s[0*p], s[1*p]);
+
+        vp8_filter(mask, hev, s - 2 * p, s - 1 * p, s, s + 1 * p);
+
+        ++s;
+    }
+    while (++i < count * 8);
+}
+
+void vp8_loop_filter_vertical_edge_c
+(
+    unsigned char *s,
+    int p,
+    const signed char *flimit,
+    const signed char *limit,
+    const signed char *thresh,
+    int count
+)
+{
+    int  hev = 0; // high edge variance
+    signed char mask = 0;
+    int i = 0;
+
+    // loop filter designed to work using chars so that we can make maximum use
+    // of 8 bit simd instructions.
+    do
+    {
+        mask = vp8_filter_mask(limit[i], flimit[i],
+                               s[-4], s[-3], s[-2], s[-1], s[0], s[1], s[2], s[3]);
+
+        hev = vp8_hevmask(thresh[i], s[-2], s[-1], s[0], s[1]);
+
+        vp8_filter(mask, hev, s - 2, s - 1, s, s + 1);
+
+        s += p;
+    }
+    while (++i < count * 8);
+}
+
+__inline void vp8_mbfilter(signed char mask, signed char hev,
+                           uc *op2, uc *op1, uc *op0, uc *oq0, uc *oq1, uc *oq2)
+{
+    signed char s, u;
+    signed char vp8_filter, Filter1, Filter2;
+    signed char ps2 = (signed char) * op2 ^ 0x80;
+    signed char ps1 = (signed char) * op1 ^ 0x80;
+    signed char ps0 = (signed char) * op0 ^ 0x80;
+    signed char qs0 = (signed char) * oq0 ^ 0x80;
+    signed char qs1 = (signed char) * oq1 ^ 0x80;
+    signed char qs2 = (signed char) * oq2 ^ 0x80;
+
+    // add outer taps if we have high edge variance
+    vp8_filter = vp8_signed_char_clamp(ps1 - qs1);
+    vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (qs0 - ps0));
+    vp8_filter &= mask;
+
+    Filter2 = vp8_filter;
+    Filter2 &= hev;
+
+    // save bottom 3 bits so that we round one side +4 and the other +3
+    Filter1 = vp8_signed_char_clamp(Filter2 + 4);
+    Filter2 = vp8_signed_char_clamp(Filter2 + 3);
+    Filter1 >>= 3;
+    Filter2 >>= 3;
+    qs0 = vp8_signed_char_clamp(qs0 - Filter1);
+    ps0 = vp8_signed_char_clamp(ps0 + Filter2);
+
+
+    // only apply wider filter if not high edge variance
+    vp8_filter &= ~hev;
+    Filter2 = vp8_filter;
+
+    // roughly 3/7th difference across boundary
+    u = vp8_signed_char_clamp((63 + Filter2 * 27) >> 7);
+    s = vp8_signed_char_clamp(qs0 - u);
+    *oq0 = s ^ 0x80;
+    s = vp8_signed_char_clamp(ps0 + u);
+    *op0 = s ^ 0x80;
+
+    // roughly 2/7th difference across boundary
+    u = vp8_signed_char_clamp((63 + Filter2 * 18) >> 7);
+    s = vp8_signed_char_clamp(qs1 - u);
+    *oq1 = s ^ 0x80;
+    s = vp8_signed_char_clamp(ps1 + u);
+    *op1 = s ^ 0x80;
+
+    // roughly 1/7th difference across boundary
+    u = vp8_signed_char_clamp((63 + Filter2 * 9) >> 7);
+    s = vp8_signed_char_clamp(qs2 - u);
+    *oq2 = s ^ 0x80;
+    s = vp8_signed_char_clamp(ps2 + u);
+    *op2 = s ^ 0x80;
+}
+
+void vp8_mbloop_filter_horizontal_edge_c
+(
+    unsigned char *s,
+    int p,
+    const signed char *flimit,
+    const signed char *limit,
+    const signed char *thresh,
+    int count
+)
+{
+    signed char hev = 0; // high edge variance
+    signed char mask = 0;
+    int i = 0;
+
+    // loop filter designed to work using chars so that we can make maximum use
+    // of 8 bit simd instructions.
+    do
+    {
+
+        mask = vp8_filter_mask(limit[i], flimit[i],
+                               s[-4*p], s[-3*p], s[-2*p], s[-1*p],
+                               s[0*p], s[1*p], s[2*p], s[3*p]);
+
+        hev = vp8_hevmask(thresh[i], s[-2*p], s[-1*p], s[0*p], s[1*p]);
+
+        vp8_mbfilter(mask, hev, s - 3 * p, s - 2 * p, s - 1 * p, s, s + 1 * p, s + 2 * p);
+
+        ++s;
+    }
+    while (++i < count * 8);
+
+}
+
+
+void vp8_mbloop_filter_vertical_edge_c
+(
+    unsigned char *s,
+    int p,
+    const signed char *flimit,
+    const signed char *limit,
+    const signed char *thresh,
+    int count
+)
+{
+    signed char hev = 0; // high edge variance
+    signed char mask = 0;
+    int i = 0;
+
+    do
+    {
+
+        mask = vp8_filter_mask(limit[i], flimit[i],
+                               s[-4], s[-3], s[-2], s[-1], s[0], s[1], s[2], s[3]);
+
+        hev = vp8_hevmask(thresh[i], s[-2], s[-1], s[0], s[1]);
+
+        vp8_mbfilter(mask, hev, s - 3, s - 2, s - 1, s, s + 1, s + 2);
+
+        s += p;
+    }
+    while (++i < count * 8);
+
+}
+
+// should we apply any filter at all ( 11111111 yes, 00000000 no)
+__inline signed char vp8_simple_filter_mask(signed char limit, signed char flimit, uc p1, uc p0, uc q0, uc q1)
+{
+// Why does this cause problems for win32?
+// error C2143: syntax error : missing ';' before 'type'
+//  (void) limit;
+#ifndef NEW_LOOPFILTER_MASK
+    signed char mask = (abs(p0 - q0) <= flimit) * -1;
+#else
+    signed char mask = (abs(p0 - q0) * 2 + abs(p1 - q1) / 2  <= flimit * 2 + limit) * -1;
+#endif
+    return mask;
+}
+
+__inline void vp8_simple_filter(signed char mask, uc *op1, uc *op0, uc *oq0, uc *oq1)
+{
+    signed char vp8_filter, Filter1, Filter2;
+    signed char p1 = (signed char) * op1 ^ 0x80;
+    signed char p0 = (signed char) * op0 ^ 0x80;
+    signed char q0 = (signed char) * oq0 ^ 0x80;
+    signed char q1 = (signed char) * oq1 ^ 0x80;
+    signed char u;
+
+    vp8_filter = vp8_signed_char_clamp(p1 - q1);
+    vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (q0 - p0));
+    vp8_filter &= mask;
+
+    // save bottom 3 bits so that we round one side +4 and the other +3
+    Filter1 = vp8_signed_char_clamp(vp8_filter + 4);
+    Filter1 >>= 3;
+    u = vp8_signed_char_clamp(q0 - Filter1);
+    *oq0  = u ^ 0x80;
+
+    Filter2 = vp8_signed_char_clamp(vp8_filter + 3);
+    Filter2 >>= 3;
+    u = vp8_signed_char_clamp(p0 + Filter2);
+    *op0 = u ^ 0x80;
+}
+
+void vp8_loop_filter_simple_horizontal_edge_c
+(
+    unsigned char *s,
+    int p,
+    const signed char *flimit,
+    const signed char *limit,
+    const signed char *thresh,
+    int count
+)
+{
+    signed char mask = 0;
+    int i = 0;
+    (void) thresh;
+
+    do
+    {
+        //mask = vp8_simple_filter_mask( limit[i], flimit[i],s[-1*p],s[0*p]);
+        mask = vp8_simple_filter_mask(limit[i], flimit[i], s[-2*p], s[-1*p], s[0*p], s[1*p]);
+        vp8_simple_filter(mask, s - 2 * p, s - 1 * p, s, s + 1 * p);
+        ++s;
+    }
+    while (++i < count * 8);
+}
+
+void vp8_loop_filter_simple_vertical_edge_c
+(
+    unsigned char *s,
+    int p,
+    const signed char *flimit,
+    const signed char *limit,
+    const signed char *thresh,
+    int count
+)
+{
+    signed char mask = 0;
+    int i = 0;
+    (void) thresh;
+
+    do
+    {
+        //mask = vp8_simple_filter_mask( limit[i], flimit[i],s[-1],s[0]);
+        mask = vp8_simple_filter_mask(limit[i], flimit[i], s[-2], s[-1], s[0], s[1]);
+        vp8_simple_filter(mask, s - 2, s - 1, s, s + 1);
+        s += p;
+    }
+    while (++i < count * 8);
+
+}
diff --git a/vp8/common/mac_specs.h b/vp8/common/mac_specs.h
new file mode 100644
index 0000000..97bffc7
--- /dev/null
+++ b/vp8/common/mac_specs.h
@@ -0,0 +1,30 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#if !defined(_mac_specs_h)
+#define _mac_specs_h
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+    extern unsigned int vp8_read_tsc();
+
+    extern unsigned int vp8_get_processor_freq();
+
+    extern unsigned int vpx_has_altivec();
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif
diff --git a/vp8/common/mbpitch.c b/vp8/common/mbpitch.c
new file mode 100644
index 0000000..a7e0ce9
--- /dev/null
+++ b/vp8/common/mbpitch.c
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "blockd.h"
+
+typedef enum
+{
+    PRED = 0,
+    DEST = 1,
+} BLOCKSET;
+
+void vp8_setup_block
+(
+    BLOCKD *b,
+    int mv_stride,
+    unsigned char **base,
+    int Stride,
+    int offset,
+    BLOCKSET bs
+)
+{
+
+    if (bs == DEST)
+    {
+        b->dst_stride = Stride;
+        b->dst = offset;
+        b->base_dst = base;
+    }
+    else
+    {
+        b->pre_stride = Stride;
+        b->pre = offset;
+        b->base_pre = base;
+    }
+
+}
+
+void vp8_setup_macroblock(MACROBLOCKD *x, BLOCKSET bs)
+{
+    int block;
+
+    unsigned char **y, **u, **v;
+
+    if (bs == DEST)
+    {
+        y = &x->dst.y_buffer;
+        u = &x->dst.u_buffer;
+        v = &x->dst.v_buffer;
+    }
+    else
+    {
+        y = &x->pre.y_buffer;
+        u = &x->pre.u_buffer;
+        v = &x->pre.v_buffer;
+    }
+
+    for (block = 0; block < 16; block++) // y blocks
+    {
+        vp8_setup_block(&x->block[block], x->dst.y_stride, y, x->dst.y_stride,
+                        (block >> 2) * 4 * x->dst.y_stride + (block & 3) * 4, bs);
+    }
+
+    for (block = 16; block < 20; block++) // U and V blocks
+    {
+        vp8_setup_block(&x->block[block], x->dst.uv_stride, u, x->dst.uv_stride,
+                        ((block - 16) >> 1) * 4 * x->dst.uv_stride + (block & 1) * 4, bs);
+
+        vp8_setup_block(&x->block[block+4], x->dst.uv_stride, v, x->dst.uv_stride,
+                        ((block - 16) >> 1) * 4 * x->dst.uv_stride + (block & 1) * 4, bs);
+    }
+}
+
+void vp8_setup_block_dptrs(MACROBLOCKD *x)
+{
+    int r, c;
+
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 4; c++)
+        {
+            x->block[r*4+c].diff      = &x->diff[r * 4 * 16 + c * 4];
+            x->block[r*4+c].predictor = x->predictor + r * 4 * 16 + c * 4;
+        }
+    }
+
+    for (r = 0; r < 2; r++)
+    {
+        for (c = 0; c < 2; c++)
+        {
+            x->block[16+r*2+c].diff      = &x->diff[256 + r * 4 * 8 + c * 4];
+            x->block[16+r*2+c].predictor = x->predictor + 256 + r * 4 * 8 + c * 4;
+
+        }
+    }
+
+    for (r = 0; r < 2; r++)
+    {
+        for (c = 0; c < 2; c++)
+        {
+            x->block[20+r*2+c].diff      = &x->diff[320+ r * 4 * 8 + c * 4];
+            x->block[20+r*2+c].predictor = x->predictor + 320 + r * 4 * 8 + c * 4;
+
+        }
+    }
+
+    x->block[24].diff = &x->diff[384];
+
+    for (r = 0; r < 25; r++)
+    {
+        x->block[r].qcoeff  = x->qcoeff  + r * 16;
+        x->block[r].dqcoeff = x->dqcoeff + r * 16;
+    }
+}
+
+void vp8_build_block_doffsets(MACROBLOCKD *x)
+{
+
+    // handle the destination pitch features
+    vp8_setup_macroblock(x, DEST);
+    vp8_setup_macroblock(x, PRED);
+}
diff --git a/vp8/common/modecont.c b/vp8/common/modecont.c
new file mode 100644
index 0000000..9301a25
--- /dev/null
+++ b/vp8/common/modecont.c
@@ -0,0 +1,39 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "entropy.h"
+
+const int vp8_mode_contexts[6][4] =
+{
+    {
+        // 0
+        7,     1,     1,   143,
+    },
+    {
+        // 1
+        14,    18,    14,   107,
+    },
+    {
+        // 2
+        135,    64,    57,    68,
+    },
+    {
+        // 3
+        60,    56,   128,    65,
+    },
+    {
+        // 4
+        159,   134,   128,    34,
+    },
+    {
+        // 5
+        234,   188,   128,    28,
+    },
+};
diff --git a/vp8/common/modecont.h b/vp8/common/modecont.h
new file mode 100644
index 0000000..0c57651
--- /dev/null
+++ b/vp8/common/modecont.h
@@ -0,0 +1,16 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_MODECONT_H
+#define __INC_MODECONT_H
+
+extern const int vp8_mode_contexts[6][4];
+
+#endif
diff --git a/vp8/common/modecontext.c b/vp8/common/modecontext.c
new file mode 100644
index 0000000..ceee74c
--- /dev/null
+++ b/vp8/common/modecontext.c
@@ -0,0 +1,145 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "entropymode.h"
+
+const unsigned int vp8_kf_default_bmode_counts [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES] =
+{
+    {
+        //Above Mode :  0
+        { 43438,   2195,    470,    316,    615,    171,    217,    412,    124,    160, }, // left_mode 0
+        {  5722,   2751,    296,    291,     81,     68,     80,    101,    100,    170, }, // left_mode 1
+        {  1629,    201,    307,     25,     47,     16,     34,     72,     19,     28, }, // left_mode 2
+        {   332,    266,     36,    500,     20,     65,     23,     14,    154,    106, }, // left_mode 3
+        {   450,     97,     10,     24,    117,     10,      2,     12,      8,     71, }, // left_mode 4
+        {   384,     49,     29,     44,     12,    162,     51,      5,     87,     42, }, // left_mode 5
+        {   495,     53,    157,     27,     14,     57,    180,     17,     17,     34, }, // left_mode 6
+        {   695,     64,     62,      9,     27,      5,      3,    147,     10,     26, }, // left_mode 7
+        {   230,     54,     20,    124,     16,    125,     29,     12,    283,     37, }, // left_mode 8
+        {   260,     87,     21,    120,     32,     16,     33,     16,     33,    203, }, // left_mode 9
+    },
+    {
+        //Above Mode :  1
+        {  3934,   2573,    355,    137,    128,     87,    133,    117,     37,     27, }, // left_mode 0
+        {  1036,   1929,    278,    135,     27,     37,     48,     55,     41,     91, }, // left_mode 1
+        {   223,    256,    253,     15,     13,      9,     28,     64,      3,      3, }, // left_mode 2
+        {   120,    129,     17,    316,     15,     11,      9,      4,     53,     74, }, // left_mode 3
+        {   129,     58,      6,     11,     38,      2,      0,      5,      2,     67, }, // left_mode 4
+        {    53,     22,     11,     16,      8,     26,     14,      3,     19,     12, }, // left_mode 5
+        {    59,     26,     61,     11,      4,      9,     35,     13,      8,      8, }, // left_mode 6
+        {   101,     52,     40,      8,      5,      2,      8,     59,      2,     20, }, // left_mode 7
+        {    48,     34,     10,     52,      8,     15,      6,      6,     63,     20, }, // left_mode 8
+        {    96,     48,     22,     63,     11,     14,      5,      8,      9,     96, }, // left_mode 9
+    },
+    {
+        //Above Mode :  2
+        {   709,    461,    506,     36,     27,     33,    151,     98,     24,      6, }, // left_mode 0
+        {   201,    375,    442,     27,     13,      8,     46,     58,      6,     19, }, // left_mode 1
+        {   122,    140,    417,      4,     13,      3,     33,     59,      4,      2, }, // left_mode 2
+        {    36,     17,     22,     16,      6,      8,     12,     17,      9,     21, }, // left_mode 3
+        {    51,     15,      7,      1,     14,      0,      4,      5,      3,     22, }, // left_mode 4
+        {    18,     11,     30,      9,      7,     20,     11,      5,      2,      6, }, // left_mode 5
+        {    38,     21,    103,      9,      4,     12,     79,     13,      2,      5, }, // left_mode 6
+        {    64,     17,     66,      2,     12,      4,      2,     65,      4,      5, }, // left_mode 7
+        {    14,      7,      7,     16,      3,     11,      4,     13,     15,     16, }, // left_mode 8
+        {    36,      8,     32,      9,      9,      4,     14,      7,      6,     24, }, // left_mode 9
+    },
+    {
+        //Above Mode :  3
+        {  1340,    173,     36,    119,     30,     10,     13,     10,     20,     26, }, // left_mode 0
+        {   156,    293,     26,    108,      5,     16,      2,      4,     23,     30, }, // left_mode 1
+        {    60,     34,     13,      7,      3,      3,      0,      8,      4,      5, }, // left_mode 2
+        {    72,     64,      1,    235,      3,      9,      2,      7,     28,     38, }, // left_mode 3
+        {    29,     14,      1,      3,      5,      0,      2,      2,      5,     13, }, // left_mode 4
+        {    22,      7,      4,     11,      2,      5,      1,      2,      6,      4, }, // left_mode 5
+        {    18,     14,      5,      6,      4,      3,     14,      0,      9,      2, }, // left_mode 6
+        {    41,     10,      7,      1,      2,      0,      0,     10,      2,      1, }, // left_mode 7
+        {    23,     19,      2,     33,      1,      5,      2,      0,     51,      8, }, // left_mode 8
+        {    33,     26,      7,     53,      3,      9,      3,      3,      9,     19, }, // left_mode 9
+    },
+    {
+        //Above Mode :  4
+        {   410,    165,     43,     31,     66,     15,     30,     54,      8,     17, }, // left_mode 0
+        {   115,     64,     27,     18,     30,      7,     11,     15,      4,     19, }, // left_mode 1
+        {    31,     23,     25,      1,      7,      2,      2,     10,      0,      5, }, // left_mode 2
+        {    17,      4,      1,      6,      8,      2,      7,      5,      5,     21, }, // left_mode 3
+        {   120,     12,      1,      2,     83,      3,      0,      4,      1,     40, }, // left_mode 4
+        {     4,      3,      1,      2,      1,      2,      5,      0,      3,      6, }, // left_mode 5
+        {    10,      2,     13,      6,      6,      6,      8,      2,      4,      5, }, // left_mode 6
+        {    58,     10,      5,      1,     28,      1,      1,     33,      1,      9, }, // left_mode 7
+        {     8,      2,      1,      4,      2,      5,      1,      1,      2,     10, }, // left_mode 8
+        {    76,      7,      5,      7,     18,      2,      2,      0,      5,     45, }, // left_mode 9
+    },
+    {
+        //Above Mode :  5
+        {   444,     46,     47,     20,     14,    110,     60,     14,     60,      7, }, // left_mode 0
+        {    59,     57,     25,     18,      3,     17,     21,      6,     14,      6, }, // left_mode 1
+        {    24,     17,     20,      6,      4,     13,      7,      2,      3,      2, }, // left_mode 2
+        {    13,     11,      5,     14,      4,      9,      2,      4,     15,      7, }, // left_mode 3
+        {     8,      5,      2,      1,      4,      0,      1,      1,      2,     12, }, // left_mode 4
+        {    19,      5,      5,      7,      4,     40,      6,      3,     10,      4, }, // left_mode 5
+        {    16,      5,      9,      1,      1,     16,     26,      2,     10,      4, }, // left_mode 6
+        {    11,      4,      8,      1,      1,      4,      4,      5,      4,      1, }, // left_mode 7
+        {    15,      1,      3,      7,      3,     21,      7,      1,     34,      5, }, // left_mode 8
+        {    18,      5,      1,      3,      4,      3,      7,      1,      2,      9, }, // left_mode 9
+    },
+    {
+        //Above Mode :  6
+        {   476,    149,     94,     13,     14,     77,    291,     27,     23,      3, }, // left_mode 0
+        {    79,     83,     42,     14,      2,     12,     63,      2,      4,     14, }, // left_mode 1
+        {    43,     36,     55,      1,      3,      8,     42,     11,      5,      1, }, // left_mode 2
+        {     9,      9,      6,     16,      1,      5,      6,      3,     11,     10, }, // left_mode 3
+        {    10,      3,      1,      3,     10,      1,      0,      1,      1,      4, }, // left_mode 4
+        {    14,      6,     15,      5,      1,     20,     25,      2,      5,      0, }, // left_mode 5
+        {    28,      7,     51,      1,      0,      8,    127,      6,      2,      5, }, // left_mode 6
+        {    13,      3,      3,      2,      3,      1,      2,      8,      1,      2, }, // left_mode 7
+        {    10,      3,      3,      3,      3,      8,      2,      2,      9,      3, }, // left_mode 8
+        {    13,      7,     11,      4,      0,      4,      6,      2,      5,      8, }, // left_mode 9
+    },
+    {
+        //Above Mode :  7
+        {   376,    135,    119,      6,     32,      8,     31,    224,      9,      3, }, // left_mode 0
+        {    93,     60,     54,      6,     13,      7,      8,     92,      2,     12, }, // left_mode 1
+        {    74,     36,     84,      0,      3,      2,      9,     67,      2,      1, }, // left_mode 2
+        {    19,      4,      4,      8,      8,      2,      4,      7,      6,     16, }, // left_mode 3
+        {    51,      7,      4,      1,     77,      3,      0,     14,      1,     15, }, // left_mode 4
+        {     7,      7,      5,      7,      4,      7,      4,      5,      0,      3, }, // left_mode 5
+        {    18,      2,     19,      2,      2,      4,     12,     11,      1,      2, }, // left_mode 6
+        {   129,      6,     27,      1,     21,      3,      0,    189,      0,      6, }, // left_mode 7
+        {     9,      1,      2,      8,      3,      7,      0,      5,      3,      3, }, // left_mode 8
+        {    20,      4,      5,     10,      4,      2,      7,     17,      3,     16, }, // left_mode 9
+    },
+    {
+        //Above Mode :  8
+        {   617,     68,     34,     79,     11,     27,     25,     14,     75,     13, }, // left_mode 0
+        {    51,     82,     21,     26,      6,     12,     13,      1,     26,     16, }, // left_mode 1
+        {    29,      9,     12,     11,      3,      7,      1,     10,      2,      2, }, // left_mode 2
+        {    17,     19,     11,     74,      4,      3,      2,      0,     58,     13, }, // left_mode 3
+        {    10,      1,      1,      3,      4,      1,      0,      2,      1,      8, }, // left_mode 4
+        {    14,      4,      5,      5,      1,     13,      2,      0,     27,      8, }, // left_mode 5
+        {    10,      3,      5,      4,      1,      7,      6,      4,      5,      1, }, // left_mode 6
+        {    10,      2,      6,      2,      1,      1,      1,      4,      2,      1, }, // left_mode 7
+        {    14,      8,      5,     23,      2,     12,      6,      2,    117,      5, }, // left_mode 8
+        {     9,      6,      2,     19,      1,      6,      3,      2,      9,      9, }, // left_mode 9
+    },
+    {
+        //Above Mode :  9
+        {   680,     73,     22,     38,     42,      5,     11,      9,      6,     28, }, // left_mode 0
+        {   113,    112,     21,     22,     10,      2,      8,      4,      6,     42, }, // left_mode 1
+        {    44,     20,     24,      6,      5,      4,      3,      3,      1,      2, }, // left_mode 2
+        {    40,     23,      7,     71,      5,      2,      4,      1,      7,     22, }, // left_mode 3
+        {    85,      9,      4,      4,     17,      2,      0,      3,      2,     23, }, // left_mode 4
+        {    13,      4,      2,      6,      1,      7,      0,      1,      7,      6, }, // left_mode 5
+        {    26,      6,      8,      3,      2,      3,      8,      1,      5,      4, }, // left_mode 6
+        {    54,      8,      9,      6,      7,      0,      1,     11,      1,      3, }, // left_mode 7
+        {     9,     10,      4,     13,      2,      5,      4,      2,     14,      8, }, // left_mode 8
+        {    92,      9,      5,     19,     15,      3,      3,      1,      6,     58, }, // left_mode 9
+    },
+};
diff --git a/vp8/common/mv.h b/vp8/common/mv.h
new file mode 100644
index 0000000..3d84181
--- /dev/null
+++ b/vp8/common/mv.h
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_MV_H
+#define __INC_MV_H
+
+typedef struct
+{
+    short row;
+    short col;
+} MV;
+
+#endif
diff --git a/vp8/common/onyx.h b/vp8/common/onyx.h
new file mode 100644
index 0000000..b66c400
--- /dev/null
+++ b/vp8/common/onyx.h
@@ -0,0 +1,222 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_VP8_H
+#define __INC_VP8_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "vpx_codec/internal/vpx_codec_internal.h"
+#include "vpx_scale/yv12config.h"
+#include "type_aliases.h"
+#include "ppflags.h"
+    typedef int *VP8_PTR;
+
+    /* Create/destroy static data structures. */
+
+    typedef enum
+    {
+        NORMAL      = 0,
+        FOURFIVE    = 1,
+        THREEFIVE   = 2,
+        ONETWO      = 3
+
+    } VPX_SCALING;
+
+    typedef enum
+    {
+        VP8_LAST_FLAG = 1,
+        VP8_GOLD_FLAG = 2,
+        VP8_ALT_FLAG = 4
+    } VP8_REFFRAME;
+
+
+    typedef enum
+    {
+        USAGE_STREAM_FROM_SERVER    = 0x0,
+        USAGE_LOCAL_FILE_PLAYBACK   = 0x1
+    } END_USAGE;
+
+
+    typedef enum
+    {
+        MODE_REALTIME       = 0x0,
+        MODE_GOODQUALITY    = 0x1,
+        MODE_BESTQUALITY    = 0x2,
+        MODE_FIRSTPASS      = 0x3,
+        MODE_SECONDPASS     = 0x4,
+        MODE_SECONDPASS_BEST = 0x5,
+    } MODE;
+
+    typedef enum
+    {
+        FRAMEFLAGS_KEY    = 1,
+        FRAMEFLAGS_GOLDEN = 2,
+        FRAMEFLAGS_ALTREF = 4,
+    } FRAMETYPE_FLAGS;
+
+
+#include <assert.h>
+    static __inline void Scale2Ratio(int mode, int *hr, int *hs)
+    {
+        switch (mode)
+        {
+        case    NORMAL:
+            *hr = 1;
+            *hs = 1;
+            break;
+        case    FOURFIVE:
+            *hr = 4;
+            *hs = 5;
+            break;
+        case    THREEFIVE:
+            *hr = 3;
+            *hs = 5;
+            break;
+        case    ONETWO:
+            *hr = 1;
+            *hs = 2;
+            break;
+        default:
+            *hr = 1;
+            *hs = 1;
+            assert(0);
+            break;
+        }
+    }
+
+    typedef struct
+    {
+        int Version;            // 4 versions of bitstream defined 0 best quality/slowest decode, 3 lowest quality/fastest decode
+        int Width;              // width of data passed to the compressor
+        int Height;             // height of data passed to the compressor
+        double frame_rate;       // set to passed in framerate
+        int target_bandwidth;    // bandwidth to be used in kilobits per second
+
+        int noise_sensitivity;   // parameter used for applying pre processing blur: recommendation 0
+        int Sharpness;          // parameter used for sharpening output: recommendation 0:
+        int cpu_used;
+
+        // mode ->
+        //(0)=Realtime/Live Encoding. This mode is optimized for realtim encoding (for example, capturing
+        //    a television signal or feed from a live camera). ( speed setting controls how fast )
+        //(1)=Good Quality Fast Encoding. The encoder balances quality with the amount of time it takes to
+        //    encode the output. ( speed setting controls how fast )
+        //(2)=One Pass - Best Quality. The encoder places priority on the quality of the output over encoding
+        //    speed. The output is compressed at the highest possible quality. This option takes the longest
+        //    amount of time to encode. ( speed setting ignored )
+        //(3)=Two Pass - First Pass. The encoder generates a file of statistics for use in the second encoding
+        //    pass. ( speed setting controls how fast )
+        //(4)=Two Pass - Second Pass. The encoder uses the statistics that were generated in the first encoding
+        //    pass to create the compressed output. ( speed setting controls how fast )
+        //(5)=Two Pass - Second Pass Best.  The encoder uses the statistics that were generated in the first
+        //    encoding pass to create the compressed output using the highest possible quality, and taking a
+        //    longer amount of time to encode.. ( speed setting ignored )
+        int Mode;               //
+
+        // Key Framing Operations
+        int auto_key;            // automatically detect cut scenes and set the keyframes
+        int key_freq;            // maximum distance to key frame.
+
+        int allow_lag;           // allow lagged compression (if 0 lagin frames is ignored)
+        int lag_in_frames;        // how many frames lag before we start encoding
+
+        //----------------------------------------------------------------
+        // DATARATE CONTROL OPTIONS
+
+        int end_usage; // vbr or cbr
+
+        // shoot to keep buffer full at all times by undershooting a bit 95 recommended
+        int under_shoot_pct;
+
+        // buffering parameters
+        int starting_buffer_level;  // in seconds
+        int optimal_buffer_level;
+        int maximum_buffer_size;
+
+        // controlling quality
+        int fixed_q;
+        int worst_allowed_q;
+        int best_allowed_q;
+
+        // allow internal resizing ( currently disabled in the build !!!!!)
+        int allow_spatial_resampling;
+        int resample_down_water_mark;
+        int resample_up_water_mark;
+
+        // allow internal frame rate alterations
+        int allow_df;
+        int drop_frames_water_mark;
+
+        // two pass datarate control
+        int two_pass_vbrbias;        // two pass datarate control tweaks
+        int two_pass_vbrmin_section;
+        int two_pass_vbrmax_section;
+        // END DATARATE CONTROL OPTIONS
+        //----------------------------------------------------------------
+
+
+        // these parameters aren't to be used in final build don't use!!!
+        int play_alternate;
+        int alt_freq;
+        int alt_q;
+        int key_q;
+        int gold_q;
+
+
+        int multi_threaded;   // how many threads to run the encoder on
+        int token_partitions; // how many token partitions to create for multi core decoding
+        int encode_breakout;  // early breakout encode threshold : for video conf recommend 800
+
+        int error_resilient_mode;  // if running over udp networks provides decodable frames after a
+        // dropped packet
+
+        int arnr_max_frames;
+        int arnr_strength ;
+        int arnr_type     ;
+
+
+        struct vpx_fixed_buf         two_pass_stats_in;
+        struct vpx_codec_pkt_list  *output_pkt_list;
+    } VP8_CONFIG;
+
+
+    void vp8_initialize();
+
+    VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf);
+    void vp8_remove_compressor(VP8_PTR *comp);
+
+    void vp8_init_config(VP8_PTR onyx, VP8_CONFIG *oxcf);
+    void vp8_change_config(VP8_PTR onyx, VP8_CONFIG *oxcf);
+
+// receive a frames worth of data caller can assume that a copy of this frame is made
+// and not just a copy of the pointer..
+    int vp8_receive_raw_frame(VP8_PTR comp, unsigned int frame_flags, YV12_BUFFER_CONFIG *sd, INT64 time_stamp, INT64 end_time_stamp);
+    int vp8_get_compressed_data(VP8_PTR comp, unsigned int *frame_flags, unsigned long *size, unsigned char *dest, INT64 *time_stamp, INT64 *time_end, int flush);
+    int vp8_get_preview_raw_frame(VP8_PTR comp, YV12_BUFFER_CONFIG *dest, int deblock_level, int noise_level, int flags);
+
+    int vp8_use_as_reference(VP8_PTR comp, int ref_frame_flags);
+    int vp8_update_reference(VP8_PTR comp, int ref_frame_flags);
+    int vp8_get_reference(VP8_PTR comp, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd);
+    int vp8_set_reference(VP8_PTR comp, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd);
+    int vp8_update_entropy(VP8_PTR comp, int update);
+    int vp8_set_roimap(VP8_PTR comp, unsigned char *map, unsigned int rows, unsigned int cols, int delta_q[4], int delta_lf[4], unsigned int threshold[4]);
+    int vp8_set_active_map(VP8_PTR comp, unsigned char *map, unsigned int rows, unsigned int cols);
+    int vp8_set_internal_size(VP8_PTR comp, VPX_SCALING horiz_mode, VPX_SCALING vert_mode);
+    int vp8_get_quantizer(VP8_PTR c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h
new file mode 100644
index 0000000..a40ffb9
--- /dev/null
+++ b/vp8/common/onyxc_int.h
@@ -0,0 +1,205 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_VP8C_INT_H
+#define __INC_VP8C_INT_H
+
+#include "vpx_ports/config.h"
+#include "vpx_codec/internal/vpx_codec_internal.h"
+#include "loopfilter.h"
+#include "entropymv.h"
+#include "entropy.h"
+#include "idct.h"
+#include "recon.h"
+#include "postproc.h"
+
+//#ifdef PACKET_TESTING
+#include "header.h"
+//#endif
+
+/* Create/destroy static data structures. */
+
+void vp8_initialize_common(void);
+
+#define MINQ 0
+#define MAXQ 127
+#define QINDEX_RANGE (MAXQ + 1)
+
+
+typedef struct frame_contexts
+{
+    vp8_prob bmode_prob [VP8_BINTRAMODES-1];
+    vp8_prob ymode_prob [VP8_YMODES-1];   /* interframe intra mode probs */
+    vp8_prob uv_mode_prob [VP8_UV_MODES-1];
+    vp8_prob sub_mv_ref_prob [VP8_SUBMVREFS-1];
+    vp8_prob coef_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1];
+    MV_CONTEXT mvc[2];
+    MV_CONTEXT pre_mvc[2];  //not to caculate the mvcost for the frame if mvc doesn't change.
+} FRAME_CONTEXT;
+
+typedef enum
+{
+    ONE_PARTITION  = 0,
+    TWO_PARTITION  = 1,
+    FOUR_PARTITION = 2,
+    EIGHT_PARTITION = 3
+} TOKEN_PARTITION;
+
+typedef enum
+{
+    RECON_CLAMP_REQUIRED        = 0,
+    RECON_CLAMP_NOTREQUIRED     = 1
+} CLAMP_TYPE;
+
+typedef enum
+{
+    SIXTAP   = 0,
+    BILINEAR = 1
+} INTERPOLATIONFILTERTYPE;
+
+typedef struct VP8_COMMON_RTCD
+{
+#if CONFIG_RUNTIME_CPU_DETECT
+    vp8_idct_rtcd_vtable_t        idct;
+    vp8_recon_rtcd_vtable_t       recon;
+    vp8_subpix_rtcd_vtable_t      subpix;
+    vp8_loopfilter_rtcd_vtable_t  loopfilter;
+    vp8_postproc_rtcd_vtable_t    postproc;
+#else
+    int unused;
+#endif
+} VP8_COMMON_RTCD;
+
+typedef struct VP8Common
+{
+    struct vpx_internal_error_info  error;
+
+    DECLARE_ALIGNED(16, short, Y1dequant[QINDEX_RANGE][4][4]);
+    DECLARE_ALIGNED(16, short, Y2dequant[QINDEX_RANGE][4][4]);
+    DECLARE_ALIGNED(16, short, UVdequant[QINDEX_RANGE][4][4]);
+
+    int Width;
+    int Height;
+    int horiz_scale;
+    int vert_scale;
+
+    YUV_TYPE clr_type;
+    CLAMP_TYPE  clamp_type;
+
+    YV12_BUFFER_CONFIG last_frame;
+    YV12_BUFFER_CONFIG golden_frame;
+    YV12_BUFFER_CONFIG alt_ref_frame;
+    YV12_BUFFER_CONFIG new_frame;
+    YV12_BUFFER_CONFIG *frame_to_show;
+    YV12_BUFFER_CONFIG post_proc_buffer;
+    YV12_BUFFER_CONFIG temp_scale_frame;
+
+    FRAME_TYPE last_frame_type;  //Add to check if vp8_frame_init_loop_filter() can be skiped.
+    FRAME_TYPE frame_type;
+
+    int show_frame;
+
+    int frame_flags;
+    int MBs;
+    int mb_rows;
+    int mb_cols;
+    int mode_info_stride;
+
+    // prfile settings
+    int mb_no_coeff_skip;
+    int no_lpf;
+    int simpler_lpf;
+    int use_bilinear_mc_filter;
+    int full_pixel;
+
+    int base_qindex;
+    int last_kf_gf_q;  // Q used on the last GF or KF
+
+    int y1dc_delta_q;
+    int y2dc_delta_q;
+    int y2ac_delta_q;
+    int uvdc_delta_q;
+    int uvac_delta_q;
+
+    unsigned int frames_since_golden;
+    unsigned int frames_till_alt_ref_frame;
+    unsigned char *gf_active_flags;   // Record of which MBs still refer to last golden frame either directly or through 0,0
+    int gf_active_count;
+
+    /* We allocate a MODE_INFO struct for each macroblock, together with
+       an extra row on top and column on the left to simplify prediction. */
+
+    MODE_INFO *mip; /* Base of allocated array */
+    MODE_INFO *mi;  /* Corresponds to upper left visible macroblock */
+
+
+    INTERPOLATIONFILTERTYPE mcomp_filter_type;
+    LOOPFILTERTYPE last_filter_type;
+    LOOPFILTERTYPE filter_type;
+    loop_filter_info lf_info[MAX_LOOP_FILTER+1];
+    prototype_loopfilter_block((*lf_mbv));
+    prototype_loopfilter_block((*lf_mbh));
+    prototype_loopfilter_block((*lf_bv));
+    prototype_loopfilter_block((*lf_bh));
+    int filter_level;
+    int last_sharpness_level;
+    int sharpness_level;
+
+    int refresh_last_frame;       // Two state 0 = NO, 1 = YES
+    int refresh_golden_frame;     // Two state 0 = NO, 1 = YES
+    int refresh_alt_ref_frame;     // Two state 0 = NO, 1 = YES
+
+    int copy_buffer_to_gf;         // 0 none, 1 Last to GF, 2 ARF to GF
+    int copy_buffer_to_arf;        // 0 none, 1 Last to ARF, 2 GF to ARF
+
+    int refresh_entropy_probs;    // Two state 0 = NO, 1 = YES
+
+    int ref_frame_sign_bias[MAX_REF_FRAMES];    // Two state 0, 1
+
+    // Y,U,V,Y2
+    ENTROPY_CONTEXT *above_context[4];   // row of context for each plane
+    ENTROPY_CONTEXT left_context[4][4];  // (up to) 4 contexts ""
+
+
+    // keyframe block modes are predicted by their above, left neighbors
+
+    vp8_prob kf_bmode_prob [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES-1];
+    vp8_prob kf_ymode_prob [VP8_YMODES-1];  /* keyframe "" */
+    vp8_prob kf_uv_mode_prob [VP8_UV_MODES-1];
+
+
+    FRAME_CONTEXT lfc; // last frame entropy
+    FRAME_CONTEXT fc;  // this frame entropy
+
+    unsigned int current_video_frame;
+
+    int near_boffset[3];
+    int version;
+
+    TOKEN_PARTITION multi_token_partition;
+
+#ifdef PACKET_TESTING
+    VP8_HEADER oh;
+#endif
+    double bitrate;
+    double framerate;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+    VP8_COMMON_RTCD rtcd;
+#endif
+    struct postproc_state  postproc_state;
+} VP8_COMMON;
+
+
+void vp8_adjust_mb_lf_value(MACROBLOCKD *mbd, int *filter_level);
+void vp8_init_loop_filter(VP8_COMMON *cm);
+extern void vp8_loop_filter_frame(VP8_COMMON *cm,    MACROBLOCKD *mbd,  int filt_val);
+
+#endif
diff --git a/vp8/common/onyxd.h b/vp8/common/onyxd.h
new file mode 100644
index 0000000..644c0ec
--- /dev/null
+++ b/vp8/common/onyxd.h
@@ -0,0 +1,67 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_VP8D_H
+#define __INC_VP8D_H
+
+
+/* Create/destroy static data structures. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include "type_aliases.h"
+#include "vpx_scale/yv12config.h"
+#include "ppflags.h"
+#include "vpx_ports/mem.h"
+
+    typedef void   *VP8D_PTR;
+    typedef struct
+    {
+        int     Width;
+        int     Height;
+        int     Version;
+        int     postprocess;
+        int     max_threads;
+    } VP8D_CONFIG;
+    typedef enum
+    {
+        VP8_LAST_FLAG = 1,
+        VP8_GOLD_FLAG = 2,
+        VP8_ALT_FLAG = 4
+    } VP8_REFFRAME;
+
+    typedef enum
+    {
+        VP8D_OK = 0
+    } VP8D_SETTING;
+
+    void vp8dx_initialize(void);
+
+    void vp8dx_set_setting(VP8D_PTR comp, VP8D_SETTING oxst, int x);
+
+    int vp8dx_get_setting(VP8D_PTR comp, VP8D_SETTING oxst);
+
+    int vp8dx_receive_compressed_data(VP8D_PTR comp, unsigned long size, const unsigned char *dest, INT64 time_stamp);
+    int vp8dx_get_raw_frame(VP8D_PTR comp, YV12_BUFFER_CONFIG *sd, INT64 *time_stamp, INT64 *time_end_stamp, int deblock_level,  int noise_level, int flags);
+
+    int vp8dx_get_reference(VP8D_PTR comp, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd);
+    int vp8dx_set_reference(VP8D_PTR comp, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd);
+
+    VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf);
+
+    void vp8dx_remove_decompressor(VP8D_PTR comp);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/vp8/common/partialgfupdate.h b/vp8/common/partialgfupdate.h
new file mode 100644
index 0000000..32a55ee
--- /dev/null
+++ b/vp8/common/partialgfupdate.h
@@ -0,0 +1,18 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_PARTIALGFUPDATE_H
+#define __INC_PARTIALGFUPDATE_H
+
+#include "onyxc_int.h"
+
+extern void update_gf_selective(ONYX_COMMON *cm, MACROBLOCKD *x);
+
+#endif
diff --git a/vp8/common/postproc.c b/vp8/common/postproc.c
new file mode 100644
index 0000000..f019925
--- /dev/null
+++ b/vp8/common/postproc.c
@@ -0,0 +1,641 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "vpx_scale/yv12config.h"
+#include "postproc.h"
+#include "vpx_scale/yv12extend.h"
+#include "vpx_scale/vpxscale.h"
+#include "systemdependent.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+// global constants
+
+static const short kernel5[] =
+{
+    1, 1, 4, 1, 1
+};
+
+const short vp8_rv[] =
+{
+    8, 5, 2, 2, 8, 12, 4, 9, 8, 3,
+    0, 3, 9, 0, 0, 0, 8, 3, 14, 4,
+    10, 1, 11, 14, 1, 14, 9, 6, 12, 11,
+    8, 6, 10, 0, 0, 8, 9, 0, 3, 14,
+    8, 11, 13, 4, 2, 9, 0, 3, 9, 6,
+    1, 2, 3, 14, 13, 1, 8, 2, 9, 7,
+    3, 3, 1, 13, 13, 6, 6, 5, 2, 7,
+    11, 9, 11, 8, 7, 3, 2, 0, 13, 13,
+    14, 4, 12, 5, 12, 10, 8, 10, 13, 10,
+    4, 14, 4, 10, 0, 8, 11, 1, 13, 7,
+    7, 14, 6, 14, 13, 2, 13, 5, 4, 4,
+    0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
+    8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
+    3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
+    3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
+    13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
+    5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
+    9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
+    4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
+    3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
+    11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
+    5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
+    0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
+    10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
+    4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
+    0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
+    8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
+    3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
+    3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
+    13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
+    5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
+    9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
+    4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
+    3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
+    11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
+    5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
+    0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
+    10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
+    4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
+    3, 8, 3, 7, 8, 5, 11, 4, 12, 3,
+    11, 9, 14, 8, 14, 13, 4, 3, 1, 2,
+    14, 6, 5, 4, 4, 11, 4, 6, 2, 1,
+    5, 8, 8, 12, 13, 5, 14, 10, 12, 13,
+    0, 9, 5, 5, 11, 10, 13, 9, 10, 13,
+};
+
+
+extern void vp8_blit_text(const char *msg, unsigned char *address, const int pitch);
+
+/***********************************************************************************************************
+ */
+void vp8_post_proc_down_and_across_c
+(
+    unsigned char *src_ptr,
+    unsigned char *dst_ptr,
+    int src_pixels_per_line,
+    int dst_pixels_per_line,
+    int rows,
+    int cols,
+    int flimit
+)
+{
+    unsigned char *p_src, *p_dst;
+    int row;
+    int col;
+    int i;
+    int v;
+    int pitch = src_pixels_per_line;
+    unsigned char d[8];
+    (void)dst_pixels_per_line;
+
+    for (row = 0; row < rows; row++)
+    {
+        // post_proc_down for one row
+        p_src = src_ptr;
+        p_dst = dst_ptr;
+
+        for (col = 0; col < cols; col++)
+        {
+
+            int kernel = 4;
+            int v = p_src[col];
+
+            for (i = -2; i <= 2; i++)
+            {
+                if (abs(v - p_src[col+i*pitch]) > flimit)
+                    goto down_skip_convolve;
+
+                kernel += kernel5[2+i] * p_src[col+i*pitch];
+            }
+
+            v = (kernel >> 3);
+        down_skip_convolve:
+            p_dst[col] = v;
+        }
+
+        // now post_proc_across
+        p_src = dst_ptr;
+        p_dst = dst_ptr;
+
+        for (i = 0; i < 8; i++)
+            d[i] = p_src[i];
+
+        for (col = 0; col < cols; col++)
+        {
+            int kernel = 4;
+            v = p_src[col];
+
+            d[col&7] = v;
+
+            for (i = -2; i <= 2; i++)
+            {
+                if (abs(v - p_src[col+i]) > flimit)
+                    goto across_skip_convolve;
+
+                kernel += kernel5[2+i] * p_src[col+i];
+            }
+
+            d[col&7] = (kernel >> 3);
+        across_skip_convolve:
+
+            if (col >= 2)
+                p_dst[col-2] = d[(col-2)&7];
+        }
+
+        //handle the last two pixels
+        p_dst[col-2] = d[(col-2)&7];
+        p_dst[col-1] = d[(col-1)&7];
+
+
+        //next row
+        src_ptr += pitch;
+        dst_ptr += pitch;
+    }
+}
+
+int vp8_q2mbl(int x)
+{
+    if (x < 20) x = 20;
+
+    x = 50 + (x - 50) * 10 / 8;
+    return x * x / 3;
+}
+void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit)
+{
+    int r, c, i;
+
+    unsigned char *s = src;
+    unsigned char d[16];
+
+
+    for (r = 0; r < rows; r++)
+    {
+        int sumsq = 0;
+        int sum   = 0;
+
+        for (i = -8; i <= 6; i++)
+        {
+            sumsq += s[i] * s[i];
+            sum   += s[i];
+            d[i+8] = 0;
+        }
+
+        for (c = 0; c < cols + 8; c++)
+        {
+            int x = s[c+7] - s[c-8];
+            int y = s[c+7] + s[c-8];
+
+            sum  += x;
+            sumsq += x * y;
+
+            d[c&15] = s[c];
+
+            if (sumsq * 15 - sum * sum < flimit)
+            {
+                d[c&15] = (8 + sum + s[c]) >> 4;
+            }
+
+            s[c-8] = d[(c-8)&15];
+        }
+
+        s += pitch;
+    }
+}
+
+
+
+
+
+void vp8_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols, int flimit)
+{
+    int r, c, i;
+    const short *rv3 = &vp8_rv[63&rand()];
+
+    for (c = 0; c < cols; c++)
+    {
+        unsigned char *s = &dst[c];
+        int sumsq = 0;
+        int sum   = 0;
+        unsigned char d[16];
+        const short *rv2 = rv3 + ((c * 17) & 127);
+
+        for (i = -8; i <= 6; i++)
+        {
+            sumsq += s[i*pitch] * s[i*pitch];
+            sum   += s[i*pitch];
+        }
+
+        for (r = 0; r < rows + 8; r++)
+        {
+            sumsq += s[7*pitch] * s[ 7*pitch] - s[-8*pitch] * s[-8*pitch];
+            sum  += s[7*pitch] - s[-8*pitch];
+            d[r&15] = s[0];
+
+            if (sumsq * 15 - sum * sum < flimit)
+            {
+                d[r&15] = (rv2[r&127] + sum + s[0]) >> 4;
+            }
+
+            s[-8*pitch] = d[(r-8)&15];
+            s += pitch;
+        }
+    }
+}
+
+
+static void vp8_deblock_and_de_macro_block(YV12_BUFFER_CONFIG         *source,
+        YV12_BUFFER_CONFIG         *post,
+        int                         q,
+        int                         low_var_thresh,
+        int                         flag,
+        vp8_postproc_rtcd_vtable_t *rtcd)
+{
+    double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
+    int ppl = (int)(level + .5);
+    (void) low_var_thresh;
+    (void) flag;
+
+    POSTPROC_INVOKE(rtcd, downacross)(source->y_buffer, post->y_buffer, source->y_stride,  post->y_stride, source->y_height, source->y_width,  ppl);
+    POSTPROC_INVOKE(rtcd, across)(post->y_buffer, post->y_stride, post->y_height, post->y_width, vp8_q2mbl(q));
+    POSTPROC_INVOKE(rtcd, down)(post->y_buffer, post->y_stride, post->y_height, post->y_width, vp8_q2mbl(q));
+
+    POSTPROC_INVOKE(rtcd, downacross)(source->u_buffer, post->u_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
+    POSTPROC_INVOKE(rtcd, downacross)(source->v_buffer, post->v_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
+
+}
+
+extern void vp8_deblock(YV12_BUFFER_CONFIG         *source,
+                        YV12_BUFFER_CONFIG         *post,
+                        int                         q,
+                        int                         low_var_thresh,
+                        int                         flag,
+                        vp8_postproc_rtcd_vtable_t *rtcd)
+{
+    double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
+    int ppl = (int)(level + .5);
+    (void) low_var_thresh;
+    (void) flag;
+
+    POSTPROC_INVOKE(rtcd, downacross)(source->y_buffer, post->y_buffer, source->y_stride,  post->y_stride, source->y_height, source->y_width,   ppl);
+    POSTPROC_INVOKE(rtcd, downacross)(source->u_buffer, post->u_buffer, source->uv_stride, post->uv_stride,  source->uv_height, source->uv_width, ppl);
+    POSTPROC_INVOKE(rtcd, downacross)(source->v_buffer, post->v_buffer, source->uv_stride, post->uv_stride, source->uv_height, source->uv_width, ppl);
+}
+
+void vp8_de_noise(YV12_BUFFER_CONFIG         *source,
+                  YV12_BUFFER_CONFIG         *post,
+                  int                         q,
+                  int                         low_var_thresh,
+                  int                         flag,
+                  vp8_postproc_rtcd_vtable_t *rtcd)
+{
+    double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
+    int ppl = (int)(level + .5);
+    (void) post;
+    (void) low_var_thresh;
+    (void) flag;
+
+    POSTPROC_INVOKE(rtcd, downacross)(
+        source->y_buffer + 2 * source->y_stride + 2,
+        source->y_buffer + 2 * source->y_stride + 2,
+        source->y_stride,
+        source->y_stride,
+        source->y_height - 4,
+        source->y_width - 4,
+        ppl);
+    POSTPROC_INVOKE(rtcd, downacross)(
+        source->u_buffer + 2 * source->uv_stride + 2,
+        source->u_buffer + 2 * source->uv_stride + 2,
+        source->uv_stride,
+        source->uv_stride,
+        source->uv_height - 4,
+        source->uv_width - 4, ppl);
+    POSTPROC_INVOKE(rtcd, downacross)(
+        source->v_buffer + 2 * source->uv_stride + 2,
+        source->v_buffer + 2 * source->uv_stride + 2,
+        source->uv_stride,
+        source->uv_stride,
+        source->uv_height - 4,
+        source->uv_width - 4, ppl);
+
+}
+
+
+//Notes: It is better to change CHAR to unsigned or signed to
+//avoid error on ARM platform.
+char vp8_an[8][64][3072];
+int vp8_cd[8][64];
+
+
+double vp8_gaussian(double sigma, double mu, double x)
+{
+    return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
+           (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
+}
+
+extern void (*vp8_clear_system_state)(void);
+
+
+static void fillrd(struct postproc_state *state, int q, int a)
+{
+    char char_dist[300];
+
+    double sigma;
+    int ai = a, qi = q, i;
+
+    vp8_clear_system_state();
+
+
+    sigma = ai + .5 + .6 * (63 - qi) / 63.0;
+
+    // set up a lookup table of 256 entries that matches
+    // a gaussian distribution with sigma determined by q.
+    //
+    {
+        double i;
+        int next, j;
+
+        next = 0;
+
+        for (i = -32; i < 32; i++)
+        {
+            int a = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i));
+
+            if (a)
+            {
+                for (j = 0; j < a; j++)
+                {
+                    char_dist[next+j] = (char) i;
+                }
+
+                next = next + j;
+            }
+
+        }
+
+        for (next = next; next < 256; next++)
+            char_dist[next] = 0;
+
+    }
+
+    for (i = 0; i < 3072; i++)
+    {
+        state->noise[i] = char_dist[rand() & 0xff];
+    }
+
+    for (i = 0; i < 16; i++)
+    {
+        state->blackclamp[i] = -char_dist[0];
+        state->whiteclamp[i] = -char_dist[0];
+        state->bothclamp[i] = -2 * char_dist[0];
+    }
+
+    state->last_q = q;
+    state->last_noise = a;
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : plane_add_noise_c
+ *
+ *  INPUTS        : unsigned char *Start    starting address of buffer to add gaussian
+ *                                  noise to
+ *                  unsigned int Width    width of plane
+ *                  unsigned int Height   height of plane
+ *                  int  Pitch    distance between subsequent lines of frame
+ *                  int  q        quantizer used to determine amount of noise
+ *                                  to add
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void.
+ *
+ *  FUNCTION      : adds gaussian noise to a plane of pixels
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+void vp8_plane_add_noise_c(unsigned char *Start, char *noise,
+                           char blackclamp[16],
+                           char whiteclamp[16],
+                           char bothclamp[16],
+                           unsigned int Width, unsigned int Height, int Pitch)
+{
+    unsigned int i, j;
+
+    for (i = 0; i < Height; i++)
+    {
+        unsigned char *Pos = Start + i * Pitch;
+        char  *Ref = (char *)(noise + (rand() & 0xff));
+
+        for (j = 0; j < Width; j++)
+        {
+            if (Pos[j] < blackclamp[0])
+                Pos[j] = blackclamp[0];
+
+            if (Pos[j] > 255 + whiteclamp[0])
+                Pos[j] = 255 + whiteclamp[0];
+
+            Pos[j] += Ref[j];
+        }
+    }
+}
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define RTCD_VTABLE(oci) (&(oci)->rtcd.postproc)
+#else
+#define RTCD_VTABLE(oci) NULL
+#endif
+
+int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest, int deblock_level, int noise_level, int flags)
+{
+    char message[512];
+    int q = oci->filter_level * 10 / 6;
+
+    if (!oci->frame_to_show)
+        return -1;
+
+    if (q > 63)
+        q = 63;
+
+    if (!flags)
+    {
+        *dest = *oci->frame_to_show;
+
+        // handle problem with extending borders
+        dest->y_width = oci->Width;
+        dest->y_height = oci->Height;
+        dest->uv_height = dest->y_height / 2;
+        return 0;
+
+    }
+
+#if ARCH_X86||ARCH_X86_64
+    vpx_reset_mmx_state();
+#endif
+
+    if (flags & VP8D_DEMACROBLOCK)
+    {
+        vp8_deblock_and_de_macro_block(oci->frame_to_show, &oci->post_proc_buffer,
+                                       q + (deblock_level - 5) * 10, 1, 0, RTCD_VTABLE(oci));
+    }
+    else if (flags & VP8D_DEBLOCK)
+    {
+        vp8_deblock(oci->frame_to_show, &oci->post_proc_buffer,
+                    q, 1, 0, RTCD_VTABLE(oci));
+    }
+    else
+    {
+        vp8_yv12_copy_frame_ptr(oci->frame_to_show, &oci->post_proc_buffer);
+    }
+
+    if (flags & VP8D_ADDNOISE)
+    {
+        if (oci->postproc_state.last_q != q
+            || oci->postproc_state.last_noise != noise_level)
+        {
+            fillrd(&oci->postproc_state, 63 - q, noise_level);
+        }
+
+        POSTPROC_INVOKE(RTCD_VTABLE(oci), addnoise)
+        (oci->post_proc_buffer.y_buffer,
+         oci->postproc_state.noise,
+         oci->postproc_state.blackclamp,
+         oci->postproc_state.whiteclamp,
+         oci->postproc_state.bothclamp,
+         oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
+         oci->post_proc_buffer.y_stride);
+    }
+
+    if (flags & VP8D_DEBUG_LEVEL1)
+    {
+        sprintf(message, "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
+                (oci->frame_type == KEY_FRAME),
+                oci->refresh_golden_frame,
+                oci->base_qindex,
+                oci->filter_level,
+                flags,
+                oci->mb_cols, oci->mb_rows);
+        vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
+    }
+    else if (flags & VP8D_DEBUG_LEVEL2)
+    {
+        int i, j;
+        unsigned char *y_ptr;
+        YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
+        int mb_rows = post->y_height >> 4;
+        int mb_cols = post->y_width  >> 4;
+        int mb_index = 0;
+        MODE_INFO *mi = oci->mi;
+
+        y_ptr = post->y_buffer + 4 * post->y_stride + 4;
+
+        // vp8_filter each macro block
+        for (i = 0; i < mb_rows; i++)
+        {
+            for (j = 0; j < mb_cols; j++)
+            {
+                char zz[4];
+
+                sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
+
+                vp8_blit_text(zz, y_ptr, post->y_stride);
+                mb_index ++;
+                y_ptr += 16;
+            }
+
+            mb_index ++; //border
+            y_ptr += post->y_stride  * 16 - post->y_width;
+
+        }
+    }
+    else if (flags & VP8D_DEBUG_LEVEL3)
+    {
+        int i, j;
+        unsigned char *y_ptr;
+        YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
+        int mb_rows = post->y_height >> 4;
+        int mb_cols = post->y_width  >> 4;
+        int mb_index = 0;
+        MODE_INFO *mi = oci->mi;
+
+        y_ptr = post->y_buffer + 4 * post->y_stride + 4;
+
+        // vp8_filter each macro block
+        for (i = 0; i < mb_rows; i++)
+        {
+            for (j = 0; j < mb_cols; j++)
+            {
+                char zz[4];
+
+                if (oci->frame_type == KEY_FRAME)
+                    sprintf(zz, "a");
+                else
+                    sprintf(zz, "%c", mi[mb_index].mbmi.dc_diff + '0');
+
+                vp8_blit_text(zz, y_ptr, post->y_stride);
+                mb_index ++;
+                y_ptr += 16;
+            }
+
+            mb_index ++; //border
+            y_ptr += post->y_stride  * 16 - post->y_width;
+
+        }
+    }
+    else if (flags & VP8D_DEBUG_LEVEL4)
+    {
+        sprintf(message, "Bitrate: %10.2f frame_rate: %10.2f ", oci->bitrate, oci->framerate);
+        vp8_blit_text(message, oci->post_proc_buffer.y_buffer, oci->post_proc_buffer.y_stride);
+#if 0
+        int i, j;
+        unsigned char *y_ptr;
+        YV12_BUFFER_CONFIG *post = &oci->post_proc_buffer;
+        int mb_rows = post->y_height >> 4;
+        int mb_cols = post->y_width  >> 4;
+        int mb_index = 0;
+        MODE_INFO *mi = oci->mi;
+
+        y_ptr = post->y_buffer + 4 * post->y_stride + 4;
+
+        // vp8_filter each macro block
+        for (i = 0; i < mb_rows; i++)
+        {
+            for (j = 0; j < mb_cols; j++)
+            {
+                char zz[4];
+
+                sprintf(zz, "%c", mi[mb_index].mbmi.dc_diff + '0');
+                vp8_blit_text(zz, y_ptr, post->y_stride);
+                mb_index ++;
+                y_ptr += 16;
+            }
+
+            mb_index ++; //border
+            y_ptr += post->y_stride  * 16 - post->y_width;
+
+        }
+
+#endif
+
+    }
+
+
+
+    *dest = oci->post_proc_buffer;
+
+    // handle problem with extending borders
+    dest->y_width = oci->Width;
+    dest->y_height = oci->Height;
+    dest->uv_height = dest->y_height / 2;
+    return 0;
+}
diff --git a/vp8/common/postproc.h b/vp8/common/postproc.h
new file mode 100644
index 0000000..c45fe92
--- /dev/null
+++ b/vp8/common/postproc.h
@@ -0,0 +1,90 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef POSTPROC_H
+#define POSTPROC_H
+
+#define prototype_postproc_inplace(sym)\
+    void sym (unsigned char *dst, int pitch, int rows, int cols,int flimit)
+
+#define prototype_postproc(sym)\
+    void sym (unsigned char *src, unsigned char *dst, int src_pitch,\
+              int dst_pitch, int rows, int cols, int flimit)
+
+#define prototype_postproc_addnoise(sym) \
+    void sym (unsigned char *s, char *noise, char blackclamp[16],\
+              char whiteclamp[16], char bothclamp[16],\
+              unsigned int w, unsigned int h, int pitch)
+
+#if ARCH_X86 || ARCH_X86_64
+#include "x86/postproc_x86.h"
+#endif
+
+#ifndef vp8_postproc_down
+#define vp8_postproc_down vp8_mbpost_proc_down_c
+#endif
+extern prototype_postproc_inplace(vp8_postproc_down);
+
+#ifndef vp8_postproc_across
+#define vp8_postproc_across vp8_mbpost_proc_across_ip_c
+#endif
+extern prototype_postproc_inplace(vp8_postproc_across);
+
+#ifndef vp8_postproc_downacross
+#define vp8_postproc_downacross vp8_post_proc_down_and_across_c
+#endif
+extern prototype_postproc(vp8_postproc_downacross);
+
+#ifndef vp8_postproc_addnoise
+#define vp8_postproc_addnoise vp8_plane_add_noise_c
+#endif
+extern prototype_postproc_addnoise(vp8_postproc_addnoise);
+
+
+typedef prototype_postproc((*vp8_postproc_fn_t));
+typedef prototype_postproc_inplace((*vp8_postproc_inplace_fn_t));
+typedef prototype_postproc_addnoise((*vp8_postproc_addnoise_fn_t));
+typedef struct
+{
+    vp8_postproc_inplace_fn_t   down;
+    vp8_postproc_inplace_fn_t   across;
+    vp8_postproc_fn_t           downacross;
+    vp8_postproc_addnoise_fn_t  addnoise;
+} vp8_postproc_rtcd_vtable_t;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define POSTPROC_INVOKE(ctx,fn) (ctx)->fn
+#else
+#define POSTPROC_INVOKE(ctx,fn) vp8_postproc_##fn
+#endif
+
+#include "vpx_ports/mem.h"
+struct postproc_state
+{
+    int           last_q;
+    int           last_noise;
+    char          noise[3072];
+    DECLARE_ALIGNED(16, char, blackclamp[16]);
+    DECLARE_ALIGNED(16, char, whiteclamp[16]);
+    DECLARE_ALIGNED(16, char, bothclamp[16]);
+};
+#include "onyxc_int.h"
+#include "ppflags.h"
+int vp8_post_proc_frame(struct VP8Common *oci, YV12_BUFFER_CONFIG *dest,
+                        int deblock_level, int noise_level, int flags);
+
+
+void vp8_de_noise(YV12_BUFFER_CONFIG         *source,
+                  YV12_BUFFER_CONFIG         *post,
+                  int                         q,
+                  int                         low_var_thresh,
+                  int                         flag,
+                  vp8_postproc_rtcd_vtable_t *rtcd);
+#endif
diff --git a/vp8/common/ppc/copy_altivec.asm b/vp8/common/ppc/copy_altivec.asm
new file mode 100644
index 0000000..e87eb21
--- /dev/null
+++ b/vp8/common/ppc/copy_altivec.asm
@@ -0,0 +1,46 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl copy_mem16x16_ppc
+
+;# r3 unsigned char *src
+;# r4 int src_stride
+;# r5 unsigned char *dst
+;# r6 int dst_stride
+
+;# Make the assumption that input will not be aligned,
+;#  but the output will be.  So two reads and a perm
+;#  for the input, but only one store for the output.
+copy_mem16x16_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xe000
+    mtspr   256, r12            ;# set VRSAVE
+
+    li      r10, 16
+    mtctr   r10
+
+cp_16x16_loop:
+    lvsl    v0,  0, r3          ;# permutate value for alignment
+
+    lvx     v1,   0, r3
+    lvx     v2, r10, r3
+
+    vperm   v1, v1, v2, v0
+
+    stvx    v1,  0, r5
+
+    add     r3, r3, r4          ;# increment source pointer
+    add     r5, r5, r6          ;# increment destination pointer
+
+    bdnz    cp_16x16_loop
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
diff --git a/vp8/common/ppc/filter_altivec.asm b/vp8/common/ppc/filter_altivec.asm
new file mode 100644
index 0000000..2a35507
--- /dev/null
+++ b/vp8/common/ppc/filter_altivec.asm
@@ -0,0 +1,1012 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl sixtap_predict_ppc
+    .globl sixtap_predict8x4_ppc
+    .globl sixtap_predict8x8_ppc
+    .globl sixtap_predict16x16_ppc
+
+.macro load_c V, LABEL, OFF, R0, R1
+    lis     \R0, \LABEL@ha
+    la      \R1, \LABEL@l(\R0)
+    lvx     \V, \OFF, \R1
+.endm
+
+.macro load_hfilter V0, V1
+    load_c \V0, HFilter, r5, r9, r10
+
+    addi    r5,  r5, 16
+    lvx     \V1, r5, r10
+.endm
+
+;# Vertical filtering
+.macro Vprolog
+    load_c v0, VFilter, r6, r3, r10
+
+    vspltish v5, 8
+    vspltish v6, 3
+    vslh    v6, v5, v6      ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    vspltb  v1, v0, 1
+    vspltb  v2, v0, 2
+    vspltb  v3, v0, 3
+    vspltb  v4, v0, 4
+    vspltb  v5, v0, 5
+    vspltb  v0, v0, 0
+.endm
+
+.macro vpre_load
+    Vprolog
+    li      r10,  16
+    lvx     v10,   0, r9    ;# v10..v14 = first 5 rows
+    lvx     v11, r10, r9
+    addi    r9,   r9, 32
+    lvx     v12,   0, r9
+    lvx     v13, r10, r9
+    addi    r9,   r9, 32
+    lvx     v14,   0, r9
+.endm
+
+.macro Msum Re, Ro, V, T, TMP
+                                ;# (Re,Ro) += (V*T)
+    vmuleub \TMP, \V, \T        ;# trashes v8
+    vadduhm \Re, \Re, \TMP      ;# Re = evens, saturation unnecessary
+    vmuloub \TMP, \V, \T
+    vadduhm \Ro, \Ro, \TMP      ;# Ro = odds
+.endm
+
+.macro vinterp_no_store P0 P1 P2 P3 P4 P5
+    vmuleub  v8, \P0, v0        ;# 64 + 4 positive taps
+    vadduhm v16, v6, v8
+    vmuloub  v8, \P0, v0
+    vadduhm v17, v6, v8
+    Msum v16, v17, \P2, v2, v8
+    Msum v16, v17, \P3, v3, v8
+    Msum v16, v17, \P5, v5, v8
+
+    vmuleub v18, \P1, v1        ;# 2 negative taps
+    vmuloub v19, \P1, v1
+    Msum v18, v19, \P4, v4, v8
+
+    vsubuhs v16, v16, v18       ;# subtract neg from pos
+    vsubuhs v17, v17, v19
+    vsrh    v16, v16, v7        ;# divide by 128
+    vsrh    v17, v17, v7        ;# v16 v17 = evens, odds
+    vmrghh  v18, v16, v17       ;# v18 v19 = 16-bit result in order
+    vmrglh  v19, v16, v17
+    vpkuhus  \P0, v18, v19      ;# P0 = 8-bit result
+.endm
+
+.macro vinterp_no_store_8x8 P0 P1 P2 P3 P4 P5
+    vmuleub v24, \P0, v13       ;# 64 + 4 positive taps
+    vadduhm v21, v20, v24
+    vmuloub v24, \P0, v13
+    vadduhm v22, v20, v24
+    Msum v21, v22, \P2, v15, v25
+    Msum v21, v22, \P3, v16, v25
+    Msum v21, v22, \P5, v18, v25
+
+    vmuleub v23, \P1, v14       ;# 2 negative taps
+    vmuloub v24, \P1, v14
+    Msum v23, v24, \P4, v17, v25
+
+    vsubuhs v21, v21, v23       ;# subtract neg from pos
+    vsubuhs v22, v22, v24
+    vsrh    v21, v21, v19       ;# divide by 128
+    vsrh    v22, v22, v19       ;# v16 v17 = evens, odds
+    vmrghh  v23, v21, v22       ;# v18 v19 = 16-bit result in order
+    vmrglh  v24, v21, v22
+    vpkuhus \P0, v23, v24       ;# P0 = 8-bit result
+.endm
+
+
+.macro Vinterp P0 P1 P2 P3 P4 P5
+    vinterp_no_store \P0, \P1, \P2, \P3, \P4, \P5
+    stvx    \P0, 0, r7
+    add     r7, r7, r8      ;# 33 ops per 16 pels
+.endm
+
+
+.macro luma_v P0, P1, P2, P3, P4, P5
+    addi    r9,   r9, 16        ;# P5 = newest input row
+    lvx     \P5,   0, r9
+    Vinterp \P0, \P1, \P2, \P3, \P4, \P5
+.endm
+
+.macro luma_vtwo
+    luma_v v10, v11, v12, v13, v14, v15
+    luma_v v11, v12, v13, v14, v15, v10
+.endm
+
+.macro luma_vfour
+    luma_vtwo
+    luma_v v12, v13, v14, v15, v10, v11
+    luma_v v13, v14, v15, v10, v11, v12
+.endm
+
+.macro luma_vsix
+    luma_vfour
+    luma_v v14, v15, v10, v11, v12, v13
+    luma_v v15, v10, v11, v12, v13, v14
+.endm
+
+.macro Interp4 R I I4
+    vmsummbm \R, v13, \I, v15
+    vmsummbm \R, v14, \I4, \R
+.endm
+
+.macro Read8x8 VD, RS, RP, increment_counter
+    lvsl    v21,  0, \RS        ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     \VD,   0, \RS
+    lvx     v20, r10, \RS
+
+.if \increment_counter
+    add     \RS, \RS, \RP
+.endif
+
+    vperm   \VD, \VD, v20, v21
+.endm
+
+.macro interp_8x8 R
+    vperm   v20, \R, \R, v16    ;# v20 = 0123 1234 2345 3456
+    vperm   v21, \R, \R, v17    ;# v21 = 4567 5678 6789 789A
+    Interp4 v20, v20,  v21      ;# v20 = result 0 1 2 3
+    vperm   \R, \R, \R, v18     ;# R   = 89AB 9ABC ABCx BCxx
+    Interp4 v21, v21, \R        ;# v21 = result 4 5 6 7
+
+    vpkswus \R, v20, v21        ;#  R = 0 1 2 3 4 5 6 7
+    vsrh    \R, \R, v19
+
+    vpkuhus \R, \R, \R          ;# saturate and pack
+
+.endm
+
+.macro Read4x4 VD, RS, RP, increment_counter
+    lvsl    v21,  0, \RS        ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v20,   0, \RS
+
+.if \increment_counter
+    add     \RS, \RS, \RP
+.endif
+
+    vperm   \VD, v20, v20, v21
+.endm
+    .text
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+sixtap_predict_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xff87
+    ori     r12, r12, 0xffc0
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    slwi.   r5, r5, 5           ;# index into horizontal filter array
+
+    vspltish v19, 7
+
+    ;# If there isn't any filtering to be done for the horizontal, then
+    ;#  just skip to the second pass.
+    beq-    vertical_only_4x4
+
+    ;# load up horizontal filter
+    load_hfilter v13, v14
+
+    ;# rounding added in on the multiply
+    vspltisw v16, 8
+    vspltisw v15, 3
+    vslw    v15, v16, v15       ;# 0x00000040000000400000004000000040
+
+    ;# Load up permutation constants
+    load_c v16, B_0123, 0, r9, r10
+    load_c v17, B_4567, 0, r9, r10
+    load_c v18, B_89AB, 0, r9, r10
+
+    ;# Back off input buffer by 2 bytes.  Need 2 before and 3 after
+    addi    r3, r3, -2
+
+    addi    r9, r3, 0
+    li      r10, 16
+    Read8x8 v2, r3, r4, 1
+    Read8x8 v3, r3, r4, 1
+    Read8x8 v4, r3, r4, 1
+    Read8x8 v5, r3, r4, 1
+
+    slwi.   r6, r6, 4           ;# index into vertical filter array
+
+    ;# filter a line
+    interp_8x8 v2
+    interp_8x8 v3
+    interp_8x8 v4
+    interp_8x8 v5
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional 5 lines that are needed
+    ;#  for the vertical filter.
+    beq-    store_4x4
+
+    ;# only needed if there is a vertical filter present
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r9, r9, r4
+    sub     r9, r9, r4
+
+    Read8x8 v0, r9, r4, 1
+    Read8x8 v1, r9, r4, 0
+    Read8x8 v6, r3, r4, 1
+    Read8x8 v7, r3, r4, 1
+    Read8x8 v8, r3, r4, 0
+
+    interp_8x8 v0
+    interp_8x8 v1
+    interp_8x8 v6
+    interp_8x8 v7
+    interp_8x8 v8
+
+    b       second_pass_4x4
+
+vertical_only_4x4:
+    ;# only needed if there is a vertical filter present
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r3, r3, r4
+    sub     r3, r3, r4
+    li      r10, 16
+
+    Read8x8 v0, r3, r4, 1
+    Read8x8 v1, r3, r4, 1
+    Read8x8 v2, r3, r4, 1
+    Read8x8 v3, r3, r4, 1
+    Read8x8 v4, r3, r4, 1
+    Read8x8 v5, r3, r4, 1
+    Read8x8 v6, r3, r4, 1
+    Read8x8 v7, r3, r4, 1
+    Read8x8 v8, r3, r4, 0
+
+    slwi    r6, r6, 4           ;# index into vertical filter array
+
+second_pass_4x4:
+    load_c   v20, b_hilo_4x4, 0, r9, r10
+    load_c   v21, b_hilo, 0, r9, r10
+
+    ;# reposition input so that it can go through the
+    ;# filtering phase with one pass.
+    vperm   v0, v0, v1, v20     ;# 0 1 x x
+    vperm   v2, v2, v3, v20     ;# 2 3 x x
+    vperm   v4, v4, v5, v20     ;# 4 5 x x
+    vperm   v6, v6, v7, v20     ;# 6 7 x x
+
+    vperm   v0, v0, v2, v21     ;# 0 1 2 3
+    vperm   v4, v4, v6, v21     ;# 4 5 6 7
+
+    vsldoi  v1, v0, v4, 4
+    vsldoi  v2, v0, v4, 8
+    vsldoi  v3, v0, v4, 12
+
+    vsldoi  v5, v4, v8, 4
+
+    load_c   v13, VFilter, r6, r9, r10
+
+    vspltish v15, 8
+    vspltish v20, 3
+    vslh    v20, v15, v20       ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    vspltb  v14, v13, 1
+    vspltb  v15, v13, 2
+    vspltb  v16, v13, 3
+    vspltb  v17, v13, 4
+    vspltb  v18, v13, 5
+    vspltb  v13, v13, 0
+
+    vinterp_no_store_8x8 v0, v1, v2, v3, v4, v5
+
+    stvx    v0, 0, r1
+
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    lwz     r0, 4(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    lwz     r0, 8(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    lwz     r0, 12(r1)
+    stw     r0, 0(r7)
+
+    b       exit_4x4
+
+store_4x4:
+
+    stvx    v2, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    stvx    v3, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    stvx    v4, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    stvx    v5, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+
+exit_4x4:
+
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+.macro w_8x8 V, D, R, P
+    stvx    \V, 0, r1
+    lwz     \R, 0(r1)
+    stw     \R, 0(r7)
+    lwz     \R, 4(r1)
+    stw     \R, 4(r7)
+    add     \D, \D, \P
+.endm
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+
+sixtap_predict8x4_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xffc0
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    slwi.   r5, r5, 5           ;# index into horizontal filter array
+
+    vspltish v19, 7
+
+    ;# If there isn't any filtering to be done for the horizontal, then
+    ;#  just skip to the second pass.
+    beq-    second_pass_pre_copy_8x4
+
+    load_hfilter v13, v14
+
+    ;# rounding added in on the multiply
+    vspltisw v16, 8
+    vspltisw v15, 3
+    vslw    v15, v16, v15       ;# 0x00000040000000400000004000000040
+
+    ;# Load up permutation constants
+    load_c v16, B_0123, 0, r9, r10
+    load_c v17, B_4567, 0, r9, r10
+    load_c v18, B_89AB, 0, r9, r10
+
+    ;# Back off input buffer by 2 bytes.  Need 2 before and 3 after
+    addi    r3, r3, -2
+
+    addi    r9, r3, 0
+    li      r10, 16
+    Read8x8 v2, r3, r4, 1
+    Read8x8 v3, r3, r4, 1
+    Read8x8 v4, r3, r4, 1
+    Read8x8 v5, r3, r4, 1
+
+    slwi.   r6, r6, 4           ;# index into vertical filter array
+
+    ;# filter a line
+    interp_8x8 v2
+    interp_8x8 v3
+    interp_8x8 v4
+    interp_8x8 v5
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional 5 lines that are needed
+    ;#  for the vertical filter.
+    beq-    store_8x4
+
+    ;# only needed if there is a vertical filter present
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r9, r9, r4
+    sub     r9, r9, r4
+
+    Read8x8 v0, r9, r4, 1
+    Read8x8 v1, r9, r4, 0
+    Read8x8 v6, r3, r4, 1
+    Read8x8 v7, r3, r4, 1
+    Read8x8 v8, r3, r4, 0
+
+    interp_8x8 v0
+    interp_8x8 v1
+    interp_8x8 v6
+    interp_8x8 v7
+    interp_8x8 v8
+
+    b       second_pass_8x4
+
+second_pass_pre_copy_8x4:
+    ;# only needed if there is a vertical filter present
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r3, r3, r4
+    sub     r3, r3, r4
+    li      r10, 16
+
+    Read8x8 v0,  r3, r4, 1
+    Read8x8 v1,  r3, r4, 1
+    Read8x8 v2,  r3, r4, 1
+    Read8x8 v3,  r3, r4, 1
+    Read8x8 v4,  r3, r4, 1
+    Read8x8 v5,  r3, r4, 1
+    Read8x8 v6,  r3, r4, 1
+    Read8x8 v7,  r3, r4, 1
+    Read8x8 v8,  r3, r4, 1
+
+    slwi    r6, r6, 4           ;# index into vertical filter array
+
+second_pass_8x4:
+    load_c v13, VFilter, r6, r9, r10
+
+    vspltish v15, 8
+    vspltish v20, 3
+    vslh    v20, v15, v20       ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    vspltb  v14, v13, 1
+    vspltb  v15, v13, 2
+    vspltb  v16, v13, 3
+    vspltb  v17, v13, 4
+    vspltb  v18, v13, 5
+    vspltb  v13, v13, 0
+
+    vinterp_no_store_8x8 v0, v1, v2, v3,  v4,  v5
+    vinterp_no_store_8x8 v1, v2, v3, v4,  v5,  v6
+    vinterp_no_store_8x8 v2, v3, v4, v5,  v6,  v7
+    vinterp_no_store_8x8 v3, v4, v5, v6,  v7,  v8
+
+    cmpi    cr0, r8, 8
+    beq     cr0, store_aligned_8x4
+
+    w_8x8   v0, r7, r0, r8
+    w_8x8   v1, r7, r0, r8
+    w_8x8   v2, r7, r0, r8
+    w_8x8   v3, r7, r0, r8
+
+    b       exit_8x4
+
+store_aligned_8x4:
+
+    load_c v10, b_hilo, 0, r9, r10
+
+    vperm   v0, v0, v1, v10
+    vperm   v2, v2, v3, v10
+
+    stvx    v0, 0, r7
+    addi    r7, r7, 16
+    stvx    v2, 0, r7
+
+    b       exit_8x4
+
+store_8x4:
+    cmpi    cr0, r8, 8
+    beq     cr0, store_aligned2_8x4
+
+    w_8x8   v2, r7, r0, r8
+    w_8x8   v3, r7, r0, r8
+    w_8x8   v4, r7, r0, r8
+    w_8x8   v5, r7, r0, r8
+
+    b       exit_8x4
+
+store_aligned2_8x4:
+    load_c v10, b_hilo, 0, r9, r10
+
+    vperm   v2, v2, v3, v10
+    vperm   v4, v4, v5, v10
+
+    stvx    v2, 0, r7
+    addi    r7, r7, 16
+    stvx    v4, 0, r7
+
+exit_8x4:
+
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+
+    blr
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+
+;# Because the width that needs to be filtered will fit in a single altivec
+;#  register there is no need to loop.  Everything can stay in registers.
+sixtap_predict8x8_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xffc0
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    slwi.   r5, r5, 5           ;# index into horizontal filter array
+
+    vspltish v19, 7
+
+    ;# If there isn't any filtering to be done for the horizontal, then
+    ;#  just skip to the second pass.
+    beq-    second_pass_pre_copy_8x8
+
+    load_hfilter v13, v14
+
+    ;# rounding added in on the multiply
+    vspltisw v16, 8
+    vspltisw v15, 3
+    vslw    v15, v16, v15       ;# 0x00000040000000400000004000000040
+
+    ;# Load up permutation constants
+    load_c v16, B_0123, 0, r9, r10
+    load_c v17, B_4567, 0, r9, r10
+    load_c v18, B_89AB, 0, r9, r10
+
+    ;# Back off input buffer by 2 bytes.  Need 2 before and 3 after
+    addi    r3, r3, -2
+
+    addi    r9, r3, 0
+    li      r10, 16
+    Read8x8 v2, r3, r4, 1
+    Read8x8 v3, r3, r4, 1
+    Read8x8 v4, r3, r4, 1
+    Read8x8 v5, r3, r4, 1
+    Read8x8 v6, r3, r4, 1
+    Read8x8 v7, r3, r4, 1
+    Read8x8 v8, r3, r4, 1
+    Read8x8 v9, r3, r4, 1
+
+    slwi.   r6, r6, 4           ;# index into vertical filter array
+
+    ;# filter a line
+    interp_8x8 v2
+    interp_8x8 v3
+    interp_8x8 v4
+    interp_8x8 v5
+    interp_8x8 v6
+    interp_8x8 v7
+    interp_8x8 v8
+    interp_8x8 v9
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional 5 lines that are needed
+    ;#  for the vertical filter.
+    beq-    store_8x8
+
+    ;# only needed if there is a vertical filter present
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r9, r9, r4
+    sub     r9, r9, r4
+
+    Read8x8 v0,  r9, r4, 1
+    Read8x8 v1,  r9, r4, 0
+    Read8x8 v10, r3, r4, 1
+    Read8x8 v11, r3, r4, 1
+    Read8x8 v12, r3, r4, 0
+
+    interp_8x8 v0
+    interp_8x8 v1
+    interp_8x8 v10
+    interp_8x8 v11
+    interp_8x8 v12
+
+    b       second_pass_8x8
+
+second_pass_pre_copy_8x8:
+    ;# only needed if there is a vertical filter present
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r3, r3, r4
+    sub     r3, r3, r4
+    li      r10, 16
+
+    Read8x8 v0,  r3, r4, 1
+    Read8x8 v1,  r3, r4, 1
+    Read8x8 v2,  r3, r4, 1
+    Read8x8 v3,  r3, r4, 1
+    Read8x8 v4,  r3, r4, 1
+    Read8x8 v5,  r3, r4, 1
+    Read8x8 v6,  r3, r4, 1
+    Read8x8 v7,  r3, r4, 1
+    Read8x8 v8,  r3, r4, 1
+    Read8x8 v9,  r3, r4, 1
+    Read8x8 v10, r3, r4, 1
+    Read8x8 v11, r3, r4, 1
+    Read8x8 v12, r3, r4, 0
+
+    slwi    r6, r6, 4           ;# index into vertical filter array
+
+second_pass_8x8:
+    load_c v13, VFilter, r6, r9, r10
+
+    vspltish v15, 8
+    vspltish v20, 3
+    vslh    v20, v15, v20       ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    vspltb  v14, v13, 1
+    vspltb  v15, v13, 2
+    vspltb  v16, v13, 3
+    vspltb  v17, v13, 4
+    vspltb  v18, v13, 5
+    vspltb  v13, v13, 0
+
+    vinterp_no_store_8x8 v0, v1, v2, v3,  v4,  v5
+    vinterp_no_store_8x8 v1, v2, v3, v4,  v5,  v6
+    vinterp_no_store_8x8 v2, v3, v4, v5,  v6,  v7
+    vinterp_no_store_8x8 v3, v4, v5, v6,  v7,  v8
+    vinterp_no_store_8x8 v4, v5, v6, v7,  v8,  v9
+    vinterp_no_store_8x8 v5, v6, v7, v8,  v9,  v10
+    vinterp_no_store_8x8 v6, v7, v8, v9,  v10, v11
+    vinterp_no_store_8x8 v7, v8, v9, v10, v11, v12
+
+    cmpi    cr0, r8, 8
+    beq     cr0, store_aligned_8x8
+
+    w_8x8   v0, r7, r0, r8
+    w_8x8   v1, r7, r0, r8
+    w_8x8   v2, r7, r0, r8
+    w_8x8   v3, r7, r0, r8
+    w_8x8   v4, r7, r0, r8
+    w_8x8   v5, r7, r0, r8
+    w_8x8   v6, r7, r0, r8
+    w_8x8   v7, r7, r0, r8
+
+    b       exit_8x8
+
+store_aligned_8x8:
+
+    load_c v10, b_hilo, 0, r9, r10
+
+    vperm   v0, v0, v1, v10
+    vperm   v2, v2, v3, v10
+    vperm   v4, v4, v5, v10
+    vperm   v6, v6, v7, v10
+
+    stvx    v0, 0, r7
+    addi    r7, r7, 16
+    stvx    v2, 0, r7
+    addi    r7, r7, 16
+    stvx    v4, 0, r7
+    addi    r7, r7, 16
+    stvx    v6, 0, r7
+
+    b       exit_8x8
+
+store_8x8:
+    cmpi    cr0, r8, 8
+    beq     cr0, store_aligned2_8x8
+
+    w_8x8   v2, r7, r0, r8
+    w_8x8   v3, r7, r0, r8
+    w_8x8   v4, r7, r0, r8
+    w_8x8   v5, r7, r0, r8
+    w_8x8   v6, r7, r0, r8
+    w_8x8   v7, r7, r0, r8
+    w_8x8   v8, r7, r0, r8
+    w_8x8   v9, r7, r0, r8
+
+    b       exit_8x8
+
+store_aligned2_8x8:
+    load_c v10, b_hilo, 0, r9, r10
+
+    vperm   v2, v2, v3, v10
+    vperm   v4, v4, v5, v10
+    vperm   v6, v6, v7, v10
+    vperm   v8, v8, v9, v10
+
+    stvx    v2, 0, r7
+    addi    r7, r7, 16
+    stvx    v4, 0, r7
+    addi    r7, r7, 16
+    stvx    v6, 0, r7
+    addi    r7, r7, 16
+    stvx    v8, 0, r7
+
+exit_8x8:
+
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+
+;# Two pass filtering.  First pass is Horizontal edges, second pass is vertical
+;#  edges.  One of the filters can be null, but both won't be.  Needs to use a
+;#  temporary buffer because the source buffer can't be modified and the buffer
+;#  for the destination is not large enough to hold the temporary data.
+sixtap_predict16x16_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xf000
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-416(r1)         ;# create space on the stack
+
+    ;# Three possiblities
+    ;#  1. First filter is null.  Don't use a temp buffer.
+    ;#  2. Second filter is null.  Don't use a temp buffer.
+    ;#  3. Neither are null, use temp buffer.
+
+    ;# First Pass (horizontal edge)
+    ;#  setup pointers for src
+    ;#  if possiblity (1) then setup the src pointer to be the orginal and jump
+    ;#  to second pass.  this is based on if x_offset is 0.
+
+    ;# load up horizontal filter
+    slwi.   r5, r5, 5           ;# index into horizontal filter array
+
+    load_hfilter v4, v5
+
+    beq-    copy_horizontal_16x21
+
+    ;# Back off input buffer by 2 bytes.  Need 2 before and 3 after
+    addi    r3, r3, -2
+
+    slwi.   r6, r6, 4           ;# index into vertical filter array
+
+    ;# setup constants
+    ;# v14 permutation value for alignment
+    load_c v14, b_hperm, 0, r9, r10
+
+    ;# These statements are guessing that there won't be a second pass,
+    ;#  but if there is then inside the bypass they need to be set
+    li      r0, 16              ;# prepare for no vertical filter
+
+    ;# Change the output pointer and pitch to be the actual
+    ;#  desination instead of a temporary buffer.
+    addi    r9, r7, 0
+    addi    r5, r8, 0
+
+    ;# no vertical filter, so write the output from the first pass
+    ;#  directly into the output buffer.
+    beq-    no_vertical_filter_bypass
+
+    ;# if the second filter is not null then need to back off by 2*pitch
+    sub     r3, r3, r4
+    sub     r3, r3, r4
+
+    ;# setup counter for the number of lines that are going to be filtered
+    li      r0, 21
+
+    ;# use the stack as temporary storage
+    la      r9, 48(r1)
+    li      r5, 16
+
+no_vertical_filter_bypass:
+
+    mtctr   r0
+
+    ;# rounding added in on the multiply
+    vspltisw v10, 8
+    vspltisw v12, 3
+    vslw    v12, v10, v12       ;# 0x00000040000000400000004000000040
+
+    ;# downshift by 7 ( divide by 128 ) at the end
+    vspltish v13, 7
+
+    ;# index to the next set of vectors in the row.
+    li      r10, 16
+    li      r12, 32
+
+horizontal_loop_16x16:
+
+    lvsl    v15,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v1,   0, r3
+    lvx     v2, r10, r3
+    lvx     v3, r12, r3
+
+    vperm   v8, v1, v2, v15
+    vperm   v9, v2, v3, v15     ;# v8 v9 = 21 input pixels left-justified
+
+    vsldoi  v11, v8, v9, 4
+
+    ;# set 0
+    vmsummbm v6, v4, v8, v12    ;# taps times elements
+    vmsummbm v0, v5, v11, v6
+
+    ;# set 1
+    vsldoi  v10, v8, v9, 1
+    vsldoi  v11, v8, v9, 5
+
+    vmsummbm v6, v4, v10, v12
+    vmsummbm v1, v5, v11, v6
+
+    ;# set 2
+    vsldoi  v10, v8, v9, 2
+    vsldoi  v11, v8, v9, 6
+
+    vmsummbm v6, v4, v10, v12
+    vmsummbm v2, v5, v11, v6
+
+    ;# set 3
+    vsldoi  v10, v8, v9, 3
+    vsldoi  v11, v8, v9, 7
+
+    vmsummbm v6, v4, v10, v12
+    vmsummbm v3, v5, v11, v6
+
+    vpkswus v0, v0, v1          ;# v0 = 0 4 8 C 1 5 9 D (16-bit)
+    vpkswus v1, v2, v3          ;# v1 = 2 6 A E 3 7 B F
+
+    vsrh    v0, v0, v13         ;# divide v0, v1 by 128
+    vsrh    v1, v1, v13
+
+    vpkuhus v0, v0, v1          ;# v0 = scrambled 8-bit result
+    vperm   v0, v0, v0, v14     ;# v0 = correctly-ordered result
+
+    stvx    v0,  0, r9
+    add     r9, r9, r5
+
+    add     r3, r3, r4
+
+    bdnz    horizontal_loop_16x16
+
+    ;# check again to see if vertical filter needs to be done.
+    cmpi    cr0, r6, 0
+    beq     cr0, end_16x16
+
+    ;# yes there is, so go to the second pass
+    b       second_pass_16x16
+
+copy_horizontal_16x21:
+    li      r10, 21
+    mtctr   r10
+
+    li      r10, 16
+
+    sub     r3, r3, r4
+    sub     r3, r3, r4
+
+    ;# this is done above if there is a horizontal filter,
+    ;#  if not it needs to be done down here.
+    slwi    r6, r6, 4           ;# index into vertical filter array
+
+    ;# always write to the stack when doing a horizontal copy
+    la      r9, 48(r1)
+
+copy_horizontal_loop_16x21:
+    lvsl    v15,  0, r3         ;# permutate value for alignment
+
+    lvx     v1,   0, r3
+    lvx     v2, r10, r3
+
+    vperm   v8, v1, v2, v15
+
+    stvx    v8,  0, r9
+    addi    r9, r9, 16
+
+    add     r3, r3, r4
+
+    bdnz    copy_horizontal_loop_16x21
+
+second_pass_16x16:
+
+    ;# always read from the stack when doing a vertical filter
+    la      r9, 48(r1)
+
+    ;# downshift by 7 ( divide by 128 ) at the end
+    vspltish v7, 7
+
+    vpre_load
+
+    luma_vsix
+    luma_vsix
+    luma_vfour
+
+end_16x16:
+
+    addi    r1, r1, 416         ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .data
+
+    .align 4
+HFilter:
+    .byte     0,  0,128,  0,  0,  0,128,  0,  0,  0,128,  0,  0,  0,128,  0
+    .byte     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     0, -6,123, 12,  0, -6,123, 12,  0, -6,123, 12,  0, -6,123, 12
+    .byte    -1,  0,  0,  0, -1,  0,  0,  0, -1,  0,  0,  0, -1,  0,  0,  0
+    .byte     2,-11,108, 36,  2,-11,108, 36,  2,-11,108, 36,  2,-11,108, 36
+    .byte    -8,  1,  0,  0, -8,  1,  0,  0, -8,  1,  0,  0, -8,  1,  0,  0
+    .byte     0, -9, 93, 50,  0, -9, 93, 50,  0, -9, 93, 50,  0, -9, 93, 50
+    .byte    -6,  0,  0,  0, -6,  0,  0,  0, -6,  0,  0,  0, -6,  0,  0,  0
+    .byte     3,-16, 77, 77,  3,-16, 77, 77,  3,-16, 77, 77,  3,-16, 77, 77
+    .byte   -16,  3,  0,  0,-16,  3,  0,  0,-16,  3,  0,  0,-16,  3,  0,  0
+    .byte     0, -6, 50, 93,  0, -6, 50, 93,  0, -6, 50, 93,  0, -6, 50, 93
+    .byte    -9,  0,  0,  0, -9,  0,  0,  0, -9,  0,  0,  0, -9,  0,  0,  0
+    .byte     1, -8, 36,108,  1, -8, 36,108,  1, -8, 36,108,  1, -8, 36,108
+    .byte   -11,  2,  0,  0,-11,  2,  0,  0,-11,  2,  0,  0,-11,  2,  0,  0
+    .byte     0, -1, 12,123,  0, -1, 12,123,  0, -1, 12,123,  0, -1, 12,123
+    .byte    -6,  0,  0,  0, -6,  0,  0,  0, -6,  0,  0,  0, -6,  0,  0,  0
+
+    .align 4
+VFilter:
+    .byte     0,  0,128,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     0,  6,123, 12,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     2, 11,108, 36,  8,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     0,  9, 93, 50,  6,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     3, 16, 77, 77, 16,  3,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     0,  6, 50, 93,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     1,  8, 36,108, 11,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte     0,  1, 12,123,  6,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+
+    .align 4
+b_hperm:
+    .byte     0,  4,  8, 12,  1,  5,  9, 13,  2,  6, 10, 14,  3,  7, 11, 15
+
+    .align 4
+B_0123:
+    .byte     0,  1,  2,  3,  1,  2,  3,  4,  2,  3,  4,  5,  3,  4,  5,  6
+
+    .align 4
+B_4567:
+    .byte     4,  5,  6,  7,  5,  6,  7,  8,  6,  7,  8,  9,  7,  8,  9, 10
+
+    .align 4
+B_89AB:
+    .byte     8,  9, 10, 11,  9, 10, 11, 12, 10, 11, 12, 13, 11, 12, 13, 14
+
+    .align 4
+b_hilo:
+    .byte     0,  1,  2,  3,  4,  5,  6,  7, 16, 17, 18, 19, 20, 21, 22, 23
+
+    .align 4
+b_hilo_4x4:
+    .byte     0,  1,  2,  3, 16, 17, 18, 19,  0,  0,  0,  0,  0,  0,  0,  0
diff --git a/vp8/common/ppc/filter_bilinear_altivec.asm b/vp8/common/ppc/filter_bilinear_altivec.asm
new file mode 100644
index 0000000..27e02a8
--- /dev/null
+++ b/vp8/common/ppc/filter_bilinear_altivec.asm
@@ -0,0 +1,676 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl bilinear_predict4x4_ppc
+    .globl bilinear_predict8x4_ppc
+    .globl bilinear_predict8x8_ppc
+    .globl bilinear_predict16x16_ppc
+
+.macro load_c V, LABEL, OFF, R0, R1
+    lis     \R0, \LABEL@ha
+    la      \R1, \LABEL@l(\R0)
+    lvx     \V, \OFF, \R1
+.endm
+
+.macro load_vfilter V0, V1
+    load_c \V0, vfilter_b, r6, r9, r10
+
+    addi    r6,  r6, 16
+    lvx     \V1, r6, r10
+.endm
+
+.macro HProlog jump_label
+    ;# load up horizontal filter
+    slwi.   r5, r5, 4           ;# index into horizontal filter array
+
+    ;# index to the next set of vectors in the row.
+    li      r10, 16
+    li      r12, 32
+
+    ;# downshift by 7 ( divide by 128 ) at the end
+    vspltish v19, 7
+
+    ;# If there isn't any filtering to be done for the horizontal, then
+    ;#  just skip to the second pass.
+    beq     \jump_label
+
+    load_c v20, hfilter_b, r5, r9, r0
+
+    ;# setup constants
+    ;# v14 permutation value for alignment
+    load_c v28, b_hperm_b, 0, r9, r0
+
+    ;# rounding added in on the multiply
+    vspltisw v21, 8
+    vspltisw v18, 3
+    vslw    v18, v21, v18       ;# 0x00000040000000400000004000000040
+
+    slwi.   r6, r6, 5           ;# index into vertical filter array
+.endm
+
+;# Filters a horizontal line
+;# expects:
+;#  r3  src_ptr
+;#  r4  pitch
+;#  r10 16
+;#  r12 32
+;#  v17 perm intput
+;#  v18 rounding
+;#  v19 shift
+;#  v20 filter taps
+;#  v21 tmp
+;#  v22 tmp
+;#  v23 tmp
+;#  v24 tmp
+;#  v25 tmp
+;#  v26 tmp
+;#  v27 tmp
+;#  v28 perm output
+;#
+.macro HFilter V
+    vperm   v24, v21, v21, v10  ;# v20 = 0123 1234 2345 3456
+    vperm   v25, v21, v21, v11  ;# v21 = 4567 5678 6789 789A
+
+    vmsummbm v24, v20, v24, v18
+    vmsummbm v25, v20, v25, v18
+
+    vpkswus v24, v24, v25       ;# v24 = 0 4 8 C 1 5 9 D (16-bit)
+
+    vsrh    v24, v24, v19       ;# divide v0, v1 by 128
+
+    vpkuhus \V, v24, v24        ;# \V = scrambled 8-bit result
+.endm
+
+.macro hfilter_8 V, increment_counter
+    lvsl    v17,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 9 bytes wide, output is 8 bytes.
+    lvx     v21,   0, r3
+    lvx     v22, r10, r3
+
+.if \increment_counter
+    add     r3, r3, r4
+.endif
+    vperm   v21, v21, v22, v17
+
+    HFilter \V
+.endm
+
+
+.macro load_and_align_8 V, increment_counter
+    lvsl    v17,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v21,   0, r3
+    lvx     v22, r10, r3
+
+.if \increment_counter
+    add     r3, r3, r4
+.endif
+
+    vperm   \V, v21, v22, v17
+.endm
+
+.macro write_aligned_8 V, increment_counter
+    stvx    \V,  0, r7
+
+.if \increment_counter
+    add     r7, r7, r8
+.endif
+.endm
+
+.macro vfilter_16 P0 P1
+    vmuleub v22, \P0, v20       ;# 64 + 4 positive taps
+    vadduhm v22, v18, v22
+    vmuloub v23, \P0, v20
+    vadduhm v23, v18, v23
+
+    vmuleub v24, \P1, v21
+    vadduhm v22, v22, v24       ;# Re = evens, saturation unnecessary
+    vmuloub v25, \P1, v21
+    vadduhm v23, v23, v25       ;# Ro = odds
+
+    vsrh    v22, v22, v19       ;# divide by 128
+    vsrh    v23, v23, v19       ;# v16 v17 = evens, odds
+    vmrghh  \P0, v22, v23       ;# v18 v19 = 16-bit result in order
+    vmrglh  v23, v22, v23
+    vpkuhus \P0, \P0, v23       ;# P0 = 8-bit result
+.endm
+
+
+.macro w_8x8 V, D, R, P
+    stvx    \V, 0, r1
+    lwz     \R, 0(r1)
+    stw     \R, 0(r7)
+    lwz     \R, 4(r1)
+    stw     \R, 4(r7)
+    add     \D, \D, \P
+.endm
+
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+bilinear_predict4x4_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xf830
+    ori     r12, r12, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    HProlog second_pass_4x4_pre_copy_b
+
+    ;# Load up permutation constants
+    load_c v10, b_0123_b, 0, r9, r12
+    load_c v11, b_4567_b, 0, r9, r12
+
+    hfilter_8 v0, 1
+    hfilter_8 v1, 1
+    hfilter_8 v2, 1
+    hfilter_8 v3, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     store_out_4x4_b
+
+    hfilter_8 v4, 0
+
+    b   second_pass_4x4_b
+
+second_pass_4x4_pre_copy_b:
+    slwi    r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_8  v0, 1
+    load_and_align_8  v1, 1
+    load_and_align_8  v2, 1
+    load_and_align_8  v3, 1
+    load_and_align_8  v4, 1
+
+second_pass_4x4_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+
+store_out_4x4_b:
+
+    stvx    v0, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    stvx    v1, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    stvx    v2, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+    add     r7, r7, r8
+
+    stvx    v3, 0, r1
+    lwz     r0, 0(r1)
+    stw     r0, 0(r7)
+
+exit_4x4:
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+bilinear_predict8x4_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xf830
+    ori     r12, r12, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    HProlog second_pass_8x4_pre_copy_b
+
+    ;# Load up permutation constants
+    load_c v10, b_0123_b, 0, r9, r12
+    load_c v11, b_4567_b, 0, r9, r12
+
+    hfilter_8 v0, 1
+    hfilter_8 v1, 1
+    hfilter_8 v2, 1
+    hfilter_8 v3, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     store_out_8x4_b
+
+    hfilter_8 v4, 0
+
+    b   second_pass_8x4_b
+
+second_pass_8x4_pre_copy_b:
+    slwi    r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_8  v0, 1
+    load_and_align_8  v1, 1
+    load_and_align_8  v2, 1
+    load_and_align_8  v3, 1
+    load_and_align_8  v4, 1
+
+second_pass_8x4_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+
+store_out_8x4_b:
+
+    cmpi    cr0, r8, 8
+    beq     cr0, store_aligned_8x4_b
+
+    w_8x8   v0, r7, r0, r8
+    w_8x8   v1, r7, r0, r8
+    w_8x8   v2, r7, r0, r8
+    w_8x8   v3, r7, r0, r8
+
+    b       exit_8x4
+
+store_aligned_8x4_b:
+    load_c v10, b_hilo_b, 0, r9, r10
+
+    vperm   v0, v0, v1, v10
+    vperm   v2, v2, v3, v10
+
+    stvx    v0, 0, r7
+    addi    r7, r7, 16
+    stvx    v2, 0, r7
+
+exit_8x4:
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+bilinear_predict8x8_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xfff0
+    ori     r12, r12, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    HProlog second_pass_8x8_pre_copy_b
+
+    ;# Load up permutation constants
+    load_c v10, b_0123_b, 0, r9, r12
+    load_c v11, b_4567_b, 0, r9, r12
+
+    hfilter_8 v0, 1
+    hfilter_8 v1, 1
+    hfilter_8 v2, 1
+    hfilter_8 v3, 1
+    hfilter_8 v4, 1
+    hfilter_8 v5, 1
+    hfilter_8 v6, 1
+    hfilter_8 v7, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     store_out_8x8_b
+
+    hfilter_8 v8, 0
+
+    b   second_pass_8x8_b
+
+second_pass_8x8_pre_copy_b:
+    slwi    r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_8  v0, 1
+    load_and_align_8  v1, 1
+    load_and_align_8  v2, 1
+    load_and_align_8  v3, 1
+    load_and_align_8  v4, 1
+    load_and_align_8  v5, 1
+    load_and_align_8  v6, 1
+    load_and_align_8  v7, 1
+    load_and_align_8  v8, 0
+
+second_pass_8x8_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+    vfilter_16 v4,  v5
+    vfilter_16 v5,  v6
+    vfilter_16 v6,  v7
+    vfilter_16 v7,  v8
+
+store_out_8x8_b:
+
+    cmpi    cr0, r8, 8
+    beq     cr0, store_aligned_8x8_b
+
+    w_8x8   v0, r7, r0, r8
+    w_8x8   v1, r7, r0, r8
+    w_8x8   v2, r7, r0, r8
+    w_8x8   v3, r7, r0, r8
+    w_8x8   v4, r7, r0, r8
+    w_8x8   v5, r7, r0, r8
+    w_8x8   v6, r7, r0, r8
+    w_8x8   v7, r7, r0, r8
+
+    b       exit_8x8
+
+store_aligned_8x8_b:
+    load_c v10, b_hilo_b, 0, r9, r10
+
+    vperm   v0, v0, v1, v10
+    vperm   v2, v2, v3, v10
+    vperm   v4, v4, v5, v10
+    vperm   v6, v6, v7, v10
+
+    stvx    v0, 0, r7
+    addi    r7, r7, 16
+    stvx    v2, 0, r7
+    addi    r7, r7, 16
+    stvx    v4, 0, r7
+    addi    r7, r7, 16
+    stvx    v6, 0, r7
+
+exit_8x8:
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+;# Filters a horizontal line
+;# expects:
+;#  r3  src_ptr
+;#  r4  pitch
+;#  r10 16
+;#  r12 32
+;#  v17 perm intput
+;#  v18 rounding
+;#  v19 shift
+;#  v20 filter taps
+;#  v21 tmp
+;#  v22 tmp
+;#  v23 tmp
+;#  v24 tmp
+;#  v25 tmp
+;#  v26 tmp
+;#  v27 tmp
+;#  v28 perm output
+;#
+.macro hfilter_16 V, increment_counter
+
+    lvsl    v17,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v21,   0, r3
+    lvx     v22, r10, r3
+    lvx     v23, r12, r3
+
+.if \increment_counter
+    add     r3, r3, r4
+.endif
+    vperm   v21, v21, v22, v17
+    vperm   v22, v22, v23, v17  ;# v8 v9 = 21 input pixels left-justified
+
+    ;# set 0
+    vmsummbm v24, v20, v21, v18 ;# taps times elements
+
+    ;# set 1
+    vsldoi  v23, v21, v22, 1
+    vmsummbm v25, v20, v23, v18
+
+    ;# set 2
+    vsldoi  v23, v21, v22, 2
+    vmsummbm v26, v20, v23, v18
+
+    ;# set 3
+    vsldoi  v23, v21, v22, 3
+    vmsummbm v27, v20, v23, v18
+
+    vpkswus v24, v24, v25       ;# v24 = 0 4 8 C 1 5 9 D (16-bit)
+    vpkswus v25, v26, v27       ;# v25 = 2 6 A E 3 7 B F
+
+    vsrh    v24, v24, v19       ;# divide v0, v1 by 128
+    vsrh    v25, v25, v19
+
+    vpkuhus \V, v24, v25        ;# \V = scrambled 8-bit result
+    vperm   \V, \V, v0, v28     ;# \V = correctly-ordered result
+.endm
+
+.macro load_and_align_16 V, increment_counter
+    lvsl    v17,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v21,   0, r3
+    lvx     v22, r10, r3
+
+.if \increment_counter
+    add     r3, r3, r4
+.endif
+
+    vperm   \V, v21, v22, v17
+.endm
+
+.macro write_16 V, increment_counter
+    stvx    \V,  0, r7
+
+.if \increment_counter
+    add     r7, r7, r8
+.endif
+.endm
+
+    .align 2
+;# r3 unsigned char * src
+;# r4 int src_pitch
+;# r5 int x_offset
+;# r6 int y_offset
+;# r7 unsigned char * dst
+;# r8 int dst_pitch
+bilinear_predict16x16_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    HProlog second_pass_16x16_pre_copy_b
+
+    hfilter_16 v0,  1
+    hfilter_16 v1,  1
+    hfilter_16 v2,  1
+    hfilter_16 v3,  1
+    hfilter_16 v4,  1
+    hfilter_16 v5,  1
+    hfilter_16 v6,  1
+    hfilter_16 v7,  1
+    hfilter_16 v8,  1
+    hfilter_16 v9,  1
+    hfilter_16 v10, 1
+    hfilter_16 v11, 1
+    hfilter_16 v12, 1
+    hfilter_16 v13, 1
+    hfilter_16 v14, 1
+    hfilter_16 v15, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     store_out_16x16_b
+
+    hfilter_16 v16, 0
+
+    b   second_pass_16x16_b
+
+second_pass_16x16_pre_copy_b:
+    slwi    r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_16  v0,  1
+    load_and_align_16  v1,  1
+    load_and_align_16  v2,  1
+    load_and_align_16  v3,  1
+    load_and_align_16  v4,  1
+    load_and_align_16  v5,  1
+    load_and_align_16  v6,  1
+    load_and_align_16  v7,  1
+    load_and_align_16  v8,  1
+    load_and_align_16  v9,  1
+    load_and_align_16  v10, 1
+    load_and_align_16  v11, 1
+    load_and_align_16  v12, 1
+    load_and_align_16  v13, 1
+    load_and_align_16  v14, 1
+    load_and_align_16  v15, 1
+    load_and_align_16  v16, 0
+
+second_pass_16x16_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+    vfilter_16 v4,  v5
+    vfilter_16 v5,  v6
+    vfilter_16 v6,  v7
+    vfilter_16 v7,  v8
+    vfilter_16 v8,  v9
+    vfilter_16 v9,  v10
+    vfilter_16 v10, v11
+    vfilter_16 v11, v12
+    vfilter_16 v12, v13
+    vfilter_16 v13, v14
+    vfilter_16 v14, v15
+    vfilter_16 v15, v16
+
+store_out_16x16_b:
+
+    write_16 v0,  1
+    write_16 v1,  1
+    write_16 v2,  1
+    write_16 v3,  1
+    write_16 v4,  1
+    write_16 v5,  1
+    write_16 v6,  1
+    write_16 v7,  1
+    write_16 v8,  1
+    write_16 v9,  1
+    write_16 v10, 1
+    write_16 v11, 1
+    write_16 v12, 1
+    write_16 v13, 1
+    write_16 v14, 1
+    write_16 v15, 0
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .data
+
+    .align 4
+hfilter_b:
+    .byte   128,  0,  0,  0,128,  0,  0,  0,128,  0,  0,  0,128,  0,  0,  0
+    .byte   112, 16,  0,  0,112, 16,  0,  0,112, 16,  0,  0,112, 16,  0,  0
+    .byte    96, 32,  0,  0, 96, 32,  0,  0, 96, 32,  0,  0, 96, 32,  0,  0
+    .byte    80, 48,  0,  0, 80, 48,  0,  0, 80, 48,  0,  0, 80, 48,  0,  0
+    .byte    64, 64,  0,  0, 64, 64,  0,  0, 64, 64,  0,  0, 64, 64,  0,  0
+    .byte    48, 80,  0,  0, 48, 80,  0,  0, 48, 80,  0,  0, 48, 80,  0,  0
+    .byte    32, 96,  0,  0, 32, 96,  0,  0, 32, 96,  0,  0, 32, 96,  0,  0
+    .byte    16,112,  0,  0, 16,112,  0,  0, 16,112,  0,  0, 16,112,  0,  0
+
+    .align 4
+vfilter_b:
+    .byte   128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128
+    .byte     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte   112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112
+    .byte    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+    .byte    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96
+    .byte    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
+    .byte    80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
+    .byte    48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
+    .byte    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+    .byte    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+    .byte    48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
+    .byte    80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
+    .byte    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
+    .byte    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96
+    .byte    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+    .byte   112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112
+
+    .align 4
+b_hperm_b:
+    .byte     0,  4,  8, 12,  1,  5,  9, 13,  2,  6, 10, 14,  3,  7, 11, 15
+
+    .align 4
+b_0123_b:
+    .byte     0,  1,  2,  3,  1,  2,  3,  4,  2,  3,  4,  5,  3,  4,  5,  6
+
+    .align 4
+b_4567_b:
+    .byte     4,  5,  6,  7,  5,  6,  7,  8,  6,  7,  8,  9,  7,  8,  9, 10
+
+b_hilo_b:
+    .byte     0,  1,  2,  3,  4,  5,  6,  7, 16, 17, 18, 19, 20, 21, 22, 23
diff --git a/vp8/common/ppc/idctllm_altivec.asm b/vp8/common/ppc/idctllm_altivec.asm
new file mode 100644
index 0000000..e88af8d
--- /dev/null
+++ b/vp8/common/ppc/idctllm_altivec.asm
@@ -0,0 +1,188 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl short_idct4x4llm_ppc
+
+.macro load_c V, LABEL, OFF, R0, R1
+    lis     \R0, \LABEL@ha
+    la      \R1, \LABEL@l(\R0)
+    lvx     \V, \OFF, \R1
+.endm
+
+;# r3 short *input
+;# r4 short *output
+;# r5 int pitch
+    .align 2
+short_idct4x4llm_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    load_c v8, sinpi8sqrt2, 0, r9, r10
+    load_c v9, cospi8sqrt2minus1, 0, r9, r10
+    load_c v10, hi_hi, 0, r9, r10
+    load_c v11, lo_lo, 0, r9, r10
+    load_c v12, shift_16, 0, r9, r10
+
+    li      r10,  16
+    lvx     v0,   0, r3         ;# input ip[0], ip[ 4]
+    lvx     v1, r10, r3         ;# input ip[8], ip[12]
+
+    ;# first pass
+    vupkhsh v2, v0
+    vupkhsh v3, v1
+    vaddsws v6, v2, v3          ;# a1 = ip[0]+ip[8]
+    vsubsws v7, v2, v3          ;# b1 = ip[0]-ip[8]
+
+    vupklsh v0, v0
+    vmulosh v4, v0, v8
+    vsraw   v4, v4, v12
+    vaddsws v4, v4, v0          ;# ip[ 4] * sin(pi/8) * sqrt(2)
+
+    vupklsh v1, v1
+    vmulosh v5, v1, v9
+    vsraw   v5, v5, v12         ;# ip[12] * cos(pi/8) * sqrt(2)
+    vaddsws v5, v5, v1
+
+    vsubsws v4, v4, v5          ;# c1
+
+    vmulosh v3, v1, v8
+    vsraw   v3, v3, v12
+    vaddsws v3, v3, v1          ;# ip[12] * sin(pi/8) * sqrt(2)
+
+    vmulosh v5, v0, v9
+    vsraw   v5, v5, v12         ;# ip[ 4] * cos(pi/8) * sqrt(2)
+    vaddsws v5, v5, v0
+
+    vaddsws v3, v3, v5          ;# d1
+
+    vaddsws v0, v6, v3          ;# a1 + d1
+    vsubsws v3, v6, v3          ;# a1 - d1
+
+    vaddsws v1, v7, v4          ;# b1 + c1
+    vsubsws v2, v7, v4          ;# b1 - c1
+
+    ;# transpose input
+    vmrghw  v4, v0, v1          ;# a0 b0 a1 b1
+    vmrghw  v5, v2, v3          ;# c0 d0 c1 d1
+
+    vmrglw  v6, v0, v1          ;# a2 b2 a3 b3
+    vmrglw  v7, v2, v3          ;# c2 d2 c3 d3
+
+    vperm   v0, v4, v5, v10     ;# a0 b0 c0 d0
+    vperm   v1, v4, v5, v11     ;# a1 b1 c1 d1
+
+    vperm   v2, v6, v7, v10     ;# a2 b2 c2 d2
+    vperm   v3, v6, v7, v11     ;# a3 b3 c3 d3
+
+    ;# second pass
+    vaddsws v6, v0, v2          ;# a1 = ip[0]+ip[8]
+    vsubsws v7, v0, v2          ;# b1 = ip[0]-ip[8]
+
+    vmulosh v4, v1, v8
+    vsraw   v4, v4, v12
+    vaddsws v4, v4, v1          ;# ip[ 4] * sin(pi/8) * sqrt(2)
+
+    vmulosh v5, v3, v9
+    vsraw   v5, v5, v12         ;# ip[12] * cos(pi/8) * sqrt(2)
+    vaddsws v5, v5, v3
+
+    vsubsws v4, v4, v5          ;# c1
+
+    vmulosh v2, v3, v8
+    vsraw   v2, v2, v12
+    vaddsws v2, v2, v3          ;# ip[12] * sin(pi/8) * sqrt(2)
+
+    vmulosh v5, v1, v9
+    vsraw   v5, v5, v12         ;# ip[ 4] * cos(pi/8) * sqrt(2)
+    vaddsws v5, v5, v1
+
+    vaddsws v3, v2, v5          ;# d1
+
+    vaddsws v0, v6, v3          ;# a1 + d1
+    vsubsws v3, v6, v3          ;# a1 - d1
+
+    vaddsws v1, v7, v4          ;# b1 + c1
+    vsubsws v2, v7, v4          ;# b1 - c1
+
+    vspltish v6, 4
+    vspltish v7, 3
+
+    vpkswss v0, v0, v1
+    vpkswss v1, v2, v3
+
+    vaddshs v0, v0, v6
+    vaddshs v1, v1, v6
+
+    vsrah   v0, v0, v7
+    vsrah   v1, v1, v7
+
+    ;# transpose output
+    vmrghh  v2, v0, v1          ;# a0 c0 a1 c1 a2 c2 a3 c3
+    vmrglh  v3, v0, v1          ;# b0 d0 b1 d1 b2 d2 b3 d3
+
+    vmrghh  v0, v2, v3          ;# a0 b0 c0 d0 a1 b1 c1 d1
+    vmrglh  v1, v2, v3          ;# a2 b2 c2 d2 a3 b3 c3 d3
+
+    stwu    r1,-416(r1)         ;# create space on the stack
+
+    stvx    v0,  0, r1
+    lwz     r6, 0(r1)
+    stw     r6, 0(r4)
+    lwz     r6, 4(r1)
+    stw     r6, 4(r4)
+
+    add     r4, r4, r5
+
+    lwz     r6,  8(r1)
+    stw     r6,  0(r4)
+    lwz     r6, 12(r1)
+    stw     r6,  4(r4)
+
+    add     r4, r4, r5
+
+    stvx    v1,  0, r1
+    lwz     r6, 0(r1)
+    stw     r6, 0(r4)
+    lwz     r6, 4(r1)
+    stw     r6, 4(r4)
+
+    add     r4, r4, r5
+
+    lwz     r6,  8(r1)
+    stw     r6,  0(r4)
+    lwz     r6, 12(r1)
+    stw     r6,  4(r4)
+
+    addi    r1, r1, 416         ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 4
+sinpi8sqrt2:
+    .short  35468, 35468, 35468, 35468, 35468, 35468, 35468, 35468
+
+    .align 4
+cospi8sqrt2minus1:
+    .short  20091, 20091, 20091, 20091, 20091, 20091, 20091, 20091
+
+    .align 4
+shift_16:
+    .long      16,    16,    16,    16
+
+    .align 4
+hi_hi:
+    .byte     0,  1,  2,  3,  4,  5,  6,  7, 16, 17, 18, 19, 20, 21, 22, 23
+
+    .align 4
+lo_lo:
+    .byte     8,  9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31
diff --git a/vp8/common/ppc/loopfilter_altivec.c b/vp8/common/ppc/loopfilter_altivec.c
new file mode 100644
index 0000000..586eed4
--- /dev/null
+++ b/vp8/common/ppc/loopfilter_altivec.c
@@ -0,0 +1,142 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "loopfilter.h"
+#include "onyxc_int.h"
+
+typedef void loop_filter_function_y_ppc
+(
+    unsigned char *s,   // source pointer
+    int p,              // pitch
+    const signed char *flimit,
+    const signed char *limit,
+    const signed char *thresh
+);
+
+typedef void loop_filter_function_uv_ppc
+(
+    unsigned char *u,   // source pointer
+    unsigned char *v,   // source pointer
+    int p,              // pitch
+    const signed char *flimit,
+    const signed char *limit,
+    const signed char *thresh
+);
+
+typedef void loop_filter_function_s_ppc
+(
+    unsigned char *s,   // source pointer
+    int p,              // pitch
+    const signed char *flimit
+);
+
+loop_filter_function_y_ppc mbloop_filter_horizontal_edge_y_ppc;
+loop_filter_function_y_ppc mbloop_filter_vertical_edge_y_ppc;
+loop_filter_function_y_ppc loop_filter_horizontal_edge_y_ppc;
+loop_filter_function_y_ppc loop_filter_vertical_edge_y_ppc;
+
+loop_filter_function_uv_ppc mbloop_filter_horizontal_edge_uv_ppc;
+loop_filter_function_uv_ppc mbloop_filter_vertical_edge_uv_ppc;
+loop_filter_function_uv_ppc loop_filter_horizontal_edge_uv_ppc;
+loop_filter_function_uv_ppc loop_filter_vertical_edge_uv_ppc;
+
+loop_filter_function_s_ppc loop_filter_simple_horizontal_edge_ppc;
+loop_filter_function_s_ppc loop_filter_simple_vertical_edge_ppc;
+
+// Horizontal MB filtering
+void loop_filter_mbh_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                         int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void)simpler_lpf;
+    mbloop_filter_horizontal_edge_y_ppc(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr);
+
+    if (u_ptr)
+        mbloop_filter_horizontal_edge_uv_ppc(u_ptr, v_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr);
+}
+
+void loop_filter_mbhs_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                          int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void)simpler_lpf;
+    (void)u_ptr;
+    (void)v_ptr;
+    (void)uv_stride;
+    loop_filter_simple_horizontal_edge_ppc(y_ptr, y_stride, lfi->mbflim);
+}
+
+// Vertical MB Filtering
+void loop_filter_mbv_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                         int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void)simpler_lpf;
+    mbloop_filter_vertical_edge_y_ppc(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr);
+
+    if (u_ptr)
+        mbloop_filter_vertical_edge_uv_ppc(u_ptr, v_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr);
+}
+
+void loop_filter_mbvs_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                          int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void)simpler_lpf;
+    (void)u_ptr;
+    (void)v_ptr;
+    (void)uv_stride;
+    loop_filter_simple_vertical_edge_ppc(y_ptr, y_stride, lfi->mbflim);
+}
+
+// Horizontal B Filtering
+void loop_filter_bh_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                        int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void)simpler_lpf;
+    // These should all be done at once with one call, instead of 3
+    loop_filter_horizontal_edge_y_ppc(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr);
+    loop_filter_horizontal_edge_y_ppc(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr);
+    loop_filter_horizontal_edge_y_ppc(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr);
+
+    if (u_ptr)
+        loop_filter_horizontal_edge_uv_ppc(u_ptr + 4 * uv_stride, v_ptr + 4 * uv_stride, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr);
+}
+
+void loop_filter_bhs_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                         int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void)simpler_lpf;
+    (void)u_ptr;
+    (void)v_ptr;
+    (void)uv_stride;
+    loop_filter_simple_horizontal_edge_ppc(y_ptr + 4 * y_stride, y_stride, lfi->flim);
+    loop_filter_simple_horizontal_edge_ppc(y_ptr + 8 * y_stride, y_stride, lfi->flim);
+    loop_filter_simple_horizontal_edge_ppc(y_ptr + 12 * y_stride, y_stride, lfi->flim);
+}
+
+// Vertical B Filtering
+void loop_filter_bv_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                        int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void)simpler_lpf;
+    loop_filter_vertical_edge_y_ppc(y_ptr, y_stride, lfi->flim, lfi->lim, lfi->thr);
+
+    if (u_ptr)
+        loop_filter_vertical_edge_uv_ppc(u_ptr + 4, v_ptr + 4, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr);
+}
+
+void loop_filter_bvs_ppc(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                         int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void)simpler_lpf;
+    (void)u_ptr;
+    (void)v_ptr;
+    (void)uv_stride;
+    loop_filter_simple_vertical_edge_ppc(y_ptr + 4,  y_stride, lfi->flim);
+    loop_filter_simple_vertical_edge_ppc(y_ptr + 8,  y_stride, lfi->flim);
+    loop_filter_simple_vertical_edge_ppc(y_ptr + 12, y_stride, lfi->flim);
+}
diff --git a/vp8/common/ppc/loopfilter_filters_altivec.asm b/vp8/common/ppc/loopfilter_filters_altivec.asm
new file mode 100644
index 0000000..78a5cf9
--- /dev/null
+++ b/vp8/common/ppc/loopfilter_filters_altivec.asm
@@ -0,0 +1,1252 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl mbloop_filter_horizontal_edge_y_ppc
+    .globl loop_filter_horizontal_edge_y_ppc
+    .globl mbloop_filter_vertical_edge_y_ppc
+    .globl loop_filter_vertical_edge_y_ppc
+
+    .globl mbloop_filter_horizontal_edge_uv_ppc
+    .globl loop_filter_horizontal_edge_uv_ppc
+    .globl mbloop_filter_vertical_edge_uv_ppc
+    .globl loop_filter_vertical_edge_uv_ppc
+
+    .globl loop_filter_simple_horizontal_edge_ppc
+    .globl loop_filter_simple_vertical_edge_ppc
+
+    .text
+;# We often need to perform transposes (and other transpose-like operations)
+;#   on matrices of data.  This is simplified by the fact that we usually
+;#   operate on hunks of data whose dimensions are powers of 2, or at least
+;#   divisible by highish powers of 2.
+;#
+;#   These operations can be very confusing.  They become more straightforward
+;#   when we think of them as permutations of address bits: Concatenate a
+;#   group of vector registers and think of it as occupying a block of
+;#   memory beginning at address zero.  The low four bits 0...3 of the
+;#   address then correspond to position within a register, the higher-order
+;#   address bits select the register.
+;#
+;#   Although register selection, at the code level, is arbitrary, things
+;#   are simpler if we use contiguous ranges of register numbers, simpler
+;#   still if the low-order bits of the register number correspond to
+;#   conceptual address bits.  We do this whenever reasonable.
+;#
+;#   A 16x16 transpose can then be thought of as an operation on
+;#   a 256-element block of memory.  It takes 8 bits 0...7 to address this
+;#   memory and the effect of a transpose is to interchange address bit
+;#   0 with 4, 1 with 5, 2 with 6, and 3 with 7.  Bits 0...3 index the
+;#   column, which is interchanged with the row addressed by bits 4..7.
+;#
+;#   The altivec merge instructions provide a rapid means of effecting
+;#   many of these transforms.  They operate at three widths (8,16,32).
+;#   Writing V(x) for vector register #x, paired merges permute address
+;#   indices as follows.
+;#
+;#   0->1  1->2  2->3  3->(4+d)  (4+s)->0:
+;#
+;#      vmrghb  V( x),          V( y), V( y + (1<<s))
+;#      vmrglb  V( x + (1<<d)), V( y), V( y + (1<<s))
+;#
+;#
+;#   =0=   1->2  2->3  3->(4+d)  (4+s)->1:
+;#
+;#      vmrghh  V( x),          V( y), V( y + (1<<s))
+;#      vmrglh  V( x + (1<<d)), V( y), V( y + (1<<s))
+;#
+;#
+;#   =0=   =1=   2->3  3->(4+d)  (4+s)->2:
+;#
+;#      vmrghw  V( x),          V( y), V( y + (1<<s))
+;#      vmrglw  V( x + (1<<d)), V( y), V( y + (1<<s))
+;#
+;#
+;#   Unfortunately, there is no doubleword merge instruction.
+;#   The following sequence uses "vperm" is a substitute.
+;#   Assuming that the selection masks b_hihi and b_lolo (defined in LFppc.c)
+;#   are in registers Vhihi and Vlolo, we can also effect the permutation
+;#
+;#   =0=   =1=   =2=   3->(4+d)  (4+s)->3   by the sequence:
+;#
+;#      vperm   V( x),          V( y), V( y + (1<<s)), Vhihi
+;#      vperm   V( x + (1<<d)), V( y), V( y + (1<<s)), Vlolo
+;#
+;#
+;#   Except for bits s and d, the other relationships between register
+;#   number (= high-order part of address) bits are at the disposal of
+;#   the programmer.
+;#
+
+;# To avoid excess transposes, we filter all 3 vertical luma subblock
+;#   edges together.  This requires a single 16x16 transpose, which, in
+;#   the above language, amounts to the following permutation of address
+;#   indices:  0<->4   1<->5  2<->6  3<->7, which we accomplish by
+;#   4 iterations of the cyclic transform 0->1->2->3->4->5->6->7->0.
+;#
+;#   Except for the fact that the destination registers get written
+;#   before we are done referencing the old contents, the cyclic transform
+;#   is effected by
+;#
+;#      x = 0;  do {
+;#          vmrghb V(2x),   V(x), V(x+8);
+;#          vmrghb V(2x+1), V(x), V(x+8);
+;#      } while( ++x < 8);
+;#
+;#   For clarity, and because we can afford it, we do this transpose
+;#   using all 32 registers, alternating the banks 0..15  and  16 .. 31,
+;#   leaving the final result in 16 .. 31, as the lower registers are
+;#   used in the filtering itself.
+;#
+.macro Tpair A, B, X, Y
+    vmrghb  \A, \X, \Y
+    vmrglb  \B, \X, \Y
+.endm
+
+;# Each step takes 8*2 = 16 instructions
+
+.macro t16_even
+    Tpair v16,v17,  v0,v8
+    Tpair v18,v19,  v1,v9
+    Tpair v20,v21,  v2,v10
+    Tpair v22,v23,  v3,v11
+    Tpair v24,v25,  v4,v12
+    Tpair v26,v27,  v5,v13
+    Tpair v28,v29,  v6,v14
+    Tpair v30,v31,  v7,v15
+.endm
+
+.macro t16_odd
+    Tpair v0,v1, v16,v24
+    Tpair v2,v3, v17,v25
+    Tpair v4,v5, v18,v26
+    Tpair v6,v7, v19,v27
+    Tpair v8,v9, v20,v28
+    Tpair v10,v11, v21,v29
+    Tpair v12,v13, v22,v30
+    Tpair v14,v15, v23,v31
+.endm
+
+;# Whole transpose takes 4*16 = 64 instructions
+
+.macro t16_full
+    t16_odd
+    t16_even
+    t16_odd
+    t16_even
+.endm
+
+;# Vertical edge filtering requires transposes.  For the simple filter,
+;#   we need to convert 16 rows of 4 pels each into 4 registers of 16 pels
+;#   each.  Writing 0 ... 63 for the pixel indices, the desired result is:
+;#
+;#  v0 =  0  1 ... 14 15
+;#  v1 = 16 17 ... 30 31
+;#  v2 = 32 33 ... 47 48
+;#  v3 = 49 50 ... 62 63
+;#
+;#  In frame-buffer memory, the layout is:
+;#
+;#     0  16  32  48
+;#     1  17  33  49
+;#     ...
+;#    15  31  47  63.
+;#
+;#  We begin by reading the data 32 bits at a time (using scalar operations)
+;#  into a temporary array, reading the rows of the array into vector registers,
+;#  with the following layout:
+;#
+;#  v0 =  0 16 32 48  4 20 36 52  8 24 40 56  12 28 44 60
+;#  v1 =  1 17 33 49  5 21 ...                      45 61
+;#  v2 =  2 18 ...                                  46 62
+;#  v3 =  3 19 ...                                  47 63
+;#
+;#  From the "address-bit" perspective discussed above, we simply need to
+;#  interchange bits 0 <-> 4 and 1 <-> 5, leaving bits 2 and 3 alone.
+;#  In other words, we transpose each of the four 4x4 submatrices.
+;#
+;#  This transformation is its own inverse, and we need to perform it
+;#  again before writing the pixels back into the frame buffer.
+;#
+;#  It acts in place on registers v0...v3, uses v4...v7 as temporaries,
+;#  and assumes that v14/v15 contain the b_hihi/b_lolo selectors
+;#  defined above.  We think of both groups of 4 registers as having
+;#  "addresses" {0,1,2,3} * 16.
+;#
+.macro Transpose4times4x4 Vlo, Vhi
+
+    ;# d=s=0        0->1  1->2  2->3  3->4  4->0  =5=
+
+    vmrghb  v4, v0, v1
+    vmrglb  v5, v0, v1
+    vmrghb  v6, v2, v3
+    vmrglb  v7, v2, v3
+
+    ;# d=0 s=1      =0=   1->2  2->3  3->4  4->5  5->1
+
+    vmrghh  v0, v4, v6
+    vmrglh  v1, v4, v6
+    vmrghh  v2, v5, v7
+    vmrglh  v3, v5, v7
+
+    ;# d=s=0        =0=   =1=   2->3  3->4  4->2  =5=
+
+    vmrghw  v4, v0, v1
+    vmrglw  v5, v0, v1
+    vmrghw  v6, v2, v3
+    vmrglw  v7, v2, v3
+
+    ;# d=0  s=1     =0=   =1=   =2=   3->4  4->5  5->3
+
+    vperm   v0, v4, v6, \Vlo
+    vperm   v1, v4, v6, \Vhi
+    vperm   v2, v5, v7, \Vlo
+    vperm   v3, v5, v7, \Vhi
+.endm
+;# end Transpose4times4x4
+
+
+;# Normal mb vertical edge filter transpose.
+;#
+;#   We read 8 columns of data, initially in the following pattern:
+;#
+;#  (0,0)  (1,0) ... (7,0)  (0,1)  (1,1) ... (7,1)
+;#  (0,2)  (1,2) ... (7,2)  (0,3)  (1,3) ... (7,3)
+;#  ...
+;#  (0,14) (1,14) .. (7,14) (0,15) (1,15) .. (7,15)
+;#
+;#   and wish to convert to:
+;#
+;#  (0,0) ... (0,15)
+;#  (1,0) ... (1,15)
+;#  ...
+;#  (7,0) ... (7,15).
+;#
+;#  In "address bit" language, we wish to map
+;#
+;#  0->4  1->5  2->6  3->0  4->1  5->2  6->3, i.e., I -> (I+4) mod 7.
+;#
+;#  This can be accomplished by 4 iterations of the cyclic transform
+;#
+;#  I -> (I+1) mod 7;
+;#
+;#  each iteration can be realized by (d=0, s=2):
+;#
+;#  x = 0;  do  Tpair( V(2x),V(2x+1),  V(x),V(x+4))  while( ++x < 4);
+;#
+;#  The input/output is in registers v0...v7.  We use v10...v17 as mirrors;
+;#  preserving v8 = sign converter.
+;#
+;#  Inverse transpose is similar, except here I -> (I+3) mod 7 and the
+;#  result lands in the "mirror" registers v10...v17
+;#
+.macro t8x16_odd
+    Tpair v10, v11,  v0, v4
+    Tpair v12, v13,  v1, v5
+    Tpair v14, v15,  v2, v6
+    Tpair v16, v17,  v3, v7
+.endm
+
+.macro t8x16_even
+    Tpair v0, v1,  v10, v14
+    Tpair v2, v3,  v11, v15
+    Tpair v4, v5,  v12, v16
+    Tpair v6, v7,  v13, v17
+.endm
+
+.macro transpose8x16_fwd
+    t8x16_odd
+    t8x16_even
+    t8x16_odd
+    t8x16_even
+.endm
+
+.macro transpose8x16_inv
+    t8x16_odd
+    t8x16_even
+    t8x16_odd
+.endm
+
+.macro Transpose16x16
+    vmrghb  v0, v16, v24
+    vmrglb  v1, v16, v24
+    vmrghb  v2, v17, v25
+    vmrglb  v3, v17, v25
+    vmrghb  v4, v18, v26
+    vmrglb  v5, v18, v26
+    vmrghb  v6, v19, v27
+    vmrglb  v7, v19, v27
+    vmrghb  v8, v20, v28
+    vmrglb  v9, v20, v28
+    vmrghb  v10, v21, v29
+    vmrglb  v11, v21, v29
+    vmrghb  v12, v22, v30
+    vmrglb  v13, v22, v30
+    vmrghb  v14, v23, v31
+    vmrglb  v15, v23, v31
+    vmrghb  v16, v0, v8
+    vmrglb  v17, v0, v8
+    vmrghb  v18, v1, v9
+    vmrglb  v19, v1, v9
+    vmrghb  v20, v2, v10
+    vmrglb  v21, v2, v10
+    vmrghb  v22, v3, v11
+    vmrglb  v23, v3, v11
+    vmrghb  v24, v4, v12
+    vmrglb  v25, v4, v12
+    vmrghb  v26, v5, v13
+    vmrglb  v27, v5, v13
+    vmrghb  v28, v6, v14
+    vmrglb  v29, v6, v14
+    vmrghb  v30, v7, v15
+    vmrglb  v31, v7, v15
+    vmrghb  v0, v16, v24
+    vmrglb  v1, v16, v24
+    vmrghb  v2, v17, v25
+    vmrglb  v3, v17, v25
+    vmrghb  v4, v18, v26
+    vmrglb  v5, v18, v26
+    vmrghb  v6, v19, v27
+    vmrglb  v7, v19, v27
+    vmrghb  v8, v20, v28
+    vmrglb  v9, v20, v28
+    vmrghb  v10, v21, v29
+    vmrglb  v11, v21, v29
+    vmrghb  v12, v22, v30
+    vmrglb  v13, v22, v30
+    vmrghb  v14, v23, v31
+    vmrglb  v15, v23, v31
+    vmrghb  v16, v0, v8
+    vmrglb  v17, v0, v8
+    vmrghb  v18, v1, v9
+    vmrglb  v19, v1, v9
+    vmrghb  v20, v2, v10
+    vmrglb  v21, v2, v10
+    vmrghb  v22, v3, v11
+    vmrglb  v23, v3, v11
+    vmrghb  v24, v4, v12
+    vmrglb  v25, v4, v12
+    vmrghb  v26, v5, v13
+    vmrglb  v27, v5, v13
+    vmrghb  v28, v6, v14
+    vmrglb  v29, v6, v14
+    vmrghb  v30, v7, v15
+    vmrglb  v31, v7, v15
+.endm
+
+;# load_g loads a global vector (whose address is in the local variable Gptr)
+;#   into vector register Vreg.  Trashes r0
+.macro load_g Vreg, Gptr
+    lwz     r0, \Gptr
+    lvx     \Vreg, 0, r0
+.endm
+
+;# exploit the saturation here.  if the answer is negative
+;# it will be clamped to 0.  orring 0 with a positive
+;# number will be the positive number (abs)
+;# RES = abs( A-B), trashes TMP
+.macro Abs RES, TMP, A, B
+    vsububs \RES, \A, \B
+    vsububs \TMP, \B, \A
+    vor     \RES, \RES, \TMP
+.endm
+
+;# RES = Max( RES, abs( A-B)), trashes TMP
+.macro max_abs RES, TMP, A, B
+    vsububs \TMP, \A, \B
+    vmaxub  \RES, \RES, \TMP
+    vsububs \TMP, \B, \A
+    vmaxub  \RES, \RES, \TMP
+.endm
+
+.macro Masks
+    ;# build masks
+    ;# input is all 8 bit unsigned (0-255).  need to
+    ;# do abs(vala-valb) > limit.  but no need to compare each
+    ;# value to the limit.  find the max of the absolute differences
+    ;# and compare that to the limit.
+    ;# First hev
+    Abs     v14, v13, v2, v3    ;# |P1 - P0|
+    max_abs  v14, v13, v5, v4    ;# |Q1 - Q0|
+
+    vcmpgtub v10, v14, v10      ;# HEV = true if thresh exceeded
+
+    ;# Next limit
+    max_abs  v14, v13, v0, v1    ;# |P3 - P2|
+    max_abs  v14, v13, v1, v2    ;# |P2 - P1|
+    max_abs  v14, v13, v6, v5    ;# |Q2 - Q1|
+    max_abs  v14, v13, v7, v6    ;# |Q3 - Q2|
+
+    vcmpgtub v9, v14, v9        ;# R = true if limit exceeded
+
+    ;# flimit
+    Abs     v14, v13, v3, v4    ;# |P0 - Q0|
+
+    vcmpgtub v8, v14, v8        ;# X = true if flimit exceeded
+
+    vor     v8, v8, v9          ;# R = true if flimit or limit exceeded
+    ;# done building masks
+.endm
+
+.macro build_constants RFL, RLI, RTH, FL, LI, TH
+    ;# build constants
+    lvx     \FL, 0, \RFL        ;# flimit
+    lvx     \LI, 0, \RLI        ;# limit
+    lvx     \TH, 0, \RTH        ;# thresh
+
+    vspltisb v11, 8
+    vspltisb v12, 4
+    vslb    v11, v11, v12       ;# 0x80808080808080808080808080808080
+.endm
+
+.macro load_data_y
+    ;# setup strides/pointers to be able to access
+    ;# all of the data
+    add     r5, r4, r4          ;# r5 = 2 * stride
+    sub     r6, r3, r5          ;# r6 -> 2 rows back
+    neg     r7, r4              ;# r7 = -stride
+
+    ;# load 16 pixels worth of data to work on
+    sub     r0, r6, r5          ;# r0 -> 4 rows back (temp)
+    lvx     v0,  0, r0          ;# P3  (read only)
+    lvx     v1, r7, r6          ;# P2
+    lvx     v2,  0, r6          ;# P1
+    lvx     v3, r7, r3          ;# P0
+    lvx     v4,  0, r3          ;# Q0
+    lvx     v5, r4, r3          ;# Q1
+    lvx     v6, r5, r3          ;# Q2
+    add     r0, r3, r5          ;# r0 -> 2 rows fwd (temp)
+    lvx     v7, r4, r0          ;# Q3  (read only)
+.endm
+
+;# Expects
+;#  v10 == HEV
+;#  v13 == tmp
+;#  v14 == tmp
+.macro common_adjust P0, Q0, P1, Q1, HEV_PRESENT
+    vxor    \P1, \P1, v11       ;# SP1
+    vxor    \P0, \P0, v11       ;# SP0
+    vxor    \Q0, \Q0, v11       ;# SQ0
+    vxor    \Q1, \Q1, v11       ;# SQ1
+
+    vsubsbs v13, \P1, \Q1       ;# f  = c (P1 - Q1)
+.if \HEV_PRESENT
+    vand    v13, v13, v10       ;# f &= hev
+.endif
+    vsubsbs v14, \Q0, \P0       ;# -126 <=  X = Q0-P0  <= +126
+    vaddsbs v13, v13, v14
+    vaddsbs v13, v13, v14
+    vaddsbs v13, v13, v14       ;# A = c( c(P1-Q1) + 3*(Q0-P0))
+
+    vandc   v13, v13, v8        ;# f &= mask
+
+    vspltisb v8, 3
+    vspltisb v9, 4
+
+    vaddsbs v14, v13, v9        ;# f1 = c (f+4)
+    vaddsbs v15, v13, v8        ;# f2 = c (f+3)
+
+    vsrab   v13, v14, v8        ;# f1 >>= 3
+    vsrab   v15, v15, v8        ;# f2 >>= 3
+
+    vsubsbs \Q0, \Q0, v13       ;# u1 = c (SQ0 - f1)
+    vaddsbs \P0, \P0, v15       ;# u2 = c (SP0 + f2)
+.endm
+
+.macro vp8_mbfilter
+    Masks
+
+    ;# start the fitering here
+    vxor    v1, v1, v11         ;# SP2
+    vxor    v2, v2, v11         ;# SP1
+    vxor    v3, v3, v11         ;# SP0
+    vxor    v4, v4, v11         ;# SQ0
+    vxor    v5, v5, v11         ;# SQ1
+    vxor    v6, v6, v11         ;# SQ2
+
+    ;# add outer taps if we have high edge variance
+    vsubsbs v13, v2, v5         ;# f  = c (SP1-SQ1)
+
+    vsubsbs v14, v4, v3         ;# SQ0-SP0
+    vaddsbs v13, v13, v14
+    vaddsbs v13, v13, v14
+    vaddsbs v13, v13, v14       ;# f  = c( c(SP1-SQ1) + 3*(SQ0-SP0))
+
+    vandc   v13, v13, v8        ;# f &= mask
+    vand    v15, v13, v10       ;# f2 = f & hev
+
+    ;# save bottom 3 bits so that we round one side +4 and the other +3
+    vspltisb v8, 3
+    vspltisb v9, 4
+
+    vaddsbs v14, v15, v9        ;# f1 = c (f+4)
+    vaddsbs v15, v15, v8        ;# f2 = c (f+3)
+
+    vsrab   v14, v14, v8        ;# f1 >>= 3
+    vsrab   v15, v15, v8        ;# f2 >>= 3
+
+    vsubsbs v4, v4, v14         ;# u1 = c (SQ0 - f1)
+    vaddsbs v3, v3, v15         ;# u2 = c (SP0 + f2)
+
+    ;# only apply wider filter if not high edge variance
+    vandc   v13, v13, v10       ;# f &= ~hev
+
+    vspltisb v9, 2
+    vnor    v8, v8, v8
+    vsrb    v9, v8, v9          ;# 0x3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f
+    vupkhsb v9, v9              ;# 0x003f003f003f003f003f003f003f003f
+    vspltisb v8, 9
+
+    ;# roughly 1/7th difference across boundary
+    vspltish v10, 7
+    vmulosb v14, v8, v13        ;# A = c( c(P1-Q1) + 3*(Q0-P0))
+    vmulesb v15, v8, v13
+    vaddshs v14, v14, v9        ;# +=  63
+    vaddshs v15, v15, v9
+    vsrah   v14, v14, v10       ;# >>= 7
+    vsrah   v15, v15, v10
+    vmrglh  v10, v15, v14
+    vmrghh  v15, v15, v14
+
+    vpkshss v10, v15, v10       ;# X = saturated down to bytes
+
+    vsubsbs v6, v6, v10         ;# subtract from Q and add to P
+    vaddsbs v1, v1, v10
+
+    vxor    v6, v6, v11
+    vxor    v1, v1, v11
+
+    ;# roughly 2/7th difference across boundary
+    vspltish v10, 7
+    vaddubm v12, v8, v8
+    vmulosb v14, v12, v13       ;# A = c( c(P1-Q1) + 3*(Q0-P0))
+    vmulesb v15, v12, v13
+    vaddshs v14, v14, v9
+    vaddshs v15, v15, v9
+    vsrah   v14, v14, v10       ;# >>= 7
+    vsrah   v15, v15, v10
+    vmrglh  v10, v15, v14
+    vmrghh  v15, v15, v14
+
+    vpkshss v10, v15, v10       ;# X = saturated down to bytes
+
+    vsubsbs v5, v5, v10         ;# subtract from Q and add to P
+    vaddsbs v2, v2, v10
+
+    vxor    v5, v5, v11
+    vxor    v2, v2, v11
+
+    ;# roughly 3/7th difference across boundary
+    vspltish v10, 7
+    vaddubm v12, v12, v8
+    vmulosb v14, v12, v13       ;# A = c( c(P1-Q1) + 3*(Q0-P0))
+    vmulesb v15, v12, v13
+    vaddshs v14, v14, v9
+    vaddshs v15, v15, v9
+    vsrah   v14, v14, v10       ;# >>= 7
+    vsrah   v15, v15, v10
+    vmrglh  v10, v15, v14
+    vmrghh  v15, v15, v14
+
+    vpkshss v10, v15, v10       ;# X = saturated down to bytes
+
+    vsubsbs v4, v4, v10         ;# subtract from Q and add to P
+    vaddsbs v3, v3, v10
+
+    vxor    v4, v4, v11
+    vxor    v3, v3, v11
+.endm
+
+.macro SBFilter
+    Masks
+
+    common_adjust v3, v4, v2, v5, 1
+
+    ;# outer tap adjustments
+    vspltisb v8, 1
+
+    vaddubm v13, v13, v8        ;# f  += 1
+    vsrab   v13, v13, v8        ;# f >>= 1
+
+    vandc   v13, v13, v10       ;# f &= ~hev
+
+    vsubsbs v5, v5, v13         ;# u1 = c (SQ1 - f)
+    vaddsbs v2, v2, v13         ;# u2 = c (SP1 + f)
+
+    vxor    v2, v2, v11
+    vxor    v3, v3, v11
+    vxor    v4, v4, v11
+    vxor    v5, v5, v11
+.endm
+
+    .align 2
+mbloop_filter_horizontal_edge_y_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    build_constants r5, r6, r7, v8, v9, v10
+
+    load_data_y
+
+    vp8_mbfilter
+
+    stvx     v1, r7, r6         ;# P2
+    stvx     v2,  0, r6         ;# P1
+    stvx     v3, r7, r3         ;# P0
+    stvx     v4,  0, r3         ;# Q0
+    stvx     v5, r4, r3         ;# Q1
+    stvx     v6, r5, r3         ;# Q2
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;#  r3 unsigned char *s
+;#  r4 int p
+;#  r5 const signed char *flimit
+;#  r6 const signed char *limit
+;#  r7 const signed char *thresh
+loop_filter_horizontal_edge_y_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    build_constants r5, r6, r7, v8, v9, v10
+
+    load_data_y
+
+    SBFilter
+
+    stvx     v2,  0, r6         ;# P1
+    stvx     v3, r7, r3         ;# P0
+    stvx     v4,  0, r3         ;# Q0
+    stvx     v5, r4, r3         ;# Q1
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+;# Filtering a vertical mb.  Each mb is aligned on a 16 byte boundary.
+;#  So we can read in an entire mb aligned.  However if we want to filter the mb
+;#  edge we run into problems.  For the loopfilter we require 4 bytes before the mb
+;#  and 4 after for a total of 8 bytes.  Reading 16 bytes inorder to get 4 is a bit
+;#  of a waste.  So this is an even uglier way to get around that.
+;# Using the regular register file words are read in and then saved back out to
+;#  memory to align and order them up.  Then they are read in using the
+;#  vector register file.
+.macro RLVmb V, R
+    lwzux   r0, r3, r4
+    stw     r0, 4(\R)
+    lwz     r0,-4(r3)
+    stw     r0, 0(\R)
+    lwzux   r0, r3, r4
+    stw     r0,12(\R)
+    lwz     r0,-4(r3)
+    stw     r0, 8(\R)
+    lvx     \V, 0, \R
+.endm
+
+.macro WLVmb V, R
+    stvx    \V, 0, \R
+    lwz     r0,12(\R)
+    stwux   r0, r3, r4
+    lwz     r0, 8(\R)
+    stw     r0,-4(r3)
+    lwz     r0, 4(\R)
+    stwux   r0, r3, r4
+    lwz     r0, 0(\R)
+    stw     r0,-4(r3)
+.endm
+
+    .align 2
+;#  r3 unsigned char *s
+;#  r4 int p
+;#  r5 const signed char *flimit
+;#  r6 const signed char *limit
+;#  r7 const signed char *thresh
+mbloop_filter_vertical_edge_y_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xc000
+    mtspr   256, r12            ;# set VRSAVE
+
+    la      r9, -48(r1)         ;# temporary space for reading in vectors
+    sub     r3, r3, r4
+
+    RLVmb v0, r9
+    RLVmb v1, r9
+    RLVmb v2, r9
+    RLVmb v3, r9
+    RLVmb v4, r9
+    RLVmb v5, r9
+    RLVmb v6, r9
+    RLVmb v7, r9
+
+    transpose8x16_fwd
+
+    build_constants r5, r6, r7, v8, v9, v10
+
+    vp8_mbfilter
+
+    transpose8x16_inv
+
+    add r3, r3, r4
+    neg r4, r4
+
+    WLVmb v17, r9
+    WLVmb v16, r9
+    WLVmb v15, r9
+    WLVmb v14, r9
+    WLVmb v13, r9
+    WLVmb v12, r9
+    WLVmb v11, r9
+    WLVmb v10, r9
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+.macro RL V, R, P
+    lvx     \V, 0,  \R
+    add     \R, \R, \P
+.endm
+
+.macro WL V, R, P
+    stvx    \V, 0,  \R
+    add     \R, \R, \P
+.endm
+
+.macro Fil P3, P2, P1, P0, Q0, Q1, Q2, Q3
+                                ;# K = |P0-P1| already
+    Abs     v14, v13, \Q0, \Q1  ;# M = |Q0-Q1|
+    vmaxub  v14, v14, v4        ;# M = max( |P0-P1|, |Q0-Q1|)
+    vcmpgtub v10, v14, v0
+
+    Abs     v4, v5, \Q2, \Q3    ;# K = |Q2-Q3| = next |P0-P1]
+
+    max_abs  v14, v13, \Q1, \Q2  ;# M = max( M, |Q1-Q2|)
+    max_abs  v14, v13, \P1, \P2  ;# M = max( M, |P1-P2|)
+    max_abs  v14, v13, \P2, \P3  ;# M = max( M, |P2-P3|)
+
+    vmaxub   v14, v14, v4       ;# M = max interior abs diff
+    vcmpgtub v9, v14, v2        ;# M = true if int_l exceeded
+
+    Abs     v14, v13, \P0, \Q0  ;# X = Abs( P0-Q0)
+    vcmpgtub v8, v14, v3        ;# X = true if edge_l exceeded
+    vor     v8, v8, v9          ;# M = true if edge_l or int_l exceeded
+
+    ;# replace P1,Q1 w/signed versions
+    common_adjust \P0, \Q0, \P1, \Q1, 1
+
+    vaddubm v13, v13, v1        ;# -16 <= M <= 15, saturation irrelevant
+    vsrab   v13, v13, v1
+    vandc   v13, v13, v10       ;# adjust P1,Q1 by (M+1)>>1  if ! hev
+    vsubsbs \Q1, \Q1, v13
+    vaddsbs \P1, \P1, v13
+
+    vxor    \P1, \P1, v11       ;# P1
+    vxor    \P0, \P0, v11       ;# P0
+    vxor    \Q0, \Q0, v11       ;# Q0
+    vxor    \Q1, \Q1, v11       ;# Q1
+.endm
+
+
+    .align 2
+;#  r3 unsigned char *s
+;#  r4 int p
+;#  r5 const signed char *flimit
+;#  r6 const signed char *limit
+;#  r7 const signed char *thresh
+loop_filter_vertical_edge_y_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    addi    r9, r3, 0
+    RL      v16, r9, r4
+    RL      v17, r9, r4
+    RL      v18, r9, r4
+    RL      v19, r9, r4
+    RL      v20, r9, r4
+    RL      v21, r9, r4
+    RL      v22, r9, r4
+    RL      v23, r9, r4
+    RL      v24, r9, r4
+    RL      v25, r9, r4
+    RL      v26, r9, r4
+    RL      v27, r9, r4
+    RL      v28, r9, r4
+    RL      v29, r9, r4
+    RL      v30, r9, r4
+    lvx     v31, 0, r9
+
+    Transpose16x16
+
+    vspltisb v1, 1
+
+    build_constants r5, r6, r7, v3, v2, v0
+
+    Abs v4, v5, v19, v18                            ;# K(v14) = first |P0-P1|
+
+    Fil v16, v17, v18, v19,  v20, v21, v22, v23
+    Fil v20, v21, v22, v23,  v24, v25, v26, v27
+    Fil v24, v25, v26, v27,  v28, v29, v30, v31
+
+    Transpose16x16
+
+    addi    r9, r3, 0
+    WL      v16, r9, r4
+    WL      v17, r9, r4
+    WL      v18, r9, r4
+    WL      v19, r9, r4
+    WL      v20, r9, r4
+    WL      v21, r9, r4
+    WL      v22, r9, r4
+    WL      v23, r9, r4
+    WL      v24, r9, r4
+    WL      v25, r9, r4
+    WL      v26, r9, r4
+    WL      v27, r9, r4
+    WL      v28, r9, r4
+    WL      v29, r9, r4
+    WL      v30, r9, r4
+    stvx    v31, 0, r9
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+;# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- UV FILTERING -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+.macro active_chroma_sel V
+    andi.   r7, r3, 8       ;# row origin modulo 16
+    add     r7, r7, r7      ;# selects selectors
+    lis     r12, _chromaSelectors@ha
+    la      r0,  _chromaSelectors@l(r12)
+    lwzux   r0, r7, r0      ;# leave selector addr in r7
+
+    lvx     \V, 0, r0       ;# mask to concatenate active U,V pels
+.endm
+
+.macro hread_uv Dest, U, V, Offs, VMask
+    lvx     \U, \Offs, r3
+    lvx     \V, \Offs, r4
+    vperm   \Dest, \U, \V, \VMask   ;# Dest = active part of U then V
+.endm
+
+.macro hwrite_uv New, U, V, Offs, Umask, Vmask
+    vperm   \U, \New, \U, \Umask    ;# Combine new pels with siblings
+    vperm   \V, \New, \V, \Vmask
+    stvx    \U, \Offs, r3           ;# Write to frame buffer
+    stvx    \V, \Offs, r4
+.endm
+
+;# Process U,V in parallel.
+.macro load_chroma_h
+    neg     r9, r5          ;# r9 = -1 * stride
+    add     r8, r9, r9      ;# r8 = -2 * stride
+    add     r10, r5, r5     ;# r10 = 2 * stride
+
+    active_chroma_sel v12
+
+    ;# P3, Q3 are read-only; need not save addresses or sibling pels
+    add     r6, r8, r8      ;# r6 = -4 * stride
+    hread_uv v0, v14, v15, r6, v12
+    add     r6, r10, r5     ;# r6 =  3 * stride
+    hread_uv v7, v14, v15, r6, v12
+
+    ;# Others are read/write; save addresses and sibling pels
+
+    add     r6, r8, r9      ;# r6 = -3 * stride
+    hread_uv v1, v16, v17, r6,  v12
+    hread_uv v2, v18, v19, r8,  v12
+    hread_uv v3, v20, v21, r9,  v12
+    hread_uv v4, v22, v23, 0,   v12
+    hread_uv v5, v24, v25, r5,  v12
+    hread_uv v6, v26, v27, r10, v12
+.endm
+
+.macro uresult_sel V
+    load_g   \V, 4(r7)
+.endm
+
+.macro vresult_sel V
+    load_g   \V, 8(r7)
+.endm
+
+;# always write P1,P0,Q0,Q1
+.macro store_chroma_h
+    uresult_sel v11
+    vresult_sel v12
+    hwrite_uv v2, v18, v19, r8, v11, v12
+    hwrite_uv v3, v20, v21, r9, v11, v12
+    hwrite_uv v4, v22, v23, 0,  v11, v12
+    hwrite_uv v5, v24, v25, r5, v11, v12
+.endm
+
+    .align 2
+;#  r3 unsigned char *u
+;#  r4 unsigned char *v
+;#  r5 int p
+;#  r6 const signed char *flimit
+;#  r7 const signed char *limit
+;#  r8 const signed char *thresh
+mbloop_filter_horizontal_edge_uv_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    build_constants r6, r7, r8, v8, v9, v10
+
+    load_chroma_h
+
+    vp8_mbfilter
+
+    store_chroma_h
+
+    hwrite_uv v1, v16, v17, r6,  v11, v12    ;# v1 == P2
+    hwrite_uv v6, v26, v27, r10, v11, v12    ;# v6 == Q2
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;#  r3 unsigned char *u
+;#  r4 unsigned char *v
+;#  r5 int p
+;#  r6 const signed char *flimit
+;#  r7 const signed char *limit
+;#  r8 const signed char *thresh
+loop_filter_horizontal_edge_uv_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    build_constants r6, r7, r8, v8, v9, v10
+
+    load_chroma_h
+
+    SBFilter
+
+    store_chroma_h
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+.macro R V, R
+    lwzux   r0, r3, r5
+    stw     r0, 4(\R)
+    lwz     r0,-4(r3)
+    stw     r0, 0(\R)
+    lwzux   r0, r4, r5
+    stw     r0,12(\R)
+    lwz     r0,-4(r4)
+    stw     r0, 8(\R)
+    lvx     \V, 0, \R
+.endm
+
+
+.macro W V, R
+    stvx    \V, 0, \R
+    lwz     r0,12(\R)
+    stwux   r0, r4, r5
+    lwz     r0, 8(\R)
+    stw     r0,-4(r4)
+    lwz     r0, 4(\R)
+    stwux   r0, r3, r5
+    lwz     r0, 0(\R)
+    stw     r0,-4(r3)
+.endm
+
+.macro chroma_vread R
+    sub r3, r3, r5          ;# back up one line for simplicity
+    sub r4, r4, r5
+
+    R v0, \R
+    R v1, \R
+    R v2, \R
+    R v3, \R
+    R v4, \R
+    R v5, \R
+    R v6, \R
+    R v7, \R
+
+    transpose8x16_fwd
+.endm
+
+.macro chroma_vwrite R
+
+    transpose8x16_inv
+
+    add     r3, r3, r5
+    add     r4, r4, r5
+    neg     r5, r5          ;# Write rows back in reverse order
+
+    W v17, \R
+    W v16, \R
+    W v15, \R
+    W v14, \R
+    W v13, \R
+    W v12, \R
+    W v11, \R
+    W v10, \R
+.endm
+
+    .align 2
+;#  r3 unsigned char *u
+;#  r4 unsigned char *v
+;#  r5 int p
+;#  r6 const signed char *flimit
+;#  r7 const signed char *limit
+;#  r8 const signed char *thresh
+mbloop_filter_vertical_edge_uv_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xc000
+    mtspr   256, r12            ;# set VRSAVE
+
+    la      r9, -48(r1)         ;# temporary space for reading in vectors
+
+    chroma_vread r9
+
+    build_constants r6, r7, r8, v8, v9, v10
+
+    vp8_mbfilter
+
+    chroma_vwrite r9
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;#  r3 unsigned char *u
+;#  r4 unsigned char *v
+;#  r5 int p
+;#  r6 const signed char *flimit
+;#  r7 const signed char *limit
+;#  r8 const signed char *thresh
+loop_filter_vertical_edge_uv_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xc000
+    mtspr   256, r12            ;# set VRSAVE
+
+    la      r9, -48(r1)         ;# temporary space for reading in vectors
+
+    chroma_vread r9
+
+    build_constants r6, r7, r8, v8, v9, v10
+
+    SBFilter
+
+    chroma_vwrite r9
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+;# -=-=-=-=-=-=-=-=-=-=-=-=-=-= SIMPLE LOOP FILTER =-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+.macro vp8_simple_filter
+    Abs v14, v13, v1, v2    ;# M = abs( P0 - Q0)
+    vcmpgtub v8, v14, v8    ;# v5 = true if _over_ limit
+
+    ;# preserve unsigned v0 and v3
+    common_adjust v1, v2, v0, v3, 0
+
+    vxor v1, v1, v11
+    vxor v2, v2, v11        ;# cvt Q0, P0 back to pels
+.endm
+
+.macro simple_vertical
+    addi    r8,  0, 16
+    addi    r7, r5, 32
+
+    lvx     v0,  0, r5
+    lvx     v1, r8, r5
+    lvx     v2,  0, r7
+    lvx     v3, r8, r7
+
+    lis     r12, _B_hihi@ha
+    la      r0,  _B_hihi@l(r12)
+    lvx     v16, 0, r0
+
+    lis     r12, _B_lolo@ha
+    la      r0,  _B_lolo@l(r12)
+    lvx     v17, 0, r0
+
+    Transpose4times4x4 v16, v17
+    vp8_simple_filter
+
+    vxor v0, v0, v11
+    vxor v3, v3, v11        ;# cvt Q0, P0 back to pels
+
+    Transpose4times4x4 v16, v17
+
+    stvx    v0,  0, r5
+    stvx    v1, r8, r5
+    stvx    v2,  0, r7
+    stvx    v3, r8, r7
+.endm
+
+    .align 2
+;#  r3 unsigned char *s
+;#  r4 int p
+;#  r5 const signed char *flimit
+loop_filter_simple_horizontal_edge_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    ;# build constants
+    lvx     v8, 0, r5           ;# flimit
+
+    vspltisb v11, 8
+    vspltisb v12, 4
+    vslb    v11, v11, v12       ;# 0x80808080808080808080808080808080
+
+    neg     r5, r4              ;# r5 = -1 * stride
+    add     r6, r5, r5          ;# r6 = -2 * stride
+
+    lvx     v0, r6, r3          ;# v0 = P1 = 16 pels two rows above edge
+    lvx     v1, r5, r3          ;# v1 = P0 = 16 pels one row  above edge
+    lvx     v2,  0, r3          ;# v2 = Q0 = 16 pels one row  below edge
+    lvx     v3, r4, r3          ;# v3 = Q1 = 16 pels two rows below edge
+
+    vp8_simple_filter
+
+    stvx    v1, r5, r3          ;# store P0
+    stvx    v2,  0, r3          ;# store Q0
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+.macro RLV Offs
+    stw     r0, (\Offs*4)(r5)
+    lwzux   r0, r7, r4
+.endm
+
+.macro WLV Offs
+    lwz     r0, (\Offs*4)(r5)
+    stwux   r0, r7, r4
+.endm
+
+    .align 2
+;#  r3 unsigned char *s
+;#  r4 int p
+;#  r5 const signed char *flimit
+loop_filter_simple_vertical_edge_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xc000
+    mtspr   256, r12            ;# set VRSAVE
+
+    ;# build constants
+    lvx     v8, 0, r5           ;# flimit
+
+    vspltisb v11, 8
+    vspltisb v12, 4
+    vslb    v11, v11, v12       ;# 0x80808080808080808080808080808080
+
+    la r5, -96(r1)              ;# temporary space for reading in vectors
+
+    ;# Store 4 pels at word "Offs" in temp array, then advance r7
+    ;#   to next row and read another 4 pels from the frame buffer.
+
+    subi    r7, r3,  2          ;# r7 -> 2 pels before start
+    lwzx    r0,  0, r7          ;# read first 4 pels
+
+    ;# 16 unaligned word accesses
+    RLV 0
+    RLV 4
+    RLV 8
+    RLV 12
+    RLV 1
+    RLV 5
+    RLV 9
+    RLV 13
+    RLV 2
+    RLV 6
+    RLV 10
+    RLV 14
+    RLV 3
+    RLV 7
+    RLV 11
+
+    stw     r0, (15*4)(r5)      ;# write last 4 pels
+
+    simple_vertical
+
+    ;# Read temp array, write frame buffer.
+    subi    r7, r3,  2          ;# r7 -> 2 pels before start
+    lwzx    r0,  0, r5          ;# read/write first 4 pels
+    stwx    r0,  0, r7
+
+    WLV 4
+    WLV 8
+    WLV 12
+    WLV 1
+    WLV 5
+    WLV 9
+    WLV 13
+    WLV 2
+    WLV 6
+    WLV 10
+    WLV 14
+    WLV 3
+    WLV 7
+    WLV 11
+    WLV 15
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .data
+
+_chromaSelectors:
+    .long   _B_hihi
+    .long   _B_Ures0
+    .long   _B_Vres0
+    .long   0
+    .long   _B_lolo
+    .long   _B_Ures8
+    .long   _B_Vres8
+    .long   0
+
+    .align 4
+_B_Vres8:
+    .byte   16, 17, 18, 19, 20, 21, 22, 23,  8,  9, 10, 11, 12, 13, 14, 15
+
+    .align 4
+_B_Ures8:
+    .byte   16, 17, 18, 19, 20, 21, 22, 23,  0,  1,  2,  3,  4,  5,  6,  7
+
+    .align 4
+_B_lolo:
+    .byte    8,  9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31
+
+    .align 4
+_B_Vres0:
+    .byte    8,  9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31
+    .align 4
+_B_Ures0:
+    .byte    0,  1,  2,  3,  4,  5,  6,  7, 24, 25, 26, 27, 28, 29, 30, 31
+
+    .align 4
+_B_hihi:
+    .byte    0,  1,  2,  3,  4,  5,  6,  7, 16, 17, 18, 19, 20, 21, 22, 23
diff --git a/vp8/common/ppc/platform_altivec.asm b/vp8/common/ppc/platform_altivec.asm
new file mode 100644
index 0000000..227ef2a
--- /dev/null
+++ b/vp8/common/ppc/platform_altivec.asm
@@ -0,0 +1,58 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl save_platform_context
+    .globl restore_platform_context
+
+.macro W V P
+    stvx    \V,  0, \P
+    addi    \P, \P, 16
+.endm
+
+.macro R V P
+    lvx     \V,  0, \P
+    addi    \P, \P, 16
+.endm
+
+;# r3 context_ptr
+    .align 2
+save_platform_contex:
+    W v20, r3
+    W v21, r3
+    W v22, r3
+    W v23, r3
+    W v24, r3
+    W v25, r3
+    W v26, r3
+    W v27, r3
+    W v28, r3
+    W v29, r3
+    W v30, r3
+    W v31, r3
+
+    blr
+
+;# r3 context_ptr
+    .align 2
+restore_platform_context:
+    R v20, r3
+    R v21, r3
+    R v22, r3
+    R v23, r3
+    R v24, r3
+    R v25, r3
+    R v26, r3
+    R v27, r3
+    R v28, r3
+    R v29, r3
+    R v30, r3
+    R v31, r3
+
+    blr
diff --git a/vp8/common/ppc/recon_altivec.asm b/vp8/common/ppc/recon_altivec.asm
new file mode 100644
index 0000000..f478b95
--- /dev/null
+++ b/vp8/common/ppc/recon_altivec.asm
@@ -0,0 +1,174 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl recon4b_ppc
+    .globl recon2b_ppc
+    .globl recon_b_ppc
+
+.macro row_of16 Diff Pred Dst Stride
+    lvx     v1,  0, \Pred           ;# v1 = pred = p0..p15
+    addi    \Pred, \Pred, 16        ;# next pred
+    vmrghb  v2, v0, v1              ;# v2 = 16-bit p0..p7
+    lvx     v3,  0, \Diff           ;# v3 = d0..d7
+    vaddshs v2, v2, v3              ;# v2 = r0..r7
+    vmrglb  v1, v0, v1              ;# v1 = 16-bit p8..p15
+    lvx     v3, r8, \Diff           ;# v3 = d8..d15
+    addi    \Diff, \Diff, 32        ;# next diff
+    vaddshs v3, v3, v1              ;# v3 = r8..r15
+    vpkshus v2, v2, v3              ;# v2 = 8-bit r0..r15
+    stvx    v2,  0, \Dst            ;# to dst
+    add     \Dst, \Dst, \Stride     ;# next dst
+.endm
+
+    .text
+    .align 2
+;#  r3 = short *diff_ptr,
+;#  r4 = unsigned char *pred_ptr,
+;#  r5 = unsigned char *dst_ptr,
+;#  r6 = int stride
+recon4b_ppc:
+    mfspr   r0, 256                     ;# get old VRSAVE
+    stw     r0, -8(r1)                  ;# save old VRSAVE to stack
+    oris    r0, r0, 0xf000
+    mtspr   256,r0                      ;# set VRSAVE
+
+    vxor    v0, v0, v0
+    li      r8, 16
+
+    row_of16 r3, r4, r5, r6
+    row_of16 r3, r4, r5, r6
+    row_of16 r3, r4, r5, r6
+    row_of16 r3, r4, r5, r6
+
+    lwz     r12, -8(r1)                 ;# restore old VRSAVE from stack
+    mtspr   256, r12                    ;# reset old VRSAVE
+
+    blr
+
+.macro two_rows_of8 Diff Pred Dst Stride write_first_four_pels
+    lvx     v1,  0, \Pred       ;# v1 = pred = p0..p15
+    vmrghb  v2, v0, v1          ;# v2 = 16-bit p0..p7
+    lvx     v3,  0, \Diff       ;# v3 = d0..d7
+    vaddshs v2, v2, v3          ;# v2 = r0..r7
+    vmrglb  v1, v0, v1          ;# v1 = 16-bit p8..p15
+    lvx     v3, r8, \Diff       ;# v2 = d8..d15
+    vaddshs v3, v3, v1          ;# v3 = r8..r15
+    vpkshus v2, v2, v3          ;# v3 = 8-bit r0..r15
+    stvx    v2,  0, r10         ;# 2 rows to dst from buf
+    lwz     r0, 0(r10)
+.if \write_first_four_pels
+    stw     r0, 0(\Dst)
+    .else
+    stwux   r0, \Dst, \Stride
+.endif
+    lwz     r0, 4(r10)
+    stw     r0, 4(\Dst)
+    lwz     r0, 8(r10)
+    stwux   r0, \Dst, \Stride       ;# advance dst to next row
+    lwz     r0, 12(r10)
+    stw     r0, 4(\Dst)
+.endm
+
+    .align 2
+;#  r3 = short *diff_ptr,
+;#  r4 = unsigned char *pred_ptr,
+;#  r5 = unsigned char *dst_ptr,
+;#  r6 = int stride
+
+recon2b_ppc:
+    mfspr   r0, 256                     ;# get old VRSAVE
+    stw     r0, -8(r1)                  ;# save old VRSAVE to stack
+    oris    r0, r0, 0xf000
+    mtspr   256,r0                      ;# set VRSAVE
+
+    vxor    v0, v0, v0
+    li      r8, 16
+
+    la      r10, -48(r1)                ;# buf
+
+    two_rows_of8 r3, r4, r5, r6, 1
+
+    addi    r4, r4, 16;                 ;# next pred
+    addi    r3, r3, 32;                 ;# next diff
+
+    two_rows_of8 r3, r4, r5, r6, 0
+
+    lwz     r12, -8(r1)                 ;# restore old VRSAVE from stack
+    mtspr   256, r12                    ;# reset old VRSAVE
+
+    blr
+
+.macro get_two_diff_rows
+    stw     r0, 0(r10)
+    lwz     r0, 4(r3)
+    stw     r0, 4(r10)
+    lwzu    r0, 32(r3)
+    stw     r0, 8(r10)
+    lwz     r0, 4(r3)
+    stw     r0, 12(r10)
+    lvx     v3, 0, r10
+.endm
+
+    .align 2
+;#  r3 = short *diff_ptr,
+;#  r4 = unsigned char *pred_ptr,
+;#  r5 = unsigned char *dst_ptr,
+;#  r6 = int stride
+recon_b_ppc:
+    mfspr   r0, 256                     ;# get old VRSAVE
+    stw     r0, -8(r1)                  ;# save old VRSAVE to stack
+    oris    r0, r0, 0xf000
+    mtspr   256,r0                      ;# set VRSAVE
+
+    vxor    v0, v0, v0
+
+    la      r10, -48(r1)    ;# buf
+
+    lwz     r0, 0(r4)
+    stw     r0, 0(r10)
+    lwz     r0, 16(r4)
+    stw     r0, 4(r10)
+    lwz     r0, 32(r4)
+    stw     r0, 8(r10)
+    lwz     r0, 48(r4)
+    stw     r0, 12(r10)
+
+    lvx     v1,  0, r10;    ;# v1 = pred = p0..p15
+
+    lwz r0, 0(r3)           ;# v3 = d0..d7
+
+    get_two_diff_rows
+
+    vmrghb  v2, v0, v1;     ;# v2 = 16-bit p0..p7
+    vaddshs v2, v2, v3;     ;# v2 = r0..r7
+
+    lwzu r0, 32(r3)         ;# v3 = d8..d15
+
+    get_two_diff_rows
+
+    vmrglb  v1, v0, v1;     ;# v1 = 16-bit p8..p15
+    vaddshs v3, v3, v1;     ;# v3 = r8..r15
+
+    vpkshus v2, v2, v3;     ;# v2 = 8-bit r0..r15
+    stvx    v2,  0, r10;    ;# 16 pels to dst from buf
+
+    lwz     r0, 0(r10)
+    stw     r0, 0(r5)
+    lwz     r0, 4(r10)
+    stwux   r0, r5, r6
+    lwz     r0, 8(r10)
+    stwux   r0, r5, r6
+    lwz     r0, 12(r10)
+    stwx    r0, r5, r6
+
+    lwz     r12, -8(r1)                 ;# restore old VRSAVE from stack
+    mtspr   256, r12                    ;# reset old VRSAVE
+
+    blr
diff --git a/vp8/common/ppc/systemdependent.c b/vp8/common/ppc/systemdependent.c
new file mode 100644
index 0000000..2847310
--- /dev/null
+++ b/vp8/common/ppc/systemdependent.c
@@ -0,0 +1,170 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "g_common.h"
+#include "subpixel.h"
+#include "loopfilter.h"
+#include "recon.h"
+#include "idct.h"
+#include "onyxc_int.h"
+
+void (*vp8_short_idct4x4)(short *input, short *output, int pitch);
+void (*vp8_short_idct4x4_1)(short *input, short *output, int pitch);
+void (*vp8_dc_only_idct)(short input_dc, short *output, int pitch);
+
+extern void (*vp8_post_proc_down_and_across)(
+    unsigned char *src_ptr,
+    unsigned char *dst_ptr,
+    int src_pixels_per_line,
+    int dst_pixels_per_line,
+    int rows,
+    int cols,
+    int flimit
+);
+
+extern void (*vp8_mbpost_proc_down)(unsigned char *dst, int pitch, int rows, int cols, int flimit);
+extern void vp8_mbpost_proc_down_c(unsigned char *dst, int pitch, int rows, int cols, int flimit);
+extern void (*vp8_mbpost_proc_across_ip)(unsigned char *src, int pitch, int rows, int cols, int flimit);
+extern void vp8_mbpost_proc_across_ip_c(unsigned char *src, int pitch, int rows, int cols, int flimit);
+
+extern void vp8_post_proc_down_and_across_c
+(
+    unsigned char *src_ptr,
+    unsigned char *dst_ptr,
+    int src_pixels_per_line,
+    int dst_pixels_per_line,
+    int rows,
+    int cols,
+    int flimit
+);
+void vp8_plane_add_noise_c(unsigned char *Start, unsigned int Width, unsigned int Height, int Pitch, int q, int a);
+
+extern copy_mem_block_function *vp8_copy_mem16x16;
+extern copy_mem_block_function *vp8_copy_mem8x8;
+extern copy_mem_block_function *vp8_copy_mem8x4;
+
+// PPC
+extern subpixel_predict_function sixtap_predict_ppc;
+extern subpixel_predict_function sixtap_predict8x4_ppc;
+extern subpixel_predict_function sixtap_predict8x8_ppc;
+extern subpixel_predict_function sixtap_predict16x16_ppc;
+extern subpixel_predict_function bilinear_predict4x4_ppc;
+extern subpixel_predict_function bilinear_predict8x4_ppc;
+extern subpixel_predict_function bilinear_predict8x8_ppc;
+extern subpixel_predict_function bilinear_predict16x16_ppc;
+
+extern copy_mem_block_function copy_mem16x16_ppc;
+
+void recon_b_ppc(short *diff_ptr, unsigned char *pred_ptr, unsigned char *dst_ptr, int stride);
+void recon2b_ppc(short *diff_ptr, unsigned char *pred_ptr, unsigned char *dst_ptr, int stride);
+void recon4b_ppc(short *diff_ptr, unsigned char *pred_ptr, unsigned char *dst_ptr, int stride);
+
+extern void short_idct4x4llm_ppc(short *input, short *output, int pitch);
+
+// Generic C
+extern subpixel_predict_function vp8_sixtap_predict_c;
+extern subpixel_predict_function vp8_sixtap_predict8x4_c;
+extern subpixel_predict_function vp8_sixtap_predict8x8_c;
+extern subpixel_predict_function vp8_sixtap_predict16x16_c;
+extern subpixel_predict_function vp8_bilinear_predict4x4_c;
+extern subpixel_predict_function vp8_bilinear_predict8x4_c;
+extern subpixel_predict_function vp8_bilinear_predict8x8_c;
+extern subpixel_predict_function vp8_bilinear_predict16x16_c;
+
+extern copy_mem_block_function vp8_copy_mem16x16_c;
+extern copy_mem_block_function vp8_copy_mem8x8_c;
+extern copy_mem_block_function vp8_copy_mem8x4_c;
+
+void vp8_recon_b_c(short *diff_ptr, unsigned char *pred_ptr, unsigned char *dst_ptr, int stride);
+void vp8_recon2b_c(short *diff_ptr, unsigned char *pred_ptr, unsigned char *dst_ptr, int stride);
+void vp8_recon4b_c(short *diff_ptr, unsigned char *pred_ptr, unsigned char *dst_ptr, int stride);
+
+extern void vp8_short_idct4x4llm_1_c(short *input, short *output, int pitch);
+extern void vp8_short_idct4x4llm_c(short *input, short *output, int pitch);
+extern void vp8_dc_only_idct_c(short input_dc, short *output, int pitch);
+
+// PPC
+extern loop_filter_block_function loop_filter_mbv_ppc;
+extern loop_filter_block_function loop_filter_bv_ppc;
+extern loop_filter_block_function loop_filter_mbh_ppc;
+extern loop_filter_block_function loop_filter_bh_ppc;
+
+extern loop_filter_block_function loop_filter_mbvs_ppc;
+extern loop_filter_block_function loop_filter_bvs_ppc;
+extern loop_filter_block_function loop_filter_mbhs_ppc;
+extern loop_filter_block_function loop_filter_bhs_ppc;
+
+// Generic C
+extern loop_filter_block_function vp8_loop_filter_mbv_c;
+extern loop_filter_block_function vp8_loop_filter_bv_c;
+extern loop_filter_block_function vp8_loop_filter_mbh_c;
+extern loop_filter_block_function vp8_loop_filter_bh_c;
+
+extern loop_filter_block_function vp8_loop_filter_mbvs_c;
+extern loop_filter_block_function vp8_loop_filter_bvs_c;
+extern loop_filter_block_function vp8_loop_filter_mbhs_c;
+extern loop_filter_block_function vp8_loop_filter_bhs_c;
+
+extern loop_filter_block_function *vp8_lf_mbvfull;
+extern loop_filter_block_function *vp8_lf_mbhfull;
+extern loop_filter_block_function *vp8_lf_bvfull;
+extern loop_filter_block_function *vp8_lf_bhfull;
+
+extern loop_filter_block_function *vp8_lf_mbvsimple;
+extern loop_filter_block_function *vp8_lf_mbhsimple;
+extern loop_filter_block_function *vp8_lf_bvsimple;
+extern loop_filter_block_function *vp8_lf_bhsimple;
+
+void vp8_clear_c(void)
+{
+}
+
+void vp8_machine_specific_config(void)
+{
+    // Pure C:
+    vp8_clear_system_state                = vp8_clear_c;
+    vp8_recon_b                          = vp8_recon_b_c;
+    vp8_recon4b                         = vp8_recon4b_c;
+    vp8_recon2b                         = vp8_recon2b_c;
+
+    vp8_bilinear_predict16x16            = bilinear_predict16x16_ppc;
+    vp8_bilinear_predict8x8              = bilinear_predict8x8_ppc;
+    vp8_bilinear_predict8x4              = bilinear_predict8x4_ppc;
+    vp8_bilinear_predict                 = bilinear_predict4x4_ppc;
+
+    vp8_sixtap_predict16x16              = sixtap_predict16x16_ppc;
+    vp8_sixtap_predict8x8                = sixtap_predict8x8_ppc;
+    vp8_sixtap_predict8x4                = sixtap_predict8x4_ppc;
+    vp8_sixtap_predict                   = sixtap_predict_ppc;
+
+    vp8_short_idct4x4_1                  = vp8_short_idct4x4llm_1_c;
+    vp8_short_idct4x4                    = short_idct4x4llm_ppc;
+    vp8_dc_only_idct                      = vp8_dc_only_idct_c;
+
+    vp8_lf_mbvfull                       = loop_filter_mbv_ppc;
+    vp8_lf_bvfull                        = loop_filter_bv_ppc;
+    vp8_lf_mbhfull                       = loop_filter_mbh_ppc;
+    vp8_lf_bhfull                        = loop_filter_bh_ppc;
+
+    vp8_lf_mbvsimple                     = loop_filter_mbvs_ppc;
+    vp8_lf_bvsimple                      = loop_filter_bvs_ppc;
+    vp8_lf_mbhsimple                     = loop_filter_mbhs_ppc;
+    vp8_lf_bhsimple                      = loop_filter_bhs_ppc;
+
+    vp8_post_proc_down_and_across           = vp8_post_proc_down_and_across_c;
+    vp8_mbpost_proc_down                  = vp8_mbpost_proc_down_c;
+    vp8_mbpost_proc_across_ip              = vp8_mbpost_proc_across_ip_c;
+    vp8_plane_add_noise                   = vp8_plane_add_noise_c;
+
+    vp8_copy_mem16x16                    = copy_mem16x16_ppc;
+    vp8_copy_mem8x8                      = vp8_copy_mem8x8_c;
+    vp8_copy_mem8x4                      = vp8_copy_mem8x4_c;
+
+}
diff --git a/vp8/common/ppflags.h b/vp8/common/ppflags.h
new file mode 100644
index 0000000..c663976
--- /dev/null
+++ b/vp8/common/ppflags.h
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_PPFLAGS_H
+#define __INC_PPFLAGS_H
+enum
+{
+    VP8D_NOFILTERING    = 0,
+    VP8D_DEBLOCK        = 1,
+    VP8D_DEMACROBLOCK   = 2,
+    VP8D_ADDNOISE       = 4,
+    VP8D_DEBUG_LEVEL1   = 8,
+    VP8D_DEBUG_LEVEL2   = 16,
+    VP8D_DEBUG_LEVEL3   = 32,
+    VP8D_DEBUG_LEVEL4   = 64,
+};
+
+#endif
diff --git a/vp8/common/pragmas.h b/vp8/common/pragmas.h
new file mode 100644
index 0000000..25a4b77
--- /dev/null
+++ b/vp8/common/pragmas.h
@@ -0,0 +1,18 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+
+
+#ifdef __INTEL_COMPILER
+#pragma warning(disable:997 1011 170)
+#endif
+#ifdef _MSC_VER
+#pragma warning(disable:4799)
+#endif
diff --git a/vp8/common/predictdc.c b/vp8/common/predictdc.c
new file mode 100644
index 0000000..df4c96e
--- /dev/null
+++ b/vp8/common/predictdc.c
@@ -0,0 +1,43 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <stdlib.h>
+#include "blockd.h"
+
+
+void vp8_predict_dc(short *lastdc, short *thisdc, short quant, short *cons)
+{
+    int diff;
+    int sign;
+    int last_dc = *lastdc;
+    int this_dc = *thisdc;
+
+    if (*cons  > DCPREDCNTTHRESH)
+    {
+        this_dc += last_dc;
+    }
+
+    diff = abs(last_dc - this_dc);
+    sign  = (last_dc >> 31) ^(this_dc >> 31);
+    sign |= (!last_dc | !this_dc);
+
+    if (sign)
+    {
+        *cons = 0;
+    }
+    else
+    {
+        if (diff <= DCPREDSIMTHRESH * quant)
+            (*cons)++ ;
+    }
+
+    *thisdc = this_dc;
+    *lastdc = this_dc;
+}
diff --git a/vp8/common/predictdc.h b/vp8/common/predictdc.h
new file mode 100644
index 0000000..b8871e4
--- /dev/null
+++ b/vp8/common/predictdc.h
@@ -0,0 +1,17 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __PREDICTDC_H
+#define __PREDICTDC_H
+
+void uvvp8_predict_dc(short *lastdc, short *thisdc, short quant, short *cons);
+void vp8_predict_dc(short *lastdc, short *thisdc, short quant, short *cons);
+
+#endif
diff --git a/vp8/common/preproc.h b/vp8/common/preproc.h
new file mode 100644
index 0000000..00ec9a8
--- /dev/null
+++ b/vp8/common/preproc.h
@@ -0,0 +1,45 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/****************************************************************************
+*
+*   Module Title :     preproc.h
+*
+*   Description  :     simple preprocessor
+*
+****************************************************************************/
+
+#ifndef __INC_PREPROC_H
+#define __INC_PREPROC_H
+
+/****************************************************************************
+*  Types
+****************************************************************************/
+
+typedef struct
+{
+    unsigned char *frame_buffer;
+    int frame;
+    unsigned int *fixed_divide;
+
+    unsigned char *frame_buffer_alloc;
+    unsigned int *fixed_divide_alloc;
+} pre_proc_instance;
+
+/****************************************************************************
+*  Functions.
+****************************************************************************/
+void pre_proc_machine_specific_config(void);
+void delete_pre_proc(pre_proc_instance *ppi);
+int init_pre_proc(pre_proc_instance *ppi, int frame_size);
+extern void spatial_filter_c(pre_proc_instance *ppi, unsigned char *s, unsigned char *d, int width, int height, int pitch, int strength);
+extern void (*temp_filter)(pre_proc_instance *ppi, unsigned char *s, unsigned char *d, int bytes, int strength);
+
+#endif
diff --git a/vp8/common/preprocif.h b/vp8/common/preprocif.h
new file mode 100644
index 0000000..986c45b
--- /dev/null
+++ b/vp8/common/preprocif.h
@@ -0,0 +1,75 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/****************************************************************************
+*
+*   Module Title :     preproc_if.h
+*
+*   Description  :     Pre-processor interface header file.
+*
+****************************************************************************/
+
+#ifndef __PREPROC_IF_H
+#define __PREPROC_IF_H
+
+/****************************************************************************
+*  Header Files
+****************************************************************************/
+#include "type_aliases.h"
+
+/****************************************************************************
+*  Types
+****************************************************************************/
+
+typedef struct
+{
+    UINT8 *Yuv0ptr;
+    UINT8 *Yuv1ptr;
+
+    UINT8   *frag_info;              // blocks coded : passed in
+    UINT32   frag_info_element_size;   // size of each element
+    UINT32   frag_info_coded_mask;     // mask to get at whether fragment is coded
+
+    UINT32 *region_index;            // Gives pixel index for top left of each block
+    UINT32 video_frame_height;
+    UINT32 video_frame_width;
+    UINT8 hfrag_pixels;
+    UINT8 vfrag_pixels;
+
+} SCAN_CONFIG_DATA;
+
+typedef enum
+{
+    SCP_FILTER_ON_OFF,
+    SCP_SET_SRF_OFFSET,
+    SCP_SET_EBO_ON_OFF,
+    SCP_SET_VCAP_LEVEL_OFFSET,
+    SCP_SET_SHOW_LOCAL
+
+} SCP_SETTINGS;
+
+typedef struct PP_INSTANCE *x_pp_inst;
+
+/****************************************************************************
+*  Module statics
+****************************************************************************/
+/* Controls whether Early break out is on or off in default case */
+#define EARLY_BREAKOUT_DEFAULT  TRUE
+
+/****************************************************************************
+*  Functions
+****************************************************************************/
+extern  void set_scan_param(x_pp_inst ppi, UINT32 param_id, INT32 param_value);
+extern  UINT32 yuvanalyse_frame(x_pp_inst ppi, UINT32 *KFIndicator);
+extern  x_pp_inst create_pp_instance(void);
+extern  void delete_pp_instance(x_pp_inst *);
+extern  BOOL scan_yuvinit(x_pp_inst,  SCAN_CONFIG_DATA *scan_config_ptr);
+
+#endif
diff --git a/vp8/common/proposed.h b/vp8/common/proposed.h
new file mode 100644
index 0000000..1171ede
--- /dev/null
+++ b/vp8/common/proposed.h
@@ -0,0 +1,70 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+typedef struct core_codec *codec_ptr;
+typedef struct interface_table *interface_ptr;
+
+typedef struct
+{
+    void (*Initialize)();
+    void (*Shutdown)();
+    codec_ptr(*Create)();
+    int (*compress_frame)(codec_ptr, unsigned int *frame_flags, YV12_BUFFER_CONFIG *sd, unsigned long *size, char *dest, INT64 time_stamp);
+    int (*show_frame)(codec_ptr , YV12_BUFFER_CONFIG *dest, int deblock_level, int noise_level, int flags);
+    void (*Remove)(codec_ptr *comp);
+    interface_ptr(*get_interface)(unsigned int id);
+
+} core_codec;
+
+typedef struct
+{
+    int (*set_bitrate)(codec_ptr, END_USAGE usage, int Datarate);
+    int (*get_bitrate)(codec_ptr, END_USAGE *usage, int *Datarate);
+    int (*set_mode)(codec_ptr, MODE mode, int Speed, char *File);
+    int (*get_mode)(codec_ptr, MODE *mode, int *Speed, char **File);
+} codec_settings_basic;
+
+typedef struct
+{
+    int (*set_bitrate)(codec_ptr, END_USAGE usage, int Datarate);
+    int (*get_bitrate)(codec_ptr, END_USAGE *usage, int *Datarate);
+    int (*set_mode)(codec_ptr, MODE  mode, int  Speed, char   *File);
+    int (*get_mode)(codec_ptr, MODE *mode, int *Speed, char **File);
+    int (*set_denoise)(codec_ptr, int  Level);
+    int (*get_denoise)(codec_ptr, int *Level);
+    int (*set_sharpness)(codec_ptr, int  sharpness);
+    int (*get_sharpness)(codec_ptr, int *sharpness);
+    int (*set_keyframing)(codec_ptr, int  Auto, int  max_distance);
+    int (*get_keyframing)(codec_ptr, int *Auto, int *max_distance);
+    int (*set_buffering)(codec_ptr, int  buffer_level, int  max_buffer_level);
+    int (*get_buffering)(codec_ptr, int *buffer_level, int *max_buffer_level);
+    int (*set_adjust_frame_rate)(codec_ptr, int Allowed, int at_buffer_level_pct);
+    int (*get_adjust_frame_rate)(codec_ptr, int *Allowed, int *at_buffer_level_pct);
+    int (*set_adjust_frame_size)(codec_ptr, int Allowed, int down_at_buffer_level_pct, int up_at_buffer_level_pct);
+    int (*get_adjust_frame_size)(codec_ptr, int *Allowed, int *down_at_buffer_level_pct, int *up_at_buffer_level_pct);
+    int (*set_adjust_quality)(codec_ptr, int Allowed, int min_quantizer, int max_quantizer);
+    int (*get_adjust_quality)(codec_ptr, int *Allowed, int *min_quantizer, int *max_quantizer);
+    int (*set_vbrparms)(codec_ptr, int Bias, int Min, int Max);
+    int (*get_vbrparms)(codec_ptr, int *Bias, int *Min, int *Max);
+
+} codec_settings_v1;
+
+typedef struct
+{
+    int (*request_recovery)(codec_ptr);
+    int (*request_droppable)(codec_ptr);
+    int (*internal_size)(codec_ptr, VPX_SCALING Vertical, VPX_SCALING Horizontal);
+    int (*update_last)(codec_ptr);
+    int (*update_gold)(codec_ptr);
+    int (*use_only_last)(codec_ptr);
+    int (*use_only_gold)(codec_ptr);
+    int (*update_entropy)(codec_ptr);
+
+} codec_realtime_requests;
diff --git a/vp8/common/quant_common.c b/vp8/common/quant_common.c
new file mode 100644
index 0000000..09fe31f
--- /dev/null
+++ b/vp8/common/quant_common.c
@@ -0,0 +1,131 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "quant_common.h"
+
+static const int dc_qlookup[QINDEX_RANGE] =
+{
+    4,    5,    6,    7,    8,    9,   10,   10,   11,   12,   13,   14,   15,   16,   17,   17,
+    18,   19,   20,   20,   21,   21,   22,   22,   23,   23,   24,   25,   25,   26,   27,   28,
+    29,   30,   31,   32,   33,   34,   35,   36,   37,   37,   38,   39,   40,   41,   42,   43,
+    44,   45,   46,   46,   47,   48,   49,   50,   51,   52,   53,   54,   55,   56,   57,   58,
+    59,   60,   61,   62,   63,   64,   65,   66,   67,   68,   69,   70,   71,   72,   73,   74,
+    75,   76,   76,   77,   78,   79,   80,   81,   82,   83,   84,   85,   86,   87,   88,   89,
+    91,   93,   95,   96,   98,  100,  101,  102,  104,  106,  108,  110,  112,  114,  116,  118,
+    122,  124,  126,  128,  130,  132,  134,  136,  138,  140,  143,  145,  148,  151,  154,  157,
+};
+
+static const int ac_qlookup[QINDEX_RANGE] =
+{
+    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19,
+    20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35,
+    36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,   49,   50,   51,
+    52,   53,   54,   55,   56,   57,   58,   60,   62,   64,   66,   68,   70,   72,   74,   76,
+    78,   80,   82,   84,   86,   88,   90,   92,   94,   96,   98,  100,  102,  104,  106,  108,
+    110,  112,  114,  116,  119,  122,  125,  128,  131,  134,  137,  140,  143,  146,  149,  152,
+    155,  158,  161,  164,  167,  170,  173,  177,  181,  185,  189,  193,  197,  201,  205,  209,
+    213,  217,  221,  225,  229,  234,  239,  245,  249,  254,  259,  264,  269,  274,  279,  284,
+};
+
+
+int vp8_dc_quant(int QIndex, int Delta)
+{
+    int retval;
+
+    QIndex = QIndex + Delta;
+
+    if (QIndex > 127)
+        QIndex = 127;
+    else if (QIndex < 0)
+        QIndex = 0;
+
+    retval = dc_qlookup[ QIndex ];
+    return retval;
+}
+
+int vp8_dc2quant(int QIndex, int Delta)
+{
+    int retval;
+
+    QIndex = QIndex + Delta;
+
+    if (QIndex > 127)
+        QIndex = 127;
+    else if (QIndex < 0)
+        QIndex = 0;
+
+    retval = dc_qlookup[ QIndex ] * 2;
+    return retval;
+
+}
+int vp8_dc_uv_quant(int QIndex, int Delta)
+{
+    int retval;
+
+    QIndex = QIndex + Delta;
+
+    if (QIndex > 127)
+        QIndex = 127;
+    else if (QIndex < 0)
+        QIndex = 0;
+
+    retval = dc_qlookup[ QIndex ];
+
+    if (retval > 132)
+        retval = 132;
+
+    return retval;
+}
+
+int vp8_ac_yquant(int QIndex)
+{
+    int retval;
+
+    if (QIndex > 127)
+        QIndex = 127;
+    else if (QIndex < 0)
+        QIndex = 0;
+
+    retval = ac_qlookup[ QIndex ];
+    return retval;
+}
+
+int vp8_ac2quant(int QIndex, int Delta)
+{
+    int retval;
+
+    QIndex = QIndex + Delta;
+
+    if (QIndex > 127)
+        QIndex = 127;
+    else if (QIndex < 0)
+        QIndex = 0;
+
+    retval = (ac_qlookup[ QIndex ] * 155) / 100;
+
+    if (retval < 8)
+        retval = 8;
+
+    return retval;
+}
+int vp8_ac_uv_quant(int QIndex, int Delta)
+{
+    int retval;
+
+    QIndex = QIndex + Delta;
+
+    if (QIndex > 127)
+        QIndex = 127;
+    else if (QIndex < 0)
+        QIndex = 0;
+
+    retval = ac_qlookup[ QIndex ];
+    return retval;
+}
diff --git a/vp8/common/quant_common.h b/vp8/common/quant_common.h
new file mode 100644
index 0000000..0c92ce8
--- /dev/null
+++ b/vp8/common/quant_common.h
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "string.h"
+#include "blockd.h"
+#include "onyxc_int.h"
+
+extern int vp8_ac_yquant(int QIndex);
+extern int vp8_dc_quant(int QIndex, int Delta);
+extern int vp8_dc2quant(int QIndex, int Delta);
+extern int vp8_ac2quant(int QIndex, int Delta);
+extern int vp8_dc_uv_quant(int QIndex, int Delta);
+extern int vp8_ac_uv_quant(int QIndex, int Delta);
diff --git a/vp8/common/recon.c b/vp8/common/recon.c
new file mode 100644
index 0000000..d1268ea
--- /dev/null
+++ b/vp8/common/recon.c
@@ -0,0 +1,137 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "recon.h"
+#include "blockd.h"
+
+void vp8_recon_b_c
+(
+    unsigned char *pred_ptr,
+    short *diff_ptr,
+    unsigned char *dst_ptr,
+    int stride
+)
+{
+    int r, c;
+
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 4; c++)
+        {
+            int a = diff_ptr[c] + pred_ptr[c] ;
+
+            if (a < 0)
+                a = 0;
+
+            if (a > 255)
+                a = 255;
+
+            dst_ptr[c] = (unsigned char) a ;
+        }
+
+        dst_ptr += stride;
+        diff_ptr += 16;
+        pred_ptr += 16;
+    }
+}
+
+void vp8_recon4b_c
+(
+    unsigned char *pred_ptr,
+    short *diff_ptr,
+    unsigned char *dst_ptr,
+    int stride
+)
+{
+    int r, c;
+
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 16; c++)
+        {
+            int a = diff_ptr[c] + pred_ptr[c] ;
+
+            if (a < 0)
+                a = 0;
+
+            if (a > 255)
+                a = 255;
+
+            dst_ptr[c] = (unsigned char) a ;
+        }
+
+        dst_ptr += stride;
+        diff_ptr += 16;
+        pred_ptr += 16;
+    }
+}
+
+void vp8_recon2b_c
+(
+    unsigned char *pred_ptr,
+    short *diff_ptr,
+    unsigned char *dst_ptr,
+    int stride
+)
+{
+    int r, c;
+
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 8; c++)
+        {
+            int a = diff_ptr[c] + pred_ptr[c] ;
+
+            if (a < 0)
+                a = 0;
+
+            if (a > 255)
+                a = 255;
+
+            dst_ptr[c] = (unsigned char) a ;
+        }
+
+        dst_ptr += stride;
+        diff_ptr += 8;
+        pred_ptr += 8;
+    }
+}
+
+void vp8_recon16x16mby(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+    int i;
+
+    for (i = 0; i < 16; i += 4)
+    {
+        BLOCKD *b = &x->block[i];
+
+        RECON_INVOKE(rtcd, recon4)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    }
+}
+
+void vp8_recon16x16mb(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+    int i;
+
+    for (i = 0; i < 16; i += 4)
+    {
+        BLOCKD *b = &x->block[i];
+
+        RECON_INVOKE(rtcd, recon4)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    }
+
+    for (i = 16; i < 24; i += 2)
+    {
+        BLOCKD *b = &x->block[i];
+
+        RECON_INVOKE(rtcd, recon2)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    }
+}
diff --git a/vp8/common/recon.h b/vp8/common/recon.h
new file mode 100644
index 0000000..f65a90f
--- /dev/null
+++ b/vp8/common/recon.h
@@ -0,0 +1,81 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_RECON_H
+#define __INC_RECON_H
+
+#define prototype_copy_block(sym) \
+    void sym(unsigned char *src, int src_pitch, unsigned char *dst, int dst_pitch)
+
+#define prototype_recon_block(sym) \
+    void sym(unsigned char *pred, short *diff, unsigned char *dst, int pitch);
+
+#if ARCH_X86 || ARCH_X86_64
+#include "x86/recon_x86.h"
+#endif
+
+#if ARCH_ARM
+#include "arm/recon_arm.h"
+#endif
+
+#ifndef vp8_recon_copy16x16
+#define vp8_recon_copy16x16 vp8_copy_mem16x16_c
+#endif
+extern prototype_copy_block(vp8_recon_copy16x16);
+
+#ifndef vp8_recon_copy8x8
+#define vp8_recon_copy8x8 vp8_copy_mem8x8_c
+#endif
+extern prototype_copy_block(vp8_recon_copy8x8);
+
+#ifndef vp8_recon_copy8x4
+#define vp8_recon_copy8x4 vp8_copy_mem8x4_c
+#endif
+extern prototype_copy_block(vp8_recon_copy8x4);
+
+#ifndef vp8_recon_recon
+#define vp8_recon_recon vp8_recon_b_c
+#endif
+extern prototype_recon_block(vp8_recon_recon);
+
+#ifndef vp8_recon_recon2
+#define vp8_recon_recon2 vp8_recon2b_c
+#endif
+extern prototype_recon_block(vp8_recon_recon2);
+
+#ifndef vp8_recon_recon4
+#define vp8_recon_recon4 vp8_recon4b_c
+#endif
+extern prototype_recon_block(vp8_recon_recon4);
+
+typedef prototype_copy_block((*vp8_copy_block_fn_t));
+typedef prototype_recon_block((*vp8_recon_fn_t));
+typedef struct
+{
+    vp8_copy_block_fn_t  copy16x16;
+    vp8_copy_block_fn_t  copy8x8;
+    vp8_copy_block_fn_t  copy8x4;
+    vp8_recon_fn_t       recon;
+    vp8_recon_fn_t       recon2;
+    vp8_recon_fn_t       recon4;
+} vp8_recon_rtcd_vtable_t;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define RECON_INVOKE(ctx,fn) (ctx)->fn
+#else
+#define RECON_INVOKE(ctx,fn) vp8_recon_##fn
+#endif
+
+#include "blockd.h"
+void vp8_recon16x16mby(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x);
+void vp8_recon16x16mb(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x);
+void vp8_recon_intra4x4mb(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x);
+void vp8_recon_intra_mbuv(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x);
+#endif
diff --git a/vp8/common/reconinter.c b/vp8/common/reconinter.c
new file mode 100644
index 0000000..c48886d
--- /dev/null
+++ b/vp8/common/reconinter.c
@@ -0,0 +1,680 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "recon.h"
+#include "subpixel.h"
+#include "blockd.h"
+#include "reconinter.h"
+#if CONFIG_RUNTIME_CPU_DETECT
+#include "onyxc_int.h"
+#endif
+
+// use this define on systems where unaligned int reads and writes are
+// not allowed, i.e. ARM architectures
+//#define MUST_BE_ALIGNED
+
+
+static const int bbb[4] = {0, 2, 8, 10};
+
+
+
+void vp8_copy_mem16x16_c(
+    unsigned char *src,
+    int src_stride,
+    unsigned char *dst,
+    int dst_stride)
+{
+
+    int r;
+
+    for (r = 0; r < 16; r++)
+    {
+#ifdef MUST_BE_ALIGNED
+        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
+        ((int *)dst)[0] = ((int *)src)[0] ;
+        ((int *)dst)[1] = ((int *)src)[1] ;
+        ((int *)dst)[2] = ((int *)src)[2] ;
+        ((int *)dst)[3] = ((int *)src)[3] ;
+
+#endif
+        src += src_stride;
+        dst += dst_stride;
+
+    }
+
+}
+
+void vp8_copy_mem8x8_c(
+    unsigned char *src,
+    int src_stride,
+    unsigned char *dst,
+    int dst_stride)
+{
+    int r;
+
+    for (r = 0; r < 8; r++)
+    {
+#ifdef MUST_BE_ALIGNED
+        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
+        ((int *)dst)[0] = ((int *)src)[0] ;
+        ((int *)dst)[1] = ((int *)src)[1] ;
+#endif
+        src += src_stride;
+        dst += dst_stride;
+
+    }
+
+}
+
+void vp8_copy_mem8x4_c(
+    unsigned char *src,
+    int src_stride,
+    unsigned char *dst,
+    int dst_stride)
+{
+    int r;
+
+    for (r = 0; r < 4; r++)
+    {
+#ifdef MUST_BE_ALIGNED
+        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
+        ((int *)dst)[0] = ((int *)src)[0] ;
+        ((int *)dst)[1] = ((int *)src)[1] ;
+#endif
+        src += src_stride;
+        dst += dst_stride;
+
+    }
+
+}
+
+
+
+void vp8_build_inter_predictors_b(BLOCKD *d, int pitch, vp8_subpix_fn_t sppf)
+{
+    int r;
+    unsigned char *ptr_base;
+    unsigned char *ptr;
+    unsigned char *pred_ptr = d->predictor;
+
+    ptr_base = *(d->base_pre);
+
+    if (d->bmi.mv.as_mv.row & 7 || d->bmi.mv.as_mv.col & 7)
+    {
+        ptr = ptr_base + d->pre + (d->bmi.mv.as_mv.row >> 3) * d->pre_stride + (d->bmi.mv.as_mv.col >> 3);
+        sppf(ptr, d->pre_stride, d->bmi.mv.as_mv.col & 7, d->bmi.mv.as_mv.row & 7, pred_ptr, pitch);
+    }
+    else
+    {
+        ptr_base += d->pre + (d->bmi.mv.as_mv.row >> 3) * d->pre_stride + (d->bmi.mv.as_mv.col >> 3);
+        ptr = ptr_base;
+
+        for (r = 0; r < 4; r++)
+        {
+#ifdef MUST_BE_ALIGNED
+            pred_ptr[0]  = ptr[0];
+            pred_ptr[1]  = ptr[1];
+            pred_ptr[2]  = ptr[2];
+            pred_ptr[3]  = ptr[3];
+#else
+            *(int *)pred_ptr = *(int *)ptr ;
+#endif
+            pred_ptr     += pitch;
+            ptr         += d->pre_stride;
+        }
+    }
+}
+
+void vp8_build_inter_predictors4b(MACROBLOCKD *x, BLOCKD *d, int pitch)
+{
+    unsigned char *ptr_base;
+    unsigned char *ptr;
+    unsigned char *pred_ptr = d->predictor;
+
+    ptr_base = *(d->base_pre);
+    ptr = ptr_base + d->pre + (d->bmi.mv.as_mv.row >> 3) * d->pre_stride + (d->bmi.mv.as_mv.col >> 3);
+
+    if (d->bmi.mv.as_mv.row & 7 || d->bmi.mv.as_mv.col & 7)
+    {
+        x->subpixel_predict8x8(ptr, d->pre_stride, d->bmi.mv.as_mv.col & 7, d->bmi.mv.as_mv.row & 7, pred_ptr, pitch);
+    }
+    else
+    {
+        RECON_INVOKE(&x->rtcd->recon, copy8x8)(ptr, d->pre_stride, pred_ptr, pitch);
+    }
+}
+
+void vp8_build_inter_predictors2b(MACROBLOCKD *x, BLOCKD *d, int pitch)
+{
+    unsigned char *ptr_base;
+    unsigned char *ptr;
+    unsigned char *pred_ptr = d->predictor;
+
+    ptr_base = *(d->base_pre);
+    ptr = ptr_base + d->pre + (d->bmi.mv.as_mv.row >> 3) * d->pre_stride + (d->bmi.mv.as_mv.col >> 3);
+
+    if (d->bmi.mv.as_mv.row & 7 || d->bmi.mv.as_mv.col & 7)
+    {
+        x->subpixel_predict8x4(ptr, d->pre_stride, d->bmi.mv.as_mv.col & 7, d->bmi.mv.as_mv.row & 7, pred_ptr, pitch);
+    }
+    else
+    {
+        RECON_INVOKE(&x->rtcd->recon, copy8x4)(ptr, d->pre_stride, pred_ptr, pitch);
+    }
+}
+
+
+void vp8_build_inter_predictors_mbuv(MACROBLOCKD *x)
+{
+    int i;
+
+    if (x->mbmi.ref_frame != INTRA_FRAME && x->mbmi.mode != SPLITMV)
+    {
+        unsigned char *uptr, *vptr;
+        unsigned char *upred_ptr = &x->predictor[256];
+        unsigned char *vpred_ptr = &x->predictor[320];
+
+        int mv_row = x->block[16].bmi.mv.as_mv.row;
+        int mv_col = x->block[16].bmi.mv.as_mv.col;
+        int offset;
+        int pre_stride = x->block[16].pre_stride;
+
+        offset = (mv_row >> 3) * pre_stride + (mv_col >> 3);
+        uptr = x->pre.u_buffer + offset;
+        vptr = x->pre.v_buffer + offset;
+
+        if ((mv_row | mv_col) & 7)
+        {
+            x->subpixel_predict8x8(uptr, pre_stride, mv_col & 7, mv_row & 7, upred_ptr, 8);
+            x->subpixel_predict8x8(vptr, pre_stride, mv_col & 7, mv_row & 7, vpred_ptr, 8);
+        }
+        else
+        {
+            RECON_INVOKE(&x->rtcd->recon, copy8x8)(uptr, pre_stride, upred_ptr, 8);
+            RECON_INVOKE(&x->rtcd->recon, copy8x8)(vptr, pre_stride, vpred_ptr, 8);
+        }
+    }
+    else
+    {
+        for (i = 16; i < 24; i += 2)
+        {
+            BLOCKD *d0 = &x->block[i];
+            BLOCKD *d1 = &x->block[i+1];
+
+            if (d0->bmi.mv.as_int == d1->bmi.mv.as_int)
+                vp8_build_inter_predictors2b(x, d0, 8);
+            else
+            {
+                vp8_build_inter_predictors_b(d0, 8, x->subpixel_predict);
+                vp8_build_inter_predictors_b(d1, 8, x->subpixel_predict);
+            }
+        }
+    }
+}
+
+
+void vp8_build_inter_predictors_mby(MACROBLOCKD *x)
+{
+    if (x->mbmi.ref_frame != INTRA_FRAME && x->mbmi.mode != SPLITMV)
+    {
+        unsigned char *ptr_base;
+        unsigned char *ptr;
+        unsigned char *pred_ptr = x->predictor;
+        int mv_row = x->mbmi.mv.as_mv.row;
+        int mv_col = x->mbmi.mv.as_mv.col;
+        int pre_stride = x->block[0].pre_stride;
+
+        ptr_base = x->pre.y_buffer;
+        ptr = ptr_base + (mv_row >> 3) * pre_stride + (mv_col >> 3);
+
+        if ((mv_row | mv_col) & 7)
+        {
+            x->subpixel_predict16x16(ptr, pre_stride, mv_col & 7, mv_row & 7, pred_ptr, 16);
+        }
+        else
+        {
+            RECON_INVOKE(&x->rtcd->recon, copy16x16)(ptr, pre_stride, pred_ptr, 16);
+        }
+    }
+    else
+    {
+        int i;
+
+        if (x->mbmi.partitioning < 3)
+        {
+            for (i = 0; i < 4; i++)
+            {
+                BLOCKD *d = &x->block[bbb[i]];
+                vp8_build_inter_predictors4b(x, d, 16);
+            }
+
+        }
+        else
+        {
+            for (i = 0; i < 16; i += 2)
+            {
+                BLOCKD *d0 = &x->block[i];
+                BLOCKD *d1 = &x->block[i+1];
+
+                if (d0->bmi.mv.as_int == d1->bmi.mv.as_int)
+                    vp8_build_inter_predictors2b(x, d0, 16);
+                else
+                {
+                    vp8_build_inter_predictors_b(d0, 16, x->subpixel_predict);
+                    vp8_build_inter_predictors_b(d1, 16, x->subpixel_predict);
+                }
+
+            }
+        }
+    }
+}
+
+void vp8_build_inter_predictors_mb(MACROBLOCKD *x)
+{
+    if (x->mbmi.ref_frame != INTRA_FRAME && x->mbmi.mode != SPLITMV)
+    {
+        int offset;
+        unsigned char *ptr_base;
+        unsigned char *ptr;
+        unsigned char *uptr, *vptr;
+        unsigned char *pred_ptr = x->predictor;
+        unsigned char *upred_ptr = &x->predictor[256];
+        unsigned char *vpred_ptr = &x->predictor[320];
+
+        int mv_row = x->mbmi.mv.as_mv.row;
+        int mv_col = x->mbmi.mv.as_mv.col;
+        int pre_stride = x->block[0].pre_stride;
+
+        ptr_base = x->pre.y_buffer;
+        ptr = ptr_base + (mv_row >> 3) * pre_stride + (mv_col >> 3);
+
+        if ((mv_row | mv_col) & 7)
+        {
+            x->subpixel_predict16x16(ptr, pre_stride, mv_col & 7, mv_row & 7, pred_ptr, 16);
+        }
+        else
+        {
+            RECON_INVOKE(&x->rtcd->recon, copy16x16)(ptr, pre_stride, pred_ptr, 16);
+        }
+
+        mv_row = x->block[16].bmi.mv.as_mv.row;
+        mv_col = x->block[16].bmi.mv.as_mv.col;
+        pre_stride >>= 1;
+        offset = (mv_row >> 3) * pre_stride + (mv_col >> 3);
+        uptr = x->pre.u_buffer + offset;
+        vptr = x->pre.v_buffer + offset;
+
+        if ((mv_row | mv_col) & 7)
+        {
+            x->subpixel_predict8x8(uptr, pre_stride, mv_col & 7, mv_row & 7, upred_ptr, 8);
+            x->subpixel_predict8x8(vptr, pre_stride, mv_col & 7, mv_row & 7, vpred_ptr, 8);
+        }
+        else
+        {
+            RECON_INVOKE(&x->rtcd->recon, copy8x8)(uptr, pre_stride, upred_ptr, 8);
+            RECON_INVOKE(&x->rtcd->recon, copy8x8)(vptr, pre_stride, vpred_ptr, 8);
+        }
+    }
+    else
+    {
+        int i;
+
+        if (x->mbmi.partitioning < 3)
+        {
+            for (i = 0; i < 4; i++)
+            {
+                BLOCKD *d = &x->block[bbb[i]];
+                vp8_build_inter_predictors4b(x, d, 16);
+            }
+        }
+        else
+        {
+            for (i = 0; i < 16; i += 2)
+            {
+                BLOCKD *d0 = &x->block[i];
+                BLOCKD *d1 = &x->block[i+1];
+
+                if (d0->bmi.mv.as_int == d1->bmi.mv.as_int)
+                    vp8_build_inter_predictors2b(x, d0, 16);
+                else
+                {
+                    vp8_build_inter_predictors_b(d0, 16, x->subpixel_predict);
+                    vp8_build_inter_predictors_b(d1, 16, x->subpixel_predict);
+                }
+
+            }
+
+        }
+
+        for (i = 16; i < 24; i += 2)
+        {
+            BLOCKD *d0 = &x->block[i];
+            BLOCKD *d1 = &x->block[i+1];
+
+            if (d0->bmi.mv.as_int == d1->bmi.mv.as_int)
+                vp8_build_inter_predictors2b(x, d0, 8);
+            else
+            {
+                vp8_build_inter_predictors_b(d0, 8, x->subpixel_predict);
+                vp8_build_inter_predictors_b(d1, 8, x->subpixel_predict);
+            }
+
+        }
+
+    }
+}
+
+void vp8_build_uvmvs(MACROBLOCKD *x, int fullpixel)
+{
+    int i, j;
+
+    if (x->mbmi.mode == SPLITMV)
+    {
+        for (i = 0; i < 2; i++)
+        {
+            for (j = 0; j < 2; j++)
+            {
+                int yoffset = i * 8 + j * 2;
+                int uoffset = 16 + i * 2 + j;
+                int voffset = 20 + i * 2 + j;
+
+                int temp;
+
+                temp = x->block[yoffset  ].bmi.mv.as_mv.row
+                       + x->block[yoffset+1].bmi.mv.as_mv.row
+                       + x->block[yoffset+4].bmi.mv.as_mv.row
+                       + x->block[yoffset+5].bmi.mv.as_mv.row;
+
+                if (temp < 0) temp -= 4;
+                else temp += 4;
+
+                x->block[uoffset].bmi.mv.as_mv.row = temp / 8;
+
+                if (fullpixel)
+                    x->block[uoffset].bmi.mv.as_mv.row = (temp / 8) & 0xfffffff8;
+
+                temp = x->block[yoffset  ].bmi.mv.as_mv.col
+                       + x->block[yoffset+1].bmi.mv.as_mv.col
+                       + x->block[yoffset+4].bmi.mv.as_mv.col
+                       + x->block[yoffset+5].bmi.mv.as_mv.col;
+
+                if (temp < 0) temp -= 4;
+                else temp += 4;
+
+                x->block[uoffset].bmi.mv.as_mv.col = temp / 8;
+
+                if (fullpixel)
+                    x->block[uoffset].bmi.mv.as_mv.col = (temp / 8) & 0xfffffff8;
+
+                x->block[voffset].bmi.mv.as_mv.row = x->block[uoffset].bmi.mv.as_mv.row ;
+                x->block[voffset].bmi.mv.as_mv.col = x->block[uoffset].bmi.mv.as_mv.col ;
+            }
+        }
+    }
+    else
+    {
+        int mvrow = x->mbmi.mv.as_mv.row;
+        int mvcol = x->mbmi.mv.as_mv.col;
+
+        if (mvrow < 0)
+            mvrow -= 1;
+        else
+            mvrow += 1;
+
+        if (mvcol < 0)
+            mvcol -= 1;
+        else
+            mvcol += 1;
+
+        mvrow /= 2;
+        mvcol /= 2;
+
+        for (i = 0; i < 8; i++)
+        {
+            x->block[ 16 + i].bmi.mv.as_mv.row = mvrow;
+            x->block[ 16 + i].bmi.mv.as_mv.col = mvcol;
+
+            if (fullpixel)
+            {
+                x->block[ 16 + i].bmi.mv.as_mv.row = mvrow & 0xfffffff8;
+                x->block[ 16 + i].bmi.mv.as_mv.col = mvcol & 0xfffffff8;
+            }
+        }
+    }
+}
+
+
+// The following functions are wriiten for skip_recon_mb() to call. Since there is no recon in this
+// situation, we can write the result directly to dst buffer instead of writing it to predictor
+// buffer and then copying it to dst buffer.
+static void vp8_build_inter_predictors_b_s(BLOCKD *d, unsigned char *dst_ptr, vp8_subpix_fn_t sppf)
+{
+    int r;
+    unsigned char *ptr_base;
+    unsigned char *ptr;
+    //unsigned char *pred_ptr = d->predictor;
+    int dst_stride = d->dst_stride;
+    int pre_stride = d->pre_stride;
+
+    ptr_base = *(d->base_pre);
+
+    if (d->bmi.mv.as_mv.row & 7 || d->bmi.mv.as_mv.col & 7)
+    {
+        ptr = ptr_base + d->pre + (d->bmi.mv.as_mv.row >> 3) * d->pre_stride + (d->bmi.mv.as_mv.col >> 3);
+        sppf(ptr, pre_stride, d->bmi.mv.as_mv.col & 7, d->bmi.mv.as_mv.row & 7, dst_ptr, dst_stride);
+    }
+    else
+    {
+        ptr_base += d->pre + (d->bmi.mv.as_mv.row >> 3) * d->pre_stride + (d->bmi.mv.as_mv.col >> 3);
+        ptr = ptr_base;
+
+        for (r = 0; r < 4; r++)
+        {
+#ifdef MUST_BE_ALIGNED
+            dst_ptr[0]   = ptr[0];
+            dst_ptr[1]   = ptr[1];
+            dst_ptr[2]   = ptr[2];
+            dst_ptr[3]   = ptr[3];
+#else
+            *(int *)dst_ptr = *(int *)ptr ;
+#endif
+            dst_ptr      += dst_stride;
+            ptr         += pre_stride;
+        }
+    }
+}
+
+
+
+void vp8_build_inter_predictors_mb_s(MACROBLOCKD *x)
+{
+    //unsigned char *pred_ptr = x->block[0].predictor;
+    //unsigned char *dst_ptr = *(x->block[0].base_dst) + x->block[0].dst;
+    unsigned char *pred_ptr = x->predictor;
+    unsigned char *dst_ptr = x->dst.y_buffer;
+
+    if (x->mbmi.mode != SPLITMV)
+    {
+        int offset;
+        unsigned char *ptr_base;
+        unsigned char *ptr;
+        unsigned char *uptr, *vptr;
+        //unsigned char *pred_ptr = x->predictor;
+        //unsigned char *upred_ptr = &x->predictor[256];
+        //unsigned char *vpred_ptr = &x->predictor[320];
+        unsigned char *udst_ptr = x->dst.u_buffer;
+        unsigned char *vdst_ptr = x->dst.v_buffer;
+
+        int mv_row = x->mbmi.mv.as_mv.row;
+        int mv_col = x->mbmi.mv.as_mv.col;
+        int pre_stride = x->dst.y_stride; //x->block[0].pre_stride;
+
+        ptr_base = x->pre.y_buffer;
+        ptr = ptr_base + (mv_row >> 3) * pre_stride + (mv_col >> 3);
+
+        if ((mv_row | mv_col) & 7)
+        {
+            x->subpixel_predict16x16(ptr, pre_stride, mv_col & 7, mv_row & 7, dst_ptr, x->dst.y_stride); //x->block[0].dst_stride);
+        }
+        else
+        {
+            RECON_INVOKE(&x->rtcd->recon, copy16x16)(ptr, pre_stride, dst_ptr, x->dst.y_stride); //x->block[0].dst_stride);
+        }
+
+        mv_row = x->block[16].bmi.mv.as_mv.row;
+        mv_col = x->block[16].bmi.mv.as_mv.col;
+        pre_stride >>= 1;
+        offset = (mv_row >> 3) * pre_stride + (mv_col >> 3);
+        uptr = x->pre.u_buffer + offset;
+        vptr = x->pre.v_buffer + offset;
+
+        if ((mv_row | mv_col) & 7)
+        {
+            x->subpixel_predict8x8(uptr, pre_stride, mv_col & 7, mv_row & 7, udst_ptr, x->dst.uv_stride);
+            x->subpixel_predict8x8(vptr, pre_stride, mv_col & 7, mv_row & 7, vdst_ptr, x->dst.uv_stride);
+        }
+        else
+        {
+            RECON_INVOKE(&x->rtcd->recon, copy8x8)(uptr, pre_stride, udst_ptr, x->dst.uv_stride);
+            RECON_INVOKE(&x->rtcd->recon, copy8x8)(vptr, pre_stride, vdst_ptr, x->dst.uv_stride);
+        }
+    }
+    else
+    {
+        //note: this whole ELSE part is not executed at all. So, no way to test the correctness of my modification. Later,
+        //if sth is wrong, go back to what it is in build_inter_predictors_mb.
+        int i;
+
+        if (x->mbmi.partitioning < 3)
+        {
+            for (i = 0; i < 4; i++)
+            {
+                BLOCKD *d = &x->block[bbb[i]];
+                //vp8_build_inter_predictors4b(x, d, 16);
+
+                {
+                    unsigned char *ptr_base;
+                    unsigned char *ptr;
+                    unsigned char *pred_ptr = d->predictor;
+
+                    ptr_base = *(d->base_pre);
+                    ptr = ptr_base + d->pre + (d->bmi.mv.as_mv.row >> 3) * d->pre_stride + (d->bmi.mv.as_mv.col >> 3);
+
+                    if (d->bmi.mv.as_mv.row & 7 || d->bmi.mv.as_mv.col & 7)
+                    {
+                        x->subpixel_predict8x8(ptr, d->pre_stride, d->bmi.mv.as_mv.col & 7, d->bmi.mv.as_mv.row & 7, dst_ptr, x->dst.y_stride); //x->block[0].dst_stride);
+                    }
+                    else
+                    {
+                        RECON_INVOKE(&x->rtcd->recon, copy8x8)(ptr, d->pre_stride, dst_ptr, x->dst.y_stride); //x->block[0].dst_stride);
+                    }
+                }
+            }
+        }
+        else
+        {
+            for (i = 0; i < 16; i += 2)
+            {
+                BLOCKD *d0 = &x->block[i];
+                BLOCKD *d1 = &x->block[i+1];
+
+                if (d0->bmi.mv.as_int == d1->bmi.mv.as_int)
+                {
+                    //vp8_build_inter_predictors2b(x, d0, 16);
+                    unsigned char *ptr_base;
+                    unsigned char *ptr;
+                    unsigned char *pred_ptr = d0->predictor;
+
+                    ptr_base = *(d0->base_pre);
+                    ptr = ptr_base + d0->pre + (d0->bmi.mv.as_mv.row >> 3) * d0->pre_stride + (d0->bmi.mv.as_mv.col >> 3);
+
+                    if (d0->bmi.mv.as_mv.row & 7 || d0->bmi.mv.as_mv.col & 7)
+                    {
+                        x->subpixel_predict8x4(ptr, d0->pre_stride, d0->bmi.mv.as_mv.col & 7, d0->bmi.mv.as_mv.row & 7, dst_ptr, x->dst.y_stride);
+                    }
+                    else
+                    {
+                        RECON_INVOKE(&x->rtcd->recon, copy8x4)(ptr, d0->pre_stride, dst_ptr, x->dst.y_stride);
+                    }
+                }
+                else
+                {
+                    vp8_build_inter_predictors_b_s(d0, dst_ptr, x->subpixel_predict);
+                    vp8_build_inter_predictors_b_s(d1, dst_ptr, x->subpixel_predict);
+                }
+            }
+        }
+
+        for (i = 16; i < 24; i += 2)
+        {
+            BLOCKD *d0 = &x->block[i];
+            BLOCKD *d1 = &x->block[i+1];
+
+            if (d0->bmi.mv.as_int == d1->bmi.mv.as_int)
+            {
+                //vp8_build_inter_predictors2b(x, d0, 8);
+                unsigned char *ptr_base;
+                unsigned char *ptr;
+                unsigned char *pred_ptr = d0->predictor;
+
+                ptr_base = *(d0->base_pre);
+                ptr = ptr_base + d0->pre + (d0->bmi.mv.as_mv.row >> 3) * d0->pre_stride + (d0->bmi.mv.as_mv.col >> 3);
+
+                if (d0->bmi.mv.as_mv.row & 7 || d0->bmi.mv.as_mv.col & 7)
+                {
+                    x->subpixel_predict8x4(ptr, d0->pre_stride, d0->bmi.mv.as_mv.col & 7, d0->bmi.mv.as_mv.row & 7, dst_ptr, x->dst.y_stride);
+                }
+                else
+                {
+                    RECON_INVOKE(&x->rtcd->recon, copy8x4)(ptr, d0->pre_stride, dst_ptr, x->dst.y_stride);
+                }
+            }
+            else
+            {
+                vp8_build_inter_predictors_b_s(d0, dst_ptr, x->subpixel_predict);
+                vp8_build_inter_predictors_b_s(d1, dst_ptr, x->subpixel_predict);
+            }
+        }
+    }
+}
diff --git a/vp8/common/reconinter.h b/vp8/common/reconinter.h
new file mode 100644
index 0000000..b2d1ae9
--- /dev/null
+++ b/vp8/common/reconinter.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_RECONINTER_H
+#define __INC_RECONINTER_H
+
+extern void vp8_build_inter_predictors_mb(MACROBLOCKD *x);
+extern void vp8_build_inter_predictors_mb_s(MACROBLOCKD *x);
+
+extern void vp8_build_inter_predictors_mby(MACROBLOCKD *x);
+extern void vp8_build_uvmvs(MACROBLOCKD *x, int fullpixel);
+extern void vp8_build_inter_predictors_b(BLOCKD *d, int pitch, vp8_subpix_fn_t sppf);
+extern void vp8_build_inter_predictors_mbuv(MACROBLOCKD *x);
+
+#endif
diff --git a/vp8/common/reconintra.c b/vp8/common/reconintra.c
new file mode 100644
index 0000000..e33bce3
--- /dev/null
+++ b/vp8/common/reconintra.c
@@ -0,0 +1,555 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "recon.h"
+#include "reconintra.h"
+#include "vpx_mem/vpx_mem.h"
+
+// For skip_recon_mb(), add vp8_build_intra_predictors_mby_s(MACROBLOCKD *x) and
+// vp8_build_intra_predictors_mbuv_s(MACROBLOCKD *x).
+
+void vp8_recon_intra_mbuv(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+    int i;
+
+    for (i = 16; i < 24; i += 2)
+    {
+        BLOCKD *b = &x->block[i];
+        RECON_INVOKE(rtcd, recon2)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    }
+}
+
+void vp8_build_intra_predictors_mby(MACROBLOCKD *x)
+{
+
+    unsigned char *yabove_row = x->dst.y_buffer - x->dst.y_stride;
+    unsigned char yleft_col[16];
+    unsigned char ytop_left = yabove_row[-1];
+    unsigned char *ypred_ptr = x->predictor;
+    int r, c, i;
+
+    for (i = 0; i < 16; i++)
+    {
+        yleft_col[i] = x->dst.y_buffer [i* x->dst.y_stride -1];
+    }
+
+    // for Y
+    switch (x->mbmi.mode)
+    {
+    case DC_PRED:
+    {
+        int expected_dc;
+        int i;
+        int shift;
+        int average = 0;
+
+
+        if (x->up_available || x->left_available)
+        {
+            if (x->up_available)
+            {
+                for (i = 0; i < 16; i++)
+                {
+                    average += yabove_row[i];
+                }
+            }
+
+            if (x->left_available)
+            {
+
+                for (i = 0; i < 16; i++)
+                {
+                    average += yleft_col[i];
+                }
+
+            }
+
+
+
+            shift = 3 + x->up_available + x->left_available;
+            expected_dc = (average + (1 << (shift - 1))) >> shift;
+        }
+        else
+        {
+            expected_dc = 128;
+        }
+
+        vpx_memset(ypred_ptr, expected_dc, 256);
+    }
+    break;
+    case V_PRED:
+    {
+
+        for (r = 0; r < 16; r++)
+        {
+
+            ((int *)ypred_ptr)[0] = ((int *)yabove_row)[0];
+            ((int *)ypred_ptr)[1] = ((int *)yabove_row)[1];
+            ((int *)ypred_ptr)[2] = ((int *)yabove_row)[2];
+            ((int *)ypred_ptr)[3] = ((int *)yabove_row)[3];
+            ypred_ptr += 16;
+        }
+    }
+    break;
+    case H_PRED:
+    {
+
+        for (r = 0; r < 16; r++)
+        {
+
+            vpx_memset(ypred_ptr, yleft_col[r], 16);
+            ypred_ptr += 16;
+        }
+
+    }
+    break;
+    case TM_PRED:
+    {
+
+        for (r = 0; r < 16; r++)
+        {
+            for (c = 0; c < 16; c++)
+            {
+                int pred =  yleft_col[r] + yabove_row[ c] - ytop_left;
+
+                if (pred < 0)
+                    pred = 0;
+
+                if (pred > 255)
+                    pred = 255;
+
+                ypred_ptr[c] = pred;
+            }
+
+            ypred_ptr += 16;
+        }
+
+    }
+    break;
+    case B_PRED:
+    case NEARESTMV:
+    case NEARMV:
+    case ZEROMV:
+    case NEWMV:
+    case SPLITMV:
+    case MB_MODE_COUNT:
+        break;
+    }
+}
+
+void vp8_build_intra_predictors_mby_s(MACROBLOCKD *x)
+{
+
+    unsigned char *yabove_row = x->dst.y_buffer - x->dst.y_stride;
+    unsigned char yleft_col[16];
+    unsigned char ytop_left = yabove_row[-1];
+    unsigned char *ypred_ptr = x->predictor;
+    int r, c, i;
+
+    int y_stride = x->dst.y_stride;
+    ypred_ptr = x->dst.y_buffer; //x->predictor;
+
+    for (i = 0; i < 16; i++)
+    {
+        yleft_col[i] = x->dst.y_buffer [i* x->dst.y_stride -1];
+    }
+
+    // for Y
+    switch (x->mbmi.mode)
+    {
+    case DC_PRED:
+    {
+        int expected_dc;
+        int i;
+        int shift;
+        int average = 0;
+
+
+        if (x->up_available || x->left_available)
+        {
+            if (x->up_available)
+            {
+                for (i = 0; i < 16; i++)
+                {
+                    average += yabove_row[i];
+                }
+            }
+
+            if (x->left_available)
+            {
+
+                for (i = 0; i < 16; i++)
+                {
+                    average += yleft_col[i];
+                }
+
+            }
+
+
+
+            shift = 3 + x->up_available + x->left_available;
+            expected_dc = (average + (1 << (shift - 1))) >> shift;
+        }
+        else
+        {
+            expected_dc = 128;
+        }
+
+        //vpx_memset(ypred_ptr, expected_dc, 256);
+        for (r = 0; r < 16; r++)
+        {
+            vpx_memset(ypred_ptr, expected_dc, 16);
+            ypred_ptr += y_stride; //16;
+        }
+    }
+    break;
+    case V_PRED:
+    {
+
+        for (r = 0; r < 16; r++)
+        {
+
+            ((int *)ypred_ptr)[0] = ((int *)yabove_row)[0];
+            ((int *)ypred_ptr)[1] = ((int *)yabove_row)[1];
+            ((int *)ypred_ptr)[2] = ((int *)yabove_row)[2];
+            ((int *)ypred_ptr)[3] = ((int *)yabove_row)[3];
+            ypred_ptr += y_stride; //16;
+        }
+    }
+    break;
+    case H_PRED:
+    {
+
+        for (r = 0; r < 16; r++)
+        {
+
+            vpx_memset(ypred_ptr, yleft_col[r], 16);
+            ypred_ptr += y_stride;  //16;
+        }
+
+    }
+    break;
+    case TM_PRED:
+    {
+
+        for (r = 0; r < 16; r++)
+        {
+            for (c = 0; c < 16; c++)
+            {
+                int pred =  yleft_col[r] + yabove_row[ c] - ytop_left;
+
+                if (pred < 0)
+                    pred = 0;
+
+                if (pred > 255)
+                    pred = 255;
+
+                ypred_ptr[c] = pred;
+            }
+
+            ypred_ptr += y_stride;  //16;
+        }
+
+    }
+    break;
+    case B_PRED:
+    case NEARESTMV:
+    case NEARMV:
+    case ZEROMV:
+    case NEWMV:
+    case SPLITMV:
+    case MB_MODE_COUNT:
+        break;
+    }
+}
+
+void vp8_build_intra_predictors_mbuv(MACROBLOCKD *x)
+{
+    unsigned char *uabove_row = x->dst.u_buffer - x->dst.uv_stride;
+    unsigned char uleft_col[16];
+    unsigned char utop_left = uabove_row[-1];
+    unsigned char *vabove_row = x->dst.v_buffer - x->dst.uv_stride;
+    unsigned char vleft_col[20];
+    unsigned char vtop_left = vabove_row[-1];
+    unsigned char *upred_ptr = &x->predictor[256];
+    unsigned char *vpred_ptr = &x->predictor[320];
+    int i, j;
+
+    for (i = 0; i < 8; i++)
+    {
+        uleft_col[i] = x->dst.u_buffer [i* x->dst.uv_stride -1];
+        vleft_col[i] = x->dst.v_buffer [i* x->dst.uv_stride -1];
+    }
+
+    switch (x->mbmi.uv_mode)
+    {
+    case DC_PRED:
+    {
+        int expected_udc;
+        int expected_vdc;
+        int i;
+        int shift;
+        int Uaverage = 0;
+        int Vaverage = 0;
+
+        if (x->up_available)
+        {
+            for (i = 0; i < 8; i++)
+            {
+                Uaverage += uabove_row[i];
+                Vaverage += vabove_row[i];
+            }
+        }
+
+        if (x->left_available)
+        {
+            for (i = 0; i < 8; i++)
+            {
+                Uaverage += uleft_col[i];
+                Vaverage += vleft_col[i];
+            }
+        }
+
+        if (!x->up_available && !x->left_available)
+        {
+            expected_udc = 128;
+            expected_vdc = 128;
+        }
+        else
+        {
+            shift = 2 + x->up_available + x->left_available;
+            expected_udc = (Uaverage + (1 << (shift - 1))) >> shift;
+            expected_vdc = (Vaverage + (1 << (shift - 1))) >> shift;
+        }
+
+
+        vpx_memset(upred_ptr, expected_udc, 64);
+        vpx_memset(vpred_ptr, expected_vdc, 64);
+
+
+    }
+    break;
+    case V_PRED:
+    {
+        int i;
+
+        for (i = 0; i < 8; i++)
+        {
+            vpx_memcpy(upred_ptr, uabove_row, 8);
+            vpx_memcpy(vpred_ptr, vabove_row, 8);
+            upred_ptr += 8;
+            vpred_ptr += 8;
+        }
+
+    }
+    break;
+    case H_PRED:
+    {
+        int i;
+
+        for (i = 0; i < 8; i++)
+        {
+            vpx_memset(upred_ptr, uleft_col[i], 8);
+            vpx_memset(vpred_ptr, vleft_col[i], 8);
+            upred_ptr += 8;
+            vpred_ptr += 8;
+        }
+    }
+
+    break;
+    case TM_PRED:
+    {
+        int i;
+
+        for (i = 0; i < 8; i++)
+        {
+            for (j = 0; j < 8; j++)
+            {
+                int predu = uleft_col[i] + uabove_row[j] - utop_left;
+                int predv = vleft_col[i] + vabove_row[j] - vtop_left;
+
+                if (predu < 0)
+                    predu = 0;
+
+                if (predu > 255)
+                    predu = 255;
+
+                if (predv < 0)
+                    predv = 0;
+
+                if (predv > 255)
+                    predv = 255;
+
+                upred_ptr[j] = predu;
+                vpred_ptr[j] = predv;
+            }
+
+            upred_ptr += 8;
+            vpred_ptr += 8;
+        }
+
+    }
+    break;
+    case B_PRED:
+    case NEARESTMV:
+    case NEARMV:
+    case ZEROMV:
+    case NEWMV:
+    case SPLITMV:
+    case MB_MODE_COUNT:
+        break;
+    }
+}
+
+void vp8_build_intra_predictors_mbuv_s(MACROBLOCKD *x)
+{
+    unsigned char *uabove_row = x->dst.u_buffer - x->dst.uv_stride;
+    unsigned char uleft_col[16];
+    unsigned char utop_left = uabove_row[-1];
+    unsigned char *vabove_row = x->dst.v_buffer - x->dst.uv_stride;
+    unsigned char vleft_col[20];
+    unsigned char vtop_left = vabove_row[-1];
+    unsigned char *upred_ptr = x->dst.u_buffer; //&x->predictor[256];
+    unsigned char *vpred_ptr = x->dst.v_buffer; //&x->predictor[320];
+    int uv_stride = x->dst.uv_stride;
+
+    int i, j;
+
+    for (i = 0; i < 8; i++)
+    {
+        uleft_col[i] = x->dst.u_buffer [i* x->dst.uv_stride -1];
+        vleft_col[i] = x->dst.v_buffer [i* x->dst.uv_stride -1];
+    }
+
+    switch (x->mbmi.uv_mode)
+    {
+    case DC_PRED:
+    {
+        int expected_udc;
+        int expected_vdc;
+        int i;
+        int shift;
+        int Uaverage = 0;
+        int Vaverage = 0;
+
+        if (x->up_available)
+        {
+            for (i = 0; i < 8; i++)
+            {
+                Uaverage += uabove_row[i];
+                Vaverage += vabove_row[i];
+            }
+        }
+
+        if (x->left_available)
+        {
+            for (i = 0; i < 8; i++)
+            {
+                Uaverage += uleft_col[i];
+                Vaverage += vleft_col[i];
+            }
+        }
+
+        if (!x->up_available && !x->left_available)
+        {
+            expected_udc = 128;
+            expected_vdc = 128;
+        }
+        else
+        {
+            shift = 2 + x->up_available + x->left_available;
+            expected_udc = (Uaverage + (1 << (shift - 1))) >> shift;
+            expected_vdc = (Vaverage + (1 << (shift - 1))) >> shift;
+        }
+
+
+        //vpx_memset(upred_ptr,expected_udc,64);
+        //vpx_memset(vpred_ptr,expected_vdc,64);
+        for (i = 0; i < 8; i++)
+        {
+            vpx_memset(upred_ptr, expected_udc, 8);
+            vpx_memset(vpred_ptr, expected_vdc, 8);
+            upred_ptr += uv_stride; //8;
+            vpred_ptr += uv_stride; //8;
+        }
+    }
+    break;
+    case V_PRED:
+    {
+        int i;
+
+        for (i = 0; i < 8; i++)
+        {
+            vpx_memcpy(upred_ptr, uabove_row, 8);
+            vpx_memcpy(vpred_ptr, vabove_row, 8);
+            upred_ptr += uv_stride; //8;
+            vpred_ptr += uv_stride; //8;
+        }
+
+    }
+    break;
+    case H_PRED:
+    {
+        int i;
+
+        for (i = 0; i < 8; i++)
+        {
+            vpx_memset(upred_ptr, uleft_col[i], 8);
+            vpx_memset(vpred_ptr, vleft_col[i], 8);
+            upred_ptr += uv_stride; //8;
+            vpred_ptr += uv_stride; //8;
+        }
+    }
+
+    break;
+    case TM_PRED:
+    {
+        int i;
+
+        for (i = 0; i < 8; i++)
+        {
+            for (j = 0; j < 8; j++)
+            {
+                int predu = uleft_col[i] + uabove_row[j] - utop_left;
+                int predv = vleft_col[i] + vabove_row[j] - vtop_left;
+
+                if (predu < 0)
+                    predu = 0;
+
+                if (predu > 255)
+                    predu = 255;
+
+                if (predv < 0)
+                    predv = 0;
+
+                if (predv > 255)
+                    predv = 255;
+
+                upred_ptr[j] = predu;
+                vpred_ptr[j] = predv;
+            }
+
+            upred_ptr += uv_stride; //8;
+            vpred_ptr += uv_stride; //8;
+        }
+
+    }
+    break;
+    case B_PRED:
+    case NEARESTMV:
+    case NEARMV:
+    case ZEROMV:
+    case NEWMV:
+    case SPLITMV:
+    case MB_MODE_COUNT:
+        break;
+    }
+}
diff --git a/vp8/common/reconintra.h b/vp8/common/reconintra.h
new file mode 100644
index 0000000..d63aa15
--- /dev/null
+++ b/vp8/common/reconintra.h
@@ -0,0 +1,28 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_RECONINTRA_H
+#define __INC_RECONINTRA_H
+
+extern void init_intra_left_above_pixels(MACROBLOCKD *x);
+
+extern void (*vp8_build_intra_predictors_mby_ptr)(MACROBLOCKD *x);
+extern void vp8_build_intra_predictors_mby(MACROBLOCKD *x);
+extern void vp8_build_intra_predictors_mby_neon(MACROBLOCKD *x);
+extern void (*vp8_build_intra_predictors_mby_s_ptr)(MACROBLOCKD *x);
+extern void vp8_build_intra_predictors_mby_s(MACROBLOCKD *x);
+extern void vp8_build_intra_predictors_mby_s_neon(MACROBLOCKD *x);
+
+extern void vp8_build_intra_predictors_mbuv(MACROBLOCKD *x);
+extern void vp8_build_intra_predictors_mbuv_s(MACROBLOCKD *x);
+
+extern void vp8_predict_intra4x4(BLOCKD *x, int b_mode, unsigned char *Predictor);
+
+#endif
diff --git a/vp8/common/reconintra4x4.c b/vp8/common/reconintra4x4.c
new file mode 100644
index 0000000..d92d5c9
--- /dev/null
+++ b/vp8/common/reconintra4x4.c
@@ -0,0 +1,330 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "recon.h"
+#include "vpx_mem/vpx_mem.h"
+#include "reconintra.h"
+
+void vp8_predict_intra4x4(BLOCKD *x,
+                          int b_mode,
+                          unsigned char *predictor)
+{
+    int i, r, c;
+
+    unsigned char *Above = *(x->base_dst) + x->dst - x->dst_stride;
+    unsigned char Left[4];
+    unsigned char top_left = Above[-1];
+
+    Left[0] = (*(x->base_dst))[x->dst - 1];
+    Left[1] = (*(x->base_dst))[x->dst - 1 + x->dst_stride];
+    Left[2] = (*(x->base_dst))[x->dst - 1 + 2 * x->dst_stride];
+    Left[3] = (*(x->base_dst))[x->dst - 1 + 3 * x->dst_stride];
+
+    switch (b_mode)
+    {
+    case B_DC_PRED:
+    {
+        int expected_dc = 0;
+
+        for (i = 0; i < 4; i++)
+        {
+            expected_dc += Above[i];
+            expected_dc += Left[i];
+        }
+
+        expected_dc = (expected_dc + 4) >> 3;
+
+        for (r = 0; r < 4; r++)
+        {
+            for (c = 0; c < 4; c++)
+            {
+                predictor[c] = expected_dc;
+            }
+
+            predictor += 16;
+        }
+    }
+    break;
+    case B_TM_PRED:
+    {
+        // prediction similar to true_motion prediction
+        for (r = 0; r < 4; r++)
+        {
+            for (c = 0; c < 4; c++)
+            {
+                int pred = Above[c] - top_left + Left[r];
+
+                if (pred < 0)
+                    pred = 0;
+
+                if (pred > 255)
+                    pred = 255;
+
+                predictor[c] = pred;
+            }
+
+            predictor += 16;
+        }
+    }
+    break;
+
+    case B_VE_PRED:
+    {
+
+        unsigned int ap[4];
+        ap[0] = (top_left  + 2 * Above[0] + Above[1] + 2) >> 2;
+        ap[1] = (Above[0] + 2 * Above[1] + Above[2] + 2) >> 2;
+        ap[2] = (Above[1] + 2 * Above[2] + Above[3] + 2) >> 2;
+        ap[3] = (Above[2] + 2 * Above[3] + Above[4] + 2) >> 2;
+
+        for (r = 0; r < 4; r++)
+        {
+            for (c = 0; c < 4; c++)
+            {
+
+                predictor[c] = ap[c];
+            }
+
+            predictor += 16;
+        }
+
+    }
+    break;
+
+
+    case B_HE_PRED:
+    {
+
+        unsigned int lp[4];
+        lp[0] = (top_left + 2 * Left[0] + Left[1] + 2) >> 2;
+        lp[1] = (Left[0] + 2 * Left[1] + Left[2] + 2) >> 2;
+        lp[2] = (Left[1] + 2 * Left[2] + Left[3] + 2) >> 2;
+        lp[3] = (Left[2] + 2 * Left[3] + Left[3] + 2) >> 2;
+
+        for (r = 0; r < 4; r++)
+        {
+            for (c = 0; c < 4; c++)
+            {
+                predictor[c] = lp[r];
+            }
+
+            predictor += 16;
+        }
+    }
+    break;
+    case B_LD_PRED:
+    {
+        unsigned char *ptr = Above;
+        predictor[0 * 16 + 0] = (ptr[0] + ptr[1] * 2 + ptr[2] + 2) >> 2;
+        predictor[0 * 16 + 1] =
+            predictor[1 * 16 + 0] = (ptr[1] + ptr[2] * 2 + ptr[3] + 2) >> 2;
+        predictor[0 * 16 + 2] =
+            predictor[1 * 16 + 1] =
+                predictor[2 * 16 + 0] = (ptr[2] + ptr[3] * 2 + ptr[4] + 2) >> 2;
+        predictor[0 * 16 + 3] =
+            predictor[1 * 16 + 2] =
+                predictor[2 * 16 + 1] =
+                    predictor[3 * 16 + 0] = (ptr[3] + ptr[4] * 2 + ptr[5] + 2) >> 2;
+        predictor[1 * 16 + 3] =
+            predictor[2 * 16 + 2] =
+                predictor[3 * 16 + 1] = (ptr[4] + ptr[5] * 2 + ptr[6] + 2) >> 2;
+        predictor[2 * 16 + 3] =
+            predictor[3 * 16 + 2] = (ptr[5] + ptr[6] * 2 + ptr[7] + 2) >> 2;
+        predictor[3 * 16 + 3] = (ptr[6] + ptr[7] * 2 + ptr[7] + 2) >> 2;
+
+    }
+    break;
+    case B_RD_PRED:
+    {
+
+        unsigned char pp[9];
+
+        pp[0] = Left[3];
+        pp[1] = Left[2];
+        pp[2] = Left[1];
+        pp[3] = Left[0];
+        pp[4] = top_left;
+        pp[5] = Above[0];
+        pp[6] = Above[1];
+        pp[7] = Above[2];
+        pp[8] = Above[3];
+
+        predictor[3 * 16 + 0] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
+        predictor[3 * 16 + 1] =
+            predictor[2 * 16 + 0] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        predictor[3 * 16 + 2] =
+            predictor[2 * 16 + 1] =
+                predictor[1 * 16 + 0] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
+        predictor[3 * 16 + 3] =
+            predictor[2 * 16 + 2] =
+                predictor[1 * 16 + 1] =
+                    predictor[0 * 16 + 0] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
+        predictor[2 * 16 + 3] =
+            predictor[1 * 16 + 2] =
+                predictor[0 * 16 + 1] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
+        predictor[1 * 16 + 3] =
+            predictor[0 * 16 + 2] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
+        predictor[0 * 16 + 3] = (pp[6] + pp[7] * 2 + pp[8] + 2) >> 2;
+
+    }
+    break;
+    case B_VR_PRED:
+    {
+
+        unsigned char pp[9];
+
+        pp[0] = Left[3];
+        pp[1] = Left[2];
+        pp[2] = Left[1];
+        pp[3] = Left[0];
+        pp[4] = top_left;
+        pp[5] = Above[0];
+        pp[6] = Above[1];
+        pp[7] = Above[2];
+        pp[8] = Above[3];
+
+
+        predictor[3 * 16 + 0] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        predictor[2 * 16 + 0] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
+        predictor[3 * 16 + 1] =
+            predictor[1 * 16 + 0] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
+        predictor[2 * 16 + 1] =
+            predictor[0 * 16 + 0] = (pp[4] + pp[5] + 1) >> 1;
+        predictor[3 * 16 + 2] =
+            predictor[1 * 16 + 1] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
+        predictor[2 * 16 + 2] =
+            predictor[0 * 16 + 1] = (pp[5] + pp[6] + 1) >> 1;
+        predictor[3 * 16 + 3] =
+            predictor[1 * 16 + 2] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
+        predictor[2 * 16 + 3] =
+            predictor[0 * 16 + 2] = (pp[6] + pp[7] + 1) >> 1;
+        predictor[1 * 16 + 3] = (pp[6] + pp[7] * 2 + pp[8] + 2) >> 2;
+        predictor[0 * 16 + 3] = (pp[7] + pp[8] + 1) >> 1;
+
+    }
+    break;
+    case B_VL_PRED:
+    {
+
+        unsigned char *pp = Above;
+
+        predictor[0 * 16 + 0] = (pp[0] + pp[1] + 1) >> 1;
+        predictor[1 * 16 + 0] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
+        predictor[2 * 16 + 0] =
+            predictor[0 * 16 + 1] = (pp[1] + pp[2] + 1) >> 1;
+        predictor[1 * 16 + 1] =
+            predictor[3 * 16 + 0] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        predictor[2 * 16 + 1] =
+            predictor[0 * 16 + 2] = (pp[2] + pp[3] + 1) >> 1;
+        predictor[3 * 16 + 1] =
+            predictor[1 * 16 + 2] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
+        predictor[0 * 16 + 3] =
+            predictor[2 * 16 + 2] = (pp[3] + pp[4] + 1) >> 1;
+        predictor[1 * 16 + 3] =
+            predictor[3 * 16 + 2] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
+        predictor[2 * 16 + 3] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
+        predictor[3 * 16 + 3] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
+    }
+    break;
+
+    case B_HD_PRED:
+    {
+        unsigned char pp[9];
+        pp[0] = Left[3];
+        pp[1] = Left[2];
+        pp[2] = Left[1];
+        pp[3] = Left[0];
+        pp[4] = top_left;
+        pp[5] = Above[0];
+        pp[6] = Above[1];
+        pp[7] = Above[2];
+        pp[8] = Above[3];
+
+
+        predictor[3 * 16 + 0] = (pp[0] + pp[1] + 1) >> 1;
+        predictor[3 * 16 + 1] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
+        predictor[2 * 16 + 0] =
+            predictor[3 * 16 + 2] = (pp[1] + pp[2] + 1) >> 1;
+        predictor[2 * 16 + 1] =
+            predictor[3 * 16 + 3] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        predictor[2 * 16 + 2] =
+            predictor[1 * 16 + 0] = (pp[2] + pp[3] + 1) >> 1;
+        predictor[2 * 16 + 3] =
+            predictor[1 * 16 + 1] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
+        predictor[1 * 16 + 2] =
+            predictor[0 * 16 + 0] = (pp[3] + pp[4] + 1) >> 1;
+        predictor[1 * 16 + 3] =
+            predictor[0 * 16 + 1] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
+        predictor[0 * 16 + 2] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
+        predictor[0 * 16 + 3] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
+    }
+    break;
+
+
+    case B_HU_PRED:
+    {
+        unsigned char *pp = Left;
+        predictor[0 * 16 + 0] = (pp[0] + pp[1] + 1) >> 1;
+        predictor[0 * 16 + 1] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
+        predictor[0 * 16 + 2] =
+            predictor[1 * 16 + 0] = (pp[1] + pp[2] + 1) >> 1;
+        predictor[0 * 16 + 3] =
+            predictor[1 * 16 + 1] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
+        predictor[1 * 16 + 2] =
+            predictor[2 * 16 + 0] = (pp[2] + pp[3] + 1) >> 1;
+        predictor[1 * 16 + 3] =
+            predictor[2 * 16 + 1] = (pp[2] + pp[3] * 2 + pp[3] + 2) >> 2;
+        predictor[2 * 16 + 2] =
+            predictor[2 * 16 + 3] =
+                predictor[3 * 16 + 0] =
+                    predictor[3 * 16 + 1] =
+                        predictor[3 * 16 + 2] =
+                            predictor[3 * 16 + 3] = pp[3];
+    }
+    break;
+
+
+    }
+}
+// copy 4 bytes from the above right down so that the 4x4 prediction modes using pixels above and
+// to the right prediction have filled in pixels to use.
+void vp8_intra_prediction_down_copy(MACROBLOCKD *x)
+{
+    unsigned char *above_right = *(x->block[0].base_dst) + x->block[0].dst - x->block[0].dst_stride + 16;
+
+    unsigned int *src_ptr = (unsigned int *)above_right;
+    unsigned int *dst_ptr0 = (unsigned int *)(above_right + 4 * x->block[0].dst_stride);
+    unsigned int *dst_ptr1 = (unsigned int *)(above_right + 8 * x->block[0].dst_stride);
+    unsigned int *dst_ptr2 = (unsigned int *)(above_right + 12 * x->block[0].dst_stride);
+
+    *dst_ptr0 = *src_ptr;
+    *dst_ptr1 = *src_ptr;
+    *dst_ptr2 = *src_ptr;
+}
+
+
+void vp8_recon_intra4x4mb(const vp8_recon_rtcd_vtable_t *rtcd, MACROBLOCKD *x)
+{
+    int i;
+
+    vp8_intra_prediction_down_copy(x);
+
+    for (i = 0; i < 16; i++)
+    {
+        BLOCKD *b = &x->block[i];
+
+        vp8_predict_intra4x4(b, x->block[i].bmi.mode, x->block[i].predictor);
+        RECON_INVOKE(rtcd, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+    }
+
+    vp8_recon_intra_mbuv(rtcd, x);
+
+}
diff --git a/vp8/common/reconintra4x4.h b/vp8/common/reconintra4x4.h
new file mode 100644
index 0000000..788c8c4
--- /dev/null
+++ b/vp8/common/reconintra4x4.h
@@ -0,0 +1,16 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_RECONINTRA4x4_H
+#define __INC_RECONINTRA4x4_H
+
+extern void vp8_intra_prediction_down_copy(MACROBLOCKD *x);
+
+#endif
diff --git a/vp8/common/segmentation_common.c b/vp8/common/segmentation_common.c
new file mode 100644
index 0000000..72b8c87
--- /dev/null
+++ b/vp8/common/segmentation_common.c
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "segmentation_common.h"
+#include "vpx_mem/vpx_mem.h"
+
+void vp8_update_gf_useage_maps(VP8_COMMON *cm, MACROBLOCKD *xd)
+{
+    int mb_row, mb_col;
+
+    MODE_INFO *this_mb_mode_info = cm->mi;
+
+    xd->gf_active_ptr = (signed char *)cm->gf_active_flags;
+
+    if ((cm->frame_type == KEY_FRAME) || (cm->refresh_golden_frame))
+    {
+        // Reset Gf useage monitors
+        vpx_memset(cm->gf_active_flags, 1, (cm->mb_rows * cm->mb_cols));
+        cm->gf_active_count = cm->mb_rows * cm->mb_cols;
+    }
+    else
+    {
+        // for each macroblock row in image
+        for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+        {
+            // for each macroblock col in image
+            for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+            {
+
+                // If using golden then set GF active flag if not already set.
+                // If using last frame 0,0 mode then leave flag as it is
+                // else if using non 0,0 motion or intra modes then clear flag if it is currently set
+                if ((this_mb_mode_info->mbmi.ref_frame == GOLDEN_FRAME) || (this_mb_mode_info->mbmi.ref_frame == ALTREF_FRAME))
+                {
+                    if (*(xd->gf_active_ptr) == 0)
+                    {
+                        *(xd->gf_active_ptr) = 1;
+                        cm->gf_active_count ++;
+                    }
+                }
+                else if ((this_mb_mode_info->mbmi.mode != ZEROMV) && *(xd->gf_active_ptr))
+                {
+                    *(xd->gf_active_ptr) = 0;
+                    cm->gf_active_count--;
+                }
+
+                xd->gf_active_ptr++;          // Step onto next entry
+                this_mb_mode_info++;           // skip to next mb
+
+            }
+
+            // this is to account for the border
+            this_mb_mode_info++;
+        }
+    }
+}
diff --git a/vp8/common/segmentation_common.h b/vp8/common/segmentation_common.h
new file mode 100644
index 0000000..bb93533
--- /dev/null
+++ b/vp8/common/segmentation_common.h
@@ -0,0 +1,15 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "string.h"
+#include "blockd.h"
+#include "onyxc_int.h"
+
+extern void vp8_update_gf_useage_maps(VP8_COMMON *cm, MACROBLOCKD *xd);
diff --git a/vp8/common/setupintrarecon.c b/vp8/common/setupintrarecon.c
new file mode 100644
index 0000000..dcaafe6
--- /dev/null
+++ b/vp8/common/setupintrarecon.c
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "setupintrarecon.h"
+#include "vpx_mem/vpx_mem.h"
+
+void vp8_setup_intra_recon(YV12_BUFFER_CONFIG *ybf)
+{
+    int i;
+
+    // set up frame new frame for intra coded blocks
+    vpx_memset(ybf->y_buffer - 1 - 2 * ybf->y_stride, 127, ybf->y_width + 5);
+    vpx_memset(ybf->y_buffer - 1 - ybf->y_stride, 127, ybf->y_width + 5);
+
+    for (i = 0; i < ybf->y_height; i++)
+        ybf->y_buffer[ybf->y_stride *i - 1] = (unsigned char) 129;
+
+    vpx_memset(ybf->u_buffer - 1 - 2 * ybf->uv_stride, 127, ybf->uv_width + 5);
+    vpx_memset(ybf->u_buffer - 1 - ybf->uv_stride, 127, ybf->uv_width + 5);
+
+    for (i = 0; i < ybf->uv_height; i++)
+        ybf->u_buffer[ybf->uv_stride *i - 1] = (unsigned char) 129;
+
+    vpx_memset(ybf->v_buffer - 1 - 2 * ybf->uv_stride, 127, ybf->uv_width + 5);
+    vpx_memset(ybf->v_buffer - 1 - ybf->uv_stride, 127, ybf->uv_width + 5);
+
+    for (i = 0; i < ybf->uv_height; i++)
+        ybf->v_buffer[ybf->uv_stride *i - 1] = (unsigned char) 129;
+
+}
diff --git a/vp8/common/setupintrarecon.h b/vp8/common/setupintrarecon.h
new file mode 100644
index 0000000..6ec79b2
--- /dev/null
+++ b/vp8/common/setupintrarecon.h
@@ -0,0 +1,12 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_scale/yv12config.h"
+extern void vp8_setup_intra_recon(YV12_BUFFER_CONFIG *ybf);
diff --git a/vp8/common/subpixel.h b/vp8/common/subpixel.h
new file mode 100644
index 0000000..fbd5f4d
--- /dev/null
+++ b/vp8/common/subpixel.h
@@ -0,0 +1,85 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef SUBPIXEL_H
+#define SUBPIXEL_H
+
+#define prototype_subpixel_predict(sym) \
+    void sym(unsigned char *src, int src_pitch, int xofst, int yofst, \
+             unsigned char *dst, int dst_pitch)
+
+#if ARCH_X86 || ARCH_X86_64
+#include "x86/subpixel_x86.h"
+#endif
+
+#if ARCH_ARM
+#include "arm/subpixel_arm.h"
+#endif
+
+#ifndef vp8_subpix_sixtap16x16
+#define vp8_subpix_sixtap16x16 vp8_sixtap_predict16x16_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_sixtap16x16);
+
+#ifndef vp8_subpix_sixtap8x8
+#define vp8_subpix_sixtap8x8 vp8_sixtap_predict8x8_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_sixtap8x8);
+
+#ifndef vp8_subpix_sixtap8x4
+#define vp8_subpix_sixtap8x4 vp8_sixtap_predict8x4_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_sixtap8x4);
+
+#ifndef vp8_subpix_sixtap4x4
+#define vp8_subpix_sixtap4x4 vp8_sixtap_predict_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_sixtap4x4);
+
+#ifndef vp8_subpix_bilinear16x16
+#define vp8_subpix_bilinear16x16 vp8_bilinear_predict16x16_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_bilinear16x16);
+
+#ifndef vp8_subpix_bilinear8x8
+#define vp8_subpix_bilinear8x8 vp8_bilinear_predict8x8_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_bilinear8x8);
+
+#ifndef vp8_subpix_bilinear8x4
+#define vp8_subpix_bilinear8x4 vp8_bilinear_predict8x4_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_bilinear8x4);
+
+#ifndef vp8_subpix_bilinear4x4
+#define vp8_subpix_bilinear4x4 vp8_bilinear_predict4x4_c
+#endif
+extern prototype_subpixel_predict(vp8_subpix_bilinear4x4);
+
+typedef prototype_subpixel_predict((*vp8_subpix_fn_t));
+typedef struct
+{
+    vp8_subpix_fn_t  sixtap16x16;
+    vp8_subpix_fn_t  sixtap8x8;
+    vp8_subpix_fn_t  sixtap8x4;
+    vp8_subpix_fn_t  sixtap4x4;
+    vp8_subpix_fn_t  bilinear16x16;
+    vp8_subpix_fn_t  bilinear8x8;
+    vp8_subpix_fn_t  bilinear8x4;
+    vp8_subpix_fn_t  bilinear4x4;
+} vp8_subpix_rtcd_vtable_t;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define SUBPIX_INVOKE(ctx,fn) (ctx)->fn
+#else
+#define SUBPIX_INVOKE(ctx,fn) vp8_subpix_##fn
+#endif
+
+#endif
diff --git a/vp8/common/swapyv12buffer.c b/vp8/common/swapyv12buffer.c
new file mode 100644
index 0000000..afe6a88
--- /dev/null
+++ b/vp8/common/swapyv12buffer.c
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "swapyv12buffer.h"
+
+void vp8_swap_yv12_buffer(YV12_BUFFER_CONFIG *new_frame, YV12_BUFFER_CONFIG *last_frame)
+{
+    unsigned char *temp;
+
+    temp = last_frame->buffer_alloc;
+    last_frame->buffer_alloc = new_frame->buffer_alloc;
+    new_frame->buffer_alloc = temp;
+
+    temp = last_frame->y_buffer;
+    last_frame->y_buffer = new_frame->y_buffer;
+    new_frame->y_buffer = temp;
+
+    temp = last_frame->u_buffer;
+    last_frame->u_buffer = new_frame->u_buffer;
+    new_frame->u_buffer = temp;
+
+    temp = last_frame->v_buffer;
+    last_frame->v_buffer = new_frame->v_buffer;
+    new_frame->v_buffer = temp;
+
+}
diff --git a/vp8/common/swapyv12buffer.h b/vp8/common/swapyv12buffer.h
new file mode 100644
index 0000000..caf9499
--- /dev/null
+++ b/vp8/common/swapyv12buffer.h
@@ -0,0 +1,18 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef SWAPYV12_BUFFER_H
+#define SWAPYV12_BUFFER_H
+
+#include "vpx_scale/yv12config.h"
+
+void vp8_swap_yv12_buffer(YV12_BUFFER_CONFIG *new_frame, YV12_BUFFER_CONFIG *last_frame);
+
+#endif
diff --git a/vp8/common/systemdependent.h b/vp8/common/systemdependent.h
new file mode 100644
index 0000000..1829b64
--- /dev/null
+++ b/vp8/common/systemdependent.h
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#if ARCH_X86 || ARCH_X86_64
+void vpx_reset_mmx_state(void);
+#define vp8_clear_system_state() vpx_reset_mmx_state()
+#else
+#define vp8_clear_system_state()
+#endif
+
+struct VP8Common;
+void vp8_machine_specific_config(struct VP8Common *);
diff --git a/vp8/common/textblit.c b/vp8/common/textblit.c
new file mode 100644
index 0000000..a45937b
--- /dev/null
+++ b/vp8/common/textblit.c
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+
+
+void vp8_blit_text(const char *msg, unsigned char *address, const int pitch)
+{
+    int letter_bitmap;
+    unsigned char *output_pos = address;
+    int colpos;
+    const int font[] =
+    {
+        0x0, 0x5C00, 0x8020, 0xAFABEA, 0xD7EC0, 0x1111111, 0x1855740, 0x18000,
+        0x45C0, 0x74400, 0x51140, 0x23880, 0xC4000, 0x21080, 0x80000, 0x111110,
+        0xE9D72E, 0x87E40, 0x12AD732, 0xAAD62A, 0x4F94C4, 0x4D6B7, 0x456AA,
+        0x3E8423, 0xAAD6AA, 0xAAD6A2, 0x2800, 0x2A00, 0x8A880, 0x52940, 0x22A20,
+        0x15422, 0x6AD62E, 0x1E4A53E, 0xAAD6BF, 0x8C62E, 0xE8C63F, 0x118D6BF,
+        0x1094BF, 0xCAC62E, 0x1F2109F, 0x118FE31, 0xF8C628, 0x8A89F, 0x108421F,
+        0x1F1105F, 0x1F4105F, 0xE8C62E, 0x2294BF, 0x164C62E, 0x12694BF, 0x8AD6A2,
+        0x10FC21, 0x1F8421F, 0x744107, 0xF8220F, 0x1151151, 0x117041, 0x119D731,
+        0x47E0, 0x1041041, 0xFC400, 0x10440, 0x1084210, 0x820
+    };
+    colpos = 0;
+
+    while (msg[colpos] != 0)
+    {
+        char letter = msg[colpos];
+        int fontcol, fontrow;
+
+        if (letter <= 'Z' && letter >= ' ')
+            letter_bitmap = font[letter-' '];
+        else if (letter <= 'z' && letter >= 'a')
+            letter_bitmap = font[letter-'a'+'A' - ' '];
+        else
+            letter_bitmap = font[0];
+
+        for (fontcol = 6; fontcol >= 0 ; fontcol--)
+            for (fontrow = 0; fontrow < 5; fontrow++)
+                output_pos[fontrow *pitch + fontcol] =
+                    ((letter_bitmap >> (fontcol * 5)) & (1 << fontrow) ? 255 : 0);
+
+        output_pos += 7;
+        colpos++;
+    }
+}
diff --git a/vp8/common/threading.h b/vp8/common/threading.h
new file mode 100644
index 0000000..a02cb24
--- /dev/null
+++ b/vp8/common/threading.h
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef _PTHREAD_EMULATION
+#define _PTHREAD_EMULATION
+
+#define VPXINFINITE 10000       //10second.
+
+/* Thread management macros */
+#ifdef _WIN32
+/* Win32 */
+#define _WIN32_WINNT 0x500 /* WINBASE.H - Enable signal_object_and_wait */
+#include <process.h>
+#include <windows.h>
+#define THREAD_FUNCTION DWORD WINAPI
+#define THREAD_FUNCTION_RETURN DWORD
+#define THREAD_SPECIFIC_INDEX DWORD
+#define pthread_t HANDLE
+#define pthread_attr_t DWORD
+#define pthread_create(thhandle,attr,thfunc,tharg) (int)((*thhandle=(HANDLE)_beginthreadex(NULL,0,(unsigned int (__stdcall *)(void *))thfunc,tharg,0,NULL))==NULL)
+#define pthread_join(thread, result) ((WaitForSingleObject((thread),VPXINFINITE)!=WAIT_OBJECT_0) || !CloseHandle(thread))
+#define pthread_detach(thread) if(thread!=NULL)CloseHandle(thread)
+#define thread_sleep(nms) Sleep(nms)
+#define pthread_cancel(thread) terminate_thread(thread,0)
+#define ts_key_create(ts_key, destructor) {ts_key = TlsAlloc();};
+#define pthread_getspecific(ts_key) TlsGetValue(ts_key)
+#define pthread_setspecific(ts_key, value) TlsSetValue(ts_key, (void *)value)
+#define pthread_self() GetCurrentThreadId()
+#else
+#ifdef __APPLE__
+#include <mach/semaphore.h>
+#include <mach/task.h>
+#include <time.h>
+#include <unistd.h>
+
+#else
+#include <semaphore.h>
+#endif
+
+#include <pthread.h>
+/* pthreads */
+/* Nearly everything is already defined */
+#define THREAD_FUNCTION void *
+#define THREAD_FUNCTION_RETURN void *
+#define THREAD_SPECIFIC_INDEX pthread_key_t
+#define ts_key_create(ts_key, destructor) pthread_key_create (&(ts_key), destructor);
+#endif
+
+/* Syncrhronization macros: Win32 and Pthreads */
+#ifdef _WIN32
+#define sem_t HANDLE
+#define pause(voidpara) __asm PAUSE
+#define sem_init(sem, sem_attr1, sem_init_value) (int)((*sem = CreateEvent(NULL,FALSE,FALSE,NULL))==NULL)
+#define sem_wait(sem) (int)(WAIT_OBJECT_0 != WaitForSingleObject(*sem,VPXINFINITE))
+#define sem_post(sem) SetEvent(*sem)
+#define sem_destroy(sem) if(*sem)((int)(CloseHandle(*sem))==TRUE)
+#define thread_sleep(nms) Sleep(nms)
+
+#else
+
+#ifdef __APPLE__
+#define sem_t semaphore_t
+#define sem_init(X,Y,Z) semaphore_create(mach_task_self(), X, SYNC_POLICY_FIFO, Z)
+#define sem_wait(sem) (semaphore_wait(*sem) )
+#define sem_post(sem) semaphore_signal(*sem)
+#define sem_destroy(sem) semaphore_destroy(mach_task_self(),*sem)
+#define thread_sleep(nms) // { struct timespec ts;ts.tv_sec=0; ts.tv_nsec = 1000*nms;nanosleep(&ts, NULL);}
+#else
+#include <unistd.h>
+#define thread_sleep(nms) usleep(nms*1000);// {struct timespec ts;ts.tv_sec=0; ts.tv_nsec = 1000*nms;nanosleep(&ts, NULL);}
+#endif
+/* Not Windows. Assume pthreads */
+
+#endif
+
+#if ARCH_X86 || ARCH_X86_64
+#include "vpx_ports/x86.h"
+#else
+#define x86_pause_hint()
+#endif
+
+#endif
diff --git a/vp8/common/treecoder.c b/vp8/common/treecoder.c
new file mode 100644
index 0000000..4ad018d
--- /dev/null
+++ b/vp8/common/treecoder.c
@@ -0,0 +1,136 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#if CONFIG_DEBUG
+#include <assert.h>
+#endif
+#include <stdio.h>
+
+#include "treecoder.h"
+
+static void tree2tok(
+    struct vp8_token_struct *const p,
+    vp8_tree t,
+    int i,
+    int v,
+    int L
+)
+{
+    v += v;
+    ++L;
+
+    do
+    {
+        const vp8_tree_index j = t[i++];
+
+        if (j <= 0)
+        {
+            p[-j].value = v;
+            p[-j].Len = L;
+        }
+        else
+            tree2tok(p, t, j, v, L);
+    }
+    while (++v & 1);
+}
+
+void vp8_tokens_from_tree(struct vp8_token_struct *p, vp8_tree t)
+{
+    tree2tok(p, t, 0, 0, 0);
+}
+
+static void branch_counts(
+    int n,                      /* n = size of alphabet */
+    vp8_token tok               [ /* n */ ],
+    vp8_tree tree,
+    unsigned int branch_ct       [ /* n-1 */ ] [2],
+    const unsigned int num_events[ /* n */ ]
+)
+{
+    const int tree_len = n - 1;
+    int t = 0;
+
+#if CONFIG_DEBUG
+    assert(tree_len);
+#endif
+
+    do
+    {
+        branch_ct[t][0] = branch_ct[t][1] = 0;
+    }
+    while (++t < tree_len);
+
+    t = 0;
+
+    do
+    {
+        int L = tok[t].Len;
+        const int enc = tok[t].value;
+        const unsigned int ct = num_events[t];
+
+        vp8_tree_index i = 0;
+
+        do
+        {
+            const int b = (enc >> --L) & 1;
+            const int j = i >> 1;
+#if CONFIG_DEBUG
+            assert(j < tree_len  &&  0 <= L);
+#endif
+
+            branch_ct [j] [b] += ct;
+            i = tree[ i + b];
+        }
+        while (i > 0);
+
+#if CONFIG_DEBUG
+        assert(!L);
+#endif
+    }
+    while (++t < n);
+
+}
+
+
+void vp8_tree_probs_from_distribution(
+    int n,                      /* n = size of alphabet */
+    vp8_token tok               [ /* n */ ],
+    vp8_tree tree,
+    vp8_prob probs          [ /* n-1 */ ],
+    unsigned int branch_ct       [ /* n-1 */ ] [2],
+    const unsigned int num_events[ /* n */ ],
+    unsigned int Pfac,
+    int rd
+)
+{
+    const int tree_len = n - 1;
+    int t = 0;
+
+    branch_counts(n, tok, tree, branch_ct, num_events);
+
+    do
+    {
+        const unsigned int *const c = branch_ct[t];
+        const unsigned int tot = c[0] + c[1];
+
+#if CONFIG_DEBUG
+        assert(tot < (1 << 24));        /* no overflow below */
+#endif
+
+        if (tot)
+        {
+            const unsigned int p = ((c[0] * Pfac) + (rd ? tot >> 1 : 0)) / tot;
+            probs[t] = p < 256 ? (p ? p : 1) : 255; /* agree w/old version for now */
+        }
+        else
+            probs[t] = vp8_prob_half;
+    }
+    while (++t < tree_len);
+}
diff --git a/vp8/common/treecoder.h b/vp8/common/treecoder.h
new file mode 100644
index 0000000..0356d2b
--- /dev/null
+++ b/vp8/common/treecoder.h
@@ -0,0 +1,87 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_TREECODER_H
+#define __INC_TREECODER_H
+
+typedef unsigned char vp8bc_index_t; // probability index
+
+
+typedef unsigned char vp8_prob;
+
+#define vp8_prob_half ( (vp8_prob) 128)
+
+typedef signed char vp8_tree_index;
+struct bool_coder_spec;
+
+typedef struct bool_coder_spec bool_coder_spec;
+typedef struct bool_writer bool_writer;
+typedef struct bool_reader bool_reader;
+
+typedef const bool_coder_spec c_bool_coder_spec;
+typedef const bool_writer c_bool_writer;
+typedef const bool_reader c_bool_reader;
+
+
+
+# define vp8_complement( x) (255 - x)
+
+
+/* We build coding trees compactly in arrays.
+   Each node of the tree is a pair of vp8_tree_indices.
+   Array index often references a corresponding probability table.
+   Index <= 0 means done encoding/decoding and value = -Index,
+   Index > 0 means need another bit, specification at index.
+   Nonnegative indices are always even;  processing begins at node 0. */
+
+typedef const vp8_tree_index vp8_tree[], *vp8_tree_p;
+
+
+typedef const struct vp8_token_struct
+{
+    int value;
+    int Len;
+} vp8_token;
+
+/* Construct encoding array from tree. */
+
+void vp8_tokens_from_tree(struct vp8_token_struct *, vp8_tree);
+
+
+/* Convert array of token occurrence counts into a table of probabilities
+   for the associated binary encoding tree.  Also writes count of branches
+   taken for each node on the tree; this facilitiates decisions as to
+   probability updates. */
+
+void vp8_tree_probs_from_distribution(
+    int n,                      /* n = size of alphabet */
+    vp8_token tok               [ /* n */ ],
+    vp8_tree tree,
+    vp8_prob probs          [ /* n-1 */ ],
+    unsigned int branch_ct       [ /* n-1 */ ] [2],
+    const unsigned int num_events[ /* n */ ],
+    unsigned int Pfactor,
+    int Round
+);
+
+/* Variant of above using coder spec rather than hardwired 8-bit probs. */
+
+void vp8bc_tree_probs_from_distribution(
+    int n,                      /* n = size of alphabet */
+    vp8_token tok               [ /* n */ ],
+    vp8_tree tree,
+    vp8_prob probs          [ /* n-1 */ ],
+    unsigned int branch_ct       [ /* n-1 */ ] [2],
+    const unsigned int num_events[ /* n */ ],
+    c_bool_coder_spec *s
+);
+
+
+#endif
diff --git a/vp8/common/type_aliases.h b/vp8/common/type_aliases.h
new file mode 100644
index 0000000..addd264
--- /dev/null
+++ b/vp8/common/type_aliases.h
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/****************************************************************************
+*
+*   Module Title :     type_aliases.h
+*
+*   Description  :     Standard type aliases
+*
+****************************************************************************/
+#ifndef __INC_TYPE_ALIASES_H
+#define __INC_TYPE_ALIASES_H
+
+/****************************************************************************
+* Macros
+****************************************************************************/
+#define EXPORT
+#define IMPORT          extern      /* Used to declare imported data & routines */
+#define PRIVATE         static      /* Used to declare & define module-local data */
+#define LOCAL           static      /* Used to define all persistent routine-local data */
+#define STD_IN_PATH     0           /* Standard input path */
+#define STD_OUT_PATH    1           /* Standard output path */
+#define STD_ERR_PATH    2           /* Standard error path */
+#define STD_IN_FILE     stdin       /* Standard input file pointer */
+#define STD_OUT_FILE    stdout      /* Standard output file pointer */
+#define STD_ERR_FILE    stderr      /* Standard error file pointer */
+#define max_int         0x7FFFFFFF
+
+#define __export
+#define _export
+
+#define CCONV
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL    0
+#else
+#define NULL    ((void *)0)
+#endif
+#endif
+
+#ifndef FALSE
+#define FALSE   0
+#endif
+
+#ifndef TRUE
+#define TRUE    1
+#endif
+
+/****************************************************************************
+* Typedefs
+****************************************************************************/
+#ifndef TYPE_INT8
+#define TYPE_INT8
+typedef signed char     INT8;
+#endif
+
+#ifndef TYPE_INT16
+//#define TYPE_INT16
+typedef signed short    INT16;
+#endif
+
+#ifndef TYPE_INT32
+//#define TYPE_INT32
+typedef signed int      INT32;
+#endif
+
+#ifndef TYPE_UINT8
+//#define TYPE_UINT8
+typedef unsigned char   UINT8;
+#endif
+
+#ifndef TYPE_UINT32
+//#define TYPE_UINT32
+typedef unsigned int    UINT32;
+#endif
+
+#ifndef TYPE_UINT16
+//#define TYPE_UINT16
+typedef unsigned short  UINT16;
+#endif
+
+#ifndef TYPE_BOOL
+//#define TYPE_BOOL
+typedef int             BOOL;
+#endif
+
+typedef unsigned char   BOOLEAN;
+
+#ifdef _MSC_VER
+typedef __int64 INT64;
+#else
+
+#ifndef TYPE_INT64
+#ifdef _TMS320C6X
+//for now we only have 40bits
+typedef long INT64;
+#else
+typedef long long INT64;
+#endif
+#endif
+
+#endif
+
+/* Floating point */
+typedef  double         FLOAT64;
+typedef  float          FLOAT32;
+
+#endif
diff --git a/vp8/common/vfwsetting.hpp b/vp8/common/vfwsetting.hpp
new file mode 100644
index 0000000..e352e7a
--- /dev/null
+++ b/vp8/common/vfwsetting.hpp
@@ -0,0 +1,75 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#if !defined(VFWSETTING_HPP)
+#define VFWSETTING_HPP
+//______________________________________________________________________________
+//
+//  VFWSetting.hpp
+//
+
+#include "four_cc.hpp"
+#include <iosfwd>
+
+namespace vpxvp
+{
+
+    //--------------------------------------
+    class VFWSetting
+    {
+        friend std::ostream& operator<<(std::ostream& os, const VFWSetting& vfws);
+
+    public:
+
+        enum Mode
+        {
+            m_setting,
+            m_config
+        };
+
+        enum
+        {
+            header_size = 8,
+            Size = 16
+        };
+
+        VFWSetting(four_cc fcc);
+        ~VFWSetting();
+
+        four_cc fcc() const;
+        Mode mode() const;
+
+        int setting() const;
+        int value() const;
+        void setting_value(int i_setting, int i_value);  //  Sets mode to m_setting
+
+        long size() const;
+        const void* data() const;
+        int data(const void* p_data, unsigned long ul_size);
+
+    private:
+
+        VFWSetting(const VFWSetting& vfws);  //  Not implemented
+        VFWSetting& operator=(const VFWSetting& vfws);  //  Not implemented
+
+        int extract_(const void* p_data, unsigned long ul_size);
+        void update_() const;
+
+        four_cc m_fcc;
+        Mode m_mode;
+        int m_i_setting;
+        int m_i_value;
+
+        mutable unsigned char m_p_data[Size];
+    };
+
+}  //  namespace vpxvp
+
+#endif  //  VFWSETTING_HPP
diff --git a/vp8/common/vpx_ref_build_prefix.h b/vp8/common/vpx_ref_build_prefix.h
new file mode 100644
index 0000000..40608c6
--- /dev/null
+++ b/vp8/common/vpx_ref_build_prefix.h
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef _VPX_REF_BUILD_PREFIX_h
+#define _VPX_REF_BUILD_PREFIX_h
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* include guards */
diff --git a/vp8/common/vpxblit.h b/vp8/common/vpxblit.h
new file mode 100644
index 0000000..d03e0bd
--- /dev/null
+++ b/vp8/common/vpxblit.h
@@ -0,0 +1,111 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef VPXBLIT_H_INCL
+#define VPXBLIT_H_INCL
+/*==============================================================================
+                              Includes
+==============================================================================*/
+
+/*==============================================================================
+                              Defines
+==============================================================================*/
+
+
+#ifdef VPX_BIG_ENDIAN
+#define BYTE_ZERO(X)    ((X & 0xFF000000) >> (24 - 2)   )
+#define BYTE_ONE(X)     ((X & 0x00FF0000) >> (16 - 2)   )
+#define BYTE_TWO(X)     ((X & 0x0000FF00) >> (8 - 2)    )
+#define BYTE_THREE(X)   ((X & 0x000000FF) << (0 + 2)    )
+
+#define BYTE_ZERO_UV(X) ((X & 0x0000FF00) >> (8 - 2)    )
+#define BYTE_ONE_UV(X)  ((X & 0x000000FF) << (0 + 2)    )
+
+#define REREFERENCE(X) (*((int *) &(X)))
+
+#else
+
+#define BYTE_THREE(X)   ((X & 0xFF000000) >> (24 - 2)   )
+#define BYTE_TWO(X)     ((X & 0x00FF0000) >> (16 - 2)   )
+#define BYTE_ONE(X)     ((X & 0x0000FF00) >> (8 - 2)    )
+#define BYTE_ZERO(X)    ((X & 0x000000FF) << (0 + 2)    )
+
+#define BYTE_ONE_UV(X) ((X & 0x0000FF00) >> (8 - 2) )
+#define BYTE_ZERO_UV(X)     ((X & 0x000000FF) << (0 + 2)    )
+
+#define REREFERENCE(X) (*((int *) &(X)))
+
+#endif
+
+
+/*==============================================================================
+                            Type Definitions
+==============================================================================*/
+typedef struct  // YUV buffer configuration structure
+{
+    int   y_width;
+    int   y_height;
+    int   y_stride;
+
+    int   uv_width;
+    int   uv_height;
+    int   uv_stride;
+
+    char *y_buffer;
+    char *u_buffer;
+    char *v_buffer;
+
+    char *uv_start;
+    int   uv_dst_area;
+    int   uv_used_area;
+
+} VPX_BLIT_CONFIG;
+
+typedef struct tx86_params
+{
+    unsigned int pushed_registers[6];
+    unsigned int return_address;
+    unsigned int dst;
+    unsigned int scrn_pitch;
+    VPX_BLIT_CONFIG *buff_config;
+} x86_params;
+
+/*=============================================================================
+                                Enums
+==============================================================================*/
+
+
+/*==============================================================================
+                              Structures
+==============================================================================*/
+
+/*==============================================================================
+                             Constants
+==============================================================================*/
+
+
+/*==============================================================================
+                               Variables
+==============================================================================*/
+
+
+
+
+/*==============================================================================
+                            Function Protoypes/MICROS
+==============================================================================*/
+int vpx_get_size_of_pixel(unsigned int bd);
+void *vpx_get_blitter(unsigned int bd);
+void vpx_set_blit(void);
+void vpx_destroy_blit(void);
+
+
+
+#endif //VPXBLIT_H_INCL
diff --git a/vp8/common/vpxblit_c64.h b/vp8/common/vpxblit_c64.h
new file mode 100644
index 0000000..a8e28f5
--- /dev/null
+++ b/vp8/common/vpxblit_c64.h
@@ -0,0 +1,47 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef _VPX_BLIT_C64_h
+#define _VPX_BLIT_C64_h
+
+/****************************************************************************
+*  Typedefs
+****************************************************************************/
+
+typedef struct  // YUV buffer configuration structure
+{
+    int     y_width;
+    int     y_height;
+    int     y_stride;
+
+    int     uv_width;
+    int     uv_height;
+    int     uv_stride;
+
+    unsigned char *y_buffer;
+    unsigned char *u_buffer;
+    unsigned char *v_buffer;
+
+    unsigned char *y_ptr_scrn;
+    unsigned char *u_ptr_scrn;
+    unsigned char *v_ptr_scrn;
+
+} DXV_YUV_BUFFER_CONFIG;
+
+typedef struct
+{
+    unsigned char *rgbptr_scrn;
+    unsigned char *y_ptr_scrn;
+    unsigned char *u_ptr_scrn;
+    unsigned char *v_ptr_scrn;
+    unsigned char *rgbptr_scrn2;
+} DXV_FINAL_VIDEO;
+
+#endif /* include guards */
diff --git a/vp8/common/vpxerrors.h b/vp8/common/vpxerrors.h
new file mode 100644
index 0000000..e4c9f3e
--- /dev/null
+++ b/vp8/common/vpxerrors.h
@@ -0,0 +1,12 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+
+#define ALLOC_FAILURE -2
diff --git a/vp8/common/x86/boolcoder.cxx b/vp8/common/x86/boolcoder.cxx
new file mode 100644
index 0000000..06faca6
--- /dev/null
+++ b/vp8/common/x86/boolcoder.cxx
@@ -0,0 +1,493 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+
+/* Arithmetic bool coder with largish probability range.
+   Timothy S Murphy  6 August 2004 */
+
+#include <assert.h>
+#include <math.h>
+
+#include "bool_coder.h"
+
+#if tim_vp8
+    extern "C" {
+#       include "VP8cx/treewriter.h"
+    }
+#endif
+
+int_types::~int_types() {}
+
+void bool_coder_spec::check_prec() const {
+    assert( w  &&  (r==Up || w > 1)  &&  w < 24  &&  (ebias || w < 17));
+}
+
+bool bool_coder_spec::float_init( uint Ebits, uint Mbits) {
+    uint b = (ebits = Ebits) + (mbits = Mbits);
+    if( b) {
+        assert( ebits < 6  &&  w + mbits < 31);
+        assert( ebits + mbits  <  sizeof(Index) * 8);
+        ebias = (1 << ebits) + 1 + mbits;
+        mmask = (1 << mbits) - 1;
+        max_index = ( ( half_index = 1 << b ) << 1) - 1;
+    } else {
+        ebias = 0;
+        max_index = 255;
+        half_index = 128;
+    }
+    check_prec();
+    return b? 1:0;
+}
+
+void bool_coder_spec::cost_init()
+{
+    static cdouble c = -(1 << 20)/log( 2.);
+
+    FILE *f = fopen( "costs.txt", "w");
+    assert( f);
+
+    assert( sizeof(int) >= 4);  /* for C interface */
+    assert( max_index <= 255);   /* size of Ctbl */
+    uint i = 0;  do {
+        cdouble p = ( *this)( (Index) i);
+        Ctbl[i] = (uint32) ( log( p) * c);
+        fprintf(
+            f, "cost( %d -> %10.7f) = %10d = %12.5f bits\n",
+            i, p, Ctbl[i], (double) Ctbl[i] / (1<<20)
+        );
+    } while( ++i <= max_index);
+    fclose( f);
+}
+
+bool_coder_spec_explicit_table::bool_coder_spec_explicit_table(
+    cuint16 tbl[256], Rounding rr, uint prec
+)
+  : bool_coder_spec( prec, rr)
+{
+    check_prec();
+    uint i = 0;
+    if( tbl)
+        do { Ptbl[i] = tbl[i];}  while( ++i < 256);
+    else
+        do { Ptbl[i] = i << 8;}  while( ++i < 256);
+    cost_init();
+}
+
+
+bool_coder_spec_exponential_table::bool_coder_spec_exponential_table(
+    uint x, Rounding rr, uint prec
+)
+  : bool_coder_spec( prec, rr)
+{
+    assert( x > 1  &&  x <= 16);
+    check_prec();
+    Ptbl[128] = 32768u;
+    Ptbl[0] = (uint16) pow( 2., 16. - x);
+    --x;
+    int i=1;  do {
+        cdouble d = pow( .5, 1. + (1. - i/128.)*x) * 65536.;
+        uint16 v = (uint16) d;
+        if( v < i)
+            v = i;
+        Ptbl[256-i] = (uint16) ( 65536U - (Ptbl[i] = v));
+    } while( ++i < 128);
+    cost_init();
+}
+
+bool_coder_spec::bool_coder_spec( FILE *fp) {
+    fscanf( fp, "%d", &w);
+    int v;
+    fscanf( fp, "%d", &v);
+    assert( 0 <= v  &&  v <= 2);
+    r = (Rounding) v;
+    fscanf( fp, "%d", &ebits);
+    fscanf( fp, "%d", &mbits);
+    if( float_init( ebits, mbits))
+        return;
+    int i=0;  do {
+        uint v;
+        fscanf( fp, "%d", &v);
+        assert( 0 <=v  &&  v <= 65535U);
+        Ptbl[i] = v;
+    } while( ++i < 256);
+    cost_init();
+}
+
+void bool_coder_spec::dump( FILE *fp) const {
+    fprintf( fp, "%d %d %d %d\n", w, (int) r, ebits, mbits);
+    if( ebits  ||  mbits)
+        return;
+    int i=0;  do { fprintf( fp, "%d\n", Ptbl[i]);}  while( ++i < 256);
+}
+
+vp8bc_index_t bool_coder_spec::operator()( double p) const
+{
+    if( p <= 0.)
+        return 0;
+    if( p >= 1.)
+        return max_index;
+    if( ebias) {
+        if( p > .5)
+            return max_index - ( *this)( 1. - p);
+        int e;
+        uint m = (uint) ldexp( frexp( p, &e), mbits + 2);
+        uint x = 1 << (mbits + 1);
+        assert( x <= m  &&  m < x<<1);
+        if( (m = (m >> 1) + (m & 1)) >= x) {
+            m = x >> 1;
+            ++e;
+        }
+        int y = 1 << ebits;
+        if( (e += y) >= y)
+            return half_index - 1;
+        if( e < 0)
+            return 0;
+        return (Index) ( (e << mbits) + (m & mmask));
+    }
+
+    cuint16 v = (uint16) (p * 65536.);
+    int i = 128;
+    int j = 128;
+    uint16 w;
+    while( w = Ptbl[i], j >>= 1) {
+        if( w < v)
+            i += j;
+        else if( w == v)
+            return (uchar) i;
+        else
+            i -= j;
+    }
+    if( w > v) {
+        cuint16 x = Ptbl[i-1];
+        if( v <= x  ||  w - v > v - x)
+            --i;
+    } else if( w < v  &&  i < 255) {
+        cuint16 x = Ptbl[i+1];
+        if( x <= v  ||  x - v < v - w)
+            ++i;
+    }
+    return (Index) i;
+}
+
+double bool_coder_spec::operator()( Index i) const {
+    if( !ebias)
+        return Ptbl[i]/65536.;
+    if( i >= half_index)
+        return 1. - ( *this)( (Index) (max_index - i));
+    return ldexp( (double)mantissa( i), - (int) exponent( i));
+}
+
+
+
+void bool_writer::carry() {
+    uchar *p = B;
+    assert( p > Bstart);
+    while( *--p == 255) { assert( p > Bstart);  *p = 0;}
+    ++*p;
+}
+
+
+bool_writer::bool_writer( c_spec& s, uchar *Dest, size_t Len)
+  : bool_coder( s),
+    Bstart( Dest),
+    Bend( Len? Dest+Len : 0),
+    B( Dest)
+{
+    assert( Dest);
+    reset();
+}
+
+bool_writer::~bool_writer() { flush();}
+
+#if 1
+    extern "C" { int bc_v = 0;}
+#else
+#   define bc_v 0
+#endif
+
+
+void bool_writer::raw( bool value, uint32 s) {
+    uint32 L = Low;
+
+    assert( Range >= min_range  &&  Range <= spec.max_range());
+    assert( !is_toast  &&  s  &&  s < Range);
+
+    if( bc_v) printf(
+        "Writing a %d, B %x  Low %x  Range %x  s %x   blag %d ...\n",
+        value? 1:0, B-Bstart, Low, Range, s, bit_lag
+    );
+    if( value) {
+        L += s;
+        s = Range - s;
+    } else
+        s -= rinc;
+    if( s < min_range) {
+        int ct = bit_lag;  do {
+            if( !--ct) {
+                ct = 8;
+                if( L & (1 << 31))
+                    carry();
+                assert( !Bend  ||  B < Bend);
+                *B++ = (uchar) (L >> 23);
+                L &= (1<<23) - 1;
+            }
+        } while( L += L, (s += s + rinc) < min_range);
+        bit_lag = ct;
+    }
+    Low = L;
+    Range = s;
+    if( bc_v)
+        printf(
+            "...done, B %x  Low %x  Range %x  blag %d \n",
+                B-Bstart, Low, Range, bit_lag
+        );
+}
+
+bool_writer& bool_writer::flush() {
+    if( is_toast)
+        return *this;
+    int b = bit_lag;
+    uint32 L = Low;
+    assert( b);
+    if( L & (1 << (32 - b)))
+        carry();
+    L <<= b & 7;
+    b >>= 3;
+    while( --b >= 0)
+        L <<= 8;
+    b = 4;
+    assert( !Bend  ||  B + 4 <= Bend);
+    do {
+        *B++ = (uchar) (L >> 24);
+        L <<= 8;
+    } while( --b);
+    is_toast = 1;
+    return *this;
+}
+
+
+bool_reader::bool_reader( c_spec& s, cuchar *src, size_t Len)
+  : bool_coder( s),
+    Bstart( src),
+    B( src),
+    Bend( Len? src+Len : 0),
+    shf( 32 - s.w),
+    bct( 8)
+{
+    int i = 4;  do { Low <<= 8;  Low |= *B++;}  while( --i);
+}
+
+
+bool bool_reader::raw( uint32 s) {
+
+    bool val = 0;
+    uint32 L = Low;
+    cuint32 S = s << shf;
+
+    assert( Range >= min_range  &&  Range <= spec.max_range());
+    assert( s  &&  s < Range  &&  (L >> shf) < Range);
+
+    if( bc_v)
+        printf(
+            "Reading, B %x  Low %x  Range %x  s %x  bct %d ...\n",
+            B-Bstart, Low, Range, s, bct
+        );
+
+    if( L >= S) {
+        L -= S;
+        s = Range - s;
+        assert( L < (s << shf));
+        val = 1;
+    } else
+        s -= rinc;
+    if( s < min_range) {
+        int ct = bct;
+        do {
+            assert( ~L & (1 << 31));
+            L += L;
+            if( !--ct) {
+                ct = 8;
+                if( !Bend  ||  B < Bend)
+                    L |= *B++;
+            }
+        } while( (s += s + rinc) < min_range);
+        bct = ct;
+    }
+    Low = L;
+    Range = s;
+    if( bc_v)
+        printf(
+            "...done, val %d  B %x  Low %x  Range %x  bct %d\n",
+            val? 1:0, B-Bstart, Low, Range, bct
+        );
+    return val;
+}
+
+
+/* C interfaces */
+
+// spec interface
+
+struct NS : bool_coder_namespace {
+    static Rounding r( vp8bc_c_prec *p, Rounding rr =down_full) {
+        return p? (Rounding) p->r : rr;
+    }
+};
+
+bool_coder_spec *vp8bc_vp6spec() {
+    return new bool_coder_spec_explicit_table( 0, bool_coder_namespace::Down, 8);
+}
+bool_coder_spec *vp8bc_float_spec(
+    unsigned int Ebits, unsigned int Mbits, vp8bc_c_prec *p
+) {
+    return new bool_coder_spec_float( Ebits, Mbits, NS::r( p), p? p->prec : 12);
+}
+bool_coder_spec *vp8bc_literal_spec(
+    const unsigned short m[256], vp8bc_c_prec *p
+) {
+    return new bool_coder_spec_explicit_table( m, NS::r( p), p? p->prec : 16);
+}
+bool_coder_spec *vp8bc_exponential_spec( unsigned int x, vp8bc_c_prec *p)
+{
+    return new bool_coder_spec_exponential_table( x, NS::r( p), p? p->prec : 16);
+}
+bool_coder_spec *vp8bc_spec_from_file( FILE *fp) {
+    return new bool_coder_spec( fp);
+}
+void vp8bc_destroy_spec( c_bool_coder_spec *p) { delete p;}
+
+void vp8bc_spec_to_file( c_bool_coder_spec *p, FILE *fp) { p->dump( fp);}
+
+vp8bc_index_t vp8bc_index( c_bool_coder_spec *p, double x) {
+    return ( *p)( x);
+}
+
+vp8bc_index_t vp8bc_index_from_counts(
+    c_bool_coder_spec *p, unsigned int L, unsigned int R
+) {
+    return ( *p)( (R += L)? (double) L/R : .5);
+}
+
+double vp8bc_probability( c_bool_coder_spec *p, vp8bc_index_t i) {
+    return ( *p)( i);
+}
+
+vp8bc_index_t vp8bc_complement( c_bool_coder_spec *p, vp8bc_index_t i) {
+    return p->complement( i);
+}
+unsigned int vp8bc_cost_zero( c_bool_coder_spec *p, vp8bc_index_t i) {
+    return p->cost_zero( i);
+}
+unsigned int vp8bc_cost_one( c_bool_coder_spec *p, vp8bc_index_t i) {
+    return p->cost_one( i);
+}
+unsigned int vp8bc_cost_bit( c_bool_coder_spec *p, vp8bc_index_t i, int v) {
+    return p->cost_bit( i, v);
+}
+
+#if tim_vp8
+    extern "C" int tok_verbose;
+
+#   define dbg_l 1000000
+
+    static vp8bc_index_t dbg_i [dbg_l];
+    static char dbg_v [dbg_l];
+    static size_t dbg_w = 0, dbg_r = 0;
+#endif
+
+// writer interface
+
+bool_writer *vp8bc_create_writer(
+    c_bool_coder_spec *p, unsigned char *D, size_t L
+) {
+    return new bool_writer( *p, D, L);
+}
+
+size_t vp8bc_destroy_writer( bool_writer *p) {
+    const size_t s = p->flush().bytes_written();
+    delete p;
+    return s;
+}
+
+void vp8bc_write_bool( bool_writer *p, int v, vp8bc_index_t i)
+{
+#   if tim_vp8
+        // bc_v = dbg_w < 10;
+        if( bc_v = tok_verbose)
+            printf( " writing %d at prob %d\n", v? 1:0, i);
+        accum_entropy_bc( &p->Spec(), i, v);
+
+        ( *p)( i, (bool) v);
+
+        if( dbg_w < dbg_l) {
+            dbg_i [dbg_w] = i;
+            dbg_v [dbg_w++] = v? 1:0;
+        }
+#   else
+        ( *p)( i, (bool) v);
+#   endif
+}
+
+void vp8bc_write_bits( bool_writer *p, unsigned int v, int n)
+{
+#   if tim_vp8
+        {
+            c_bool_coder_spec * const s = & p->Spec();
+            const vp8bc_index_t i = s->half_index();
+            int m = n;
+            while( --m >= 0)
+                accum_entropy_bc( s, i, (v>>m) & 1);
+        }
+#   endif
+
+    p->write_bits( n, v);
+}
+
+c_bool_coder_spec *vp8bc_writer_spec( c_bool_writer *w) { return & w->Spec();}
+
+// reader interface
+
+bool_reader *vp8bc_create_reader(
+    c_bool_coder_spec *p, const unsigned char *S, size_t L
+) {
+    return new bool_reader( *p, S, L);
+}
+
+void vp8bc_destroy_reader( bool_reader * p) { delete p;}
+
+int vp8bc_read_bool( bool_reader *p, vp8bc_index_t i)
+{
+#   if tim_vp8
+        // bc_v = dbg_r < 10;
+        bc_v = tok_verbose;
+        const int v = ( *p)( i)? 1:0;
+        if( tok_verbose)
+            printf( " reading %d at prob %d\n", v, i);
+        if( dbg_r < dbg_l) {
+            assert( dbg_r <= dbg_w);
+            if( i != dbg_i[dbg_r]  ||  v != dbg_v[dbg_r]) {
+                printf(
+        "Position %d: INCORRECTLY READING %d  prob %d, wrote %d  prob %d\n",
+                    dbg_r, v, i, dbg_v[dbg_r], dbg_i[dbg_r]
+                );
+            }
+            ++dbg_r;
+        }
+        return v;
+#   else
+        return ( *p)( i)? 1:0;
+#   endif
+}
+
+unsigned int vp8bc_read_bits( bool_reader *p, int n) { return p->read_bits( n);}
+
+c_bool_coder_spec *vp8bc_reader_spec( c_bool_reader *r) { return & r->Spec();}
+
+#undef bc_v
diff --git a/vp8/common/x86/idct_x86.h b/vp8/common/x86/idct_x86.h
new file mode 100644
index 0000000..5dfb212
--- /dev/null
+++ b/vp8/common/x86/idct_x86.h
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef IDCT_X86_H
+#define IDCT_X86_H
+
+/* Note:
+ *
+ * This platform is commonly built for runtime CPU detection. If you modify
+ * any of the function mappings present in this file, be sure to also update
+ * them in the function pointer initialization code
+ */
+
+#if HAVE_MMX
+extern prototype_idct(vp8_short_idct4x4llm_1_mmx);
+extern prototype_idct(vp8_short_idct4x4llm_mmx);
+extern prototype_idct_scalar(vp8_dc_only_idct_mmx);
+
+extern prototype_second_order(vp8_short_inv_walsh4x4_mmx);
+extern prototype_second_order(vp8_short_inv_walsh4x4_1_mmx);
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_idct_idct1
+#define vp8_idct_idct1 vp8_short_idct4x4llm_1_mmx
+
+#undef  vp8_idct_idct16
+#define vp8_idct_idct16 vp8_short_idct4x4llm_mmx
+
+#undef  vp8_idct_idct1_scalar
+#define vp8_idct_idct1_scalar vp8_dc_only_idct_mmx
+
+#undef vp8_idct_iwalsh16
+#define vp8_idct_iwalsh16 vp8_short_inv_walsh4x4_mmx
+
+#undef vp8_idct_iwalsh1
+#define vp8_idct_iwalsh1 vp8_short_inv_walsh4x4_1_mmx
+
+#endif
+#endif
+
+#if HAVE_SSE2
+
+extern prototype_second_order(vp8_short_inv_walsh4x4_sse2);
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+
+#undef vp8_idct_iwalsh16
+#define vp8_idct_iwalsh16 vp8_short_inv_walsh4x4_sse2
+
+#endif
+
+#endif
+
+
+
+#endif
diff --git a/vp8/common/x86/idctllm_mmx.asm b/vp8/common/x86/idctllm_mmx.asm
new file mode 100644
index 0000000..2751c69
--- /dev/null
+++ b/vp8/common/x86/idctllm_mmx.asm
@@ -0,0 +1,265 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+; /****************************************************************************
+; * Notes:
+; *
+; * This implementation makes use of 16 bit fixed point verio of two multiply
+; * constants:
+; *        1.   sqrt(2) * cos (pi/8)
+; *         2.   sqrt(2) * sin (pi/8)
+; * Becuase the first constant is bigger than 1, to maintain the same 16 bit
+; * fixed point prrcision as the second one, we use a trick of
+; *        x * a = x + x*(a-1)
+; * so
+; *        x * sqrt(2) * cos (pi/8) = x + x * (sqrt(2) *cos(pi/8)-1).
+; *
+; * For     the second constant, becuase of the 16bit version is 35468, which
+; * is bigger than 32768, in signed 16 bit multiply, it become a negative
+; * number.
+; *        (x * (unsigned)35468 >> 16) = x * (signed)35468 >> 16 + x
+; *
+; **************************************************************************/
+
+
+;void short_idct4x4llm_mmx(short *input, short *output, int pitch)
+global sym(vp8_short_idct4x4llm_mmx)
+sym(vp8_short_idct4x4llm_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    GET_GOT     rbx
+    ; end prolog
+
+        mov         rax,            arg(0) ;input
+        mov         rdx,            arg(1) ;output
+
+        movq        mm0,            [rax   ]
+        movq        mm1,            [rax+ 8]
+
+        movq        mm2,            [rax+16]
+        movq        mm3,            [rax+24]
+
+        movsxd      rax,            dword ptr arg(2) ;pitch
+
+        psubw       mm0,            mm2             ; b1= 0-2
+        paddw       mm2,            mm2             ;
+
+        movq        mm5,            mm1
+        paddw       mm2,            mm0             ; a1 =0+2
+
+        pmulhw      mm5,            [x_s1sqr2 GLOBAL]        ;
+        paddw       mm5,            mm1             ; ip1 * sin(pi/8) * sqrt(2)
+
+        movq        mm7,            mm3             ;
+        pmulhw      mm7,            [x_c1sqr2less1 GLOBAL]    ;
+
+        paddw       mm7,            mm3             ; ip3 * cos(pi/8) * sqrt(2)
+        psubw       mm7,            mm5             ; c1
+
+        movq        mm5,            mm1
+        movq        mm4,            mm3
+
+        pmulhw      mm5,            [x_c1sqr2less1 GLOBAL]
+        paddw       mm5,            mm1
+
+        pmulhw      mm3,            [x_s1sqr2 GLOBAL]
+        paddw       mm3,            mm4
+
+        paddw       mm3,            mm5             ; d1
+        movq        mm6,            mm2             ; a1
+
+        movq        mm4,            mm0             ; b1
+        paddw       mm2,            mm3             ;0
+
+        paddw       mm4,            mm7             ;1
+        psubw       mm0,            mm7             ;2
+
+        psubw       mm6,            mm3             ;3
+
+        movq        mm1,            mm2             ; 03 02 01 00
+        movq        mm3,            mm4             ; 23 22 21 20
+
+        punpcklwd   mm1,            mm0             ; 11 01 10 00
+        punpckhwd   mm2,            mm0             ; 13 03 12 02
+
+        punpcklwd   mm3,            mm6             ; 31 21 30 20
+        punpckhwd   mm4,            mm6             ; 33 23 32 22
+
+        movq        mm0,            mm1             ; 11 01 10 00
+        movq        mm5,            mm2             ; 13 03 12 02
+
+        punpckldq   mm0,            mm3             ; 30 20 10 00
+        punpckhdq   mm1,            mm3             ; 31 21 11 01
+
+        punpckldq   mm2,            mm4             ; 32 22 12 02
+        punpckhdq   mm5,            mm4             ; 33 23 13 03
+
+        movq        mm3,            mm5             ; 33 23 13 03
+
+        psubw       mm0,            mm2             ; b1= 0-2
+        paddw       mm2,            mm2             ;
+
+        movq        mm5,            mm1
+        paddw       mm2,            mm0             ; a1 =0+2
+
+        pmulhw      mm5,            [x_s1sqr2 GLOBAL]         ;
+        paddw       mm5,            mm1             ; ip1 * sin(pi/8) * sqrt(2)
+
+        movq        mm7,            mm3             ;
+        pmulhw      mm7,            [x_c1sqr2less1 GLOBAL]    ;
+
+        paddw       mm7,            mm3             ; ip3 * cos(pi/8) * sqrt(2)
+        psubw       mm7,            mm5             ; c1
+
+        movq        mm5,            mm1
+        movq        mm4,            mm3
+
+        pmulhw      mm5,            [x_c1sqr2less1 GLOBAL]
+        paddw       mm5,            mm1
+
+        pmulhw      mm3,            [x_s1sqr2 GLOBAL]
+        paddw       mm3,            mm4
+
+        paddw       mm3,            mm5             ; d1
+        paddw       mm0,            [fours GLOBAL]
+
+        paddw       mm2,            [fours GLOBAL]
+        movq        mm6,            mm2             ; a1
+
+        movq        mm4,            mm0             ; b1
+        paddw       mm2,            mm3             ;0
+
+        paddw       mm4,            mm7             ;1
+        psubw       mm0,            mm7             ;2
+
+        psubw       mm6,            mm3             ;3
+        psraw       mm2,            3
+
+        psraw       mm0,            3
+        psraw       mm4,            3
+
+        psraw       mm6,            3
+
+        movq        mm1,            mm2             ; 03 02 01 00
+        movq        mm3,            mm4             ; 23 22 21 20
+
+        punpcklwd   mm1,            mm0             ; 11 01 10 00
+        punpckhwd   mm2,            mm0             ; 13 03 12 02
+
+        punpcklwd   mm3,            mm6             ; 31 21 30 20
+        punpckhwd   mm4,            mm6             ; 33 23 32 22
+
+        movq        mm0,            mm1             ; 11 01 10 00
+        movq        mm5,            mm2             ; 13 03 12 02
+
+        punpckldq   mm0,            mm3             ; 30 20 10 00
+        punpckhdq   mm1,            mm3             ; 31 21 11 01
+
+        punpckldq   mm2,            mm4             ; 32 22 12 02
+        punpckhdq   mm5,            mm4             ; 33 23 13 03
+
+        movq        [rdx],          mm0
+
+        movq        [rdx+rax],      mm1
+        movq        [rdx+rax*2],    mm2
+
+        add         rdx,            rax
+        movq        [rdx+rax*2],    mm5
+
+    ; begin epilog
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void short_idct4x4llm_1_mmx(short *input, short *output, int pitch)
+global sym(vp8_short_idct4x4llm_1_mmx)
+sym(vp8_short_idct4x4llm_1_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    GET_GOT     rbx
+    ; end prolog
+
+        mov         rax,            arg(0) ;input
+        movd        mm0,            [rax]
+
+        paddw       mm0,            [fours GLOBAL]
+        mov         rdx,            arg(1) ;output
+
+        psraw       mm0,            3
+        movsxd      rax,            dword ptr arg(2) ;pitch
+
+        punpcklwd   mm0,            mm0
+        punpckldq   mm0,            mm0
+
+        movq        [rdx],          mm0
+        movq        [rdx+rax],      mm0
+
+        movq        [rdx+rax*2],    mm0
+        add         rdx,            rax
+
+        movq        [rdx+rax*2],    mm0
+
+
+    ; begin epilog
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void dc_only_idct_mmx(short input_dc, short *output, int pitch)
+global sym(vp8_dc_only_idct_mmx)
+sym(vp8_dc_only_idct_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    GET_GOT     rbx
+    ; end prolog
+
+        movd        mm0,            arg(0) ;input_dc
+
+        paddw       mm0,            [fours GLOBAL]
+        mov         rdx,            arg(1) ;output
+
+        psraw       mm0,            3
+        movsxd      rax,            dword ptr arg(2) ;pitch
+
+        punpcklwd   mm0,            mm0
+        punpckldq   mm0,            mm0
+
+        movq        [rdx],          mm0
+        movq        [rdx+rax],      mm0
+
+        movq        [rdx+rax*2],    mm0
+        add         rdx,            rax
+
+        movq        [rdx+rax*2],    mm0
+
+    ; begin epilog
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+x_s1sqr2:
+    times 4 dw 0x8A8C
+align 16
+x_c1sqr2less1:
+    times 4 dw 0x4E7B
+align 16
+fours:
+    times 4 dw 0x0004
diff --git a/vp8/common/x86/iwalsh_mmx.asm b/vp8/common/x86/iwalsh_mmx.asm
new file mode 100644
index 0000000..562e590
--- /dev/null
+++ b/vp8/common/x86/iwalsh_mmx.asm
@@ -0,0 +1,172 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_short_inv_walsh4x4_1_mmx(short *input, short *output)
+global sym(vp8_short_inv_walsh4x4_1_mmx)
+sym(vp8_short_inv_walsh4x4_1_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    mov     rsi, arg(0)
+    mov     rax, 3
+
+    mov     rdi, arg(1)
+    add     rax, [rsi]          ;input[0] + 3
+
+    movd    mm0, eax
+
+    punpcklwd mm0, mm0          ;x x val val
+
+    punpckldq mm0, mm0          ;val val val val
+
+    psraw   mm0, 3            ;(input[0] + 3) >> 3
+
+    movq  [rdi + 0], mm0
+    movq  [rdi + 8], mm0
+    movq  [rdi + 16], mm0
+    movq  [rdi + 24], mm0
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_short_inv_walsh4x4_mmx(short *input, short *output)
+global sym(vp8_short_inv_walsh4x4_mmx)
+sym(vp8_short_inv_walsh4x4_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    mov     rax, 3
+    mov     rsi, arg(0)
+    mov     rdi, arg(1)
+    shl     rax, 16
+
+    movq    mm0, [rsi + 0]        ;ip[0]
+    movq    mm1, [rsi + 8]        ;ip[4]
+    or      rax, 3            ;00030003h
+
+    movq    mm2, [rsi + 16]       ;ip[8]
+    movq    mm3, [rsi + 24]       ;ip[12]
+
+    movd    mm7, rax
+    movq    mm4, mm0
+
+    punpcklwd mm7, mm7          ;0003000300030003h
+    movq    mm5, mm1
+
+    paddw   mm4, mm3          ;ip[0] + ip[12] aka al
+    paddw   mm5, mm2          ;ip[4] + ip[8] aka bl
+
+    movq    mm6, mm4          ;temp al
+
+    paddw   mm4, mm5          ;al + bl
+    psubw   mm6, mm5          ;al - bl
+
+    psubw   mm0, mm3          ;ip[0] - ip[12] aka d1
+    psubw   mm1, mm2          ;ip[4] - ip[8] aka c1
+
+    movq    mm5, mm0          ;temp dl
+
+    paddw   mm0, mm1          ;dl + cl
+    psubw   mm5, mm1          ;dl - cl
+
+    ; 03 02 01 00
+    ; 13 12 11 10
+    ; 23 22 21 20
+    ; 33 32 31 30
+
+    movq    mm3, mm4          ; 03 02 01 00
+    punpcklwd mm4, mm0          ; 11 01 10 00
+    punpckhwd mm3, mm0          ; 13 03 12 02
+
+    movq    mm1, mm6          ; 23 22 21 20
+    punpcklwd mm6, mm5          ; 31 21 30 20
+    punpckhwd mm1, mm5          ; 33 23 32 22
+
+    movq    mm0, mm4          ; 11 01 10 00
+    movq    mm2, mm3          ; 13 03 12 02
+
+    punpckldq mm0, mm6          ; 30 20 10 00 aka ip[0]
+    punpckhdq mm4, mm6          ; 31 21 11 01 aka ip[4]
+
+    punpckldq mm2, mm1          ; 32 22 12 02 aka ip[8]
+    punpckhdq mm3, mm1          ; 33 23 13 03 aka ip[12]
+;~~~~~~~~~~~~~~~~~~~~~
+    movq    mm1, mm0
+    movq    mm5, mm4
+
+    paddw   mm1, mm3          ;ip[0] + ip[12] aka al
+    paddw   mm5, mm2          ;ip[4] + ip[8] aka bl
+
+    movq    mm6, mm1          ;temp al
+
+    paddw   mm1, mm5          ;al + bl
+    psubw   mm6, mm5          ;al - bl
+
+    psubw   mm0, mm3          ;ip[0] - ip[12] aka d1
+    psubw   mm4, mm2          ;ip[4] - ip[8] aka c1
+
+    movq    mm5, mm0          ;temp dl
+
+    paddw   mm0, mm4          ;dl + cl
+    psubw   mm5, mm4          ;dl - cl
+;~~~~~~~~~~~~~~~~~~~~~
+    movq    mm3, mm1          ; 03 02 01 00
+    punpcklwd mm1, mm0          ; 11 01 10 00
+    punpckhwd mm3, mm0          ; 13 03 12 02
+
+    movq    mm4, mm6          ; 23 22 21 20
+    punpcklwd mm6, mm5          ; 31 21 30 20
+    punpckhwd mm4, mm5          ; 33 23 32 22
+
+    movq    mm0, mm1          ; 11 01 10 00
+    movq    mm2, mm3          ; 13 03 12 02
+
+    punpckldq mm0, mm6          ; 30 20 10 00 aka ip[0]
+    punpckhdq mm1, mm6          ; 31 21 11 01 aka ip[4]
+
+    punpckldq mm2, mm4          ; 32 22 12 02 aka ip[8]
+    punpckhdq mm3, mm4          ; 33 23 13 03 aka ip[12]
+
+    paddw   mm0, mm7
+    paddw   mm1, mm7
+    paddw   mm2, mm7
+    paddw   mm3, mm7
+
+    psraw   mm0, 3
+    psraw   mm1, 3
+    psraw   mm2, 3
+    psraw   mm3, 3
+
+    movq  [rdi + 0], mm0
+    movq  [rdi + 8], mm1
+    movq  [rdi + 16], mm2
+    movq  [rdi + 24], mm3
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
diff --git a/vp8/common/x86/iwalsh_sse2.asm b/vp8/common/x86/iwalsh_sse2.asm
new file mode 100644
index 0000000..96943df
--- /dev/null
+++ b/vp8/common/x86/iwalsh_sse2.asm
@@ -0,0 +1,116 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_short_inv_walsh4x4_sse2(short *input, short *output)
+global sym(vp8_short_inv_walsh4x4_sse2)
+sym(vp8_short_inv_walsh4x4_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    mov     rsi, arg(0)
+    mov     rdi, arg(1)
+    mov     rax, 3
+
+    movdqa    xmm0, [rsi + 0]       ;ip[4] ip[0]
+    movdqa    xmm1, [rsi + 16]      ;ip[12] ip[8]
+
+    shl     rax, 16
+    or      rax, 3            ;00030003h
+
+    pshufd    xmm2, xmm1, 4eh       ;ip[8] ip[12]
+    movdqa    xmm3, xmm0          ;ip[4] ip[0]
+
+    paddw   xmm0, xmm2          ;ip[4]+ip[8] ip[0]+ip[12] aka b1 a1
+    psubw   xmm3, xmm2          ;ip[4]-ip[8] ip[0]-ip[12] aka c1 d1
+
+    movdqa    xmm4, xmm0
+    punpcklqdq  xmm0, xmm3          ;d1 a1
+    punpckhqdq  xmm4, xmm3          ;c1 b1
+    movd    xmm7, eax
+
+    movdqa    xmm1, xmm4          ;c1 b1
+    paddw   xmm4, xmm0          ;dl+cl a1+b1 aka op[4] op[0]
+    psubw   xmm0, xmm1          ;d1-c1 a1-b1 aka op[12] op[8]
+
+;;;temp output
+;;  movdqu  [rdi + 0], xmm4
+;;  movdqu  [rdi + 16], xmm3
+
+;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    ; 13 12 11 10 03 02 01 00
+    ;
+    ; 33 32 31 30 23 22 21 20
+    ;
+    movdqa    xmm3, xmm4          ; 13 12 11 10 03 02 01 00
+    punpcklwd xmm4, xmm0          ; 23 03 22 02 21 01 20 00
+    punpckhwd xmm3, xmm0          ; 33 13 32 12 31 11 30 10
+    movdqa    xmm1, xmm4          ; 23 03 22 02 21 01 20 00
+    punpcklwd xmm4, xmm3          ; 31 21 11 01 30 20 10 00
+    punpckhwd xmm1, xmm3          ; 33 23 13 03 32 22 12 02
+    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    pshufd    xmm2, xmm1, 4eh       ;ip[8] ip[12]
+    movdqa    xmm3, xmm4          ;ip[4] ip[0]
+
+    pshufd    xmm7, xmm7, 0       ;03 03 03 03 03 03 03 03
+
+    paddw   xmm4, xmm2          ;ip[4]+ip[8] ip[0]+ip[12] aka b1 a1
+    psubw   xmm3, xmm2          ;ip[4]-ip[8] ip[0]-ip[12] aka c1 d1
+
+    movdqa    xmm5, xmm4
+    punpcklqdq  xmm4, xmm3          ;d1 a1
+    punpckhqdq  xmm5, xmm3          ;c1 b1
+
+    movdqa    xmm1, xmm5          ;c1 b1
+    paddw   xmm5, xmm4          ;dl+cl a1+b1 aka op[4] op[0]
+    psubw   xmm4, xmm1          ;d1-c1 a1-b1 aka op[12] op[8]
+;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    ; 13 12 11 10 03 02 01 00
+    ;
+    ; 33 32 31 30 23 22 21 20
+    ;
+    movdqa    xmm0, xmm5          ; 13 12 11 10 03 02 01 00
+    punpcklwd xmm5, xmm4          ; 23 03 22 02 21 01 20 00
+    punpckhwd xmm0, xmm4          ; 33 13 32 12 31 11 30 10
+    movdqa    xmm1, xmm5          ; 23 03 22 02 21 01 20 00
+    punpcklwd xmm5, xmm0          ; 31 21 11 01 30 20 10 00
+    punpckhwd xmm1, xmm0          ; 33 23 13 03 32 22 12 02
+;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    paddw   xmm5, xmm7
+    paddw   xmm1, xmm7
+
+    psraw   xmm5, 3
+    psraw   xmm1, 3
+
+    movdqa  [rdi + 0], xmm5
+    movdqa  [rdi + 16], xmm1
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+x_s1sqr2:
+    times 4 dw 0x8A8C
+align 16
+x_c1sqr2less1:
+    times 4 dw 0x4E7B
+align 16
+fours:
+    times 4 dw 0x0004
diff --git a/vp8/common/x86/loopfilter_mmx.asm b/vp8/common/x86/loopfilter_mmx.asm
new file mode 100644
index 0000000..6e4d2b6
--- /dev/null
+++ b/vp8/common/x86/loopfilter_mmx.asm
@@ -0,0 +1,1776 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+
+;void vp8_loop_filter_horizontal_edge_mmx
+;(
+;    unsigned char *src_ptr,
+;    int src_pixel_step,
+;    const char *flimit,
+;    const char *limit,
+;    const char *thresh,
+;    int  count
+;)
+global sym(vp8_loop_filter_horizontal_edge_mmx)
+sym(vp8_loop_filter_horizontal_edge_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 32                         ; reserve 32 bytes
+    %define t0 [rsp + 0]    ;__declspec(align(16)) char t0[8];
+    %define t1 [rsp + 16]   ;__declspec(align(16)) char t1[8];
+
+        mov         rsi, arg(0) ;src_ptr
+        movsxd      rax, dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        movsxd      rcx, dword ptr arg(5) ;count
+next8_h:
+        mov         rdx, arg(3) ;limit
+        movq        mm7, [rdx]
+        mov         rdi, rsi              ; rdi points to row +1 for indirect addressing
+        add         rdi, rax
+
+        ; calculate breakout conditions
+        movq        mm2, [rdi+2*rax]      ; q3
+        movq        mm1, [rsi+2*rax]      ; q2
+        movq        mm6, mm1              ; q2
+        psubusb     mm1, mm2              ; q2-=q3
+        psubusb     mm2, mm6              ; q3-=q2
+        por         mm1, mm2              ; abs(q3-q2)
+        psubusb     mm1, mm7              ;
+
+
+        movq        mm4, [rsi+rax]        ; q1
+        movq        mm3, mm4              ; q1
+        psubusb     mm4, mm6              ; q1-=q2
+        psubusb     mm6, mm3              ; q2-=q1
+        por         mm4, mm6              ; abs(q2-q1)
+
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+        movq        mm4, [rsi]            ; q0
+        movq        mm0, mm4              ; q0
+        psubusb     mm4, mm3              ; q0-=q1
+        psubusb     mm3, mm0              ; q1-=q0
+        por         mm4, mm3              ; abs(q0-q1)
+        movq        t0, mm4               ; save to t0
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+
+        neg         rax                   ; negate pitch to deal with above border
+
+        movq        mm2, [rsi+4*rax]      ; p3
+        movq        mm4, [rdi+4*rax]      ; p2
+        movq        mm5, mm4              ; p2
+        psubusb     mm4, mm2              ; p2-=p3
+        psubusb     mm2, mm5              ; p3-=p2
+        por         mm4, mm2              ; abs(p3 - p2)
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+
+        movq        mm4, [rsi+2*rax]      ; p1
+        movq        mm3, mm4              ; p1
+        psubusb     mm4, mm5              ; p1-=p2
+        psubusb     mm5, mm3              ; p2-=p1
+        por         mm4, mm5              ; abs(p2 - p1)
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+        movq        mm2, mm3              ; p1
+
+        movq        mm4, [rsi+rax]        ; p0
+        movq        mm5, mm4              ; p0
+        psubusb     mm4, mm3              ; p0-=p1
+        psubusb     mm3, mm5              ; p1-=p0
+        por         mm4, mm3              ; abs(p1 - p0)
+        movq        t1, mm4               ; save to t1
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+        movq        mm3, [rdi]            ; q1
+        movq        mm4, mm3              ; q1
+        psubusb     mm3, mm2              ; q1-=p1
+        psubusb     mm2, mm4              ; p1-=q1
+        por         mm2, mm3              ; abs(p1-q1)
+        pand        mm2, [tfe GLOBAL]     ; set lsb of each byte to zero
+        psrlw       mm2, 1                ; abs(p1-q1)/2
+
+        movq        mm6, mm5              ; p0
+        movq        mm3, [rsi]            ; q0
+        psubusb     mm5, mm3              ; p0-=q0
+        psubusb     mm3, mm6              ; q0-=p0
+        por         mm5, mm3              ; abs(p0 - q0)
+        paddusb     mm5, mm5              ; abs(p0-q0)*2
+        paddusb     mm5, mm2              ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        mov         rdx, arg(2) ;flimit           ; get flimit
+        movq        mm2, [rdx]            ; flimit mm2
+        paddb       mm2, mm2              ; flimit*2 (less than 255)
+        paddb       mm7, mm2              ; flimit * 2 + limit (less than 255)
+
+        psubusb     mm5,    mm7           ; abs (p0 - q0) *2 + abs(p1-q1)/2  > flimit * 2 + limit
+        por         mm1,    mm5
+        pxor        mm5,    mm5
+        pcmpeqb     mm1,    mm5           ; mask mm1
+
+        ; calculate high edge variance
+        mov         rdx, arg(4) ;thresh           ; get thresh
+        movq        mm7, [rdx]            ;
+        movq        mm4, t0               ; get abs (q1 - q0)
+        psubusb     mm4, mm7
+        movq        mm3, t1               ; get abs (p1 - p0)
+        psubusb     mm3, mm7
+        paddb       mm4, mm3              ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+
+        pcmpeqb     mm4,        mm5
+
+        pcmpeqb     mm5,        mm5
+        pxor        mm4,        mm5
+
+
+        ; start work on filters
+        movq        mm2, [rsi+2*rax]      ; p1
+        movq        mm7, [rdi]            ; q1
+        pxor        mm2, [t80 GLOBAL]     ; p1 offset to convert to signed values
+        pxor        mm7, [t80 GLOBAL]     ; q1 offset to convert to signed values
+        psubsb      mm2, mm7              ; p1 - q1
+        pand        mm2, mm4              ; high var mask (hvm)(p1 - q1)
+        pxor        mm6, [t80 GLOBAL]     ; offset to convert to signed values
+        pxor        mm0, [t80 GLOBAL]     ; offset to convert to signed values
+        movq        mm3, mm0              ; q0
+        psubsb      mm0, mm6              ; q0 - p0
+        paddsb      mm2, mm0              ; 1 * (q0 - p0) + hvm(p1 - q1)
+        paddsb      mm2, mm0              ; 2 * (q0 - p0) + hvm(p1 - q1)
+        paddsb      mm2, mm0              ; 3 * (q0 - p0) + hvm(p1 - q1)
+        pand        mm1, mm2                  ; mask filter values we don't care about
+        movq        mm2, mm1
+        paddsb      mm1, [t4 GLOBAL]      ; 3* (q0 - p0) + hvm(p1 - q1) + 4
+        paddsb      mm2, [t3 GLOBAL]      ; 3* (q0 - p0) + hvm(p1 - q1) + 3
+
+        pxor        mm0, mm0             ;
+        pxor        mm5, mm5
+        punpcklbw   mm0, mm2            ;
+        punpckhbw   mm5, mm2            ;
+        psraw       mm0, 11             ;
+        psraw       mm5, 11
+        packsswb    mm0, mm5
+        movq        mm2, mm0            ;  (3* (q0 - p0) + hvm(p1 - q1) + 3) >> 3;
+
+        pxor        mm0, mm0              ; 0
+        movq        mm5, mm1              ; abcdefgh
+        punpcklbw   mm0, mm1              ; e0f0g0h0
+        psraw       mm0, 11               ; sign extended shift right by 3
+        pxor        mm1, mm1              ; 0
+        punpckhbw   mm1, mm5              ; a0b0c0d0
+        psraw       mm1, 11               ; sign extended shift right by 3
+        movq        mm5, mm0              ; save results
+
+        packsswb    mm0, mm1              ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>3
+        paddsw      mm5, [ones GLOBAL]
+        paddsw      mm1, [ones GLOBAL]
+        psraw       mm5, 1                ; partial shifted one more time for 2nd tap
+        psraw       mm1, 1                ; partial shifted one more time for 2nd tap
+        packsswb    mm5, mm1              ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>4
+        pandn       mm4, mm5              ; high edge variance additive
+
+        paddsb      mm6, mm2              ; p0+= p0 add
+        pxor        mm6, [t80 GLOBAL]     ; unoffset
+        movq        [rsi+rax], mm6        ; write back
+
+        movq        mm6, [rsi+2*rax]      ; p1
+        pxor        mm6, [t80 GLOBAL]     ; reoffset
+        paddsb      mm6, mm4              ; p1+= p1 add
+        pxor        mm6, [t80 GLOBAL]     ; unoffset
+        movq        [rsi+2*rax], mm6      ; write back
+
+        psubsb      mm3, mm0              ; q0-= q0 add
+        pxor        mm3, [t80 GLOBAL]     ; unoffset
+        movq        [rsi], mm3            ; write back
+
+        psubsb      mm7, mm4              ; q1-= q1 add
+        pxor        mm7, [t80 GLOBAL]     ; unoffset
+        movq        [rdi], mm7            ; write back
+
+        add         rsi,8
+        neg         rax
+        dec         rcx
+        jnz         next8_h
+
+    add rsp, 32
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_loop_filter_vertical_edge_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *flimit,
+;    const char *limit,
+;    const char *thresh,
+;    int count
+;)
+global sym(vp8_loop_filter_vertical_edge_mmx)
+sym(vp8_loop_filter_vertical_edge_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub          rsp, 64      ; reserve 64 bytes
+    %define t0   [rsp + 0]    ;__declspec(align(16)) char t0[8];
+    %define t1   [rsp + 16]   ;__declspec(align(16)) char t1[8];
+    %define srct [rsp + 32]   ;__declspec(align(16)) char srct[32];
+
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rax,        dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        lea         rsi,        [rsi + rax*4 - 4]
+
+        movsxd      rcx,        dword ptr arg(5) ;count
+next8_v:
+        mov         rdi,        rsi           ; rdi points to row +1 for indirect addressing
+        add         rdi,        rax
+
+
+        ;transpose
+        movq        mm6,        [rsi+2*rax]                 ; 67 66 65 64 63 62 61 60
+        movq        mm7,        mm6                         ; 77 76 75 74 73 72 71 70
+
+        punpckhbw   mm7,        [rdi+2*rax]                 ; 77 67 76 66 75 65 74 64
+        punpcklbw   mm6,        [rdi+2*rax]                 ; 73 63 72 62 71 61 70 60
+
+        movq        mm4,        [rsi]                       ; 47 46 45 44 43 42 41 40
+        movq        mm5,        mm4                         ; 47 46 45 44 43 42 41 40
+
+        punpckhbw   mm5,        [rsi+rax]                   ; 57 47 56 46 55 45 54 44
+        punpcklbw   mm4,        [rsi+rax]                   ; 53 43 52 42 51 41 50 40
+
+        movq        mm3,        mm5                         ; 57 47 56 46 55 45 54 44
+        punpckhwd   mm5,        mm7                         ; 77 67 57 47 76 66 56 46
+
+        punpcklwd   mm3,        mm7                         ; 75 65 55 45 74 64 54 44
+        movq        mm2,        mm4                         ; 53 43 52 42 51 41 50 40
+
+        punpckhwd   mm4,        mm6                         ; 73 63 53 43 72 62 52 42
+        punpcklwd   mm2,        mm6                         ; 71 61 51 41 70 60 50 40
+
+        neg         rax
+        movq        mm6,        [rsi+rax*2]                 ; 27 26 25 24 23 22 21 20
+
+        movq        mm1,        mm6                         ; 27 26 25 24 23 22 21 20
+        punpckhbw   mm6,        [rsi+rax]                   ; 37 27 36 36 35 25 34 24
+
+        punpcklbw   mm1,        [rsi+rax]                   ; 33 23 32 22 31 21 30 20
+        movq        mm7,        [rsi+rax*4];                ; 07 06 05 04 03 02 01 00
+
+        punpckhbw   mm7,        [rdi+rax*4]                 ; 17 07 16 06 15 05 14 04
+        movq        mm0,        mm7                         ; 17 07 16 06 15 05 14 04
+
+        punpckhwd   mm7,        mm6                         ; 37 27 17 07 36 26 16 06
+        punpcklwd   mm0,        mm6                         ; 35 25 15 05 34 24 14 04
+
+        movq        mm6,        mm7                         ; 37 27 17 07 36 26 16 06
+        punpckhdq   mm7,        mm5                         ; 77 67 57 47 37 27 17 07  = q3
+
+        punpckldq   mm6,        mm5                         ; 76 66 56 46 36 26 16 06  = q2
+
+        movq        mm5,        mm6                         ; 76 66 56 46 36 26 16 06
+        psubusb     mm5,        mm7                         ; q2-q3
+
+        psubusb     mm7,        mm6                         ; q3-q2
+        por         mm7,        mm5;                        ; mm7=abs (q3-q2)
+
+        movq        mm5,        mm0                         ; 35 25 15 05 34 24 14 04
+        punpckhdq   mm5,        mm3                         ; 75 65 55 45 35 25 15 05 = q1
+
+        punpckldq   mm0,        mm3                         ; 74 64 54 44 34 24 15 04 = q0
+        movq        mm3,        mm5                         ; 75 65 55 45 35 25 15 05 = q1
+
+        psubusb     mm3,        mm6                         ; q1-q2
+        psubusb     mm6,        mm5                         ; q2-q1
+
+        por         mm6,        mm3                         ; mm6=abs(q2-q1)
+        lea         rdx,        srct
+
+        movq        [rdx+24],   mm5                         ; save q1
+        movq        [rdx+16],   mm0                         ; save q0
+
+        movq        mm3,        [rsi+rax*4]                 ; 07 06 05 04 03 02 01 00
+        punpcklbw   mm3,        [rdi+rax*4]                 ; 13 03 12 02 11 01 10 00
+
+        movq        mm0,        mm3                         ; 13 03 12 02 11 01 10 00
+        punpcklwd   mm0,        mm1                         ; 31 21 11 01 30 20 10 00
+
+        punpckhwd   mm3,        mm1                         ; 33 23 13 03 32 22 12 02
+        movq        mm1,        mm0                         ; 31 21 11 01 30 20 10 00
+
+        punpckldq   mm0,        mm2                         ; 70 60 50 40 30 20 10 00  =p3
+        punpckhdq   mm1,        mm2                         ; 71 61 51 41 31 21 11 01  =p2
+
+        movq        mm2,        mm1                         ; 71 61 51 41 31 21 11 01  =p2
+        psubusb     mm2,        mm0                         ; p2-p3
+
+        psubusb     mm0,        mm1                         ; p3-p2
+        por         mm0,        mm2                         ; mm0=abs(p3-p2)
+
+        movq        mm2,        mm3                         ; 33 23 13 03 32 22 12 02
+        punpckldq   mm2,        mm4                         ; 72 62 52 42 32 22 12 02 = p1
+
+        punpckhdq   mm3,        mm4                         ; 73 63 53 43 33 23 13 03 = p0
+        movq        [rdx+8],    mm3                         ; save p0
+
+        movq        [rdx],      mm2                         ; save p1
+        movq        mm5,        mm2                         ; mm5 = p1
+
+        psubusb     mm2,        mm1                         ; p1-p2
+        psubusb     mm1,        mm5                         ; p2-p1
+
+        por         mm1,        mm2                         ; mm1=abs(p2-p1)
+        mov         rdx,        arg(3) ;limit
+
+        movq        mm4,        [rdx]                       ; mm4 = limit
+        psubusb     mm7,        mm4
+
+        psubusb     mm0,        mm4
+        psubusb     mm1,        mm4
+
+        psubusb     mm6,        mm4
+        por         mm7,        mm6
+
+        por         mm0,        mm1
+        por         mm0,        mm7                         ;   abs(q3-q2) > limit || abs(p3-p2) > limit ||abs(p2-p1) > limit || abs(q2-q1) > limit
+
+        movq        mm1,        mm5                         ; p1
+
+        movq        mm7,        mm3                         ; mm3=mm7=p0
+        psubusb     mm7,        mm5                         ; p0 - p1
+
+        psubusb     mm5,        mm3                         ; p1 - p0
+        por         mm5,        mm7                         ; abs(p1-p0)
+
+        movq        t0,         mm5                         ; save abs(p1-p0)
+        lea         rdx,        srct
+
+        psubusb     mm5,        mm4
+        por         mm0,        mm5                         ; mm0=mask
+
+        movq        mm5,        [rdx+16]                    ; mm5=q0
+        movq        mm7,        [rdx+24]                    ; mm7=q1
+
+        movq        mm6,        mm5                         ; mm6=q0
+        movq        mm2,        mm7                         ; q1
+        psubusb     mm5,        mm7                         ; q0-q1
+
+        psubusb     mm7,        mm6                         ; q1-q0
+        por         mm7,        mm5                         ; abs(q1-q0)
+
+        movq        t1,         mm7                         ; save abs(q1-q0)
+        psubusb     mm7,        mm4
+
+        por         mm0,        mm7                         ; mask
+
+        movq        mm5,        mm2                         ; q1
+        psubusb     mm5,        mm1                         ; q1-=p1
+        psubusb     mm1,        mm2                         ; p1-=q1
+        por         mm5,        mm1                         ; abs(p1-q1)
+        pand        mm5,        [tfe GLOBAL]                ; set lsb of each byte to zero
+        psrlw       mm5,        1                           ; abs(p1-q1)/2
+
+        mov         rdx,        arg(2) ;flimit                      ;
+
+        movq        mm2,        [rdx]                       ;flimit  mm2
+        movq        mm1,        mm3                         ; mm1=mm3=p0
+
+        movq        mm7,        mm6                         ; mm7=mm6=q0
+        psubusb     mm1,        mm7                         ; p0-q0
+
+        psubusb     mm7,        mm3                         ; q0-p0
+        por         mm1,        mm7                         ; abs(q0-p0)
+        paddusb     mm1,        mm1                         ; abs(q0-p0)*2
+        paddusb     mm1,        mm5                         ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        paddb       mm2,        mm2                         ; flimit*2 (less than 255)
+        paddb       mm4,        mm2                         ; flimit * 2 + limit (less than 255)
+
+        psubusb     mm1,        mm4                         ; abs (p0 - q0) *2 + abs(p1-q1)/2  > flimit * 2 + limit
+        por         mm1,        mm0;                        ; mask
+
+        pxor        mm0,        mm0
+        pcmpeqb     mm1,        mm0
+
+        ; calculate high edge variance
+        mov         rdx,        arg(4) ;thresh            ; get thresh
+        movq        mm7,        [rdx]
+        ;
+        movq        mm4,        t0              ; get abs (q1 - q0)
+        psubusb     mm4,        mm7
+
+        movq        mm3,        t1              ; get abs (p1 - p0)
+        psubusb     mm3,        mm7
+
+        por         mm4,        mm3             ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+        pcmpeqb     mm4,        mm0
+
+        pcmpeqb     mm0,        mm0
+        pxor        mm4,        mm0
+
+
+
+        ; start work on filters
+        lea         rdx,        srct
+
+        movq        mm2,        [rdx]           ; p1
+        movq        mm7,        [rdx+24]        ; q1
+
+        movq        mm6,        [rdx+8]         ; p0
+        movq        mm0,        [rdx+16]        ; q0
+
+        pxor        mm2,        [t80 GLOBAL]    ; p1 offset to convert to signed values
+        pxor        mm7,        [t80 GLOBAL]    ; q1 offset to convert to signed values
+
+        psubsb      mm2,        mm7             ; p1 - q1
+        pand        mm2,        mm4             ; high var mask (hvm)(p1 - q1)
+
+        pxor        mm6,        [t80 GLOBAL]    ; offset to convert to signed values
+        pxor        mm0,        [t80 GLOBAL]    ; offset to convert to signed values
+
+        movq        mm3,        mm0             ; q0
+        psubsb      mm0,        mm6             ; q0 - p0
+
+        paddsb      mm2,        mm0             ; 1 * (q0 - p0) + hvm(p1 - q1)
+        paddsb      mm2,        mm0             ; 2 * (q0 - p0) + hvm(p1 - q1)
+
+        paddsb      mm2,        mm0             ; 3 * (q0 - p0) + hvm(p1 - q1)
+        pand       mm1,        mm2              ; mask filter values we don't care about
+
+        movq        mm2,        mm1
+        paddsb      mm1,        [t4 GLOBAL]       ; 3* (q0 - p0) + hvm(p1 - q1) + 4
+
+        paddsb      mm2,        [t3 GLOBAL]       ; 3* (q0 - p0) + hvm(p1 - q1) + 3
+        pxor        mm0,        mm0          ;
+
+        pxor        mm5,        mm5
+        punpcklbw   mm0,        mm2         ;
+
+        punpckhbw   mm5,        mm2         ;
+        psraw       mm0,        11              ;
+
+        psraw       mm5,        11
+        packsswb    mm0,        mm5
+
+        movq        mm2,        mm0         ;  (3* (q0 - p0) + hvm(p1 - q1) + 3) >> 3;
+
+        pxor        mm0,        mm0           ; 0
+        movq        mm5,        mm1           ; abcdefgh
+
+        punpcklbw   mm0,        mm1           ; e0f0g0h0
+        psraw       mm0,        11                ; sign extended shift right by 3
+
+        pxor        mm1,        mm1           ; 0
+        punpckhbw   mm1,        mm5           ; a0b0c0d0
+
+        psraw       mm1,        11                ; sign extended shift right by 3
+        movq        mm5,        mm0              ; save results
+
+        packsswb    mm0,        mm1           ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>3
+        paddsw      mm5,        [ones GLOBAL]
+
+        paddsw      mm1,        [ones GLOBAL]
+        psraw       mm5,        1                 ; partial shifted one more time for 2nd tap
+
+        psraw       mm1,        1                 ; partial shifted one more time for 2nd tap
+        packsswb    mm5,        mm1           ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>4
+
+        pandn       mm4,        mm5             ; high edge variance additive
+
+        paddsb      mm6,        mm2             ; p0+= p0 add
+        pxor        mm6,        [t80 GLOBAL]    ; unoffset
+
+        ; mm6=p0                               ;
+        movq        mm1,        [rdx]           ; p1
+        pxor        mm1,        [t80 GLOBAL]    ; reoffset
+
+        paddsb      mm1,        mm4                 ; p1+= p1 add
+        pxor        mm1,        [t80 GLOBAL]        ; unoffset
+        ; mm6 = p0 mm1 = p1
+
+        psubsb      mm3,        mm0                 ; q0-= q0 add
+        pxor        mm3,        [t80 GLOBAL]        ; unoffset
+
+        ; mm3 = q0
+        psubsb      mm7,        mm4                 ; q1-= q1 add
+        pxor        mm7,        [t80 GLOBAL]        ; unoffset
+        ; mm7 = q1
+
+        ; tranpose and write back
+        ; mm1 =    72 62 52 42 32 22 12 02
+        ; mm6 =    73 63 53 43 33 23 13 03
+        ; mm3 =    74 64 54 44 34 24 14 04
+        ; mm7 =    75 65 55 45 35 25 15 05
+
+        movq        mm2,        mm1             ; 72 62 52 42 32 22 12 02
+        punpcklbw   mm2,        mm6             ; 33 32 23 22 13 12 03 02
+
+        movq        mm4,        mm3             ; 74 64 54 44 34 24 14 04
+        punpckhbw   mm1,        mm6             ; 73 72 63 62 53 52 43 42
+
+        punpcklbw   mm4,        mm7             ; 35 34 25 24 15 14 05 04
+        punpckhbw   mm3,        mm7             ; 75 74 65 64 55 54 45 44
+
+        movq        mm6,        mm2             ; 33 32 23 22 13 12 03 02
+        punpcklwd   mm2,        mm4             ; 15 14 13 12 05 04 03 02
+
+        punpckhwd   mm6,        mm4             ; 35 34 33 32 25 24 23 22
+        movq        mm5,        mm1             ; 73 72 63 62 53 52 43 42
+
+        punpcklwd   mm1,        mm3             ; 55 54 53 52 45 44 43 42
+        punpckhwd   mm5,        mm3             ; 75 74 73 72 65 64 63 62
+
+
+        ; mm2 = 15 14 13 12 05 04 03 02
+        ; mm6 = 35 34 33 32 25 24 23 22
+        ; mm5 = 55 54 53 52 45 44 43 42
+        ; mm1 = 75 74 73 72 65 64 63 62
+
+
+
+        movd        [rsi+rax*4+2], mm2
+        psrlq       mm2,        32
+
+        movd        [rdi+rax*4+2], mm2
+        movd        [rsi+rax*2+2], mm6
+
+        psrlq       mm6,        32
+        movd        [rsi+rax+2],mm6
+
+        movd        [rsi+2],    mm1
+        psrlq       mm1,        32
+
+        movd        [rdi+2],    mm1
+        neg         rax
+
+        movd        [rdi+rax+2],mm5
+        psrlq       mm5,        32
+
+        movd        [rdi+rax*2+2], mm5
+
+        lea         rsi,        [rsi+rax*8]
+        dec         rcx
+        jnz         next8_v
+
+    add rsp, 64
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_mbloop_filter_horizontal_edge_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *flimit,
+;    const char *limit,
+;    const char *thresh,
+;    int count
+;)
+global sym(vp8_mbloop_filter_horizontal_edge_mmx)
+sym(vp8_mbloop_filter_horizontal_edge_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub          rsp, 32      ; reserve 32 bytes
+    %define t0   [rsp + 0]    ;__declspec(align(16)) char t0[8];
+    %define t1   [rsp + 16]   ;__declspec(align(16)) char t1[8];
+
+        mov         rsi, arg(0) ;src_ptr
+        movsxd      rax, dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        movsxd      rcx, dword ptr arg(5) ;count
+next8_mbh:
+        mov         rdx, arg(3) ;limit
+        movq        mm7, [rdx]
+        mov         rdi, rsi              ; rdi points to row +1 for indirect addressing
+        add         rdi, rax
+
+        ; calculate breakout conditions
+        movq        mm2, [rdi+2*rax]      ; q3
+
+        movq        mm1, [rsi+2*rax]      ; q2
+        movq        mm6, mm1              ; q2
+        psubusb     mm1, mm2              ; q2-=q3
+        psubusb     mm2, mm6              ; q3-=q2
+        por         mm1, mm2              ; abs(q3-q2)
+        psubusb     mm1, mm7
+
+
+        ; mm1 = abs(q3-q2), mm6 =q2, mm7 = limit
+        movq        mm4, [rsi+rax]        ; q1
+        movq        mm3, mm4              ; q1
+        psubusb     mm4, mm6              ; q1-=q2
+        psubusb     mm6, mm3              ; q2-=q1
+        por         mm4, mm6              ; abs(q2-q1)
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+
+        ; mm1 = mask,      mm3=q1, mm7 = limit
+
+        movq        mm4, [rsi]            ; q0
+        movq        mm0, mm4              ; q0
+        psubusb     mm4, mm3              ; q0-=q1
+        psubusb     mm3, mm0              ; q1-=q0
+        por         mm4, mm3              ; abs(q0-q1)
+        movq        t0, mm4               ; save to t0
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+
+        ; mm1 = mask, mm0=q0,  mm7 = limit, t0 = abs(q0-q1)
+
+        neg         rax                   ; negate pitch to deal with above border
+
+        movq        mm2, [rsi+4*rax]      ; p3
+        movq        mm4, [rdi+4*rax]      ; p2
+        movq        mm5, mm4              ; p2
+        psubusb     mm4, mm2              ; p2-=p3
+        psubusb     mm2, mm5              ; p3-=p2
+        por         mm4, mm2              ; abs(p3 - p2)
+        psubusb     mm4, mm7
+        por        mm1, mm4
+        ; mm1 = mask, mm0=q0,  mm7 = limit, t0 = abs(q0-q1)
+
+        movq        mm4, [rsi+2*rax]      ; p1
+        movq        mm3, mm4              ; p1
+        psubusb     mm4, mm5              ; p1-=p2
+        psubusb     mm5, mm3              ; p2-=p1
+        por         mm4, mm5              ; abs(p2 - p1)
+        psubusb     mm4, mm7
+        por        mm1, mm4
+
+        movq        mm2, mm3              ; p1
+
+
+        ; mm1 = mask, mm0=q0,  mm7 = limit, t0 = abs(q0-q1)
+
+        movq        mm4, [rsi+rax]        ; p0
+        movq        mm5, mm4              ; p0
+        psubusb     mm4, mm3              ; p0-=p1
+        psubusb     mm3, mm5              ; p1-=p0
+        por         mm4, mm3              ; abs(p1 - p0)
+        movq        t1, mm4               ; save to t1
+        psubusb     mm4, mm7
+        por        mm1, mm4
+        ; mm1 = mask, mm0=q0,  mm7 = limit, t0 = abs(q0-q1) t1 = abs(p1-p0)
+        ; mm5 = p0
+        movq        mm3, [rdi]            ; q1
+        movq        mm4, mm3              ; q1
+        psubusb     mm3, mm2              ; q1-=p1
+        psubusb     mm2, mm4              ; p1-=q1
+        por         mm2, mm3              ; abs(p1-q1)
+        pand        mm2, [tfe GLOBAL]     ; set lsb of each byte to zero
+        psrlw       mm2, 1                ; abs(p1-q1)/2
+
+        movq        mm6, mm5              ; p0
+        movq        mm3, mm0              ; q0
+        psubusb     mm5, mm3              ; p0-=q0
+        psubusb     mm3, mm6              ; q0-=p0
+        por         mm5, mm3              ; abs(p0 - q0)
+        paddusb     mm5, mm5              ; abs(p0-q0)*2
+        paddusb     mm5, mm2              ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        mov         rdx, arg(2) ;flimit           ; get flimit
+        movq        mm2, [rdx]            ; flimit mm2
+        paddb       mm2, mm2              ; flimit*2 (less than 255)
+        paddb       mm7, mm2              ; flimit * 2 + limit (less than 255)
+
+        psubusb     mm5,    mm7           ; abs (p0 - q0) *2 + abs(p1-q1)/2  > flimit * 2 + limit
+        por         mm1,    mm5
+        pxor        mm5,    mm5
+        pcmpeqb     mm1,    mm5           ; mask mm1
+
+        ; mm1 = mask, mm0=q0,  mm7 = flimit, t0 = abs(q0-q1) t1 = abs(p1-p0)
+        ; mm6 = p0,
+
+        ; calculate high edge variance
+        mov         rdx, arg(4) ;thresh           ; get thresh
+        movq        mm7, [rdx]            ;
+        movq        mm4, t0               ; get abs (q1 - q0)
+        psubusb     mm4, mm7
+        movq        mm3, t1               ; get abs (p1 - p0)
+        psubusb     mm3, mm7
+        paddb       mm4, mm3              ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+
+        pcmpeqb     mm4,        mm5
+
+        pcmpeqb     mm5,        mm5
+        pxor        mm4,        mm5
+
+
+
+        ; mm1 = mask, mm0=q0,  mm7 = thresh, t0 = abs(q0-q1) t1 = abs(p1-p0)
+        ; mm6 = p0, mm4=hev
+        ; start work on filters
+        movq        mm2, [rsi+2*rax]      ; p1
+        movq        mm7, [rdi]            ; q1
+        pxor        mm2, [t80 GLOBAL]     ; p1 offset to convert to signed values
+        pxor        mm7, [t80 GLOBAL]     ; q1 offset to convert to signed values
+        psubsb      mm2, mm7              ; p1 - q1
+
+        pxor        mm6, [t80 GLOBAL]     ; offset to convert to signed values
+        pxor        mm0, [t80 GLOBAL]     ; offset to convert to signed values
+        movq        mm3, mm0              ; q0
+        psubsb      mm0, mm6              ; q0 - p0
+        paddsb      mm2, mm0              ; 1 * (q0 - p0) + (p1 - q1)
+        paddsb      mm2, mm0              ; 2 * (q0 - p0)
+        paddsb      mm2, mm0              ; 3 * (q0 - p0) + (p1 - q1)
+        pand        mm1, mm2              ; mask filter values we don't care about
+
+
+        ; mm1 = vp8_filter, mm4=hev, mm6=ps0, mm3=qs0
+        movq        mm2, mm1              ; vp8_filter
+        pand        mm2, mm4;             ; Filter2 = vp8_filter & hev
+
+        movq        mm5,        mm2       ;
+        paddsb      mm5,        [t3 GLOBAL];
+
+        pxor        mm0, mm0              ; 0
+        pxor        mm7, mm7              ; 0
+
+        punpcklbw   mm0, mm5              ; e0f0g0h0
+        psraw       mm0, 11               ; sign extended shift right by 3
+        punpckhbw   mm7, mm5              ; a0b0c0d0
+        psraw       mm7, 11               ; sign extended shift right by 3
+        packsswb    mm0, mm7              ; Filter2 >>=3;
+
+        movq        mm5, mm0              ; Filter2
+
+        paddsb      mm2, [t4 GLOBAL]      ; vp8_signed_char_clamp(Filter2 + 4)
+        pxor        mm0, mm0              ; 0
+        pxor        mm7, mm7              ; 0
+
+        punpcklbw   mm0, mm2              ; e0f0g0h0
+        psraw       mm0, 11               ; sign extended shift right by 3
+        punpckhbw   mm7, mm2              ; a0b0c0d0
+        psraw       mm7, 11               ; sign extended shift right by 3
+        packsswb    mm0, mm7              ; Filter2 >>=3;
+
+        ; mm0= filter2 mm1 = vp8_filter,  mm3 =qs0 mm5=s mm4 =hev mm6=ps0
+        psubsb      mm3, mm0              ; qs0 =qs0 - filter1
+        paddsb      mm6, mm5              ; ps0 =ps0 + Fitler2
+
+        ; mm1=vp8_filter, mm3=qs0, mm4 =hev mm6=ps0
+        ; vp8_filter &= ~hev;
+        ; Filter2 = vp8_filter;
+        pandn       mm4, mm1              ; vp8_filter&=~hev
+
+
+        ; mm3=qs0, mm4=filter2, mm6=ps0
+
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7);
+        ; s = vp8_signed_char_clamp(qs0 - u);
+        ; *oq0 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps0 + u);
+        ; *op0 = s^0x80;
+        pxor        mm0, mm0
+
+        pxor        mm1, mm1
+        pxor        mm2, mm2
+        punpcklbw   mm1, mm4
+        punpckhbw   mm2, mm4
+        pmulhw      mm1, [s27 GLOBAL]
+        pmulhw      mm2, [s27 GLOBAL]
+        paddw       mm1, [s63 GLOBAL]
+        paddw       mm2, [s63 GLOBAL]
+        psraw       mm1, 7
+        psraw       mm2, 7
+        packsswb    mm1, mm2
+
+        psubsb      mm3, mm1
+        paddsb      mm6, mm1
+
+        pxor        mm3, [t80 GLOBAL]
+        pxor        mm6, [t80 GLOBAL]
+        movq        [rsi+rax], mm6
+        movq        [rsi],     mm3
+
+        ; roughly 2/7th difference across boundary
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7);
+        ; s = vp8_signed_char_clamp(qs1 - u);
+        ; *oq1 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps1 + u);
+        ; *op1 = s^0x80;
+        pxor        mm1, mm1
+        pxor        mm2, mm2
+        punpcklbw   mm1, mm4
+        punpckhbw   mm2, mm4
+        pmulhw      mm1, [s18 GLOBAL]
+        pmulhw      mm2, [s18 GLOBAL]
+        paddw       mm1, [s63 GLOBAL]
+        paddw       mm2, [s63 GLOBAL]
+        psraw       mm1, 7
+        psraw       mm2, 7
+        packsswb    mm1, mm2
+
+        movq        mm3, [rdi]
+        movq        mm6, [rsi+rax*2]       ; p1
+
+        pxor        mm3, [t80 GLOBAL]
+        pxor        mm6, [t80 GLOBAL]
+
+        paddsb      mm6, mm1
+        psubsb      mm3, mm1
+
+        pxor        mm6, [t80 GLOBAL]
+        pxor        mm3, [t80 GLOBAL]
+        movq        [rdi], mm3
+        movq        [rsi+rax*2], mm6
+
+        ; roughly 1/7th difference across boundary
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7);
+        ; s = vp8_signed_char_clamp(qs2 - u);
+        ; *oq2 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps2 + u);
+        ; *op2 = s^0x80;
+        pxor        mm1, mm1
+        pxor        mm2, mm2
+        punpcklbw   mm1, mm4
+        punpckhbw   mm2, mm4
+        pmulhw      mm1, [s9 GLOBAL]
+        pmulhw      mm2, [s9 GLOBAL]
+        paddw       mm1, [s63 GLOBAL]
+        paddw       mm2, [s63 GLOBAL]
+        psraw       mm1, 7
+        psraw       mm2, 7
+        packsswb    mm1, mm2
+
+
+        movq        mm6, [rdi+rax*4]
+        neg         rax
+        movq        mm3, [rdi+rax  ]
+
+        pxor        mm6, [t80 GLOBAL]
+        pxor        mm3, [t80 GLOBAL]
+
+        paddsb      mm6, mm1
+        psubsb      mm3, mm1
+
+        pxor        mm6, [t80 GLOBAL]
+        pxor        mm3, [t80 GLOBAL]
+        movq        [rdi+rax  ], mm3
+        neg         rax
+        movq        [rdi+rax*4], mm6
+
+;EARLY_BREAK_OUT:
+        neg         rax
+        add         rsi,8
+        dec         rcx
+        jnz         next8_mbh
+
+    add rsp, 32
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_mbloop_filter_vertical_edge_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *flimit,
+;    const char *limit,
+;    const char *thresh,
+;    int count
+;)
+global sym(vp8_mbloop_filter_vertical_edge_mmx)
+sym(vp8_mbloop_filter_vertical_edge_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub          rsp, 96      ; reserve 96 bytes
+    %define t0   [rsp + 0]    ;__declspec(align(16)) char t0[8];
+    %define t1   [rsp + 16]   ;__declspec(align(16)) char t1[8];
+    %define srct [rsp + 32]   ;__declspec(align(16)) char srct[64];
+
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rax,        dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        lea         rsi,        [rsi + rax*4 - 4]
+
+        movsxd      rcx,        dword ptr arg(5) ;count
+next8_mbv:
+        lea         rdi,        [rsi + rax]  ; rdi points to row +1 for indirect addressing
+
+        ;transpose
+        movq        mm0,        [rdi+2*rax]                 ; 77 76 75 74 73 72 71 70
+        movq        mm6,        [rsi+2*rax]                 ; 67 66 65 64 63 62 61 60
+
+        movq        mm7,        mm6                         ; 77 76 75 74 73 72 71 70
+        punpckhbw   mm7,        mm0                         ; 77 67 76 66 75 65 74 64
+
+        punpcklbw   mm6,        mm0                         ; 73 63 72 62 71 61 70 60
+        movq        mm0,        [rsi+rax]                   ; 57 56 55 54 53 52 51 50
+
+        movq        mm4,        [rsi]                       ; 47 46 45 44 43 42 41 40
+        movq        mm5,        mm4                         ; 47 46 45 44 43 42 41 40
+
+        punpckhbw   mm5,        mm0                         ; 57 47 56 46 55 45 54 44
+        punpcklbw   mm4,        mm0                         ; 53 43 52 42 51 41 50 40
+
+        movq        mm3,        mm5                         ; 57 47 56 46 55 45 54 44
+        punpckhwd   mm5,        mm7                         ; 77 67 57 47 76 66 56 46
+
+        punpcklwd   mm3,        mm7                         ; 75 65 55 45 74 64 54 44
+        movq        mm2,        mm4                         ; 53 43 52 42 51 41 50 40
+
+        punpckhwd   mm4,        mm6                         ; 73 63 53 43 72 62 52 42
+        punpcklwd   mm2,        mm6                         ; 71 61 51 41 70 60 50 40
+
+        neg         rax
+
+        movq        mm7,        [rsi+rax]                   ; 37 36 35 34 33 32 31 30
+        movq        mm6,        [rsi+rax*2]                 ; 27 26 25 24 23 22 21 20
+
+        movq        mm1,        mm6                         ; 27 26 25 24 23 22 21 20
+        punpckhbw   mm6,        mm7                         ; 37 27 36 36 35 25 34 24
+
+        punpcklbw   mm1,        mm7                         ; 33 23 32 22 31 21 30 20
+
+        movq        mm7,        [rsi+rax*4];                ; 07 06 05 04 03 02 01 00
+        punpckhbw   mm7,        [rdi+rax*4]                 ; 17 07 16 06 15 05 14 04
+
+        movq        mm0,        mm7                         ; 17 07 16 06 15 05 14 04
+        punpckhwd   mm7,        mm6                         ; 37 27 17 07 36 26 16 06
+
+        punpcklwd   mm0,        mm6                         ; 35 25 15 05 34 24 14 04
+        movq        mm6,        mm7                         ; 37 27 17 07 36 26 16 06
+
+        punpckhdq   mm7,        mm5                         ; 77 67 57 47 37 27 17 07  = q3
+        punpckldq   mm6,        mm5                         ; 76 66 56 46 36 26 16 06  = q2
+
+        lea         rdx,        srct
+        movq        mm5,        mm6                         ; 76 66 56 46 36 26 16 06
+
+        movq        [rdx+56],   mm7
+        psubusb     mm5,        mm7                         ; q2-q3
+
+
+        movq        [rdx+48],   mm6
+        psubusb     mm7,        mm6                         ; q3-q2
+
+        por         mm7,        mm5;                        ; mm7=abs (q3-q2)
+        movq        mm5,        mm0                         ; 35 25 15 05 34 24 14 04
+
+        punpckhdq   mm5,        mm3                         ; 75 65 55 45 35 25 15 05 = q1
+        punpckldq   mm0,        mm3                         ; 74 64 54 44 34 24 15 04 = q0
+
+        movq        mm3,        mm5                         ; 75 65 55 45 35 25 15 05 = q1
+        psubusb     mm3,        mm6                         ; q1-q2
+
+        psubusb     mm6,        mm5                         ; q2-q1
+        por         mm6,        mm3                         ; mm6=abs(q2-q1)
+
+        movq        [rdx+40],   mm5                         ; save q1
+        movq        [rdx+32],   mm0                         ; save q0
+
+        movq        mm3,        [rsi+rax*4]                 ; 07 06 05 04 03 02 01 00
+        punpcklbw   mm3,        [rdi+rax*4]                 ; 13 03 12 02 11 01 10 00
+
+        movq        mm0,        mm3                         ; 13 03 12 02 11 01 10 00
+        punpcklwd   mm0,        mm1                         ; 31 21 11 01 30 20 10 00
+
+        punpckhwd   mm3,        mm1                         ; 33 23 13 03 32 22 12 02
+        movq        mm1,        mm0                         ; 31 21 11 01 30 20 10 00
+
+        punpckldq   mm0,        mm2                         ; 70 60 50 40 30 20 10 00  =p3
+        punpckhdq   mm1,        mm2                         ; 71 61 51 41 31 21 11 01  =p2
+
+        movq        [rdx],      mm0                         ; save p3
+        movq        [rdx+8],    mm1                         ; save p2
+
+        movq        mm2,        mm1                         ; 71 61 51 41 31 21 11 01  =p2
+        psubusb     mm2,        mm0                         ; p2-p3
+
+        psubusb     mm0,        mm1                         ; p3-p2
+        por         mm0,        mm2                         ; mm0=abs(p3-p2)
+
+        movq        mm2,        mm3                         ; 33 23 13 03 32 22 12 02
+        punpckldq   mm2,        mm4                         ; 72 62 52 42 32 22 12 02 = p1
+
+        punpckhdq   mm3,        mm4                         ; 73 63 53 43 33 23 13 03 = p0
+        movq        [rdx+24],   mm3                         ; save p0
+
+        movq        [rdx+16],   mm2                         ; save p1
+        movq        mm5,        mm2                         ; mm5 = p1
+
+        psubusb     mm2,        mm1                         ; p1-p2
+        psubusb     mm1,        mm5                         ; p2-p1
+
+        por         mm1,        mm2                         ; mm1=abs(p2-p1)
+        mov         rdx,        arg(3) ;limit
+
+        movq        mm4,        [rdx]                       ; mm4 = limit
+        psubusb     mm7,        mm4                         ; abs(q3-q2) > limit
+
+        psubusb     mm0,        mm4                         ; abs(p3-p2) > limit
+        psubusb     mm1,        mm4                         ; abs(p2-p1) > limit
+
+        psubusb     mm6,        mm4                         ; abs(q2-q1) > limit
+        por         mm7,        mm6                         ; or
+
+        por         mm0,        mm1                         ;
+        por         mm0,        mm7                         ; abs(q3-q2) > limit || abs(p3-p2) > limit ||abs(p2-p1) > limit || abs(q2-q1) > limit
+
+        movq        mm1,        mm5                         ; p1
+
+        movq        mm7,        mm3                         ; mm3=mm7=p0
+        psubusb     mm7,        mm5                         ; p0 - p1
+
+        psubusb     mm5,        mm3                         ; p1 - p0
+        por         mm5,        mm7                         ; abs(p1-p0)
+
+        movq        t0,         mm5                         ; save abs(p1-p0)
+        lea         rdx,        srct
+
+        psubusb     mm5,        mm4                         ; mm5 = abs(p1-p0) > limit
+        por         mm0,        mm5                         ; mm0=mask
+
+        movq        mm5,        [rdx+32]                    ; mm5=q0
+        movq        mm7,        [rdx+40]                    ; mm7=q1
+
+        movq        mm6,        mm5                         ; mm6=q0
+        movq        mm2,        mm7                         ; q1
+        psubusb     mm5,        mm7                         ; q0-q1
+
+        psubusb     mm7,        mm6                         ; q1-q0
+        por         mm7,        mm5                         ; abs(q1-q0)
+
+        movq        t1,         mm7                         ; save abs(q1-q0)
+        psubusb     mm7,        mm4                         ; mm7=abs(q1-q0)> limit
+
+        por         mm0,        mm7                         ; mask
+
+        movq        mm5,        mm2                         ; q1
+        psubusb     mm5,        mm1                         ; q1-=p1
+        psubusb     mm1,        mm2                         ; p1-=q1
+        por         mm5,        mm1                         ; abs(p1-q1)
+        pand        mm5,        [tfe GLOBAL]                ; set lsb of each byte to zero
+        psrlw       mm5,        1                           ; abs(p1-q1)/2
+
+        mov         rdx,        arg(2) ;flimit                      ;
+
+        movq        mm2,        [rdx]                       ;flimit  mm2
+        movq        mm1,        mm3                         ; mm1=mm3=p0
+
+        movq        mm7,        mm6                         ; mm7=mm6=q0
+        psubusb     mm1,        mm7                         ; p0-q0
+
+        psubusb     mm7,        mm3                         ; q0-p0
+        por         mm1,        mm7                         ; abs(q0-p0)
+        paddusb     mm1,        mm1                         ; abs(q0-p0)*2
+        paddusb     mm1,        mm5                         ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        paddb       mm2,        mm2                         ; flimit*2 (less than 255)
+        paddb       mm4,        mm2                         ; flimit * 2 + limit (less than 255)
+
+        psubusb     mm1,        mm4                         ; abs (p0 - q0) *2 + abs(p1-q1)/2  > flimit * 2 + limit
+        por         mm1,        mm0;                        ; mask
+
+        pxor        mm0,        mm0
+        pcmpeqb     mm1,        mm0
+
+        ; calculate high edge variance
+        mov         rdx,        arg(4) ;thresh            ; get thresh
+        movq        mm7,        [rdx]
+        ;
+        movq        mm4,        t0              ; get abs (q1 - q0)
+        psubusb     mm4,        mm7             ; abs(q1 - q0) > thresh
+
+        movq        mm3,        t1              ; get abs (p1 - p0)
+        psubusb     mm3,        mm7             ; abs(p1 - p0)> thresh
+
+        por         mm4,        mm3             ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+        pcmpeqb     mm4,        mm0
+
+        pcmpeqb     mm0,        mm0
+        pxor        mm4,        mm0
+
+
+
+
+        ; start work on filters
+        lea         rdx,        srct
+
+        ; start work on filters
+        movq        mm2, [rdx+16]         ; p1
+        movq        mm7, [rdx+40]         ; q1
+        pxor        mm2, [t80 GLOBAL]     ; p1 offset to convert to signed values
+        pxor        mm7, [t80 GLOBAL]     ; q1 offset to convert to signed values
+        psubsb      mm2, mm7              ; p1 - q1
+
+        movq        mm6, [rdx+24]         ; p0
+        movq        mm0, [rdx+32]         ; q0
+        pxor        mm6, [t80 GLOBAL]     ; offset to convert to signed values
+        pxor        mm0, [t80 GLOBAL]     ; offset to convert to signed values
+
+        movq        mm3, mm0              ; q0
+        psubsb      mm0, mm6              ; q0 - p0
+        paddsb      mm2, mm0              ; 1 * (q0 - p0) + (p1 - q1)
+        paddsb      mm2, mm0              ; 2 * (q0 - p0)
+        paddsb      mm2, mm0              ; 3 * (q0 - p0) + (p1 - q1)
+        pand       mm1, mm2           ; mask filter values we don't care about
+
+        ; mm1 = vp8_filter, mm4=hev, mm6=ps0, mm3=qs0
+        movq        mm2, mm1              ; vp8_filter
+        pand        mm2, mm4;             ; Filter2 = vp8_filter & hev
+
+        movq        mm5,        mm2       ;
+        paddsb      mm5,        [t3 GLOBAL];
+
+        pxor        mm0, mm0              ; 0
+        pxor        mm7, mm7              ; 0
+
+        punpcklbw   mm0, mm5              ; e0f0g0h0
+        psraw       mm0, 11               ; sign extended shift right by 3
+        punpckhbw   mm7, mm5              ; a0b0c0d0
+        psraw       mm7, 11               ; sign extended shift right by 3
+        packsswb    mm0, mm7              ; Filter2 >>=3;
+
+        movq        mm5, mm0              ; Filter2
+
+        paddsb      mm2, [t4 GLOBAL]      ; vp8_signed_char_clamp(Filter2 + 4)
+        pxor        mm0, mm0              ; 0
+        pxor        mm7, mm7              ; 0
+
+        punpcklbw   mm0, mm2              ; e0f0g0h0
+        psraw       mm0, 11               ; sign extended shift right by 3
+        punpckhbw   mm7, mm2              ; a0b0c0d0
+        psraw       mm7, 11               ; sign extended shift right by 3
+        packsswb    mm0, mm7              ; Filter2 >>=3;
+
+        ; mm0= filter2 mm1 = vp8_filter,  mm3 =qs0 mm5=s mm4 =hev mm6=ps0
+        psubsb      mm3, mm0              ; qs0 =qs0 - filter1
+        paddsb      mm6, mm5              ; ps0 =ps0 + Fitler2
+
+        ; mm1=vp8_filter, mm3=qs0, mm4 =hev mm6=ps0
+        ; vp8_filter &= ~hev;
+        ; Filter2 = vp8_filter;
+        pandn       mm4, mm1              ; vp8_filter&=~hev
+
+
+        ; mm3=qs0, mm4=filter2, mm6=ps0
+
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7);
+        ; s = vp8_signed_char_clamp(qs0 - u);
+        ; *oq0 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps0 + u);
+        ; *op0 = s^0x80;
+        pxor        mm0, mm0
+
+        pxor        mm1, mm1
+        pxor        mm2, mm2
+        punpcklbw   mm1, mm4
+        punpckhbw   mm2, mm4
+        pmulhw      mm1, [s27 GLOBAL]
+        pmulhw      mm2, [s27 GLOBAL]
+        paddw       mm1, [s63 GLOBAL]
+        paddw       mm2, [s63 GLOBAL]
+        psraw       mm1, 7
+        psraw       mm2, 7
+        packsswb    mm1, mm2
+
+        psubsb      mm3, mm1
+        paddsb      mm6, mm1
+
+        pxor        mm3, [t80 GLOBAL]
+        pxor        mm6, [t80 GLOBAL]
+        movq        [rdx+24], mm6
+        movq        [rdx+32], mm3
+
+        ; roughly 2/7th difference across boundary
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7);
+        ; s = vp8_signed_char_clamp(qs1 - u);
+        ; *oq1 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps1 + u);
+        ; *op1 = s^0x80;
+        pxor        mm1, mm1
+        pxor        mm2, mm2
+        punpcklbw   mm1, mm4
+        punpckhbw   mm2, mm4
+        pmulhw      mm1, [s18 GLOBAL]
+        pmulhw      mm2, [s18 GLOBAL]
+        paddw       mm1, [s63 GLOBAL]
+        paddw       mm2, [s63 GLOBAL]
+        psraw       mm1, 7
+        psraw       mm2, 7
+        packsswb    mm1, mm2
+
+        movq        mm3, [rdx + 40]
+        movq        mm6, [rdx + 16]       ; p1
+        pxor        mm3, [t80 GLOBAL]
+        pxor        mm6, [t80 GLOBAL]
+
+        paddsb      mm6, mm1
+        psubsb      mm3, mm1
+
+        pxor        mm6, [t80 GLOBAL]
+        pxor        mm3, [t80 GLOBAL]
+        movq        [rdx + 40], mm3
+        movq        [rdx + 16], mm6
+
+        ; roughly 1/7th difference across boundary
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7);
+        ; s = vp8_signed_char_clamp(qs2 - u);
+        ; *oq2 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps2 + u);
+        ; *op2 = s^0x80;
+        pxor        mm1, mm1
+        pxor        mm2, mm2
+        punpcklbw   mm1, mm4
+        punpckhbw   mm2, mm4
+        pmulhw      mm1, [s9 GLOBAL]
+        pmulhw      mm2, [s9 GLOBAL]
+        paddw       mm1, [s63 GLOBAL]
+        paddw       mm2, [s63 GLOBAL]
+        psraw       mm1, 7
+        psraw       mm2, 7
+        packsswb    mm1, mm2
+
+        movq        mm6, [rdx+ 8]
+        movq        mm3, [rdx+48]
+
+        pxor        mm6, [t80 GLOBAL]
+        pxor        mm3, [t80 GLOBAL]
+
+        paddsb      mm6, mm1
+        psubsb      mm3, mm1
+
+        pxor        mm6, [t80 GLOBAL]           ; mm6 = 71 61 51 41 31 21 11 01
+        pxor        mm3, [t80 GLOBAL]           ; mm3 = 76 66 56 46 36 26 15 06
+
+        ; tranpose and write back
+        movq        mm0,    [rdx]               ; mm0 = 70 60 50 40 30 20 10 00
+        movq        mm1,    mm0                 ; mm0 = 70 60 50 40 30 20 10 00
+
+        punpcklbw   mm0,    mm6                 ; mm0 = 31 30 21 20 11 10 01 00
+        punpckhbw   mm1,    mm6                 ; mm3 = 71 70 61 60 51 50 41 40
+
+        movq        mm2,    [rdx+16]            ; mm2 = 72 62 52 42 32 22 12 02
+        movq        mm6,    mm2                 ; mm3 = 72 62 52 42 32 22 12 02
+
+        punpcklbw   mm2,    [rdx+24]            ; mm2 = 33 32 23 22 13 12 03 02
+        punpckhbw   mm6,    [rdx+24]            ; mm3 = 73 72 63 62 53 52 43 42
+
+        movq        mm5,    mm0                 ; mm5 = 31 30 21 20 11 10 01 00
+        punpcklwd   mm0,    mm2                 ; mm0 = 13 12 11 10 03 02 01 00
+
+        punpckhwd   mm5,    mm2                 ; mm5 = 33 32 31 30 23 22 21 20
+        movq        mm4,    mm1                 ; mm4 = 71 70 61 60 51 50 41 40
+
+        punpcklwd   mm1,    mm6                 ; mm1 = 53 52 51 50 43 42 41 40
+        punpckhwd   mm4,    mm6                 ; mm4 = 73 72 71 70 63 62 61 60
+
+        movq        mm2,    [rdx+32]            ; mm2 = 74 64 54 44 34 24 14 04
+        punpcklbw   mm2,    [rdx+40]            ; mm2 = 35 34 25 24 15 14 05 04
+
+        movq        mm6,    mm3                 ; mm6 = 76 66 56 46 36 26 15 06
+        punpcklbw   mm6,    [rdx+56]            ; mm6 = 37 36 27 26 17 16 07 06
+
+        movq        mm7,    mm2                 ; mm7 = 35 34 25 24 15 14 05 04
+        punpcklwd   mm2,    mm6                 ; mm2 = 17 16 15 14 07 06 05 04
+
+        punpckhwd   mm7,    mm6                 ; mm7 = 37 36 35 34 27 26 25 24
+        movq        mm6,    mm0                 ; mm6 = 13 12 11 10 03 02 01 00
+
+        punpckldq   mm0,    mm2                 ; mm0 = 07 06 05 04 03 02 01 00
+        punpckhdq   mm6,    mm2                 ; mm6 = 17 16 15 14 13 12 11 10
+
+        movq        [rsi+rax*4], mm0            ; write out
+        movq        [rdi+rax*4], mm6            ; write out
+
+        movq        mm0,    mm5                 ; mm0 = 33 32 31 30 23 22 21 20
+        punpckldq   mm0,    mm7                 ; mm0 = 27 26 25 24 23 22 20 20
+
+        punpckhdq   mm5,    mm7                 ; mm5 = 37 36 35 34 33 32 31 30
+        movq        [rsi+rax*2], mm0            ; write out
+
+        movq        [rdi+rax*2], mm5            ; write out
+        movq        mm2,    [rdx+32]            ; mm2 = 74 64 54 44 34 24 14 04
+
+        punpckhbw   mm2,    [rdx+40]            ; mm2 = 75 74 65 64 54 54 45 44
+        punpckhbw   mm3,    [rdx+56]            ; mm3 = 77 76 67 66 57 56 47 46
+
+        movq        mm5,    mm2                 ; mm5 = 75 74 65 64 54 54 45 44
+        punpcklwd   mm2,    mm3                 ; mm2 = 57 56 55 54 47 46 45 44
+
+        punpckhwd   mm5,    mm3                 ; mm5 = 77 76 75 74 67 66 65 64
+        movq        mm0,    mm1                 ; mm0=  53 52 51 50 43 42 41 40
+
+        movq        mm3,    mm4                 ; mm4 = 73 72 71 70 63 62 61 60
+        punpckldq   mm0,    mm2                 ; mm0 = 47 46 45 44 43 42 41 40
+
+        punpckhdq   mm1,    mm2                 ; mm1 = 57 56 55 54 53 52 51 50
+        movq        [rsi],  mm0                 ; write out
+
+        movq        [rdi],  mm1                 ; write out
+        neg         rax
+
+        punpckldq   mm3,    mm5                 ; mm3 = 67 66 65 64 63 62 61 60
+        punpckhdq   mm4,    mm5                 ; mm4 = 77 76 75 74 73 72 71 60
+
+        movq        [rsi+rax*2], mm3
+        movq        [rdi+rax*2], mm4
+
+        lea         rsi,        [rsi+rax*8]
+        dec         rcx
+
+        jnz         next8_mbv
+
+    add rsp, 96
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_loop_filter_simple_horizontal_edge_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *flimit,
+;    const char *limit,
+;    const char *thresh,
+;    int count
+;)
+global sym(vp8_loop_filter_simple_horizontal_edge_mmx)
+sym(vp8_loop_filter_simple_horizontal_edge_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi, arg(0) ;src_ptr
+        movsxd      rax, dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        movsxd      rcx, dword ptr arg(5) ;count
+nexts8_h:
+        mov         rdx, arg(3) ;limit
+        movq        mm7, [rdx]
+        mov         rdx, arg(2) ;flimit           ; get flimit
+        movq        mm3, [rdx]            ;
+        paddb       mm3, mm3              ; flimit*2 (less than 255)
+        paddb       mm3, mm7              ; flimit * 2 + limit (less than 255)
+
+        mov         rdi, rsi              ; rdi points to row +1 for indirect addressing
+        add         rdi, rax
+        neg         rax
+
+        ; calculate mask
+        movq        mm1, [rsi+2*rax]      ; p1
+        movq        mm0, [rdi]            ; q1
+        movq        mm2, mm1
+        movq        mm7, mm0
+        movq        mm4, mm0
+        psubusb     mm0, mm1              ; q1-=p1
+        psubusb     mm1, mm4              ; p1-=q1
+        por         mm1, mm0              ; abs(p1-q1)
+        pand        mm1, [tfe GLOBAL]     ; set lsb of each byte to zero
+        psrlw       mm1, 1                ; abs(p1-q1)/2
+
+        movq        mm5, [rsi+rax]        ; p0
+        movq        mm4, [rsi]            ; q0
+        movq        mm0, mm4              ; q0
+        movq        mm6, mm5              ; p0
+        psubusb     mm5, mm4              ; p0-=q0
+        psubusb     mm4, mm6              ; q0-=p0
+        por         mm5, mm4              ; abs(p0 - q0)
+        paddusb     mm5, mm5              ; abs(p0-q0)*2
+        paddusb     mm5, mm1              ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        psubusb     mm5, mm3              ; abs(p0 - q0) *2 + abs(p1-q1)/2  > flimit * 2 + limit
+        pxor        mm3, mm3
+        pcmpeqb     mm5, mm3
+
+        ; start work on filters
+        pxor        mm2, [t80 GLOBAL]     ; p1 offset to convert to signed values
+        pxor        mm7, [t80 GLOBAL]     ; q1 offset to convert to signed values
+        psubsb      mm2, mm7              ; p1 - q1
+
+        pxor        mm6, [t80 GLOBAL]     ; offset to convert to signed values
+        pxor        mm0, [t80 GLOBAL]     ; offset to convert to signed values
+        movq        mm3, mm0              ; q0
+        psubsb      mm0, mm6              ; q0 - p0
+        paddsb      mm2, mm0              ; p1 - q1 + 1 * (q0 - p0)
+        paddsb      mm2, mm0              ; p1 - q1 + 2 * (q0 - p0)
+        paddsb      mm2, mm0              ; p1 - q1 + 3 * (q0 - p0)
+        pand        mm5, mm2              ; mask filter values we don't care about
+
+        ; do + 4 side
+        paddsb      mm5, [t4 GLOBAL]      ; 3* (q0 - p0) + (p1 - q1) + 4
+
+        movq        mm0, mm5              ; get a copy of filters
+        psllw       mm0, 8                ; shift left 8
+        psraw       mm0, 3                ; arithmetic shift right 11
+        psrlw       mm0, 8
+        movq        mm1, mm5              ; get a copy of filters
+        psraw       mm1, 11               ; arithmetic shift right 11
+        psllw       mm1, 8                ; shift left 8 to put it back
+
+        por         mm0, mm1              ; put the two together to get result
+
+        psubsb      mm3, mm0              ; q0-= q0 add
+        pxor        mm3, [t80 GLOBAL]     ; unoffset
+        movq        [rsi], mm3            ; write back
+
+
+        ; now do +3 side
+        psubsb      mm5, [t1s GLOBAL]      ; +3 instead of +4
+
+        movq        mm0, mm5              ; get a copy of filters
+        psllw       mm0, 8                ; shift left 8
+        psraw       mm0, 3                ; arithmetic shift right 11
+        psrlw       mm0, 8
+        psraw       mm5, 11               ; arithmetic shift right 11
+        psllw       mm5, 8                ; shift left 8 to put it back
+        por         mm0, mm5              ; put the two together to get result
+
+
+        paddsb      mm6, mm0              ; p0+= p0 add
+        pxor        mm6, [t80 GLOBAL]     ; unoffset
+        movq        [rsi+rax], mm6        ; write back
+
+        add         rsi,8
+        neg         rax
+        dec         rcx
+        jnz         nexts8_h
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_loop_filter_simple_vertical_edge_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *flimit,
+;    const char *limit,
+;    const char *thresh,
+;    int count
+;)
+global sym(vp8_loop_filter_simple_vertical_edge_mmx)
+sym(vp8_loop_filter_simple_vertical_edge_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub          rsp, 32      ; reserve 32 bytes
+    %define t0   [rsp + 0]    ;__declspec(align(16)) char t0[8];
+    %define t1   [rsp + 16]   ;__declspec(align(16)) char t1[8];
+
+        mov         rsi, arg(0) ;src_ptr
+        movsxd      rax, dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        lea         rsi, [rsi + rax*4- 2];  ;
+        movsxd      rcx, dword ptr arg(5) ;count
+nexts8_v:
+
+        lea         rdi,        [rsi + rax];
+        movd        mm0,        [rdi + rax * 2]                 ; xx xx xx xx 73 72 71 70
+
+        movd        mm6,        [rsi + rax * 2]                 ; xx xx xx xx 63 62 61 60
+        punpcklbw   mm6,        mm0                             ; 73 63 72 62 71 61 70 60
+
+        movd        mm0,        [rsi + rax]                     ; xx xx xx xx 53 52 51 50
+        movd        mm4,        [rsi]                           ; xx xx xx xx 43 42 41 40
+
+        punpcklbw   mm4,        mm0                             ; 53 43 52 42 51 41 50 40
+        movq        mm5,        mm4                             ; 53 43 52 42 51 41 50 40
+
+        punpcklwd   mm4,        mm6                             ; 71 61 51 41 70 60 50 40
+        punpckhwd   mm5,        mm6                             ; 73 63 53 43 72 62 52 42
+
+        neg         rax
+
+        movd        mm7,        [rsi + rax]                     ; xx xx xx xx 33 32 31 30
+        movd        mm6,        [rsi + rax * 2]                 ; xx xx xx xx 23 22 21 20
+
+        punpcklbw   mm6,        mm7                             ; 33 23 32 22 31 21 30 20
+        movd        mm1,        [rdi + rax * 4]                 ; xx xx xx xx 13 12 11 10
+
+        movd        mm0,        [rsi + rax * 4]                 ; xx xx xx xx 03 02 01 00
+        punpcklbw   mm0,        mm1                             ; 13 03 12 02 11 01 10 00
+
+        movq        mm2,        mm0                             ; 13 03 12 02 11 01 10 00
+        punpcklwd   mm0,        mm6                             ; 31 21 11 01 30 20 10 00
+
+        punpckhwd   mm2,        mm6                             ; 33 23 13 03 32 22 12 02
+        movq        mm1,        mm0                             ; 13 03 12 02 11 01 10 00
+
+        punpckldq   mm0,        mm4                             ; 70 60 50 40 30 20 10 00       = p1
+        movq        mm3,        mm2                             ; 33 23 13 03 32 22 12 02
+
+        punpckhdq   mm1,        mm4                             ; 71 61 51 41 31 21 11 01       = p0
+        punpckldq   mm2,        mm5                             ; 72 62 52 42 32 22 12 02       = q0
+
+        punpckhdq   mm3,        mm5                             ; 73 63 53 43 33 23 13 03       = q1
+
+
+        ; calculate mask
+        movq        mm6,        mm0                             ; p1
+        movq        mm7,        mm3                             ; q1
+        psubusb     mm7,        mm6                             ; q1-=p1
+        psubusb     mm6,        mm3                             ; p1-=q1
+        por         mm6,        mm7                             ; abs(p1-q1)
+        pand        mm6,        [tfe GLOBAL]                    ; set lsb of each byte to zero
+        psrlw       mm6,        1                               ; abs(p1-q1)/2
+
+        movq        mm5,        mm1                             ; p0
+        movq        mm4,        mm2                             ; q0
+
+        psubusb     mm5,        mm2                             ; p0-=q0
+        psubusb     mm4,        mm1                             ; q0-=p0
+
+        por         mm5,        mm4                             ; abs(p0 - q0)
+        paddusb     mm5,        mm5                             ; abs(p0-q0)*2
+        paddusb     mm5,        mm6                             ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        mov         rdx,        arg(2) ;flimit                          ; get flimit
+        movq        mm7,        [rdx]
+        mov         rdx,        arg(3)                          ; get limit
+        movq        mm6,        [rdx]
+        paddb       mm7,        mm7                             ; flimit*2 (less than 255)
+        paddb       mm7,        mm6                             ; flimit * 2 + limit (less than 255)
+
+        psubusb     mm5,        mm7                             ; abs(p0 - q0) *2 + abs(p1-q1)/2  > flimit * 2 + limit
+        pxor        mm7,        mm7
+        pcmpeqb     mm5,        mm7                             ; mm5 = mask
+
+        ; start work on filters
+        movq        t0,         mm0
+        movq        t1,         mm3
+
+        pxor        mm0,        [t80 GLOBAL]                    ; p1 offset to convert to signed values
+        pxor        mm3,        [t80 GLOBAL]                    ; q1 offset to convert to signed values
+
+        psubsb      mm0,        mm3                             ; p1 - q1
+        movq        mm6,        mm1                             ; p0
+
+        movq        mm7,        mm2                             ; q0
+        pxor        mm6,        [t80 GLOBAL]                    ; offset to convert to signed values
+
+        pxor        mm7,        [t80 GLOBAL]                    ; offset to convert to signed values
+        movq        mm3,        mm7                             ; offseted ; q0
+
+        psubsb      mm7,        mm6                             ; q0 - p0
+        paddsb      mm0,        mm7                             ; p1 - q1 + 1 * (q0 - p0)
+
+        paddsb      mm0,        mm7                             ; p1 - q1 + 2 * (q0 - p0)
+        paddsb      mm0,        mm7                             ; p1 - q1 + 3 * (q0 - p0)
+
+        pand        mm5,        mm0                             ; mask filter values we don't care about
+
+        paddsb      mm5,        [t4 GLOBAL]                     ;  3* (q0 - p0) + (p1 - q1) + 4
+
+        movq        mm0,        mm5                             ; get a copy of filters
+        psllw       mm0,        8                               ; shift left 8
+        psraw       mm0,        3                               ; arithmetic shift right 11
+        psrlw       mm0,        8
+
+        movq        mm7,        mm5                             ; get a copy of filters
+        psraw       mm7,        11                              ; arithmetic shift right 11
+        psllw       mm7,        8                               ; shift left 8 to put it back
+
+        por         mm0,        mm7                             ; put the two together to get result
+
+        psubsb      mm3,        mm0                             ; q0-= q0sz add
+        pxor        mm3,        [t80 GLOBAL]                    ; unoffset
+
+        ; now do +3 side
+        psubsb      mm5, [t1s GLOBAL]                           ; +3 instead of +4
+
+        movq        mm0, mm5                                    ; get a copy of filters
+        psllw       mm0, 8                                      ; shift left 8
+        psraw       mm0, 3                                      ; arithmetic shift right 11
+        psrlw       mm0, 8
+
+        psraw       mm5, 11                                     ; arithmetic shift right 11
+        psllw       mm5, 8                                      ; shift left 8 to put it back
+        por         mm0, mm5                                    ; put the two together to get result
+
+        paddsb      mm6, mm0                                    ; p0+= p0 add
+        pxor        mm6, [t80 GLOBAL]                           ; unoffset
+
+
+        movq        mm0,        t0
+        movq        mm4,        t1
+
+        ; mm0 = 70 60 50 40 30 20 10 00
+        ; mm6 = 71 61 51 41 31 21 11 01
+        ; mm3 = 72 62 52 42 32 22 12 02
+        ; mm4 = 73 63 53 43 33 23 13 03
+        ; transpose back to write out
+
+        movq        mm1,        mm0                         ;
+        punpcklbw   mm0,        mm6                         ; 31 30 21 20 11 10 01 00
+
+        punpckhbw   mm1,        mm6                         ; 71 70 61 60 51 50 41 40
+        movq        mm2,        mm3                         ;
+
+        punpcklbw   mm2,        mm4                         ; 33 32 23 22 13 12 03 02
+        movq        mm5,        mm1                         ; 71 70 61 60 51 50 41 40
+
+        punpckhbw   mm3,        mm4                         ; 73 72 63 62 53 52 43 42
+        movq        mm6,        mm0                         ; 31 30 21 20 11 10 01 00
+
+        punpcklwd   mm0,        mm2                         ; 13 12 11 10 03 02 01 00
+        punpckhwd   mm6,        mm2                         ; 33 32 31 30 23 22 21 20
+
+        movd        [rsi+rax*4], mm0                        ; write 03 02 01 00
+        punpcklwd   mm1,        mm3                         ; 53 52 51 50 43 42 41 40
+
+        psrlq       mm0,        32                          ; xx xx xx xx 13 12 11 10
+        punpckhwd   mm5,        mm3                         ; 73 72 71 70 63 62 61 60
+
+        movd        [rdi+rax*4], mm0                        ; write 13 12 11 10
+        movd        [rsi+rax*2], mm6                        ; write 23 22 21 20
+
+        psrlq       mm6,        32                          ; 33 32 31 30
+        movd        [rsi],      mm1                         ; write 43 42 41 40
+
+        movd        [rsi + rax], mm6                        ; write 33 32 31 30
+        neg         rax
+
+        movd        [rsi + rax*2], mm5                      ; write 63 62 61 60
+        psrlq       mm1,        32                          ; 53 52 51 50
+
+        movd        [rdi],      mm1                         ; write out 53 52 51 50
+        psrlq       mm5,        32                          ; 73 72 71 70
+
+        movd        [rdi + rax*2], mm5                      ; write 73 72 71 70
+
+        lea         rsi,        [rsi+rax*8]                 ; next 8
+
+        dec         rcx
+        jnz         nexts8_v
+
+    add rsp, 32
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+;void fast_loop_filter_vertical_edges_mmx(unsigned char *y_ptr,
+;                  int y_stride,
+;                  loop_filter_info *lfi)
+;{
+;
+;
+;    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr+4, y_stride, lfi->flim,lfi->lim,lfi->thr,2);
+;    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr+8, y_stride, lfi->flim,lfi->lim,lfi->thr,2);
+;    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr+12, y_stride, lfi->flim,lfi->lim,lfi->thr,2);
+;}
+
+SECTION_RODATA
+align 16
+tfe:
+    times 8 db 0xfe
+align 16
+t80:
+    times 8 db 0x80
+align 16
+t1s:
+    times 8 db 0x01
+align 16
+t3:
+    times 8 db 0x03
+align 16
+t4:
+    times 8 db 0x04
+align 16
+ones:
+    times 4 dw 0x0001
+align 16
+s27:
+    times 4 dw 0x1b00
+align 16
+s18:
+    times 4 dw 0x1200
+align 16
+s9:
+    times 4 dw 0x0900
+align 16
+s63:
+    times 4 dw 0x003f
diff --git a/vp8/common/x86/loopfilter_sse2.asm b/vp8/common/x86/loopfilter_sse2.asm
new file mode 100644
index 0000000..5275dfa
--- /dev/null
+++ b/vp8/common/x86/loopfilter_sse2.asm
@@ -0,0 +1,1978 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+
+;void vp8_loop_filter_horizontal_edge_sse2
+;(
+;    unsigned char *src_ptr,
+;    int            src_pixel_step,
+;    const char    *flimit,
+;    const char    *limit,
+;    const char    *thresh,
+;    int            count
+;)
+global sym(vp8_loop_filter_horizontal_edge_sse2)
+sym(vp8_loop_filter_horizontal_edge_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 32                         ; reserve 32 bytes
+    %define t0 [rsp + 0]    ;__declspec(align(16)) char t0[16];
+    %define t1 [rsp + 16]   ;__declspec(align(16)) char t1[16];
+
+        mov         rsi, arg(0) ;src_ptr
+        movsxd      rax, dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        mov         rdx,    arg(3) ;limit
+        movdqa      xmm7,   XMMWORD PTR [rdx]
+        mov         rdi,    rsi           ; rdi points to row +1 for indirect addressing
+        add         rdi,    rax
+
+        ; calculate breakout conditions
+        movdqu      xmm2,   [rdi+2*rax]      ; q3
+        movdqu      xmm1,   [rsi+2*rax]      ; q2
+        movdqa      xmm6,   xmm1              ; q2
+        psubusb     xmm1,   xmm2              ; q2-=q3
+        psubusb     xmm2,   xmm6              ; q3-=q2
+        por         xmm1,   xmm2              ; abs(q3-q2)
+        psubusb     xmm1,   xmm7              ;
+
+
+        movdqu      xmm4,   [rsi+rax]         ; q1
+        movdqa      xmm3,   xmm4              ; q1
+        psubusb     xmm4,   xmm6              ; q1-=q2
+        psubusb     xmm6,   xmm3              ; q2-=q1
+        por         xmm4,   xmm6              ; abs(q2-q1)
+
+        psubusb     xmm4,   xmm7
+        por         xmm1,   xmm4
+
+        movdqu      xmm4,   [rsi]             ; q0
+        movdqa      xmm0,   xmm4              ; q0
+        psubusb     xmm4,   xmm3              ; q0-=q1
+        psubusb     xmm3,   xmm0              ; q1-=q0
+        por         xmm4,   xmm3              ; abs(q0-q1)
+        movdqa        t0,       xmm4                  ; save to t0
+        psubusb     xmm4,   xmm7
+        por         xmm1,   xmm4
+
+        neg         rax                   ; negate pitch to deal with above border
+        movdqu      xmm2,   [rsi+4*rax]      ; p3
+        movdqu      xmm4,   [rdi+4*rax]      ; p2
+        movdqa      xmm5,   xmm4              ; p2
+        psubusb     xmm4,   xmm2              ; p2-=p3
+        psubusb     xmm2,   xmm5              ; p3-=p2
+        por         xmm4,   xmm2              ; abs(p3 - p2)
+        psubusb     xmm4,   xmm7
+        por         xmm1,   xmm4
+
+
+        movdqu      xmm4,   [rsi+2*rax]      ; p1
+        movdqa      xmm3,   xmm4              ; p1
+        psubusb     xmm4,   xmm5              ; p1-=p2
+        psubusb     xmm5,   xmm3              ; p2-=p1
+        por         xmm4,   xmm5              ; abs(p2 - p1)
+        psubusb     xmm4,   xmm7
+        por         xmm1,   xmm4
+
+        movdqa      xmm2,   xmm3              ; p1
+
+        movdqu      xmm4,   [rsi+rax]         ; p0
+        movdqa      xmm5,   xmm4              ; p0
+        psubusb     xmm4,   xmm3              ; p0-=p1
+        psubusb     xmm3,   xmm5              ; p1-=p0
+        por         xmm4,   xmm3              ; abs(p1 - p0)
+        movdqa      t1,     xmm4                  ; save to t1
+        psubusb     xmm4,   xmm7
+        por         xmm1,    xmm4
+
+        movdqu      xmm3,   [rdi]             ; q1
+        movdqa      xmm4,   xmm3              ; q1
+        psubusb     xmm3,   xmm2              ; q1-=p1
+        psubusb     xmm2,   xmm4              ; p1-=q1
+        por         xmm2,   xmm3              ; abs(p1-q1)
+        pand        xmm2,   [tfe GLOBAL]      ; set lsb of each byte to zero
+        psrlw       xmm2,   1                 ; abs(p1-q1)/2
+
+        movdqa      xmm6,   xmm5              ; p0
+        movdqu      xmm3,   [rsi]             ; q0
+        psubusb     xmm5,   xmm3              ; p0-=q0
+        psubusb     xmm3,   xmm6              ; q0-=p0
+        por         xmm5,   xmm3              ; abs(p0 - q0)
+        paddusb     xmm5,   xmm5              ; abs(p0-q0)*2
+        paddusb     xmm5,   xmm2              ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        mov         rdx,    arg(2) ;flimit            ; get flimit
+        movdqa      xmm2,   [rdx]             ;
+
+        paddb       xmm2,   xmm2              ; flimit*2 (less than 255)
+        paddb       xmm7,   xmm2              ; flimit * 2 + limit (less than 255)
+
+        psubusb     xmm5,    xmm7             ; abs (p0 - q0) *2 + abs(p1-q1)/2  > flimit * 2 + limit
+        por         xmm1,    xmm5
+        pxor        xmm5,    xmm5
+        pcmpeqb     xmm1,    xmm5             ; mask mm1
+
+
+        ; calculate high edge variance
+        mov         rdx,    arg(4) ;thresh            ; get thresh
+        movdqa      xmm7,   [rdx]             ;
+        movdqa      xmm4,   t0                ; get abs (q1 - q0)
+        psubusb     xmm4,   xmm7
+        movdqa      xmm3,   t1                ; get abs (p1 - p0)
+        psubusb     xmm3,   xmm7
+        paddb       xmm4,   xmm3              ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+        pcmpeqb     xmm4,        xmm5
+        pcmpeqb     xmm5,        xmm5
+        pxor        xmm4,        xmm5
+
+
+        ; start work on filters
+        movdqu      xmm2, [rsi+2*rax]     ; p1
+        movdqu      xmm7, [rdi]           ; q1
+        pxor        xmm2, [t80 GLOBAL]    ; p1 offset to convert to signed values
+        pxor        xmm7, [t80 GLOBAL]    ; q1 offset to convert to signed values
+        psubsb      xmm2, xmm7            ; p1 - q1
+        pand        xmm2, xmm4            ; high var mask (hvm)(p1 - q1)
+        pxor        xmm6, [t80 GLOBAL]    ; offset to convert to signed values
+        pxor        xmm0, [t80 GLOBAL]    ; offset to convert to signed values
+        movdqa      xmm3, xmm0            ; q0
+        psubsb      xmm0, xmm6            ; q0 - p0
+        paddsb      xmm2, xmm0            ; 1 * (q0 - p0) + hvm(p1 - q1)
+        paddsb      xmm2, xmm0            ; 2 * (q0 - p0) + hvm(p1 - q1)
+        paddsb      xmm2, xmm0            ; 3 * (q0 - p0) + hvm(p1 - q1)
+        pand        xmm1, xmm2            ; mask filter values we don't care about
+        movdqa      xmm2, xmm1
+        paddsb      xmm1, [t4 GLOBAL]         ; 3* (q0 - p0) + hvm(p1 - q1) + 4
+        paddsb      xmm2, [t3 GLOBAL]         ; 3* (q0 - p0) + hvm(p1 - q1) + 3
+
+        pxor        xmm0, xmm0           ;
+        pxor        xmm5, xmm5
+        punpcklbw   xmm0, xmm2          ;
+        punpckhbw   xmm5, xmm2          ;
+        psraw       xmm0, 11                ;
+        psraw       xmm5, 11
+        packsswb    xmm0, xmm5
+        movdqa      xmm2, xmm0          ;  (3* (q0 - p0) + hvm(p1 - q1) + 3) >> 3;
+
+        pxor        xmm0, xmm0            ; 0
+        movdqa      xmm5, xmm1            ; abcdefgh
+        punpcklbw   xmm0, xmm1            ; e0f0g0h0
+        psraw       xmm0, 11                  ; sign extended shift right by 3
+        pxor        xmm1, xmm1            ; 0
+        punpckhbw   xmm1, xmm5            ; a0b0c0d0
+        psraw       xmm1, 11                  ; sign extended shift right by 3
+        movdqa      xmm5, xmm0              ; save results
+
+        packsswb    xmm0, xmm1            ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>3
+        paddsw      xmm5, [ones GLOBAL]
+        paddsw      xmm1, [ones GLOBAL]
+        psraw       xmm5, 1               ; partial shifted one more time for 2nd tap
+        psraw       xmm1, 1               ; partial shifted one more time for 2nd tap
+        packsswb    xmm5, xmm1            ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>4
+        pandn       xmm4, xmm5            ; high edge variance additive
+
+        paddsb      xmm6, xmm2            ; p0+= p0 add
+        pxor        xmm6, [t80 GLOBAL]    ; unoffset
+        movdqu      [rsi+rax], xmm6       ; write back
+
+        movdqu      xmm6, [rsi+2*rax]     ; p1
+        pxor        xmm6, [t80 GLOBAL]    ; reoffset
+        paddsb      xmm6, xmm4            ; p1+= p1 add
+        pxor        xmm6, [t80 GLOBAL]    ; unoffset
+        movdqu      [rsi+2*rax], xmm6     ; write back
+
+        psubsb      xmm3, xmm0            ; q0-= q0 add
+        pxor        xmm3, [t80 GLOBAL]    ; unoffset
+        movdqu      [rsi], xmm3           ; write back
+
+        psubsb      xmm7, xmm4            ; q1-= q1 add
+        pxor        xmm7, [t80 GLOBAL]    ; unoffset
+        movdqu      [rdi], xmm7           ; write back
+
+    add rsp, 32
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_loop_filter_vertical_edge_sse2
+;(
+;    unsigned char *src_ptr,
+;    int            src_pixel_step,
+;    const char    *flimit,
+;    const char    *limit,
+;    const char    *thresh,
+;    int            count
+;)
+global sym(vp8_loop_filter_vertical_edge_sse2)
+sym(vp8_loop_filter_vertical_edge_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub          rsp, 96      ; reserve 96 bytes
+    %define t0   [rsp + 0]    ;__declspec(align(16)) char t0[16];
+    %define t1   [rsp + 16]   ;__declspec(align(16)) char t1[16];
+    %define srct [rsp + 32]   ;__declspec(align(16)) char srct[64];
+
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rax,        dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        lea         rsi,        [rsi + rax*4 - 4]
+        mov         rdi,        rsi           ; rdi points to row +1 for indirect addressing
+
+        add         rdi,        rax
+        lea         rcx,        [rdi + rax *8]
+
+        ;transpose
+        movq        xmm7,       QWORD PTR [rsi+2*rax]                 ; 67 66 65 64 63 62 61 60
+        movq        xmm6,       QWORD PTR [rdi+2*rax]                 ; 77 76 75 74 73 72 71 70
+
+        punpcklbw   xmm7,       xmm6                        ; 77 67 76 66 75 65 74 64 73 63 72 62 71 61 70 60
+        movq        xmm5,       QWORD PTR [rsi]                       ; 47 46 45 44 43 42 41 40
+
+        movq        xmm4,       QWORD PTR [rsi+rax]                   ; 57 56 55 54 53 52 51 50
+        punpcklbw   xmm5,       xmm4                        ; 57 47 56 46 55 45 54 44 53 43 52 42 51 41 50 40
+
+        movdqa      xmm3,       xmm5                        ; 57 47 56 46 55 45 54 44 53 43 52 42 51 41 50 40
+        punpckhwd   xmm5,       xmm7                        ; 77 67 57 47 76 66 56 46 75 65 55 45 74 64 54 44
+
+        lea         rsi,        [rsi+ rax*8]
+
+        punpcklwd   xmm3,       xmm7                        ; 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40
+        movq        xmm6,       QWORD PTR [rsi + 2*rax]               ; e7 e6 e5 e4 e3 e2 e1 e0
+
+        movq        xmm7,       QWORD PTR [rcx + 2*rax]               ; f7 f6 f5 f4 f3 f2 f1 f0
+        punpcklbw   xmm6,       xmm7                        ; f7 e7 f6 e6 f5 e5 f4 e4 f3 e3 f2 e2 f1 e1 f0 e0
+
+        movq        xmm4,       QWORD PTR [rsi]                       ; c7 c6 c5 c4 c3 c2 c1 c0
+        movq        xmm7,       QWORD PTR [rsi + rax]                 ; d7 d6 d5 d4 d3 d2 d1 d0
+
+        punpcklbw   xmm4,       xmm7                        ; d7 c7 d6 c6 d5 c5 d4 c4 d3 c3 d2 c2 d1 c1 d0 c0
+        movdqa      xmm7,       xmm4                        ; d7 c7 d6 c6 d5 c5 d4 c4 d3 c3 d2 c2 d1 c1 d0 c0
+
+        punpckhwd   xmm7,       xmm6                        ; f7 e7 d7 c7 f6 e6 d6 c6 f5 e5 d5 c5 f4 e4 d4 c4
+        punpcklwd   xmm4,       xmm6                        ; f3 e3 d3 c3 f2 e2 d2 c2 f1 e1 d1 c1 f0 e0 d0 c0
+
+        ; xmm3 xmm4, xmm5 xmm7   in use
+        neg         rax
+
+        lea         rsi,        [rsi+rax*8]
+        movq        xmm6,       QWORD PTR [rsi+rax*2]                 ; 27 26 25 24 23 22 21 20
+
+        movq        xmm1,       QWORD PTR [rsi+rax  ]                 ; 37 36 35 34 33 32 31 30
+        punpcklbw   xmm6,       xmm1                        ; 37 27 36 26 35 25 34 24 33 23 32 22 31 21 30 20
+
+        movq        xmm2,       QWORD PTR [rsi+rax*4]                 ; 07 06 05 04 03 02 01 00
+        movq        xmm1,       QWORD PTR [rdi+rax*4]                 ; 17 16 15 14 13 12 11 10
+
+        punpcklbw   xmm2,       xmm1                        ; 17 07 16 06 15 05 14 04 13 03 12 02 11 01 10 00
+        movdqa      xmm0,       xmm2
+
+        punpckhwd   xmm2,       xmm6                        ; 37 27 17 07 36 26 16 06 35 25 15 05 34 24 14 04
+        punpcklwd   xmm0,       xmm6                        ; 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
+
+        movdqa      xmm6,       xmm2
+        punpckldq   xmm2,       xmm5                        ; 75 65 55 45 35 25 15 05 74 64 54 44 34 24 14 04
+
+        punpckhdq   xmm6,       xmm5                        ; 77 67 57 47 37 27 17 07 76 66 56 46 36 26 16 06
+        ;xmm0 xmm2 xmm3 xmm4, xmm6, xmm7
+
+        movdqa      xmm5,       xmm0                        ; 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
+        punpckhdq   xmm5,       xmm3                        ; 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
+
+        punpckldq   xmm0,       xmm3                        ; 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
+        lea         rsi,        [rcx+rax]
+        ; xmm1, xmm3 free
+        movq        xmm1,       QWORD PTR [rsi+rax*2]                 ; a7 a6 a5 a4 a3 a2 a1 a0
+        movq        xmm3,       QWORD PTR [rsi+rax]                   ; b7 b6 b5 b4 b3 b2 b1 b0
+
+        punpcklbw   xmm1,       xmm3                        ;
+        lea         rdx,        srct                        ;
+
+        movdqa      [rdx+16],   xmm1                        ; b7 a7 b6 a6 b5 a5 b4 a4 b3 a3 b2 a2 b1 a1 b0 a0
+        movq        xmm3,       QWORD PTR [rsi+rax*4]                 ; 87 86 85 84 83 82 81 80
+
+        movq        xmm1,       QWORD PTR [rcx+rax*4]
+        punpcklbw   xmm3,       xmm1                        ; 97 87 96 86 95 85 94 84 93 83 92 82 91 81 90 80
+
+        movdqa      [rdx],      xmm3                        ; 97 87 96 86 95 85 94 84 93 83 92 82 91 81 90 80
+
+        punpckhwd   xmm3,       [rdx+16]                    ; b7 a7 97 87 b6 a6 96 86 b5 a5 95 85 b4 a4 94 84
+        movdqa      xmm1,       xmm3                        ; b7 a7 97 87 b6 a6 96 86 b5 a5 95 85 b4 a4 94 84
+
+        punpckhdq   xmm1,       xmm7                        ; f7 e7 d7 c7 b7 a7 97 87 f6 e6 d6 c6 b6 a6 96 86
+        punpckldq   xmm3,       xmm7                        ; f5 e5 d5 c5 b5 a5 95 85 f4 e4 d4 c4 b4 a4 94 84
+
+        movdqa      xmm7,       xmm2                        ; 75 65 55 45 35 25 15 05 74 64 54 44 34 24 14 04
+        punpcklqdq  xmm7,       xmm3                        ; f4 e4 d4 c4 b4 a4 94 84 74 64 54 44 34 24 14 04
+
+        punpckhqdq  xmm2,       xmm3                        ; f5 e5 d5 c5 b5 a5 95 85 75 65 55 45 35 25 15 05
+        movdqa      [rdx+32],   xmm7                        ; save 4s
+
+        movdqa      [rdx+48],   xmm2                        ; save 5s
+        movdqa      xmm7,       xmm6                        ; 77 67 57 47 37 27 17 07 76 66 56 46 36 26 16 06
+
+        punpckhqdq  xmm7,       xmm1                        ; f7 e7 d7 c7 b7 a7 97 87 77 67 57 47 37 27 17 07 = q3
+        punpcklqdq  xmm6,       xmm1                        ; f6 e6 d6 c6 b6 a6 96 86 76 66 56 46 36 26 16 06 = q2
+
+        ; free 1, 3   xmm7-7s xmm6-6s, xmm2-5s
+        movq        xmm1,       QWORD PTR [rdx]                       ; 93 83 92 82 91 81 90 80
+        movq        xmm3,       QWORD PTR [rdx+16]                    ; b3 a3 b2 a2 b1 a1 b0 a0
+
+        punpcklwd   xmm1,       xmm3                        ; b3 a3 93 83 b2 a2 92 82 b1 a1 91 81 b0 a0 90 80
+        movdqa      xmm3,       xmm1                        ; b3 a3 93 83 b2 a2 92 82 b1 a1 91 81 b0 a0 90 80
+
+        punpckhdq   xmm3,       xmm4                        ; f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82
+        punpckldq   xmm1,       xmm4                        ; f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80
+
+        movdqa      xmm4,       xmm5                        ; 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
+        punpcklqdq  xmm5,       xmm3                        ; f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+
+        punpckhqdq  xmm4,       xmm3                        ; f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
+        movdqa      [rdx],      xmm5                        ; save 2s
+
+        movdqa      [rdx+16],   xmm4                        ; save 3s
+
+        movdqa      xmm3,       xmm6                        ;
+        psubusb     xmm3,       xmm7                        ; q3 - q2
+
+        psubusb     xmm7,       xmm6                        ; q2 - q3
+        por         xmm7,       xmm3                        ; abs(q3-q2)
+
+        movdqa      xmm3,       xmm2                        ; q1
+        psubusb     xmm3,       xmm6                        ; q1 - q2
+
+        psubusb     xmm6,       xmm2                        ; q2 - q1
+        por         xmm6,       xmm3                        ; abs(q2-q1)
+
+
+        movdqa      xmm3,       xmm0                        ; 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
+        punpcklqdq  xmm0,       xmm1                        ; f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+
+        punpckhqdq  xmm3,       xmm1                        ; f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
+        movdqa      xmm1,       xmm3
+
+        psubusb     xmm3,       xmm0                        ; p2-p3
+        psubusb     xmm0,       xmm1                        ; p3-p2
+
+        por         xmm0,       xmm3                        ; abs(p3-p2)
+        movdqa      xmm3,       xmm5                        ; f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+
+        psubusb     xmm3,       xmm1                        ; p1-p2
+        psubusb     xmm1,       xmm5                        ; p2-p1
+
+        por         xmm1,       xmm3                        ; abs(p1-p2)
+        mov         rdx,        arg(3) ;limit
+
+        movdqa      xmm3,       [rdx]                       ; limit
+
+        psubusb     xmm7,       xmm3
+        psubusb     xmm0,       xmm3
+
+        psubusb     xmm1,       xmm3
+        psubusb     xmm6,       xmm3
+
+        por         xmm7,       xmm6
+        por         xmm0,       xmm1
+
+        por         xmm0,       xmm7                         ;   abs(q3-q2) > limit || abs(p3-p2) > limit ||abs(p2-p1) > limit || abs(q2-q1) > limit
+
+        movdqa      xmm1,       xmm5                         ; p1
+
+        movdqa      xmm7,       xmm4                        ; xmm4 xmm7 = p0
+
+        psubusb     xmm7,       xmm5                        ; p0 - p1
+        psubusb     xmm5,       xmm4                        ; p1 - p0
+
+        por         xmm5,       xmm7                        ; abs(p1-p0)
+        movdqa        t0,       xmm5                        ; save abs(p1-p0)
+
+        lea         rdx,        srct
+        psubusb     xmm5,       xmm3
+
+        por         xmm0,       xmm5                        ; xmm0=mask
+        movdqa      xmm5,       [rdx+32]                    ; xmm5=q0
+
+        movdqa      xmm7,       [rdx+48]                    ; xmm7=q1
+        movdqa      xmm6,       xmm5                        ; mm6=q0
+
+        movdqa      xmm2,       xmm7                        ; q1
+
+        psubusb     xmm5,       xmm7                        ; q0-q1
+        psubusb     xmm7,       xmm6                        ; q1-q0
+
+        por         xmm7,       xmm5                        ; abs(q1-q0)
+        movdqa        t1,       xmm7                        ; save abs(q1-q0)
+
+        psubusb     xmm7,       xmm3
+        por         xmm0,       xmm7                        ; mask
+
+        movdqa      xmm5,       xmm2                        ; q1
+        psubusb     xmm5,       xmm1                        ; q1-=p1
+        psubusb     xmm1,       xmm2                        ; p1-=q1
+        por         xmm5,       xmm1                        ; abs(p1-q1)
+        pand        xmm5,       [tfe GLOBAL]                ; set lsb of each byte to zero
+        psrlw       xmm5,       1                           ; abs(p1-q1)/2
+
+        mov         rdx,        arg(2) ;flimit                      ;
+        movdqa        xmm2,       [rdx]                       ;flimit  xmm2
+
+        movdqa      xmm1,       xmm4                        ; xmm1=xmm4=p0
+
+        movdqa      xmm7,       xmm6                        ; xmm7=xmm6=q0
+        psubusb     xmm1,       xmm7                        ; p0-q0
+
+        psubusb     xmm7,       xmm4                        ; q0-p0
+        por         xmm1,       xmm7                        ; abs(q0-p0)
+        paddusb     xmm1,       xmm1                        ; abs(q0-p0)*2
+        paddusb     xmm1,       xmm5                        ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        paddb       xmm2,       xmm2                        ; flimit*2 (less than 255)
+        paddb       xmm3,       xmm2                        ; flimit * 2 + limit (less than 255)
+
+        psubusb     xmm1,       xmm3                         ; abs (p0 - q0) *2 + abs(p1-q1)/2  > flimit * 2 + limit
+
+        por         xmm1,       xmm0;                       ; mask
+
+        pxor        xmm0,       xmm0
+        pcmpeqb     xmm1,       xmm0
+        ; calculate high edge variance
+        mov         rdx,        arg(4) ;thresh            ; get thresh
+        movdqa      xmm7,       [rdx]
+
+        ;
+        movdqa      xmm4,       t0              ; get abs (q1 - q0)
+        psubusb     xmm4,       xmm7
+
+        movdqa      xmm3,       t1              ; get abs (p1 - p0)
+        psubusb     xmm3,       xmm7
+
+        por         xmm4,       xmm3            ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+        pcmpeqb     xmm4,       xmm0
+
+        pcmpeqb     xmm0,       xmm0
+        pxor        xmm4,       xmm0
+
+        ; start work on filters
+        lea         rdx,        srct
+
+        movdqa      xmm2,       [rdx]           ; p1
+        movdqa      xmm7,       [rdx+48]        ; q1
+
+        movdqa      xmm6,       [rdx+16]        ; p0
+        movdqa      xmm0,       [rdx+32]        ; q0
+
+        pxor        xmm2,       [t80 GLOBAL]    ; p1 offset to convert to signed values
+        pxor        xmm7,       [t80 GLOBAL]    ; q1 offset to convert to signed values
+
+        psubsb      xmm2,       xmm7            ; p1 - q1
+        pand        xmm2,       xmm4            ; high var mask (hvm)(p1 - q1)
+
+        pxor        xmm6,       [t80 GLOBAL]    ; offset to convert to signed values
+        pxor        xmm0,       [t80 GLOBAL]    ; offset to convert to signed values
+
+        movdqa      xmm3,       xmm0            ; q0
+        psubsb      xmm0,       xmm6            ; q0 - p0
+
+        paddsb      xmm2,       xmm0            ; 1 * (q0 - p0) + hvm(p1 - q1)
+        paddsb      xmm2,       xmm0            ; 2 * (q0 - p0) + hvm(p1 - q1)
+
+        paddsb      xmm2,       xmm0            ; 3 * (q0 - p0) + hvm(p1 - q1)
+        pand        xmm1,       xmm2            ; mask filter values we don't care about
+
+        movdqa      xmm2,       xmm1
+        paddsb      xmm1,       [t4 GLOBAL]       ; 3* (q0 - p0) + hvm(p1 - q1) + 4
+
+        paddsb      xmm2,       [t3 GLOBAL]       ; 3* (q0 - p0) + hvm(p1 - q1) + 3
+        pxor        xmm0,       xmm0             ;
+
+        pxor        xmm5,       xmm5
+        punpcklbw   xmm0,       xmm2            ;
+
+        punpckhbw   xmm5,       xmm2            ;
+        psraw       xmm0,       11              ;
+
+        psraw       xmm5,       11
+        packsswb    xmm0,       xmm5
+
+        movdqa      xmm2,       xmm0            ;  (3* (q0 - p0) + hvm(p1 - q1) + 3) >> 3;
+
+        pxor        xmm0,       xmm0              ; 0
+        movdqa      xmm5,       xmm1              ; abcdefgh
+
+        punpcklbw   xmm0,       xmm1              ; e0f0g0h0
+        psraw       xmm0,       11                ; sign extended shift right by 3
+
+        pxor        xmm1,       xmm1              ; 0
+        punpckhbw   xmm1,       xmm5              ; a0b0c0d0
+
+        psraw       xmm1,       11                ; sign extended shift right by 3
+        movdqa      xmm5,       xmm0              ; save results
+
+        packsswb    xmm0,       xmm1              ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>3
+        paddsw      xmm5,       [ones GLOBAL]
+
+        paddsw      xmm1,       [ones GLOBAL]
+        psraw       xmm5,       1                 ; partial shifted one more time for 2nd tap
+
+        psraw       xmm1,       1                 ; partial shifted one more time for 2nd tap
+        packsswb    xmm5,       xmm1              ; (3* (q0 - p0) + hvm(p1 - q1) + 4) >>4
+
+        pandn       xmm4,       xmm5            ; high edge variance additive
+
+        paddsb      xmm6,       xmm2            ; p0+= p0 add
+        pxor        xmm6,       [t80 GLOBAL]    ; unoffset
+
+        ; mm6=p0                               ;
+        movdqa      xmm1,       [rdx]           ; p1
+        pxor        xmm1,       [t80 GLOBAL]    ; reoffset
+
+        paddsb      xmm1,       xmm4            ; p1+= p1 add
+        pxor        xmm1,       [t80 GLOBAL]    ; unoffset
+        ; mm6 = p0 mm1 = p1
+
+        psubsb      xmm3,       xmm0            ; q0-= q0 add
+        pxor        xmm3,       [t80 GLOBAL]    ; unoffset
+
+        ; mm3 = q0
+        psubsb      xmm7,       xmm4            ; q1-= q1 add
+        pxor        xmm7,       [t80 GLOBAL]    ; unoffset
+        ; mm7 = q1
+
+        ; tranpose and write back
+        ; xmm1 =    f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+        ; xmm6 =    f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
+        ; xmm3 =    f4 e4 d4 c4 b4 a4 94 84 74 64 54 44 34 24 14 04
+        ; xmm7 =    f5 e5 d5 c5 b5 a5 95 85 75 65 55 45 35 25 15 05
+        movdqa      xmm2,       xmm1            ; f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+        punpcklbw   xmm2,       xmm6            ; 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
+
+        movdqa      xmm4,       xmm3            ; f4 e4 d4 c4 b4 a4 94 84 74 64 54 44 34 24 14 04
+        punpckhbw   xmm1,       xmm6            ; f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
+
+        punpcklbw   xmm4,       xmm7            ; 75 74 65 64 55 54 45 44 35 34 25 24 15 14 05 04
+        punpckhbw   xmm3,       xmm7            ; f5 f4 e5 e4 d5 d4 c5 c4 b5 b4 a5 a4 95 94 85 84
+
+        movdqa      xmm6,       xmm2            ; 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
+        punpcklwd   xmm2,       xmm4            ; 35 34 33 32 25 24 23 22 15 14 13 12 05 04 03 02
+
+        punpckhwd   xmm6,       xmm4            ; 75 74 73 72 65 64 63 62 55 54 53 52 45 44 43 42
+        movdqa      xmm5,       xmm1            ; f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
+
+        punpcklwd   xmm1,       xmm3            ; f5 f4 f3 f2 e5 e4 e3 e2 d5 d4 d3 d2 c5 c4 c3 c2
+        punpckhwd   xmm5,       xmm3            ; b5 b4 b3 b2 a5 a4 a3 a2 95 94 93 92 85 84 83 82
+
+        ; xmm2 = 35 34 33 32 25 24 23 22 15 14 13 12 05 04 03 02
+        ; xmm6 = 75 74 73 72 65 64 63 62 55 54 53 52 45 44 43 42
+        ; xmm5 = f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
+        ; xmm1 = b5 b4 b3 b2 a5 a4 a3 a2 95 94 93 92 85 84 83 82
+        lea         rsi,           [rsi+rax*8]
+
+        movd        [rsi+rax*4+2], xmm2
+        psrldq      xmm2,   4
+
+        movd        [rdi+rax*4+2], xmm2
+        psrldq      xmm2,   4
+
+        movd        [rsi+rax*2+2], xmm2
+        psrldq      xmm2,   4
+
+        movd        [rdi+rax*2+2], xmm2
+        movd        [rsi+2],       xmm6
+
+        psrldq      xmm6,   4
+        movd        [rdi+2],       xmm6
+
+        psrldq      xmm6,   4
+        neg         rax
+
+        movd        [rdi+rax+2],    xmm6
+        psrldq      xmm6,   4
+
+        movd        [rdi+rax*2+2],  xmm6
+        lea         rsi,       [rsi+rax*8]
+
+        neg         rax
+        ;;;;;;;;;;;;;;;;;;;;/
+        movd        [rsi+rax*4+2], xmm1
+        psrldq      xmm1,   4
+
+        movd        [rcx+rax*4+2], xmm1
+        psrldq      xmm1,   4
+
+        movd        [rsi+rax*2+2], xmm1
+        psrldq      xmm1,   4
+
+        movd        [rcx+rax*2+2], xmm1
+        psrldq      xmm1,   4
+
+        movd        [rsi+2],       xmm5
+        psrldq      xmm5,   4
+
+        movd        [rcx+2],        xmm5
+        psrldq      xmm5,   4
+
+        neg         rax
+        movd        [rcx+rax+2],    xmm5
+
+        psrldq      xmm5,   4
+        movd        [rcx+rax*2+2],  xmm5
+
+    add rsp, 96
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_mbloop_filter_horizontal_edge_sse2
+;(
+;    unsigned char *src_ptr,
+;    int            src_pixel_step,
+;    const char    *flimit,
+;    const char    *limit,
+;    const char    *thresh,
+;    int            count
+;)
+global sym(vp8_mbloop_filter_horizontal_edge_sse2)
+sym(vp8_mbloop_filter_horizontal_edge_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 32                         ; reserve 32 bytes
+    %define t0  [rsp + 0]    ;__declspec(align(16)) char t0[8];
+    %define t1  [rsp + 16]   ;__declspec(align(16)) char t1[8];
+
+        mov         rsi,                    arg(0) ;src_ptr
+        movsxd      rax,                    dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        mov         rdx,                    arg(3) ;limit
+        movdqa      xmm7,                   XMMWORD PTR [rdx]
+
+        mov         rdi,                    rsi           ; rdi points to row +1 for indirect addressing
+        add         rdi,                    rax
+
+        ; calculate breakout conditions
+        movdqa      xmm2,                   XMMWORD PTR [rdi+2*rax]      ; q3
+        movdqa      xmm1,                   XMMWORD PTR [rsi+2*rax]      ; q2
+
+        movdqa      xmm6,                   xmm1              ; q2
+        psubusb     xmm1,                   xmm2              ; q2-=q3
+
+
+        psubusb     xmm2,                   xmm6              ; q3-=q2
+        por         xmm1,                   xmm2              ; abs(q3-q2)
+
+        psubusb     xmm1,                   xmm7
+
+        ; mm1 = abs(q3-q2), mm6 =q2, mm7 = limit
+        movdqa      xmm4,                   XMMWORD PTR [rsi+rax]         ; q1
+        movdqa      xmm3,                   xmm4              ; q1
+
+        psubusb     xmm4,                   xmm6              ; q1-=q2
+        psubusb     xmm6,                   xmm3              ; q2-=q1
+
+        por         xmm4,                   xmm6              ; abs(q2-q1)
+        psubusb     xmm4,                   xmm7
+
+        por         xmm1,                   xmm4
+        ; mm1 = mask,      mm3=q1, mm7 = limit
+
+        movdqa      xmm4,                   XMMWORD PTR [rsi]             ; q0
+        movdqa      xmm0,                   xmm4              ; q0
+
+        psubusb     xmm4,                   xmm3              ; q0-=q1
+        psubusb     xmm3,                   xmm0              ; q1-=q0
+
+        por         xmm4,                   xmm3              ; abs(q0-q1)
+        movdqa      t0,                     xmm4                  ; save to t0
+
+        psubusb     xmm4,                   xmm7
+        por         xmm1,                   xmm4
+
+        ; mm1 = mask, mm0=q0,  mm7 = limit, t0 = abs(q0-q1)
+        neg         rax                   ; negate pitch to deal with above border
+
+        movdqa      xmm2,                   XMMWORD PTR [rsi+4*rax]      ; p3
+        movdqa      xmm4,                   XMMWORD PTR [rdi+4*rax]      ; p2
+
+        movdqa      xmm5,                   xmm4              ; p2
+        psubusb     xmm4,                   xmm2              ; p2-=p3
+
+        psubusb     xmm2,                   xmm5              ; p3-=p2
+        por         xmm4,                   xmm2              ; abs(p3 - p2)
+
+        psubusb     xmm4,                   xmm7
+        por         xmm1,                   xmm4
+
+        ; mm1 = mask, mm0=q0,  mm7 = limit, t0 = abs(q0-q1)
+        movdqa      xmm4,                   XMMWORD PTR [rsi+2*rax]      ; p1
+        movdqa      xmm3,                   xmm4              ; p1
+
+        psubusb     xmm4,                   xmm5              ; p1-=p2
+        psubusb     xmm5,                   xmm3              ; p2-=p1
+
+        por         xmm4,                   xmm5              ; abs(p2 - p1)
+        psubusb     xmm4,                   xmm7
+
+        por         xmm1,                   xmm4
+
+        movdqa      xmm2,                   xmm3              ; p1
+
+        ; mm1 = mask, mm0=q0,  mm7 = limit, t0 = abs(q0-q1)
+        movdqa      xmm4,                   XMMWORD PTR [rsi+rax]         ; p0
+        movdqa      xmm5,                   xmm4              ; p0
+
+        psubusb     xmm4,                   xmm3              ; p0-=p1
+        psubusb     xmm3,                   xmm5              ; p1-=p0
+
+        por         xmm4,                   xmm3              ; abs(p1 - p0)
+        movdqa        t1,                   xmm4                  ; save to t1
+
+        psubusb     xmm4,                   xmm7
+        por         xmm1,                   xmm4
+
+        ; mm1 = mask, mm0=q0,  mm7 = limit, t0 = abs(q0-q1) t1 = abs(p1-p0)
+        ; mm5 = p0
+        movdqa      xmm3,                   XMMWORD PTR [rdi] ; q1
+        movdqa      xmm4,                   xmm3              ; q1
+        psubusb     xmm3,                   xmm2              ; q1-=p1
+        psubusb     xmm2,                   xmm4              ; p1-=q1
+        por         xmm2,                   xmm3              ; abs(p1-q1)
+        pand        xmm2,                   [tfe GLOBAL]      ; set lsb of each byte to zero
+        psrlw       xmm2,                   1                 ; abs(p1-q1)/2
+
+        movdqa      xmm6,                   xmm5              ; p0
+        movdqa      xmm3,                   xmm0              ; q0
+
+        psubusb     xmm5,                   xmm3              ; p0-=q0
+        psubusb     xmm3,                   xmm6              ; q0-=p0
+
+        por         xmm5,                   xmm3              ; abs(p0 - q0)
+        paddusb     xmm5,                   xmm5              ; abs(p0-q0)*2
+        paddusb     xmm5,                   xmm2              ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        mov         rdx,                    arg(2) ;flimit            ; get flimit
+        movdqa      xmm2,                   XMMWORD PTR [rdx]             ;
+        paddb       xmm2,                   xmm2              ; flimit*2 (less than 255)
+        paddb       xmm7,                   xmm2              ; flimit * 2 + limit (less than 255)
+
+        psubusb     xmm5,                   xmm7              ; abs (p0 - q0) *2 + abs(p1-q1)/2  > flimit * 2 + limit
+        por         xmm1,                   xmm5
+        pxor        xmm5,                   xmm5
+        pcmpeqb     xmm1,                   xmm5               ; mask mm1
+        ; mm1 = mask, mm0=q0,  mm7 = flimit, t0 = abs(q0-q1) t1 = abs(p1-p0)
+        ; mm6 = p0,
+
+        ; calculate high edge variance
+        mov         rdx,                    arg(4) ;thresh            ; get thresh
+        movdqa      xmm7,                   XMMWORD PTR [rdx]             ;
+
+        movdqa      xmm4,                   t0                ; get abs (q1 - q0)
+        psubusb     xmm4,                   xmm7
+
+        movdqa      xmm3,                   t1                ; get abs (p1 - p0)
+        psubusb     xmm3,                   xmm7
+
+        paddb       xmm4,                   xmm3              ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+        pcmpeqb     xmm4,                   xmm5
+
+        pcmpeqb     xmm5,                   xmm5
+        pxor        xmm4,                   xmm5
+        ; mm1 = mask, mm0=q0,  mm7 = thresh, t0 = abs(q0-q1) t1 = abs(p1-p0)
+        ; mm6 = p0, mm4=hev
+        ; start work on filters
+        movdqa      xmm2,                   XMMWORD PTR [rsi+2*rax]   ; p1
+        movdqa      xmm7,                   XMMWORD PTR [rdi]             ; q1
+
+        pxor        xmm2,                   [t80 GLOBAL]  ; p1 offset to convert to signed values
+        pxor        xmm7,                   [t80 GLOBAL]  ; q1 offset to convert to signed values
+
+        psubsb      xmm2,                   xmm7              ; p1 - q1
+        pxor        xmm6,                   [t80 GLOBAL]  ; offset to convert to signed values
+
+        pxor        xmm0,                   [t80 GLOBAL]  ; offset to convert to signed values
+        movdqa      xmm3,                   xmm0              ; q0
+
+        psubsb      xmm0,                   xmm6              ; q0 - p0
+        paddsb      xmm2,                   xmm0              ; 1 * (q0 - p0) + (p1 - q1)
+
+        paddsb      xmm2,                   xmm0              ; 2 * (q0 - p0)
+        paddsb      xmm2,                   xmm0              ; 3 * (q0 - p0) + (p1 - q1)
+
+        pand        xmm1,                   xmm2              ; mask filter values we don't care about
+        ; mm1 = vp8_filter, mm4=hev, mm6=ps0, mm3=qs0
+        movdqa      xmm2,                   xmm1              ; vp8_filter
+        pand        xmm2,                   xmm4;             ; Filter2 = vp8_filter & hev
+
+
+        movdqa      xmm5,                   xmm2          ;
+        paddsb      xmm5,                   [t3 GLOBAL];
+
+        pxor        xmm0,                   xmm0              ; 0
+        pxor        xmm7,                   xmm7              ; 0
+
+        punpcklbw   xmm0,                   xmm5              ; e0f0g0h0
+        psraw       xmm0,                   11                ; sign extended shift right by 3
+
+        punpckhbw   xmm7,                   xmm5              ; a0b0c0d0
+        psraw       xmm7,                   11                ; sign extended shift right by 3
+
+        packsswb    xmm0,                   xmm7              ; Filter2 >>=3;
+        movdqa      xmm5,                   xmm0              ; Filter2
+
+        paddsb      xmm2,                   [t4 GLOBAL]      ; vp8_signed_char_clamp(Filter2 + 4)
+        pxor        xmm0,                   xmm0              ; 0
+
+        pxor        xmm7,                   xmm7              ; 0
+        punpcklbw   xmm0,                   xmm2              ; e0f0g0h0
+
+        psraw       xmm0,                   11                ; sign extended shift right by 3
+        punpckhbw   xmm7,                   xmm2              ; a0b0c0d0
+
+        psraw       xmm7,                   11                ; sign extended shift right by 3
+        packsswb    xmm0,                   xmm7              ; Filter2 >>=3;
+
+        ; mm0= filter2 mm1 = vp8_filter,  mm3 =qs0 mm5=s mm4 =hev mm6=ps0
+        psubsb      xmm3,                   xmm0              ; qs0 =qs0 - filter1
+        paddsb      xmm6,                   xmm5              ; ps0 =ps0 + Fitler2
+
+        ; mm1=vp8_filter, mm3=qs0, mm4 =hev mm6=ps0
+        ; vp8_filter &= ~hev;
+        ; Filter2 = vp8_filter;
+        pandn       xmm4,                   xmm1              ; vp8_filter&=~hev
+
+
+        ; mm3=qs0, mm4=filter2, mm6=ps0
+
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7);
+        ; s = vp8_signed_char_clamp(qs0 - u);
+        ; *oq0 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps0 + u);
+        ; *op0 = s^0x80;
+        pxor        xmm0,                   xmm0
+        pxor        xmm1,                   xmm1
+
+        pxor        xmm2,                   xmm2
+        punpcklbw   xmm1,                   xmm4
+
+        punpckhbw   xmm2,                   xmm4
+        pmulhw      xmm1,                   [s27 GLOBAL]
+
+        pmulhw      xmm2,                   [s27 GLOBAL]
+        paddw       xmm1,                   [s63 GLOBAL]
+
+        paddw       xmm2,                   [s63 GLOBAL]
+        psraw       xmm1,                   7
+
+        psraw       xmm2,                   7
+        packsswb    xmm1,                   xmm2
+
+        psubsb      xmm3,                   xmm1
+        paddsb      xmm6,                   xmm1
+
+        pxor        xmm3,                   [t80 GLOBAL]
+        pxor        xmm6,                   [t80 GLOBAL]
+
+        movdqa      XMMWORD PTR [rsi+rax],  xmm6
+        movdqa      XMMWORD PTR [rsi],      xmm3
+
+        ; roughly 2/7th difference across boundary
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7);
+        ; s = vp8_signed_char_clamp(qs1 - u);
+        ; *oq1 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps1 + u);
+        ; *op1 = s^0x80;
+        pxor        xmm1,                   xmm1
+        pxor        xmm2,                   xmm2
+
+        punpcklbw   xmm1,                   xmm4
+        punpckhbw   xmm2,                   xmm4
+
+        pmulhw      xmm1,                   [s18 GLOBAL]
+        pmulhw      xmm2,                   [s18 GLOBAL]
+
+        paddw       xmm1,                   [s63 GLOBAL]
+        paddw       xmm2,                   [s63 GLOBAL]
+
+        psraw       xmm1,                   7
+        psraw       xmm2,                   7
+
+        packsswb    xmm1,                   xmm2
+
+        movdqa      xmm3,                   XMMWORD PTR [rdi]
+        movdqa      xmm6,                   XMMWORD PTR [rsi+rax*2]       ; p1
+
+        pxor        xmm3,                   [t80 GLOBAL]
+        pxor        xmm6,                   [t80 GLOBAL]
+
+        paddsb      xmm6,                   xmm1
+        psubsb      xmm3,                   xmm1
+
+        pxor        xmm6,                   [t80 GLOBAL]
+        pxor        xmm3,                   [t80 GLOBAL]
+
+        movdqa      XMMWORD PTR [rdi],      xmm3
+        movdqa      XMMWORD PTR [rsi+rax*2],xmm6
+
+        ; roughly 1/7th difference across boundary
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7);
+        ; s = vp8_signed_char_clamp(qs2 - u);
+        ; *oq2 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps2 + u);
+        ; *op2 = s^0x80;
+        pxor        xmm1,                   xmm1
+        pxor        xmm2,                   xmm2
+
+        punpcklbw   xmm1,                   xmm4
+        punpckhbw   xmm2,                   xmm4
+
+        pmulhw      xmm1,                   [s9 GLOBAL]
+        pmulhw      xmm2,                   [s9 GLOBAL]
+
+        paddw       xmm1,                   [s63 GLOBAL]
+        paddw       xmm2,                   [s63 GLOBAL]
+
+        psraw       xmm1,                   7
+        psraw       xmm2,                   7
+
+        packsswb    xmm1,                   xmm2
+
+
+        movdqa      xmm6,                   XMMWORD PTR [rdi+rax*4]
+        neg         rax
+
+        movdqa      xmm3,                   XMMWORD PTR [rdi+rax  ]
+
+        pxor        xmm6,                   [t80 GLOBAL]
+        pxor        xmm3,                   [t80 GLOBAL]
+
+        paddsb      xmm6,                   xmm1
+        psubsb      xmm3,                   xmm1
+
+        pxor        xmm6,                   [t80 GLOBAL]
+        pxor        xmm3,                   [t80 GLOBAL]
+
+        movdqa      XMMWORD PTR [rdi+rax  ], xmm3
+        neg         rax
+
+        movdqa      XMMWORD PTR [rdi+rax*4], xmm6
+
+    add rsp, 32
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_mbloop_filter_vertical_edge_sse2
+;(
+;    unsigned char *src_ptr,
+;    int            src_pixel_step,
+;    const char    *flimit,
+;    const char    *limit,
+;    const char    *thresh,
+;    int            count
+;)
+global sym(vp8_mbloop_filter_vertical_edge_sse2)
+sym(vp8_mbloop_filter_vertical_edge_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub          rsp, 160     ; reserve 160 bytes
+    %define t0   [rsp + 0]    ;__declspec(align(16)) char t0[16];
+    %define t1   [rsp + 16]   ;__declspec(align(16)) char t1[16];
+    %define srct [rsp + 32]   ;__declspec(align(16)) char srct[128];
+
+
+        mov         rsi,                arg(0) ;src_ptr
+        movsxd      rax,                dword ptr arg(1) ;src_pixel_step                    ; destination pitch?
+
+        lea         rsi,                [rsi + rax*4 - 4]
+        lea         rdi,                [rsi + rax]                     ; rdi points to row +1 for indirect addressing
+
+        mov         rcx,                rax
+        neg         rcx
+
+        ; Transpose
+        movq        xmm0,               QWORD PTR [rdi+rax*2]           ; xx xx xx xx xx xx xx xx 77 76 75 74 73 72 71 70
+        movq        xmm7,               QWORD PTR [rsi+rax*2]           ; xx xx xx xx xx xx xx xx 67 66 65 64 63 62 61 60
+
+        punpcklbw   xmm7,               xmm0                            ; 77 67 76 66 75 65 74 64 73 63 72 62 71 61 70 60
+        movq        xmm0,               QWORD PTR [rsi+rax]             ;
+
+        movq        xmm5,               QWORD PTR [rsi]                 ;
+        punpcklbw   xmm5,               xmm0                            ; 57 47 56 46 55 45 54 44 53 43 52 42 51 41 50 40
+
+        movdqa      xmm6,               xmm5                            ; 57 47 56 46 55 45 54 44 53 43 52 42 51 41 50 40
+        punpcklwd   xmm5,               xmm7                            ; 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40
+
+        punpckhwd   xmm6,               xmm7                            ; 77 67 57 47 76 66 56 46 75 65 55 45 74 64 54 44
+        movq        xmm7,               QWORD PTR [rsi + rcx]           ; xx xx xx xx xx xx xx xx 37 36 35 34 33 32 31 30
+
+        movq        xmm0,               QWORD PTR [rsi + rcx*2]         ; xx xx xx xx xx xx xx xx 27 26 25 24 23 22 21 20
+        punpcklbw   xmm0,               xmm7                            ; 37 27 36 36 35 25 34 24 33 23 32 22 31 21 30 20
+
+        movq        xmm4,               QWORD PTR [rsi + rcx*4]         ; xx xx xx xx xx xx xx xx 07 06 05 04 03 02 01 00
+        movq        xmm7,               QWORD PTR [rdi + rcx*4]         ; xx xx xx xx xx xx xx xx 17 16 15 14 13 12 11 10
+
+        punpcklbw   xmm4,               xmm7                            ; 17 07 16 06 15 05 14 04 13 03 12 02 11 01 10 00
+        movdqa      xmm3,               xmm4                            ; 17 07 16 06 15 05 14 04 13 03 12 02 11 01 10 00
+
+        punpcklwd   xmm3,               xmm0                            ; 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
+        punpckhwd   xmm4,               xmm0                            ; 37 27 17 07 36 26 16 06 35 25 15 05 34 24 14 04
+
+        movdqa      xmm7,               xmm4                            ; 37 27 17 07 36 26 16 06 35 25 15 05 34 24 14 04
+        movdqa      xmm2,               xmm3                            ; 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
+
+        punpckhdq   xmm7,               xmm6                            ; 77 67 57 47 37 27 17 07 76 66 56 46 36 26 16 06
+        punpckldq   xmm4,               xmm6                            ; 75 65 55 45 35 25 15 05 74 64 54 44 34 24 14 04
+
+        punpckhdq   xmm3,               xmm5                            ; 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
+        punpckldq   xmm2,               xmm5                            ; 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
+
+        movdqa      t0,                 xmm2                            ; save to free XMM2
+        ;movdqa        t1,                 xmm3
+
+        ; XMM3 XMM4 XMM7 in use
+        lea         rsi,                [rsi+rax*8]
+        lea         rdi,                [rdi+rax*8]
+
+        movq        xmm6,               QWORD PTR [rdi+rax*2]           ; xx xx xx xx xx xx xx xx f7 f6 f5 f4 f3 f2 f1 f0
+        movq        xmm5,               QWORD PTR [rsi+rax*2]           ; xx xx xx xx xx xx xx xx e7 e6 e5 e4 e3 e2 e1 e0
+
+        punpcklbw   xmm5,               xmm6                            ; f7 e7 f6 e6 f5 e5 f4 e4 f3 e3 f2 e2 f1 e1 f0 e0
+        movq        xmm6,               QWORD PTR [rsi+rax]             ; xx xx xx xx xx xx xx xx d7 d6 d5 d4 d3 d2 d1 d0
+
+        movq        xmm1,               QWORD PTR [rsi]                 ; xx xx xx xx xx xx xx xx c7 c6 c5 c4 c3 c2 c1 c0
+        punpcklbw   xmm1,               xmm6                            ; d7 c7 d6 c6 d5 c5 d4 c4 d3 c3 d2 c2 d1 e1 d0 c0
+
+        movdqa      xmm6,               xmm1                            ;
+        punpckhwd   xmm6,               xmm5                            ; f7 e7 d7 c7 f6 e6 d6 c6 f5 e5 d5 c5 f4 e4 d4 c4
+
+        punpcklwd   xmm1,               xmm5                            ; f3 e3 d3 c3 f2 e2 d2 c2 f1 e1 d1 c1 f0 e0 d0 c0
+        movq        xmm5,               QWORD PTR [rsi+rcx]             ; xx xx xx xx xx xx xx xx b7 b6 b5 b4 b3 b2 b1 b0
+
+        movq        xmm0,               QWORD PTR [rsi+rcx*2]           ; xx xx xx xx xx xx xx xx a7 a6 a5 a4 a3 a2 a1 a0
+        punpcklbw   xmm0,               xmm5                            ; b7 a7 b6 a6 b5 a5 b4 a4 b3 a3 b2 a2 b1 a1 b0 a0
+
+        movq        xmm2,               QWORD PTR [rsi+rcx*4]           ; xx xx xx xx xx xx xx xx 87 86 85 84 83 82 81 80
+        movq        xmm5,               QWORD PTR [rdi+rcx*4]           ; xx xx xx xx xx xx xx xx 97 96 95 94 93 92 91 90
+
+        punpcklbw   xmm2,               xmm5                            ; 97 87 96 86 95 85 94 84 93 83 92 82 91 81 90 80
+        movdqa      xmm5,               xmm2                            ; 97 87 96 86 95 85 94 84 93 83 92 82 91 81 90 80
+
+        punpcklwd   xmm5,               xmm0                            ; b3 a3 93 83 b2 a2 92 82 b1 a1 91 81 b0 a0 90 80
+        punpckhwd   xmm2,               xmm0                            ; b7 a7 97 87 b6 a6 96 86 b5 a5 95 85 b4 a4 94 84
+
+        movdqa      xmm0,               xmm5
+        punpckldq   xmm0,               xmm1                            ; f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80
+
+
+        punpckhdq   xmm5,               xmm1                            ; f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82
+        movdqa      xmm1,               xmm2                            ; b7 a7 97 87 b6 a6 96 86 b5 a5 95 85 b4 a4 94 84
+
+        punpckldq   xmm1,               xmm6                            ; f5 e5 d5 c5 b5 a5 95 85 f4 e4 d4 c4 b4 a4 94 84
+        punpckhdq   xmm2,               xmm6                            ; f7 e7 d7 c7 b7 a7 97 87 f6 e6 d6 c6 b6 a6 96 86
+
+        movdqa      xmm6,               xmm7                            ; 77 67 57 47 37 27 17 07 76 66 56 46 36 26 16 06
+        punpcklqdq  xmm6,               xmm2                            ; f6 e6 d6 c6 b6 a6 96 86 76 66 56 46 36 26 16 06
+
+
+        lea         rdx,                srct
+        punpckhqdq  xmm7,               xmm2                            ; f7 e7 d7 c7 b7 a7 97 87 77 67 57 47 37 27 17 07
+
+        movdqa      [rdx+112],          xmm7                            ; save 7
+        movdqa      xmm2,               xmm3                            ; 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
+
+        movdqa      [rdx+96],           xmm6                            ; save 6
+        punpcklqdq  xmm2,               xmm5                            ; f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+
+        punpckhqdq  xmm3,               xmm5                            ; f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
+        movdqa      [rdx+32],           xmm2                            ; save 2
+
+        movdqa      xmm5,               xmm4                            ; 75 65 55 45 35 25 15 05 74 64 54 44 34 24 14 04
+        punpcklqdq  xmm4,               xmm1                            ; f4 e4 d4 c4 b4 a4 94 84 74 64 54 44 34 24 14 04
+
+        movdqa      [rdx+48],           xmm3                            ; save 3
+        punpckhqdq  xmm5,               xmm1                            ; f5 e5 d5 c5 b5 a5 95 85 75 65 55 45 35 25 15 05
+
+        movdqa      [rdx+64],           xmm4                            ; save 4
+        movdqa      [rdx+80],           xmm5                            ; save 5
+
+        movdqa      xmm1,               t0                              ; get
+        movdqa      xmm2,               xmm1                            ;
+
+        punpckhqdq  xmm1,               xmm0                            ; f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
+        punpcklqdq  xmm2,               xmm0                            ; f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+
+        movdqa      [rdx+16],           xmm1
+        movdqa      [rdx],              xmm2
+
+        movdqa      xmm0,               xmm6                            ; q2
+        psubusb     xmm0,               xmm7                            ; q2-q3
+
+        psubusb     xmm7,               xmm6                            ; q3-q2
+        por         xmm7,               xmm0                            ; abs (q3-q2)
+
+        movdqa      xmm1,               xmm5                            ; q1
+        psubusb     xmm1,               xmm6                            ; q1-q2
+
+        psubusb     xmm6,               xmm5                            ; q2-q1
+        por         xmm6,               xmm1                            ; abs (q2-q1)
+
+        ;/*
+        ;movdqa      xmm0,               xmm4                            ; q0
+        ;psubusb     xmm0                xmm5                            ; q0-q1
+        ;
+        ;pusbusb     xmm5,               xmm4                            ; q1-q0
+        ;por         xmm5,               xmm0                            ; abs (q1-q0)
+        ;*/
+
+        movdqa      xmm1,               [rdx+16]                        ; p2
+        movdqa      xmm0,               xmm1
+
+        psubusb     xmm0,               xmm2                            ; p2 - p3;
+        psubusb     xmm2,               xmm1                            ; p3 - p2;
+
+        por         xmm0,               xmm2                            ; abs(p2-p3)
+
+        movdqa      xmm2,               [rdx+32]                        ; p1
+        movdqa      xmm5,               xmm2                            ; p1
+
+        psubusb     xmm5,               xmm1                            ; p1-p2
+        psubusb     xmm1,               xmm2                            ; p2-p1
+
+        por         xmm1,               xmm5                            ; abs(p2-p1)
+        mov         rdx,                arg(3) ;limit
+
+        movdqa      xmm4,               [rdx]                           ; limit
+        psubusb     xmm7,               xmm4                            ;
+
+
+        psubusb     xmm0,               xmm4                            ; abs(p3-p2) > limit
+        psubusb     xmm1,               xmm4                            ; abs(p2-p1) > limit
+
+        psubusb     xmm6,               xmm4                            ; abs(q2-q1) > limit
+        por         xmm7,               xmm6                            ; or
+
+        por         xmm0,               xmm1                            ;
+        por         xmm0,               xmm7                            ; abs(q3-q2) > limit || abs(p3-p2) > limit ||abs(p2-p1) > limit || abs(q2-q1) > limit
+
+        movdqa      xmm1,               xmm2                            ; p1
+
+        movdqa      xmm7,               xmm3                            ; p0
+        psubusb     xmm7,               xmm2                            ; p0-p1
+
+        psubusb     xmm2,               xmm3                            ; p1-p0
+        por         xmm2,               xmm7                            ; abs(p1-p0)
+
+        movdqa      t0,                 xmm2                            ; save abs(p1-p0)
+        lea         rdx,                srct
+
+        psubusb     xmm2,               xmm4                            ; abs(p1-p0)>limit
+        por         xmm0,               xmm2                            ; mask
+
+        movdqa      xmm5,               [rdx+64]                        ; q0
+        movdqa      xmm7,               [rdx+80]                        ; q1
+
+        movdqa      xmm6,               xmm5                            ; q0
+        movdqa      xmm2,               xmm7                            ; q1
+        psubusb     xmm5,               xmm7                            ; q0-q1
+
+        psubusb     xmm7,               xmm6                            ; q1-q0
+        por         xmm7,               xmm5                            ; abs(q1-q0)
+
+        movdqa      t1,                 xmm7                            ; save abs(q1-q0)
+        psubusb     xmm7,               xmm4                            ; abs(q1-q0)> limit
+
+        por         xmm0,               xmm7                            ; mask
+
+        movdqa      xmm5,                xmm2                           ; q1
+        psubusb     xmm5,                xmm1                           ; q1-=p1
+        psubusb     xmm1,                xmm2                           ; p1-=q1
+        por         xmm5,                xmm1                           ; abs(p1-q1)
+        pand        xmm5,                [tfe GLOBAL]                   ; set lsb of each byte to zero
+        psrlw       xmm5,                1                              ; abs(p1-q1)/2
+
+        mov         rdx,                arg(2) ;flimit                          ;
+        movdqa      xmm2,               [rdx]                           ; flimit
+
+        movdqa      xmm1,               xmm3                            ; p0
+        movdqa      xmm7,               xmm6                            ; q0
+        psubusb     xmm1,               xmm7                            ; p0-q0
+        psubusb     xmm7,               xmm3                            ; q0-p0
+        por         xmm1,               xmm7                            ; abs(q0-p0)
+        paddusb     xmm1,               xmm1                            ; abs(q0-p0)*2
+        paddusb     xmm1,               xmm5                            ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        paddb       xmm2,               xmm2                            ; flimit*2 (less than 255)
+        paddb       xmm4,               xmm2                            ; flimit * 2 + limit (less than 255)
+
+        psubusb     xmm1,               xmm4                            ; abs (p0 - q0) *2 + abs(p1-q1)/2  > flimit * 2 + limit
+        por         xmm1,               xmm0;                           ; mask
+        pxor        xmm0,               xmm0
+        pcmpeqb     xmm1,               xmm0
+
+        ; calculate high edge variance
+        mov         rdx,                arg(4) ;thresh                          ; get thresh
+        movdqa      xmm7,               [rdx]
+
+        movdqa      xmm4,               t0                              ; get abs (q1 - q0)
+        psubusb     xmm4,               xmm7                            ; abs(q1 - q0) > thresh
+
+        movdqa      xmm3,               t1                              ; get abs (p1 - p0)
+        psubusb     xmm3,               xmm7                            ; abs(p1 - p0)> thresh
+
+        por         xmm4,               xmm3                            ; abs(q1 - q0) > thresh || abs(p1 - p0) > thresh
+        pcmpeqb     xmm4,               xmm0
+
+        pcmpeqb     xmm0,               xmm0
+        pxor        xmm4,               xmm0
+
+
+        ; start work on filters
+        lea         rdx,                srct
+
+        ; start work on filters
+        movdqa      xmm2,               [rdx+32]                        ; p1
+        movdqa      xmm7,               [rdx+80]                        ; q1
+
+        pxor        xmm2,               [t80 GLOBAL]                    ; p1 offset to convert to signed values
+        pxor        xmm7,               [t80 GLOBAL]                    ; q1 offset to convert to signed values
+
+        psubsb      xmm2,               xmm7                            ; p1 - q1
+        movdqa      xmm6,               [rdx+48]                        ; p0
+
+        movdqa      xmm0,               [rdx+64]                        ; q0
+        pxor        xmm6,               [t80 GLOBAL]                    ; offset to convert to signed values
+
+        pxor        xmm0,               [t80 GLOBAL]                    ; offset to convert to signed values
+        movdqa      xmm3,               xmm0                            ; q0
+
+        psubsb      xmm0,               xmm6                            ; q0 - p0
+        paddsb      xmm2,               xmm0                            ; 1 * (q0 - p0) + (p1 - q1)
+
+        paddsb      xmm2,               xmm0                            ; 2 * (q0 - p0)
+        paddsb      xmm2,               xmm0                            ; 3 * (q0 - p0)+ (p1 - q1)
+
+        pand        xmm1,               xmm2                            ; mask filter values we don't care about
+
+        ; xmm1 = vp8_filter, xmm4=hev, xmm6=ps0, xmm3=qs0
+        movdqa      xmm2,               xmm1                            ; vp8_filter
+        pand        xmm2,               xmm4;                           ; Filter2 = vp8_filter & hev
+
+        movdqa      xmm5,               xmm2
+        paddsb      xmm5,               [t3 GLOBAL]
+
+        pxor        xmm0,               xmm0                            ; 0
+        pxor        xmm7,               xmm7                            ; 0
+
+        punpcklbw   xmm0,               xmm5                            ; e0f0g0h0
+        psraw       xmm0,               11                              ; sign extended shift right by 3
+
+        punpckhbw   xmm7,               xmm5                            ; a0b0c0d0
+        psraw       xmm7,               11                              ; sign extended shift right by 3
+
+        packsswb    xmm0,               xmm7                            ; Filter2 >>=3;
+        movdqa      xmm5,               xmm0                            ; Filter2
+
+        paddsb      xmm2,               [t4 GLOBAL]                     ; vp8_signed_char_clamp(Filter2 + 4)
+        pxor        xmm0,               xmm0                            ; 0
+
+        pxor        xmm7,               xmm7                            ; 0
+        punpcklbw   xmm0,               xmm2                            ; e0f0g0h0
+
+        psraw       xmm0,               11                              ; sign extended shift right by 3
+        punpckhbw   xmm7,               xmm2                            ; a0b0c0d0
+
+        psraw       xmm7,               11                              ; sign extended shift right by 3
+        packsswb    xmm0,               xmm7                            ; Filter2 >>=3;
+
+        ; xmm0= filter2 xmm1 = vp8_filter,  xmm3 =qs0 xmm5=s xmm4 =hev xmm6=ps0
+        psubsb      xmm3,               xmm0                            ; qs0 =qs0 - filter1
+        paddsb      xmm6,               xmm5                            ; ps0 =ps0 + Fitler2
+
+
+        ; xmm1=vp8_filter, xmm3=qs0, xmm4 =hev xmm6=ps0
+        ; vp8_filter &= ~hev;
+        ; Filter2 = vp8_filter;
+        pandn       xmm4,                   xmm1                        ; vp8_filter&=~hev
+
+        ; xmm3=qs0, xmm4=filter2, xmm6=ps0
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7);
+        ; s = vp8_signed_char_clamp(qs0 - u);
+        ; *oq0 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps0 + u);
+        ; *op0 = s^0x80;
+        pxor        xmm0,                   xmm0
+        pxor        xmm1,                   xmm1
+
+        pxor        xmm2,                   xmm2
+        punpcklbw   xmm1,                   xmm4
+
+        punpckhbw   xmm2,                   xmm4
+        pmulhw      xmm1,                   [s27 GLOBAL]
+
+        pmulhw      xmm2,                   [s27 GLOBAL]
+        paddw       xmm1,                   [s63 GLOBAL]
+
+        paddw       xmm2,                   [s63 GLOBAL]
+        psraw       xmm1,                   7
+
+        psraw       xmm2,                   7
+        packsswb    xmm1,                   xmm2
+
+        psubsb      xmm3,                   xmm1
+        paddsb      xmm6,                   xmm1
+
+        pxor        xmm3,                   [t80 GLOBAL]
+        pxor        xmm6,                   [t80 GLOBAL]
+
+        movdqa      [rdx+48],               xmm6
+        movdqa      [rdx+64],               xmm3
+
+        ; roughly 2/7th difference across boundary
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 18)>>7);
+        ; s = vp8_signed_char_clamp(qs1 - u);
+        ; *oq1 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps1 + u);
+        ; *op1 = s^0x80;
+        pxor        xmm1,                       xmm1
+        pxor        xmm2,                       xmm2
+
+        punpcklbw   xmm1,                       xmm4
+        punpckhbw   xmm2,                       xmm4
+
+        pmulhw      xmm1,                       [s18 GLOBAL]
+        pmulhw      xmm2,                       [s18 GLOBAL]
+
+        paddw       xmm1,                       [s63 GLOBAL]
+        paddw       xmm2,                       [s63 GLOBAL]
+
+        psraw       xmm1,                       7
+        psraw       xmm2,                       7
+
+        packsswb    xmm1,                       xmm2
+
+        movdqa      xmm3,                       [rdx + 80]              ;/q1
+        movdqa      xmm6,                       [rdx + 32]              ; p1
+
+        pxor        xmm3,                       [t80 GLOBAL]
+        pxor        xmm6,                       [t80 GLOBAL]
+
+        paddsb      xmm6,                       xmm1
+        psubsb      xmm3,                       xmm1
+
+        pxor        xmm6,                       [t80 GLOBAL]
+        pxor        xmm3,                       [t80 GLOBAL]
+
+        movdqa      [rdx + 80],                 xmm3
+        movdqa      [rdx + 32],                 xmm6
+
+
+        ; roughly 1/7th difference across boundary
+        ; u = vp8_signed_char_clamp((63 + Filter2 * 9)>>7);
+        ; s = vp8_signed_char_clamp(qs2 - u);
+        ; *oq2 = s^0x80;
+        ; s = vp8_signed_char_clamp(ps2 + u);
+        ; *op2 = s^0x80;
+        pxor        xmm1,                       xmm1
+        pxor        xmm2,                       xmm2
+
+        punpcklbw   xmm1,                       xmm4
+        punpckhbw   xmm2,                       xmm4
+
+        pmulhw      xmm1,                       [s9 GLOBAL]
+        pmulhw      xmm2,                       [s9 GLOBAL]
+
+        paddw       xmm1,                       [s63 GLOBAL]
+        paddw       xmm2,                       [s63 GLOBAL]
+
+        psraw       xmm1,                       7
+        psraw       xmm2,                       7
+
+        packsswb    xmm1,                       xmm2
+
+        movdqa      xmm6,                       [rdx+16]
+        movdqa      xmm3,                       [rdx+96]
+
+        pxor        xmm6,                       [t80 GLOBAL]
+        pxor        xmm3,                       [t80 GLOBAL]
+
+        paddsb      xmm6,                       xmm1
+        psubsb      xmm3,                       xmm1
+
+        pxor        xmm6,                       [t80 GLOBAL]        ; xmm6 = f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
+        pxor        xmm3,                       [t80 GLOBAL]        ; xmm3 = f6 e6 d6 c6 b6 a6 96 86 76 66 56 46 36 26 15 06
+
+
+        ; transpose and write back
+        movdqa      xmm0,                       [rdx]               ; f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+        movdqa      xmm1,                       xmm0                ; f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+
+        punpcklbw   xmm0,                       xmm6                ; 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00
+        punpckhbw   xmm1,                       xmm6                ; f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80
+
+        movdqa      xmm2,                       [rdx+32]            ; f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+        movdqa      xmm6,                       xmm2                ; f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+
+        punpcklbw   xmm2,                       [rdx+48]            ; 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
+        punpckhbw   xmm6,                       [rdx+48]            ; f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
+
+        movdqa      xmm5,                       xmm0                ; 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00
+        punpcklwd   xmm0,                       xmm2                ; 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00
+
+        punpckhwd   xmm5,                       xmm2                ; 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40
+        movdqa      xmm4,                       xmm1                ; f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80
+
+        punpcklwd   xmm1,                       xmm6                ; b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80
+        punpckhwd   xmm4,                       xmm6                ; f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0
+
+        movdqa      xmm2,                       [rdx+64]            ; f4 e4 d4 c4 b4 a4 94 84 74 64 54 44 34 24 14 04
+        punpcklbw   xmm2,                       [rdx+80]            ; 75 74 65 64 55 54 45 44 35 34 25 24 15 14 05 04
+
+        movdqa      xmm6,                       xmm3                ; f6 e6 d6 c6 b6 a6 96 86 76 66 56 46 36 26 16 06
+        punpcklbw   xmm6,                       [rdx+112]           ; 77 76 67 66 57 56 47 46 37 36 27 26 17 16 07 06
+
+        movdqa      xmm7,                       xmm2                ; 75 74 65 64 55 54 45 44 35 34 25 24 15 14 05 04
+        punpcklwd   xmm2,                       xmm6                ; 37 36 35 34 27 26 25 24 17 16 15 14 07 06 05 04
+
+        punpckhwd   xmm7,                       xmm6                ; 77 76 75 74 67 66 65 64 57 56 55 54 47 46 45 44
+        movdqa      xmm6,                       xmm0                ; 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00
+
+        punpckldq   xmm0,                       xmm2                ; 17 16 15 14 13 12 11 10 07 06 05 04 03 02 01 00
+        punpckhdq   xmm6,                       xmm2                ; 37 36 35 34 33 32 31 30 27 26 25 24 23 22 21 20
+
+        lea         rsi,                        [rsi+rcx*8]
+        lea         rdi,                        [rdi+rcx*8]
+
+        movq        QWORD PTR [rsi+rcx*4],      xmm0
+        psrldq      xmm0,                       8
+
+        movq        QWORD PTR [rsi+rcx*2],      xmm6
+        psrldq      xmm6,                       8
+
+        movq        QWORD PTR [rdi+rcx*4],      xmm0
+        movq        QWORD PTR [rsi+rcx],        xmm6
+
+        movdqa      xmm0,                       xmm5                ; 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40
+        punpckldq   xmm0,                       xmm7                ; 57 56 55 54 53 52 51 50 47 46 45 44 43 42 41 40
+
+        punpckhdq   xmm5,                       xmm7                ; 77 76 75 74 73 72 71 70 67 66 65 64 63 62 61 60
+
+        movq        QWORD PTR [rsi],            xmm0
+        psrldq      xmm0,                       8
+
+        movq        QWORD PTR [rsi+rax*2],      xmm5
+        psrldq      xmm5,                       8
+
+        movq        QWORD PTR [rsi+rax],        xmm0
+        movq        QWORD PTR [rdi+rax*2],      xmm5
+
+        movdqa      xmm2,                       [rdx+64]            ; f4 e4 d4 c4 b4 a4 94 84 74 64 54 44 34 24 14 04
+        punpckhbw   xmm2,                       [rdx+80]            ; f5 f4 e5 e4 d5 d4 c5 c4 b5 b4 a5 a4 95 94 85 84
+
+        punpckhbw   xmm3,                       [rdx+112]           ; f7 f6 e7 e6 d7 d6 c7 c6 b7 b6 a7 a6 97 96 87 86
+        movdqa      xmm0,                       xmm2
+
+        punpcklwd   xmm0,                       xmm3                ; b7 b6 b4 b4 a7 a6 a5 a4 97 96 95 94 87 86 85 84
+        punpckhwd   xmm2,                       xmm3                ; f7 f6 f5 f4 e7 e6 e5 e4 d7 d6 d5 d4 c7 c6 c5 c4
+
+        movdqa      xmm3,                       xmm1                ; b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80
+        punpckldq   xmm1,                       xmm0                ; 97 96 95 94 93 92 91 90 87 86 85 83 84 82 81 80
+
+        punpckhdq   xmm3,                       xmm0                ; b7 b6 b5 b4 b3 b2 b1 b0 a7 a6 a5 a4 a3 a2 a1 a0
+
+        lea         rsi,                        [rsi+rax*8]
+        lea         rdi,                        [rdi+rax*8]
+
+        movq        QWORD PTR [rsi+rcx*4],      xmm1
+        psrldq      xmm1,                       8
+
+        movq        QWORD PTR [rsi+rcx*2],      xmm3
+        psrldq      xmm3,                       8
+
+        movq        QWORD PTR [rdi+rcx*4],      xmm1
+        movq        QWORD PTR [rsi+rcx],        xmm3
+
+        movdqa      xmm1,                       xmm4                ; f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0
+        punpckldq   xmm1,                       xmm2                ; d7 d6 d5 d4 d3 d2 d1 d0 c7 c6 c5 c4 c3 c2 c1 c0
+
+        punpckhdq   xmm4,                       xmm2                ; f7 f6 f4 f4 f3 f2 f1 f0 e7 e6 e5 e4 e3 e2 e1 e0
+        movq        QWORD PTR [rsi],            xmm1
+
+        psrldq      xmm1,                       8
+
+        movq        QWORD PTR [rsi+rax*2],      xmm4
+        psrldq      xmm4,                       8
+
+        movq        QWORD PTR [rsi+rax],        xmm1
+        movq        QWORD PTR [rdi+rax*2],      xmm4
+
+    add rsp, 160
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_loop_filter_simple_horizontal_edge_sse2
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *flimit,
+;    const char *limit,
+;    const char *thresh,
+;    int count
+;)
+global sym(vp8_loop_filter_simple_horizontal_edge_sse2)
+sym(vp8_loop_filter_simple_horizontal_edge_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi, arg(0)             ;src_ptr
+        movsxd      rax, dword ptr arg(1)   ;src_pixel_step     ; destination pitch?
+        mov         rdx, arg(2) ;flimit     ; get flimit
+        movdqa      xmm3, XMMWORD PTR [rdx]
+        mov         rdx, arg(3) ;limit
+        movdqa      xmm7, XMMWORD PTR [rdx]
+
+        paddb       xmm3, xmm3              ; flimit*2 (less than 255)
+        paddb       xmm3, xmm7              ; flimit * 2 + limit (less than 255)
+
+        mov         rdi, rsi                ; rdi points to row +1 for indirect addressing
+        add         rdi, rax
+        neg         rax
+
+        ; calculate mask
+        movdqu      xmm1, [rsi+2*rax]       ; p1
+        movdqu      xmm0, [rdi]             ; q1
+        movdqa      xmm2, xmm1
+        movdqa      xmm7, xmm0
+        movdqa      xmm4, xmm0
+        psubusb     xmm0, xmm1              ; q1-=p1
+        psubusb     xmm1, xmm4              ; p1-=q1
+        por         xmm1, xmm0              ; abs(p1-q1)
+        pand        xmm1, [tfe GLOBAL]      ; set lsb of each byte to zero
+        psrlw       xmm1, 1                 ; abs(p1-q1)/2
+
+        movdqu      xmm5, [rsi+rax]         ; p0
+        movdqu      xmm4, [rsi]             ; q0
+        movdqa      xmm0, xmm4              ; q0
+        movdqa      xmm6, xmm5              ; p0
+        psubusb     xmm5, xmm4              ; p0-=q0
+        psubusb     xmm4, xmm6              ; q0-=p0
+        por         xmm5, xmm4              ; abs(p0 - q0)
+        paddusb     xmm5, xmm5              ; abs(p0-q0)*2
+        paddusb     xmm5, xmm1              ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        psubusb     xmm5, xmm3              ; abs(p0 - q0) *2 + abs(p1-q1)/2  > flimit * 2 + limit
+        pxor        xmm3, xmm3
+        pcmpeqb     xmm5, xmm3
+
+        ; start work on filters
+        pxor        xmm2, [t80 GLOBAL]      ; p1 offset to convert to signed values
+        pxor        xmm7, [t80 GLOBAL]      ; q1 offset to convert to signed values
+        psubsb      xmm2, xmm7              ; p1 - q1
+
+        pxor        xmm6, [t80 GLOBAL]      ; offset to convert to signed values
+        pxor        xmm0, [t80 GLOBAL]      ; offset to convert to signed values
+        movdqa      xmm3, xmm0              ; q0
+        psubsb      xmm0, xmm6              ; q0 - p0
+        paddsb      xmm2, xmm0              ; p1 - q1 + 1 * (q0 - p0)
+        paddsb      xmm2, xmm0              ; p1 - q1 + 2 * (q0 - p0)
+        paddsb      xmm2, xmm0              ; p1 - q1 + 3 * (q0 - p0)
+        pand        xmm5, xmm2              ; mask filter values we don't care about
+
+        ; do + 4 side
+        paddsb      xmm5, [t4 GLOBAL]       ; 3* (q0 - p0) + (p1 - q1) + 4
+
+        movdqa      xmm0, xmm5              ; get a copy of filters
+        psllw       xmm0, 8                 ; shift left 8
+        psraw       xmm0, 3                 ; arithmetic shift right 11
+        psrlw       xmm0, 8
+        movdqa      xmm1, xmm5              ; get a copy of filters
+        psraw       xmm1, 11                ; arithmetic shift right 11
+        psllw       xmm1, 8                 ; shift left 8 to put it back
+
+        por         xmm0, xmm1              ; put the two together to get result
+
+        psubsb      xmm3, xmm0              ; q0-= q0 add
+        pxor        xmm3, [t80 GLOBAL]      ; unoffset
+        movdqu      [rsi], xmm3             ; write back
+
+        ; now do +3 side
+        psubsb      xmm5, [t1s GLOBAL]      ; +3 instead of +4
+
+        movdqa      xmm0, xmm5              ; get a copy of filters
+        psllw       xmm0, 8                 ; shift left 8
+        psraw       xmm0, 3                 ; arithmetic shift right 11
+        psrlw       xmm0, 8
+        psraw       xmm5, 11                ; arithmetic shift right 11
+        psllw       xmm5, 8                 ; shift left 8 to put it back
+        por         xmm0, xmm5              ; put the two together to get result
+
+
+        paddsb      xmm6, xmm0              ; p0+= p0 add
+        pxor        xmm6, [t80 GLOBAL]      ; unoffset
+        movdqu      [rsi+rax], xmm6         ; write back
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_loop_filter_simple_vertical_edge_sse2
+;(
+;    unsigned char *src_ptr,
+;    int  src_pixel_step,
+;    const char *flimit,
+;    const char *limit,
+;    const char *thresh,
+;    int count
+;)
+global sym(vp8_loop_filter_simple_vertical_edge_sse2)
+sym(vp8_loop_filter_simple_vertical_edge_sse2):
+    push        rbp         ; save old base pointer value.
+    mov         rbp, rsp    ; set new base pointer value.
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx         ; save callee-saved reg
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 32                         ; reserve 32 bytes
+    %define t0  [rsp + 0]    ;__declspec(align(16)) char t0[16];
+    %define t1  [rsp + 16]   ;__declspec(align(16)) char t1[16];
+
+        mov         rsi, arg(0) ;src_ptr
+        movsxd      rax, dword ptr arg(1) ;src_pixel_step     ; destination pitch?
+
+        lea         rsi,        [rsi - 2 ]
+        lea         rdi,        [rsi + rax]
+        lea         rdx,        [rsi + rax*4]
+        lea         rcx,        [rdx + rax]
+
+        movdqu      xmm0,       [rsi]                   ; (high 96 bits unused) 03 02 01 00
+        movdqu      xmm1,       [rdx]                   ; (high 96 bits unused) 43 42 41 40
+        movdqu      xmm2,       [rdi]                   ; 13 12 11 10
+        movdqu      xmm3,       [rcx]                   ; 53 52 51 50
+        punpckldq   xmm0,       xmm1                    ; (high 64 bits unused) 43 42 41 40 03 02 01 00
+        punpckldq   xmm2,       xmm3                    ; 53 52 51 50 13 12 11 10
+
+        movdqu      xmm4,       [rsi + rax*2]           ; 23 22 21 20
+        movdqu      xmm5,       [rdx + rax*2]           ; 63 62 61 60
+        movdqu      xmm6,       [rdi + rax*2]           ; 33 32 31 30
+        movdqu      xmm7,       [rcx + rax*2]           ; 73 72 71 70
+        punpckldq   xmm4,       xmm5                    ; 63 62 61 60 23 22 21 20
+        punpckldq   xmm6,       xmm7                    ; 73 72 71 70 33 32 31 30
+
+        punpcklbw   xmm0,       xmm2                    ; 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00
+        punpcklbw   xmm4,       xmm6                    ; 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20
+
+        movdqa      xmm1,       xmm0
+        punpcklwd   xmm0,       xmm4                    ; 33 23 13 03 32 22 12 02 31 21 11 01 30 20 10 00
+        punpckhwd   xmm1,       xmm4                    ; 73 63 53 43 72 62 52 42 71 61 51 41 70 60 50 40
+
+        movdqa      xmm2,       xmm0
+        punpckldq   xmm0,       xmm1                    ; 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
+        punpckhdq   xmm2,       xmm1                    ; 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
+
+        movdqa      t0,         xmm0                    ; save to t0
+        movdqa      t1,         xmm2                    ; save to t1
+
+        lea         rsi,        [rsi + rax*8]
+        lea         rdi,        [rsi + rax]
+        lea         rdx,        [rsi + rax*4]
+        lea         rcx,        [rdx + rax]
+
+        movdqu      xmm4,       [rsi]                   ; 83 82 81 80
+        movdqu      xmm1,       [rdx]                   ; c3 c2 c1 c0
+        movdqu      xmm6,       [rdi]                   ; 93 92 91 90
+        movdqu      xmm3,       [rcx]                   ; d3 d2 d1 d0
+        punpckldq   xmm4,       xmm1                    ; c3 c2 c1 c0 83 82 81 80
+        punpckldq   xmm6,       xmm3                    ; d3 d2 d1 d0 93 92 91 90
+
+        movdqu      xmm0,       [rsi + rax*2]           ; a3 a2 a1 a0
+        movdqu      xmm5,       [rdx + rax*2]           ; e3 e2 e1 e0
+        movdqu      xmm2,       [rdi + rax*2]           ; b3 b2 b1 b0
+        movdqu      xmm7,       [rcx + rax*2]           ; f3 f2 f1 f0
+        punpckldq   xmm0,       xmm5                    ; e3 e2 e1 e0 a3 a2 a1 a0
+        punpckldq   xmm2,       xmm7                    ; f3 f2 f1 f0 b3 b2 b1 b0
+
+        punpcklbw   xmm4,       xmm6                    ; d3 c3 d2 c2 d1 c1 d0 c0 93 83 92 82 91 81 90 80
+        punpcklbw   xmm0,       xmm2                    ; f3 e3 f2 e2 f1 e1 f0 e0 b3 a3 b2 a2 b1 a1 b0 a0
+
+        movdqa      xmm1,       xmm4
+        punpcklwd   xmm4,       xmm0                    ; b3 a3 93 83 b2 a2 92 82 b1 a1 91 81 b0 a0 90 80
+        punpckhwd   xmm1,       xmm0                    ; f3 e3 d3 c3 f2 e2 d2 c2 f1 e1 d1 c1 f0 e0 d0 c0
+
+        movdqa      xmm6,       xmm4
+        punpckldq   xmm4,       xmm1                    ; f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80
+        punpckhdq   xmm6,       xmm1                    ; f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82
+
+        movdqa      xmm0,       t0                      ; 71 61 51 41 31 21 11 01 70 60 50 40 30 20 10 00
+        movdqa      xmm2,       t1                      ; 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02
+        movdqa      xmm1,       xmm0
+        movdqa      xmm3,       xmm2
+
+        punpcklqdq  xmm0,       xmm4                    ; p1  f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+        punpckhqdq  xmm1,       xmm4                    ; p0  f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
+        punpcklqdq  xmm2,       xmm6                    ; q0  f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+        punpckhqdq  xmm3,       xmm6                    ; q1  f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
+
+        ; calculate mask
+        movdqa      xmm6,       xmm0                            ; p1
+        movdqa      xmm7,       xmm3                            ; q1
+        psubusb     xmm7,       xmm0                            ; q1-=p1
+        psubusb     xmm6,       xmm3                            ; p1-=q1
+        por         xmm6,       xmm7                            ; abs(p1-q1)
+        pand        xmm6,       [tfe GLOBAL]                    ; set lsb of each byte to zero
+        psrlw       xmm6,       1                               ; abs(p1-q1)/2
+
+        movdqa      xmm5,       xmm1                            ; p0
+        movdqa      xmm4,       xmm2                            ; q0
+        psubusb     xmm5,       xmm2                            ; p0-=q0
+        psubusb     xmm4,       xmm1                            ; q0-=p0
+        por         xmm5,       xmm4                            ; abs(p0 - q0)
+        paddusb     xmm5,       xmm5                            ; abs(p0-q0)*2
+        paddusb     xmm5,       xmm6                            ; abs (p0 - q0) *2 + abs(p1-q1)/2
+
+        mov         rdx,        arg(2)                          ;flimit
+        movdqa      xmm7, XMMWORD PTR [rdx]
+        mov         rdx,        arg(3)                          ; get limit
+        movdqa      xmm6, XMMWORD PTR [rdx]
+        paddb       xmm7,        xmm7                           ; flimit*2 (less than 255)
+        paddb       xmm7,        xmm6                           ; flimit * 2 + limit (less than 255)
+
+        psubusb     xmm5,        xmm7                           ; abs(p0 - q0) *2 + abs(p1-q1)/2  > flimit * 2 + limit
+        pxor        xmm7,        xmm7
+        pcmpeqb     xmm5,        xmm7                           ; mm5 = mask
+
+        ; start work on filters
+        movdqa        t0,        xmm0
+        movdqa        t1,        xmm3
+
+        pxor        xmm0,        [t80 GLOBAL]                   ; p1 offset to convert to signed values
+        pxor        xmm3,        [t80 GLOBAL]                   ; q1 offset to convert to signed values
+
+        psubsb      xmm0,        xmm3                           ; p1 - q1
+        movdqa      xmm6,        xmm1                           ; p0
+
+        movdqa      xmm7,        xmm2                           ; q0
+        pxor        xmm6,        [t80 GLOBAL]                   ; offset to convert to signed values
+
+        pxor        xmm7,        [t80 GLOBAL]                   ; offset to convert to signed values
+        movdqa      xmm3,        xmm7                           ; offseted ; q0
+
+        psubsb      xmm7,        xmm6                           ; q0 - p0
+        paddsb      xmm0,        xmm7                           ; p1 - q1 + 1 * (q0 - p0)
+
+        paddsb      xmm0,        xmm7                           ; p1 - q1 + 2 * (q0 - p0)
+        paddsb      xmm0,        xmm7                           ; p1 - q1 + 3 * (q0 - p0)
+
+        pand        xmm5,        xmm0                           ; mask filter values we don't care about
+
+
+        paddsb      xmm5,        [t4 GLOBAL]                    ;  3* (q0 - p0) + (p1 - q1) + 4
+
+        movdqa      xmm0,        xmm5                           ; get a copy of filters
+        psllw       xmm0,        8                              ; shift left 8
+
+        psraw       xmm0,        3                              ; arithmetic shift right 11
+        psrlw       xmm0,        8
+
+        movdqa      xmm7,        xmm5                           ; get a copy of filters
+        psraw       xmm7,        11                             ; arithmetic shift right 11
+
+        psllw       xmm7,        8                              ; shift left 8 to put it back
+        por         xmm0,        xmm7                           ; put the two together to get result
+
+        psubsb      xmm3,        xmm0                           ; q0-= q0sz add
+        pxor        xmm3,        [t80 GLOBAL]                   ; unoffset   q0
+
+        ; now do +3 side
+        psubsb      xmm5,        [t1s GLOBAL]                   ; +3 instead of +4
+        movdqa      xmm0,        xmm5                           ; get a copy of filters
+
+        psllw       xmm0,        8                              ; shift left 8
+        psraw       xmm0,        3                              ; arithmetic shift right 11
+
+        psrlw       xmm0,        8
+        psraw       xmm5,        11                             ; arithmetic shift right 11
+
+        psllw       xmm5,        8                              ; shift left 8 to put it back
+        por         xmm0,        xmm5                           ; put the two together to get result
+
+        paddsb      xmm6,        xmm0                           ; p0+= p0 add
+        pxor        xmm6,        [t80 GLOBAL]                   ; unoffset   p0
+
+        movdqa      xmm0,        t0                             ; p1
+        movdqa      xmm4,        t1                             ; q1
+
+        ; transpose back to write out
+        ; p1  f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00
+        ; p0  f1 e1 d1 c1 b1 a1 91 81 71 61 51 41 31 21 11 01
+        ; q0  f2 e2 d2 c2 b2 a2 92 82 72 62 52 42 32 22 12 02
+        ; q1  f3 e3 d3 c3 b3 a3 93 83 73 63 53 43 33 23 13 03
+        movdqa      xmm1,       xmm0
+        punpcklbw   xmm0,       xmm6                               ; 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00
+        punpckhbw   xmm1,       xmm6                               ; f1 f0 e1 e0 d1 d0 c1 c0 b1 b0 a1 a0 91 90 81 80
+
+        movdqa      xmm5,       xmm3
+        punpcklbw   xmm3,       xmm4                               ; 73 72 63 62 53 52 43 42 33 32 23 22 13 12 03 02
+        punpckhbw   xmm5,       xmm4                               ; f3 f2 e3 e2 d3 d2 c3 c2 b3 b2 a3 a2 93 92 83 82
+
+        movdqa      xmm2,       xmm0
+        punpcklwd   xmm0,       xmm3                               ; 33 32 31 30 23 22 21 20 13 12 11 10 03 02 01 00
+        punpckhwd   xmm2,       xmm3                               ; 73 72 71 70 63 62 61 60 53 52 51 50 43 42 41 40
+
+        movdqa      xmm3,       xmm1
+        punpcklwd   xmm1,       xmm5                               ; b3 b2 b1 b0 a3 a2 a1 a0 93 92 91 90 83 82 81 80
+        punpckhwd   xmm3,       xmm5                               ; f3 f2 f1 f0 e3 e2 e1 e0 d3 d2 d1 d0 c3 c2 c1 c0
+
+        ; write out order: xmm0 xmm2 xmm1 xmm3
+        lea         rdx,        [rsi + rax*4]
+
+        movd        [rsi],      xmm1                               ; write the second 8-line result
+        psrldq      xmm1,       4
+        movd        [rdi],      xmm1
+        psrldq      xmm1,       4
+        movd        [rsi + rax*2], xmm1
+        psrldq      xmm1,       4
+        movd        [rdi + rax*2], xmm1
+
+        movd        [rdx],      xmm3
+        psrldq      xmm3,       4
+        movd        [rcx],      xmm3
+        psrldq      xmm3,       4
+        movd        [rdx + rax*2], xmm3
+        psrldq      xmm3,       4
+        movd        [rcx + rax*2], xmm3
+
+        neg         rax
+        lea         rsi,        [rsi + rax*8]
+        neg         rax
+        lea         rdi,        [rsi + rax]
+        lea         rdx,        [rsi + rax*4]
+        lea         rcx,        [rdx + rax]
+
+        movd        [rsi],      xmm0                                ; write the first 8-line result
+        psrldq      xmm0,       4
+        movd        [rdi],      xmm0
+        psrldq      xmm0,       4
+        movd        [rsi + rax*2], xmm0
+        psrldq      xmm0,       4
+        movd        [rdi + rax*2], xmm0
+
+        movd        [rdx],      xmm2
+        psrldq      xmm2,       4
+        movd        [rcx],      xmm2
+        psrldq      xmm2,       4
+        movd        [rdx + rax*2], xmm2
+        psrldq      xmm2,       4
+        movd        [rcx + rax*2], xmm2
+
+    add rsp, 32
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+SECTION_RODATA
+align 16
+tfe:
+    times 16 db 0xfe
+align 16
+t80:
+    times 16 db 0x80
+align 16
+t1s:
+    times 16 db 0x01
+align 16
+t3:
+    times 16 db 0x03
+align 16
+t4:
+    times 16 db 0x04
+align 16
+ones:
+    times 8 dw 0x0001
+align 16
+s27:
+    times 8 dw 0x1b00
+align 16
+s18:
+    times 8 dw 0x1200
+align 16
+s9:
+    times 8 dw 0x0900
+align 16
+s63:
+    times 8 dw 0x003f
diff --git a/vp8/common/x86/loopfilter_x86.c b/vp8/common/x86/loopfilter_x86.c
new file mode 100644
index 0000000..143ee74
--- /dev/null
+++ b/vp8/common/x86/loopfilter_x86.c
@@ -0,0 +1,274 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "loopfilter.h"
+
+prototype_loopfilter(vp8_loop_filter_horizontal_edge_c);
+prototype_loopfilter(vp8_loop_filter_vertical_edge_c);
+prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_c);
+prototype_loopfilter(vp8_mbloop_filter_vertical_edge_c);
+prototype_loopfilter(vp8_loop_filter_simple_horizontal_edge_c);
+prototype_loopfilter(vp8_loop_filter_simple_vertical_edge_c);
+
+prototype_loopfilter(vp8_mbloop_filter_vertical_edge_mmx);
+prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_mmx);
+prototype_loopfilter(vp8_loop_filter_vertical_edge_mmx);
+prototype_loopfilter(vp8_loop_filter_horizontal_edge_mmx);
+prototype_loopfilter(vp8_loop_filter_simple_vertical_edge_mmx);
+prototype_loopfilter(vp8_loop_filter_simple_horizontal_edge_mmx);
+
+prototype_loopfilter(vp8_loop_filter_vertical_edge_sse2);
+prototype_loopfilter(vp8_loop_filter_horizontal_edge_sse2);
+prototype_loopfilter(vp8_mbloop_filter_vertical_edge_sse2);
+prototype_loopfilter(vp8_mbloop_filter_horizontal_edge_sse2);
+prototype_loopfilter(vp8_loop_filter_simple_vertical_edge_sse2);
+prototype_loopfilter(vp8_loop_filter_simple_horizontal_edge_sse2);
+prototype_loopfilter(vp8_fast_loop_filter_vertical_edges_sse2);
+
+#if HAVE_MMX
+// Horizontal MB filtering
+void vp8_loop_filter_mbh_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_mbloop_filter_horizontal_edge_mmx(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_horizontal_edge_mmx(u_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_horizontal_edge_mmx(v_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+}
+
+
+void vp8_loop_filter_mbhs_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_horizontal_edge_mmx(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+}
+
+
+// Vertical MB Filtering
+void vp8_loop_filter_mbv_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_mbloop_filter_vertical_edge_mmx(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_vertical_edge_mmx(u_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_vertical_edge_mmx(v_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+}
+
+
+void vp8_loop_filter_mbvs_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+}
+
+
+// Horizontal B Filtering
+void vp8_loop_filter_bh_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                            int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_loop_filter_horizontal_edge_mmx(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_horizontal_edge_mmx(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_horizontal_edge_mmx(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_horizontal_edge_mmx(u_ptr + 4 * uv_stride, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_horizontal_edge_mmx(v_ptr + 4 * uv_stride, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+}
+
+
+void vp8_loop_filter_bhs_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_horizontal_edge_mmx(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_horizontal_edge_mmx(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_horizontal_edge_mmx(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+}
+
+
+// Vertical B Filtering
+void vp8_loop_filter_bv_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                            int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_loop_filter_vertical_edge_mmx(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_vertical_edge_mmx(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_vertical_edge_mmx(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_vertical_edge_mmx(u_ptr + 4, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_vertical_edge_mmx(v_ptr + 4, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+}
+
+
+void vp8_loop_filter_bvs_mmx(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_vertical_edge_mmx(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+}
+#endif
+
+
+// Horizontal MB filtering
+#if HAVE_SSE2
+void vp8_loop_filter_mbh_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_mbloop_filter_horizontal_edge_sse2(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_horizontal_edge_mmx(u_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_horizontal_edge_mmx(v_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+}
+
+
+void vp8_loop_filter_mbhs_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                               int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_horizontal_edge_sse2(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+}
+
+
+// Vertical MB Filtering
+void vp8_loop_filter_mbv_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_mbloop_filter_vertical_edge_sse2(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+
+    if (u_ptr)
+        vp8_mbloop_filter_vertical_edge_mmx(u_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+
+    if (v_ptr)
+        vp8_mbloop_filter_vertical_edge_mmx(v_ptr, uv_stride, lfi->uvmbflim, lfi->uvlim, lfi->uvmbthr, 1);
+}
+
+
+void vp8_loop_filter_mbvs_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                               int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr, y_stride, lfi->mbflim, lfi->lim, lfi->mbthr, 2);
+}
+
+
+// Horizontal B Filtering
+void vp8_loop_filter_bh_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_loop_filter_horizontal_edge_sse2(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_horizontal_edge_sse2(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_horizontal_edge_sse2(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_horizontal_edge_mmx(u_ptr + 4 * uv_stride, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_horizontal_edge_mmx(v_ptr + 4 * uv_stride, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+}
+
+
+void vp8_loop_filter_bhs_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_horizontal_edge_sse2(y_ptr + 4 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_horizontal_edge_sse2(y_ptr + 8 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_horizontal_edge_sse2(y_ptr + 12 * y_stride, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+}
+
+
+// Vertical B Filtering
+void vp8_loop_filter_bv_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                             int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) simpler_lpf;
+    vp8_loop_filter_vertical_edge_sse2(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_vertical_edge_sse2(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_vertical_edge_sse2(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+
+    if (u_ptr)
+        vp8_loop_filter_vertical_edge_mmx(u_ptr + 4, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+
+    if (v_ptr)
+        vp8_loop_filter_vertical_edge_mmx(v_ptr + 4, uv_stride, lfi->uvflim, lfi->uvlim, lfi->uvthr, 1);
+}
+
+
+void vp8_loop_filter_bvs_sse2(unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr,
+                              int y_stride, int uv_stride, loop_filter_info *lfi, int simpler_lpf)
+{
+    (void) u_ptr;
+    (void) v_ptr;
+    (void) uv_stride;
+    (void) simpler_lpf;
+    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+}
+
+#endif
+
+#if 0
+void vp8_fast_loop_filter_vertical_edges_sse(unsigned char *y_ptr,
+        int y_stride,
+        loop_filter_info *lfi)
+{
+
+    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr + 4, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr + 8, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+    vp8_loop_filter_simple_vertical_edge_sse2(y_ptr + 12, y_stride, lfi->flim, lfi->lim, lfi->thr, 2);
+}
+#endif
diff --git a/vp8/common/x86/loopfilter_x86.h b/vp8/common/x86/loopfilter_x86.h
new file mode 100644
index 0000000..c87f38a
--- /dev/null
+++ b/vp8/common/x86/loopfilter_x86.h
@@ -0,0 +1,99 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef LOOPFILTER_X86_H
+#define LOOPFILTER_X86_H
+
+/* Note:
+ *
+ * This platform is commonly built for runtime CPU detection. If you modify
+ * any of the function mappings present in this file, be sure to also update
+ * them in the function pointer initialization code
+ */
+
+#if HAVE_MMX
+extern prototype_loopfilter_block(vp8_loop_filter_mbv_mmx);
+extern prototype_loopfilter_block(vp8_loop_filter_bv_mmx);
+extern prototype_loopfilter_block(vp8_loop_filter_mbh_mmx);
+extern prototype_loopfilter_block(vp8_loop_filter_bh_mmx);
+extern prototype_loopfilter_block(vp8_loop_filter_mbvs_mmx);
+extern prototype_loopfilter_block(vp8_loop_filter_bvs_mmx);
+extern prototype_loopfilter_block(vp8_loop_filter_mbhs_mmx);
+extern prototype_loopfilter_block(vp8_loop_filter_bhs_mmx);
+
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_lf_normal_mb_v
+#define vp8_lf_normal_mb_v vp8_loop_filter_mbv_mmx
+
+#undef  vp8_lf_normal_b_v
+#define vp8_lf_normal_b_v vp8_loop_filter_bv_mmx
+
+#undef  vp8_lf_normal_mb_h
+#define vp8_lf_normal_mb_h vp8_loop_filter_mbh_mmx
+
+#undef  vp8_lf_normal_b_h
+#define vp8_lf_normal_b_h vp8_loop_filter_bh_mmx
+
+#undef  vp8_lf_simple_mb_v
+#define vp8_lf_simple_mb_v vp8_loop_filter_mbvs_mmx
+
+#undef  vp8_lf_simple_b_v
+#define vp8_lf_simple_b_v vp8_loop_filter_bvs_mmx
+
+#undef  vp8_lf_simple_mb_h
+#define vp8_lf_simple_mb_h vp8_loop_filter_mbhs_mmx
+
+#undef  vp8_lf_simple_b_h
+#define vp8_lf_simple_b_h vp8_loop_filter_bhs_mmx
+#endif
+#endif
+
+
+#if HAVE_SSE2
+extern prototype_loopfilter_block(vp8_loop_filter_mbv_sse2);
+extern prototype_loopfilter_block(vp8_loop_filter_bv_sse2);
+extern prototype_loopfilter_block(vp8_loop_filter_mbh_sse2);
+extern prototype_loopfilter_block(vp8_loop_filter_bh_sse2);
+extern prototype_loopfilter_block(vp8_loop_filter_mbvs_sse2);
+extern prototype_loopfilter_block(vp8_loop_filter_bvs_sse2);
+extern prototype_loopfilter_block(vp8_loop_filter_mbhs_sse2);
+extern prototype_loopfilter_block(vp8_loop_filter_bhs_sse2);
+
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_lf_normal_mb_v
+#define vp8_lf_normal_mb_v vp8_loop_filter_mbv_sse2
+
+#undef  vp8_lf_normal_b_v
+#define vp8_lf_normal_b_v vp8_loop_filter_bv_sse2
+
+#undef  vp8_lf_normal_mb_h
+#define vp8_lf_normal_mb_h vp8_loop_filter_mbh_sse2
+
+#undef  vp8_lf_normal_b_h
+#define vp8_lf_normal_b_h vp8_loop_filter_bh_sse2
+
+#undef  vp8_lf_simple_mb_v
+#define vp8_lf_simple_mb_v vp8_loop_filter_mbvs_sse2
+
+#undef  vp8_lf_simple_b_v
+#define vp8_lf_simple_b_v vp8_loop_filter_bvs_sse2
+
+#undef  vp8_lf_simple_mb_h
+#define vp8_lf_simple_mb_h vp8_loop_filter_mbhs_sse2
+
+#undef  vp8_lf_simple_b_h
+#define vp8_lf_simple_b_h vp8_loop_filter_bhs_sse2
+#endif
+#endif
+
+
+#endif
diff --git a/vp8/common/x86/postproc_mmx.asm b/vp8/common/x86/postproc_mmx.asm
new file mode 100644
index 0000000..721c8d6
--- /dev/null
+++ b/vp8/common/x86/postproc_mmx.asm
@@ -0,0 +1,533 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%define VP8_FILTER_WEIGHT 128
+%define VP8_FILTER_SHIFT  7
+
+;void vp8_post_proc_down_and_across_mmx
+;(
+;    unsigned char *src_ptr,
+;    unsigned char *dst_ptr,
+;    int src_pixels_per_line,
+;    int dst_pixels_per_line,
+;    int rows,
+;    int cols,
+;    int flimit
+;)
+global sym(vp8_post_proc_down_and_across_mmx)
+sym(vp8_post_proc_down_and_across_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+%if ABI_IS_32BIT=1 && CONFIG_PIC=1
+    ; move the global rd onto the stack, since we don't have enough registers
+    ; to do PIC addressing
+    movq        mm0, [rd GLOBAL]
+    sub         rsp, 8
+    movq        [rsp], mm0
+%define RD [rsp]
+%else
+%define RD [rd GLOBAL]
+%endif
+
+        push        rbx
+        lea         rbx, [Blur GLOBAL]
+        movd        mm2, dword ptr arg(6) ;flimit
+        punpcklwd   mm2, mm2
+        punpckldq   mm2, mm2
+
+        mov         rsi,        arg(0) ;src_ptr
+        mov         rdi,        arg(1) ;dst_ptr
+
+        movsxd      rcx, DWORD PTR arg(4) ;rows
+        movsxd      rax, DWORD PTR arg(2) ;src_pixels_per_line ; destination pitch?
+        pxor        mm0, mm0              ; mm0 = 00000000
+
+nextrow:
+
+        xor         rdx,        rdx       ; clear out rdx for use as loop counter
+nextcol:
+
+        pxor        mm7, mm7              ; mm7 = 00000000
+        movq        mm6, [rbx + 32 ]      ; mm6 = kernel 2 taps
+        movq        mm3, [rsi]            ; mm4 = r0 p0..p7
+        punpcklbw   mm3, mm0              ; mm3 = p0..p3
+        movq        mm1, mm3              ; mm1 = p0..p3
+        pmullw      mm3, mm6              ; mm3 *= kernel 2 modifiers
+
+        movq        mm6, [rbx + 48]       ; mm6 = kernel 3 taps
+        movq        mm5, [rsi + rax]      ; mm4 = r1 p0..p7
+        punpcklbw   mm5, mm0              ; mm5 = r1 p0..p3
+        pmullw      mm6, mm5              ; mm6 *= p0..p3 * kernel 3 modifiers
+        paddusw     mm3, mm6              ; mm3 += mm6
+
+        ; thresholding
+        movq        mm7, mm1              ; mm7 = r0 p0..p3
+        psubusw     mm7, mm5              ; mm7 = r0 p0..p3 - r1 p0..p3
+        psubusw     mm5, mm1              ; mm5 = r1 p0..p3 - r0 p0..p3
+        paddusw     mm7, mm5              ; mm7 = abs(r0 p0..p3 - r1 p0..p3)
+        pcmpgtw     mm7, mm2
+
+        movq        mm6, [rbx + 64 ]      ; mm6 = kernel 4 modifiers
+        movq        mm5, [rsi + 2*rax]    ; mm4 = r2 p0..p7
+        punpcklbw   mm5, mm0              ; mm5 = r2 p0..p3
+        pmullw      mm6, mm5              ; mm5 *= kernel 4 modifiers
+        paddusw     mm3, mm6              ; mm3 += mm5
+
+        ; thresholding
+        movq        mm6, mm1              ; mm6 = r0 p0..p3
+        psubusw     mm6, mm5              ; mm6 = r0 p0..p3 - r2 p0..p3
+        psubusw     mm5, mm1              ; mm5 = r2 p0..p3 - r2 p0..p3
+        paddusw     mm6, mm5              ; mm6 = abs(r0 p0..p3 - r2 p0..p3)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ; accumulate thresholds
+
+
+        neg         rax
+        movq        mm6, [rbx ]           ; kernel 0 taps
+        movq        mm5, [rsi+2*rax]      ; mm4 = r-2 p0..p7
+        punpcklbw   mm5, mm0              ; mm5 = r-2 p0..p3
+        pmullw      mm6, mm5              ; mm5 *= kernel 0 modifiers
+        paddusw     mm3, mm6              ; mm3 += mm5
+
+        ; thresholding
+        movq        mm6, mm1              ; mm6 = r0 p0..p3
+        psubusw     mm6, mm5              ; mm6 = p0..p3 - r-2 p0..p3
+        psubusw     mm5, mm1              ; mm5 = r-2 p0..p3 - p0..p3
+        paddusw     mm6, mm5              ; mm6 = abs(r0 p0..p3 - r-2 p0..p3)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ; accumulate thresholds
+
+        movq        mm6, [rbx + 16]       ; kernel 1 taps
+        movq        mm4, [rsi+rax]        ; mm4 = r-1 p0..p7
+        punpcklbw   mm4, mm0              ; mm4 = r-1 p0..p3
+        pmullw      mm6, mm4              ; mm4 *= kernel 1 modifiers.
+        paddusw     mm3, mm6              ; mm3 += mm5
+
+        ; thresholding
+        movq        mm6, mm1              ; mm6 = r0 p0..p3
+        psubusw     mm6, mm4              ; mm6 = p0..p3 - r-2 p0..p3
+        psubusw     mm4, mm1              ; mm5 = r-1 p0..p3 - p0..p3
+        paddusw     mm6, mm4              ; mm6 = abs(r0 p0..p3 - r-1 p0..p3)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ; accumulate thresholds
+
+
+        paddusw     mm3, RD               ; mm3 += round value
+        psraw       mm3, VP8_FILTER_SHIFT     ; mm3 /= 128
+
+        pand        mm1, mm7              ; mm1 select vals > thresh from source
+        pandn       mm7, mm3              ; mm7 select vals < thresh from blurred result
+        paddusw     mm1, mm7              ; combination
+
+        packuswb    mm1, mm0              ; pack to bytes
+
+        movd        [rdi], mm1            ;
+        neg         rax                   ; pitch is positive
+
+
+        add         rsi, 4
+        add         rdi, 4
+        add         rdx, 4
+
+        cmp         edx, dword ptr arg(5) ;cols
+        jl          nextcol
+        ; done with the all cols, start the across filtering in place
+        sub         rsi, rdx
+        sub         rdi, rdx
+
+
+        push        rax
+        xor         rdx,    rdx
+        mov         rax,    [rdi-4];
+
+acrossnextcol:
+        pxor        mm7, mm7              ; mm7 = 00000000
+        movq        mm6, [rbx + 32 ]      ;
+        movq        mm4, [rdi+rdx]        ; mm4 = p0..p7
+        movq        mm3, mm4              ; mm3 = p0..p7
+        punpcklbw   mm3, mm0              ; mm3 = p0..p3
+        movq        mm1, mm3              ; mm1 = p0..p3
+        pmullw      mm3, mm6              ; mm3 *= kernel 2 modifiers
+
+        movq        mm6, [rbx + 48]
+        psrlq       mm4, 8                ; mm4 = p1..p7
+        movq        mm5, mm4              ; mm5 = p1..p7
+        punpcklbw   mm5, mm0              ; mm5 = p1..p4
+        pmullw      mm6, mm5              ; mm6 *= p1..p4 * kernel 3 modifiers
+        paddusw     mm3, mm6              ; mm3 += mm6
+
+        ; thresholding
+        movq        mm7, mm1              ; mm7 = p0..p3
+        psubusw     mm7, mm5              ; mm7 = p0..p3 - p1..p4
+        psubusw     mm5, mm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     mm7, mm5              ; mm7 = abs(p0..p3 - p1..p4)
+        pcmpgtw     mm7, mm2
+
+        movq        mm6, [rbx + 64 ]
+        psrlq       mm4, 8                ; mm4 = p2..p7
+        movq        mm5, mm4              ; mm5 = p2..p7
+        punpcklbw   mm5, mm0              ; mm5 = p2..p5
+        pmullw      mm6, mm5              ; mm5 *= kernel 4 modifiers
+        paddusw     mm3, mm6              ; mm3 += mm5
+
+        ; thresholding
+        movq        mm6, mm1              ; mm6 = p0..p3
+        psubusw     mm6, mm5              ; mm6 = p0..p3 - p1..p4
+        psubusw     mm5, mm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     mm6, mm5              ; mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ; accumulate thresholds
+
+
+        movq        mm6, [rbx ]
+        movq        mm4, [rdi+rdx-2]      ; mm4 = p-2..p5
+        movq        mm5, mm4              ; mm5 = p-2..p5
+        punpcklbw   mm5, mm0              ; mm5 = p-2..p1
+        pmullw      mm6, mm5              ; mm5 *= kernel 0 modifiers
+        paddusw     mm3, mm6              ; mm3 += mm5
+
+        ; thresholding
+        movq        mm6, mm1              ; mm6 = p0..p3
+        psubusw     mm6, mm5              ; mm6 = p0..p3 - p1..p4
+        psubusw     mm5, mm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     mm6, mm5              ; mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ; accumulate thresholds
+
+        movq        mm6, [rbx + 16]
+        psrlq       mm4, 8                ; mm4 = p-1..p5
+        punpcklbw   mm4, mm0              ; mm4 = p-1..p2
+        pmullw      mm6, mm4              ; mm4 *= kernel 1 modifiers.
+        paddusw     mm3, mm6              ; mm3 += mm5
+
+        ; thresholding
+        movq        mm6, mm1              ; mm6 = p0..p3
+        psubusw     mm6, mm4              ; mm6 = p0..p3 - p1..p4
+        psubusw     mm4, mm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     mm6, mm4              ; mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ; accumulate thresholds
+
+        paddusw     mm3, RD               ; mm3 += round value
+        psraw       mm3, VP8_FILTER_SHIFT     ; mm3 /= 128
+
+        pand        mm1, mm7              ; mm1 select vals > thresh from source
+        pandn       mm7, mm3              ; mm7 select vals < thresh from blurred result
+        paddusw     mm1, mm7              ; combination
+
+        packuswb    mm1, mm0              ; pack to bytes
+        mov         DWORD PTR [rdi+rdx-4],  eax   ; store previous four bytes
+        movd        eax,    mm1
+
+        add         rdx, 4
+        cmp         edx, dword ptr arg(5) ;cols
+        jl          acrossnextcol;
+
+        mov         DWORD PTR [rdi+rdx-4],  eax
+        pop         rax
+
+        ; done with this rwo
+        add         rsi,rax               ; next line
+        movsxd      rax, dword ptr arg(3) ;dst_pixels_per_line ; destination pitch?
+        add         rdi,rax               ; next destination
+        movsxd      rax, dword ptr arg(2) ;src_pixels_per_line ; destination pitch?
+
+        dec         rcx                   ; decrement count
+        jnz         nextrow               ; next row
+        pop         rbx
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%undef RD
+
+
+;void vp8_mbpost_proc_down_mmx(unsigned char *dst,
+;                             int pitch, int rows, int cols,int flimit)
+extern sym(vp8_rv)
+global sym(vp8_mbpost_proc_down_mmx)
+sym(vp8_mbpost_proc_down_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 136
+
+    ; unsigned char d[16][8] at [rsp]
+    ; create flimit2 at [rsp+128]
+    mov         eax, dword ptr arg(4) ;flimit
+    mov         [rsp+128], eax
+    mov         [rsp+128+4], eax
+%define flimit2 [rsp+128]
+
+%if ABI_IS_32BIT=0
+    lea         r8,       [sym(vp8_rv) GLOBAL]
+%endif
+
+    ;rows +=8;
+    add         dword ptr arg(2), 8
+
+    ;for(c=0; c<cols; c+=4)
+loop_col:
+            mov         rsi,        arg(0)  ;s
+            pxor        mm0,        mm0     ;
+
+            movsxd      rax,        dword ptr arg(1) ;pitch       ;
+            neg         rax                                     ; rax = -pitch
+
+            lea         rsi,        [rsi + rax*8];              ; rdi = s[-pitch*8]
+            neg         rax
+
+
+            pxor        mm5,        mm5
+            pxor        mm6,        mm6     ;
+
+            pxor        mm7,        mm7     ;
+            mov         rdi,        rsi
+
+            mov         rcx,        15          ;
+
+loop_initvar:
+            movd        mm1,        DWORD PTR [rdi];
+            punpcklbw   mm1,        mm0     ;
+
+            paddw       mm5,        mm1     ;
+            pmullw      mm1,        mm1     ;
+
+            movq        mm2,        mm1     ;
+            punpcklwd   mm1,        mm0     ;
+
+            punpckhwd   mm2,        mm0     ;
+            paddd       mm6,        mm1     ;
+
+            paddd       mm7,        mm2     ;
+            lea         rdi,        [rdi+rax]   ;
+
+            dec         rcx
+            jne         loop_initvar
+            ;save the var and sum
+            xor         rdx,        rdx
+loop_row:
+            movd        mm1,        DWORD PTR [rsi]     ; [s-pitch*8]
+            movd        mm2,        DWORD PTR [rdi]     ; [s+pitch*7]
+
+            punpcklbw   mm1,        mm0
+            punpcklbw   mm2,        mm0
+
+            paddw       mm5,        mm2
+            psubw       mm5,        mm1
+
+            pmullw      mm2,        mm2
+            movq        mm4,        mm2
+
+            punpcklwd   mm2,        mm0
+            punpckhwd   mm4,        mm0
+
+            paddd       mm6,        mm2
+            paddd       mm7,        mm4
+
+            pmullw      mm1,        mm1
+            movq        mm2,        mm1
+
+            punpcklwd   mm1,        mm0
+            psubd       mm6,        mm1
+
+            punpckhwd   mm2,        mm0
+            psubd       mm7,        mm2
+
+
+            movq        mm3,        mm6
+            pslld       mm3,        4
+
+            psubd       mm3,        mm6
+            movq        mm1,        mm5
+
+            movq        mm4,        mm5
+            pmullw      mm1,        mm1
+
+            pmulhw      mm4,        mm4
+            movq        mm2,        mm1
+
+            punpcklwd   mm1,        mm4
+            punpckhwd   mm2,        mm4
+
+            movq        mm4,        mm7
+            pslld       mm4,        4
+
+            psubd       mm4,        mm7
+
+            psubd       mm3,        mm1
+            psubd       mm4,        mm2
+
+            psubd       mm3,        flimit2
+            psubd       mm4,        flimit2
+
+            psrad       mm3,        31
+            psrad       mm4,        31
+
+            packssdw    mm3,        mm4
+            packsswb    mm3,        mm0
+
+            movd        mm1,        DWORD PTR [rsi+rax*8]
+
+            movq        mm2,        mm1
+            punpcklbw   mm1,        mm0
+
+            paddw       mm1,        mm5
+            mov         rcx,        rdx
+
+            and         rcx,        127
+%if ABI_IS_32BIT=1 && CONFIG_PIC=1
+            push        rax
+            lea         rax,        [sym(vp8_rv) GLOBAL]
+            movq        mm4,        [rax + rcx*2] ;vp8_rv[rcx*2]
+            pop         rax
+%elif ABI_IS_32BIT=0
+            movq        mm4,        [r8 + rcx*2] ;vp8_rv[rcx*2]
+%else
+            movq        mm4,        [sym(vp8_rv) + rcx*2]
+%endif
+            paddw       mm1,        mm4
+            ;paddw     xmm1,       eight8s
+            psraw       mm1,        4
+
+            packuswb    mm1,        mm0
+            pand        mm1,        mm3
+
+            pandn       mm3,        mm2
+            por         mm1,        mm3
+
+            and         rcx,        15
+            movd        DWORD PTR   [rsp+rcx*4], mm1 ;d[rcx*4]
+
+            mov         rcx,        rdx
+            sub         rcx,        8
+
+            and         rcx,        15
+            movd        mm1,        DWORD PTR [rsp+rcx*4] ;d[rcx*4]
+
+            movd        [rsi],      mm1
+            lea         rsi,        [rsi+rax]
+
+            lea         rdi,        [rdi+rax]
+            add         rdx,        1
+
+            cmp         edx,        dword arg(2) ;rows
+            jl          loop_row
+
+
+        add         dword arg(0), 4 ; s += 4
+        sub         dword arg(3), 4 ; cols -= 4
+        cmp         dword arg(3), 0
+        jg          loop_col
+
+    add         rsp, 136
+    pop         rsp
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%undef flimit2
+
+
+;void vp8_plane_add_noise_mmx (unsigned char *Start, unsigned char *noise,
+;                            unsigned char blackclamp[16],
+;                            unsigned char whiteclamp[16],
+;                            unsigned char bothclamp[16],
+;                            unsigned int Width, unsigned int Height, int Pitch)
+extern sym(rand)
+global sym(vp8_plane_add_noise_mmx)
+sym(vp8_plane_add_noise_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+addnoise_loop:
+    call sym(rand) WRT_PLT
+    mov     rcx, arg(1) ;noise
+    and     rax, 0xff
+    add     rcx, rax
+
+    ; we rely on the fact that the clamping vectors are stored contiguously
+    ; in black/white/both order. Note that we have to reload this here because
+    ; rdx could be trashed by rand()
+    mov     rdx, arg(2) ; blackclamp
+
+
+            mov     rdi, rcx
+            movsxd  rcx, dword arg(5) ;[Width]
+            mov     rsi, arg(0) ;Pos
+            xor         rax,rax
+
+addnoise_nextset:
+            movq        mm1,[rsi+rax]         ; get the source
+
+            psubusb     mm1, [rdx]    ;blackclamp        ; clamp both sides so we don't outrange adding noise
+            paddusb     mm1, [rdx+32] ;bothclamp
+            psubusb     mm1, [rdx+16] ;whiteclamp
+
+            movq        mm2,[rdi+rax]         ; get the noise for this line
+            paddb       mm1,mm2              ; add it in
+            movq        [rsi+rax],mm1         ; store the result
+
+            add         rax,8                 ; move to the next line
+
+            cmp         rax, rcx
+            jl          addnoise_nextset
+
+    movsxd  rax, dword arg(7) ; Pitch
+    add     arg(0), rax ; Start += Pitch
+    sub     dword arg(6), 1   ; Height -= 1
+    jg      addnoise_loop
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+SECTION_RODATA
+align 16
+Blur:
+    times 16 dw 16
+    times  8 dw 64
+    times 16 dw 16
+    times  8 dw  0
+
+rd:
+    times 4 dw 0x40
diff --git a/vp8/common/x86/postproc_mmx.c b/vp8/common/x86/postproc_mmx.c
new file mode 100644
index 0000000..095797b
--- /dev/null
+++ b/vp8/common/x86/postproc_mmx.c
@@ -0,0 +1,1507 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <math.h>
+#include <stdlib.h>
+#include "vpx_scale/yv12config.h"
+#include "pragmas.h"
+
+#define VP8_FILTER_WEIGHT 128
+#define VP8_FILTER_SHIFT  7
+
+
+
+/* static constants */
+__declspec(align(16))
+const static short  Blur[48] =
+{
+
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    64, 64, 64, 64, 64, 64, 64, 64,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    0,  0,  0,  0,  0,  0,  0,  0,
+
+};
+#define RD  __declspec(align(16)) __int64 rd  = 0x0040004000400040;
+#define R4D2 __declspec(align(16)) __int64 rd42[2] = {0x0004000400040004,0x0004000400040004};
+
+#ifndef RELOCATEABLE
+const static RD;
+const static R4D2;
+#endif
+
+
+/* external references */
+extern double vp8_gaussian(double sigma, double mu, double x);
+extern short vp8_rv[];
+extern int vp8_q2mbl(int x) ;
+
+
+
+void vp8_post_proc_down_and_across_mmx
+(
+    unsigned char *src_ptr,
+    unsigned char *dst_ptr,
+    int src_pixels_per_line,
+    int dst_pixels_per_line,
+    int rows,
+    int cols,
+    int flimit
+)
+{
+#ifdef RELOCATEABLE
+    RD
+    R4D2
+#endif
+
+    __asm
+    {
+        push        ebx
+        lea         ebx, Blur
+        movd        mm2, flimit
+        punpcklwd   mm2, mm2
+        punpckldq   mm2, mm2
+
+        mov         esi,        src_ptr
+        mov         edi,        dst_ptr
+
+        mov         ecx, DWORD PTR rows
+        mov         eax, src_pixels_per_line ;
+        destination pitch?
+        pxor        mm0, mm0              ;
+        mm0 = 00000000
+
+        nextrow:
+
+        xor         edx,        edx       ;
+
+        clear out edx for use as loop counter
+        nextcol:
+
+        pxor        mm7, mm7              ;
+
+    mm7 = 00000000
+    movq        mm6, [ebx + 32 ]      ;
+        mm6 = kernel 2 taps
+        movq        mm3, [esi]            ;
+        mm4 = r0 p0..p7
+        punpcklbw   mm3, mm0              ;
+        mm3 = p0..p3
+        movq        mm1, mm3              ;
+        mm1 = p0..p3
+        pmullw      mm3, mm6              ;
+        mm3 *= kernel 2 modifiers
+
+        movq        mm6, [ebx + 48]       ;
+        mm6 = kernel 3 taps
+        movq        mm5, [esi + eax]      ;
+        mm4 = r1 p0..p7
+        punpcklbw   mm5, mm0              ;
+        mm5 = r1 p0..p3
+        pmullw      mm6, mm5              ;
+        mm6 *= p0..p3 * kernel 3 modifiers
+        paddusw     mm3, mm6              ;
+        mm3 += mm6
+
+        ;
+        thresholding
+        movq        mm7, mm1              ;
+        mm7 = r0 p0..p3
+        psubusw     mm7, mm5              ;
+        mm7 = r0 p0..p3 - r1 p0..p3
+        psubusw     mm5, mm1              ;
+        mm5 = r1 p0..p3 - r0 p0..p3
+        paddusw     mm7, mm5              ;
+        mm7 = abs(r0 p0..p3 - r1 p0..p3)
+        pcmpgtw     mm7, mm2
+
+        movq        mm6, [ebx + 64 ]      ;
+        mm6 = kernel 4 modifiers
+        movq        mm5, [esi + 2*eax]    ;
+        mm4 = r2 p0..p7
+        punpcklbw   mm5, mm0              ;
+        mm5 = r2 p0..p3
+        pmullw      mm6, mm5              ;
+        mm5 *= kernel 4 modifiers
+        paddusw     mm3, mm6              ;
+        mm3 += mm5
+
+        ;
+        thresholding
+        movq        mm6, mm1              ;
+        mm6 = r0 p0..p3
+        psubusw     mm6, mm5              ;
+        mm6 = r0 p0..p3 - r2 p0..p3
+        psubusw     mm5, mm1              ;
+        mm5 = r2 p0..p3 - r2 p0..p3
+        paddusw     mm6, mm5              ;
+        mm6 = abs(r0 p0..p3 - r2 p0..p3)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ;
+        accumulate thresholds
+
+
+        neg         eax
+        movq        mm6, [ebx ]           ;
+        kernel 0 taps
+        movq        mm5, [esi+2*eax]      ;
+        mm4 = r-2 p0..p7
+        punpcklbw   mm5, mm0              ;
+        mm5 = r-2 p0..p3
+        pmullw      mm6, mm5              ;
+        mm5 *= kernel 0 modifiers
+        paddusw     mm3, mm6              ;
+        mm3 += mm5
+
+        ;
+        thresholding
+        movq        mm6, mm1              ;
+        mm6 = r0 p0..p3
+        psubusw     mm6, mm5              ;
+        mm6 = p0..p3 - r-2 p0..p3
+        psubusw     mm5, mm1              ;
+        mm5 = r-2 p0..p3 - p0..p3
+        paddusw     mm6, mm5              ;
+        mm6 = abs(r0 p0..p3 - r-2 p0..p3)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ;
+        accumulate thresholds
+
+        movq        mm6, [ebx + 16]       ;
+        kernel 1 taps
+        movq        mm4, [esi+eax]        ;
+        mm4 = r-1 p0..p7
+        punpcklbw   mm4, mm0              ;
+        mm4 = r-1 p0..p3
+        pmullw      mm6, mm4              ;
+        mm4 *= kernel 1 modifiers.
+        paddusw     mm3, mm6              ;
+        mm3 += mm5
+
+        ;
+        thresholding
+        movq        mm6, mm1              ;
+        mm6 = r0 p0..p3
+        psubusw     mm6, mm4              ;
+        mm6 = p0..p3 - r-2 p0..p3
+        psubusw     mm4, mm1              ;
+        mm5 = r-1 p0..p3 - p0..p3
+        paddusw     mm6, mm4              ;
+        mm6 = abs(r0 p0..p3 - r-1 p0..p3)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ;
+        accumulate thresholds
+
+
+        paddusw     mm3, rd               ;
+        mm3 += round value
+        psraw       mm3, VP8_FILTER_SHIFT     ;
+        mm3 /= 128
+
+        pand        mm1, mm7              ;
+        mm1 select vals > thresh from source
+        pandn       mm7, mm3              ;
+        mm7 select vals < thresh from blurred result
+        paddusw     mm1, mm7              ;
+        combination
+
+        packuswb    mm1, mm0              ;
+        pack to bytes
+
+        movd        [edi], mm1            ;
+        neg         eax                   ;
+        pitch is positive
+
+
+        add         esi, 4
+        add         edi, 4
+        add         edx, 4
+
+        cmp         edx, cols
+        jl          nextcol
+        // done with the all cols, start the across filtering in place
+        sub         esi, edx
+        sub         edi, edx
+
+
+        push        eax
+        xor         edx,    edx
+        mov         eax,    [edi-4];
+
+        acrossnextcol:
+        pxor        mm7, mm7              ;
+        mm7 = 00000000
+        movq        mm6, [ebx + 32 ]      ;
+        movq        mm4, [edi+edx]        ;
+        mm4 = p0..p7
+        movq        mm3, mm4              ;
+        mm3 = p0..p7
+        punpcklbw   mm3, mm0              ;
+        mm3 = p0..p3
+        movq        mm1, mm3              ;
+        mm1 = p0..p3
+        pmullw      mm3, mm6              ;
+        mm3 *= kernel 2 modifiers
+
+        movq        mm6, [ebx + 48]
+        psrlq       mm4, 8                ;
+        mm4 = p1..p7
+        movq        mm5, mm4              ;
+        mm5 = p1..p7
+        punpcklbw   mm5, mm0              ;
+        mm5 = p1..p4
+        pmullw      mm6, mm5              ;
+        mm6 *= p1..p4 * kernel 3 modifiers
+        paddusw     mm3, mm6              ;
+        mm3 += mm6
+
+        ;
+        thresholding
+        movq        mm7, mm1              ;
+        mm7 = p0..p3
+        psubusw     mm7, mm5              ;
+        mm7 = p0..p3 - p1..p4
+        psubusw     mm5, mm1              ;
+        mm5 = p1..p4 - p0..p3
+        paddusw     mm7, mm5              ;
+        mm7 = abs(p0..p3 - p1..p4)
+        pcmpgtw     mm7, mm2
+
+        movq        mm6, [ebx + 64 ]
+        psrlq       mm4, 8                ;
+        mm4 = p2..p7
+        movq        mm5, mm4              ;
+        mm5 = p2..p7
+        punpcklbw   mm5, mm0              ;
+        mm5 = p2..p5
+        pmullw      mm6, mm5              ;
+        mm5 *= kernel 4 modifiers
+        paddusw     mm3, mm6              ;
+        mm3 += mm5
+
+        ;
+        thresholding
+        movq        mm6, mm1              ;
+        mm6 = p0..p3
+        psubusw     mm6, mm5              ;
+        mm6 = p0..p3 - p1..p4
+        psubusw     mm5, mm1              ;
+        mm5 = p1..p4 - p0..p3
+        paddusw     mm6, mm5              ;
+        mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ;
+        accumulate thresholds
+
+
+        movq        mm6, [ebx ]
+        movq        mm4, [edi+edx-2]      ;
+        mm4 = p-2..p5
+        movq        mm5, mm4              ;
+        mm5 = p-2..p5
+        punpcklbw   mm5, mm0              ;
+        mm5 = p-2..p1
+        pmullw      mm6, mm5              ;
+        mm5 *= kernel 0 modifiers
+        paddusw     mm3, mm6              ;
+        mm3 += mm5
+
+        ;
+        thresholding
+        movq        mm6, mm1              ;
+        mm6 = p0..p3
+        psubusw     mm6, mm5              ;
+        mm6 = p0..p3 - p1..p4
+        psubusw     mm5, mm1              ;
+        mm5 = p1..p4 - p0..p3
+        paddusw     mm6, mm5              ;
+        mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ;
+        accumulate thresholds
+
+        movq        mm6, [ebx + 16]
+        psrlq       mm4, 8                ;
+        mm4 = p-1..p5
+        punpcklbw   mm4, mm0              ;
+        mm4 = p-1..p2
+        pmullw      mm6, mm4              ;
+        mm4 *= kernel 1 modifiers.
+        paddusw     mm3, mm6              ;
+        mm3 += mm5
+
+        ;
+        thresholding
+        movq        mm6, mm1              ;
+        mm6 = p0..p3
+        psubusw     mm6, mm4              ;
+        mm6 = p0..p3 - p1..p4
+        psubusw     mm4, mm1              ;
+        mm5 = p1..p4 - p0..p3
+        paddusw     mm6, mm4              ;
+        mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     mm6, mm2
+        por         mm7, mm6              ;
+        accumulate thresholds
+
+        paddusw     mm3, rd               ;
+        mm3 += round value
+        psraw       mm3, VP8_FILTER_SHIFT     ;
+        mm3 /= 128
+
+        pand        mm1, mm7              ;
+        mm1 select vals > thresh from source
+        pandn       mm7, mm3              ;
+        mm7 select vals < thresh from blurred result
+        paddusw     mm1, mm7              ;
+        combination
+
+        packuswb    mm1, mm0              ;
+        pack to bytes
+        mov         DWORD PTR [edi+edx-4],  eax   ;
+        store previous four bytes
+        movd        eax,    mm1
+
+        add         edx, 4
+        cmp         edx, cols
+        jl          acrossnextcol;
+
+        mov         DWORD PTR [edi+edx-4],  eax
+        pop         eax
+
+        // done with this rwo
+        add         esi, eax               ;
+        next line
+        mov         eax, dst_pixels_per_line ;
+        destination pitch?
+        add         edi, eax               ;
+        next destination
+        mov         eax, src_pixels_per_line ;
+        destination pitch?
+
+        dec         ecx                   ;
+        decrement count
+        jnz         nextrow               ;
+        next row
+        pop         ebx
+
+    }
+}
+
+
+
+void vp8_post_proc_down_and_across_xmm
+(
+    unsigned char *src_ptr,
+    unsigned char *dst_ptr,
+    int src_pixels_per_line,
+    int dst_pixels_per_line,
+    int rows,
+    int cols,
+    int flimit
+)
+{
+#ifdef RELOCATEABLE
+    R4D2
+#endif
+
+    __asm
+    {
+        movd        xmm2,       flimit
+        punpcklwd   xmm2,       xmm2
+        punpckldq   xmm2,       xmm2
+        punpcklqdq  xmm2,       xmm2
+
+        mov         esi,        src_ptr
+        mov         edi,        dst_ptr
+
+        mov         ecx,        DWORD PTR rows
+        mov         eax,        src_pixels_per_line ;
+        destination pitch?
+        pxor        xmm0,       xmm0              ;
+        mm0 = 00000000
+
+        nextrow:
+
+        xor         edx,        edx       ;
+
+        clear out edx for use as loop counter
+        nextcol:
+        movq        xmm3,       QWORD PTR [esi]         ;
+
+        mm4 = r0 p0..p7
+        punpcklbw   xmm3,       xmm0                    ;
+        mm3 = p0..p3
+        movdqa      xmm1,       xmm3                    ;
+        mm1 = p0..p3
+        psllw       xmm3,       2                       ;
+
+        movq        xmm5,       QWORD PTR [esi + eax]   ;
+        mm4 = r1 p0..p7
+        punpcklbw   xmm5,       xmm0                    ;
+        mm5 = r1 p0..p3
+        paddusw     xmm3,       xmm5                    ;
+        mm3 += mm6
+
+        ;
+        thresholding
+        movdqa      xmm7,       xmm1                    ;
+        mm7 = r0 p0..p3
+        psubusw     xmm7,       xmm5                    ;
+        mm7 = r0 p0..p3 - r1 p0..p3
+        psubusw     xmm5,       xmm1                    ;
+        mm5 = r1 p0..p3 - r0 p0..p3
+        paddusw     xmm7,       xmm5                    ;
+        mm7 = abs(r0 p0..p3 - r1 p0..p3)
+        pcmpgtw     xmm7,       xmm2
+
+        movq        xmm5,       QWORD PTR [esi + 2*eax] ;
+        mm4 = r2 p0..p7
+        punpcklbw   xmm5,       xmm0                    ;
+        mm5 = r2 p0..p3
+        paddusw     xmm3,       xmm5                    ;
+        mm3 += mm5
+
+        ;
+        thresholding
+        movdqa      xmm6,       xmm1                    ;
+        mm6 = r0 p0..p3
+        psubusw     xmm6,       xmm5                    ;
+        mm6 = r0 p0..p3 - r2 p0..p3
+        psubusw     xmm5,       xmm1                    ;
+        mm5 = r2 p0..p3 - r2 p0..p3
+        paddusw     xmm6,       xmm5                    ;
+        mm6 = abs(r0 p0..p3 - r2 p0..p3)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6                    ;
+        accumulate thresholds
+
+
+        neg         eax
+        movq        xmm5,       QWORD PTR [esi+2*eax]   ;
+        mm4 = r-2 p0..p7
+        punpcklbw   xmm5,       xmm0                    ;
+        mm5 = r-2 p0..p3
+        paddusw     xmm3,       xmm5                    ;
+        mm3 += mm5
+
+        ;
+        thresholding
+        movdqa      xmm6,       xmm1                    ;
+        mm6 = r0 p0..p3
+        psubusw     xmm6,       xmm5                    ;
+        mm6 = p0..p3 - r-2 p0..p3
+        psubusw     xmm5,       xmm1                    ;
+        mm5 = r-2 p0..p3 - p0..p3
+        paddusw     xmm6,       xmm5                    ;
+        mm6 = abs(r0 p0..p3 - r-2 p0..p3)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6                    ;
+        accumulate thresholds
+
+        movq        xmm4,       QWORD PTR [esi+eax]     ;
+        mm4 = r-1 p0..p7
+        punpcklbw   xmm4,       xmm0                    ;
+        mm4 = r-1 p0..p3
+        paddusw     xmm3,       xmm4                    ;
+        mm3 += mm5
+
+        ;
+        thresholding
+        movdqa      xmm6,       xmm1                    ;
+        mm6 = r0 p0..p3
+        psubusw     xmm6,       xmm4                    ;
+        mm6 = p0..p3 - r-2 p0..p3
+        psubusw     xmm4,       xmm1                    ;
+        mm5 = r-1 p0..p3 - p0..p3
+        paddusw     xmm6,       xmm4                    ;
+        mm6 = abs(r0 p0..p3 - r-1 p0..p3)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6                    ;
+        accumulate thresholds
+
+
+        paddusw     xmm3,       rd42                    ;
+        mm3 += round value
+        psraw       xmm3,       3                       ;
+        mm3 /= 8
+
+        pand        xmm1,       xmm7                    ;
+        mm1 select vals > thresh from source
+        pandn       xmm7,       xmm3                    ;
+        mm7 select vals < thresh from blurred result
+        paddusw     xmm1,       xmm7                    ;
+        combination
+
+        packuswb    xmm1,       xmm0                    ;
+        pack to bytes
+        movq        QWORD PTR [edi], xmm1             ;
+
+        neg         eax                   ;
+        pitch is positive
+        add         esi,        8
+        add         edi,        8
+
+        add         edx,        8
+        cmp         edx,        cols
+
+        jl          nextcol
+
+        // done with the all cols, start the across filtering in place
+        sub         esi,        edx
+        sub         edi,        edx
+
+        xor         edx,        edx
+        movq        mm0,        QWORD PTR [edi-8];
+
+        acrossnextcol:
+        movq        xmm7,       QWORD PTR [edi +edx -2]
+        movd        xmm4,       DWORD PTR [edi +edx +6]
+
+        pslldq      xmm4,       8
+        por         xmm4,       xmm7
+
+        movdqa      xmm3,       xmm4
+        psrldq      xmm3,       2
+        punpcklbw   xmm3,       xmm0              ;
+        mm3 = p0..p3
+        movdqa      xmm1,       xmm3              ;
+        mm1 = p0..p3
+        psllw       xmm3,       2
+
+
+        movdqa      xmm5,       xmm4
+        psrldq      xmm5,       3
+        punpcklbw   xmm5,       xmm0              ;
+        mm5 = p1..p4
+        paddusw     xmm3,       xmm5              ;
+        mm3 += mm6
+
+        ;
+        thresholding
+        movdqa      xmm7,       xmm1              ;
+        mm7 = p0..p3
+        psubusw     xmm7,       xmm5              ;
+        mm7 = p0..p3 - p1..p4
+        psubusw     xmm5,       xmm1              ;
+        mm5 = p1..p4 - p0..p3
+        paddusw     xmm7,       xmm5              ;
+        mm7 = abs(p0..p3 - p1..p4)
+        pcmpgtw     xmm7,       xmm2
+
+        movdqa      xmm5,       xmm4
+        psrldq      xmm5,       4
+        punpcklbw   xmm5,       xmm0              ;
+        mm5 = p2..p5
+        paddusw     xmm3,       xmm5              ;
+        mm3 += mm5
+
+        ;
+        thresholding
+        movdqa      xmm6,       xmm1              ;
+        mm6 = p0..p3
+        psubusw     xmm6,       xmm5              ;
+        mm6 = p0..p3 - p1..p4
+        psubusw     xmm5,       xmm1              ;
+        mm5 = p1..p4 - p0..p3
+        paddusw     xmm6,       xmm5              ;
+        mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6              ;
+        accumulate thresholds
+
+
+        movdqa      xmm5,       xmm4              ;
+        mm5 = p-2..p5
+        punpcklbw   xmm5,       xmm0              ;
+        mm5 = p-2..p1
+        paddusw     xmm3,       xmm5              ;
+        mm3 += mm5
+
+        ;
+        thresholding
+        movdqa      xmm6,       xmm1              ;
+        mm6 = p0..p3
+        psubusw     xmm6,       xmm5              ;
+        mm6 = p0..p3 - p1..p4
+        psubusw     xmm5,       xmm1              ;
+        mm5 = p1..p4 - p0..p3
+        paddusw     xmm6,       xmm5              ;
+        mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6              ;
+        accumulate thresholds
+
+        psrldq      xmm4,       1                   ;
+        mm4 = p-1..p5
+        punpcklbw   xmm4,       xmm0              ;
+        mm4 = p-1..p2
+        paddusw     xmm3,       xmm4              ;
+        mm3 += mm5
+
+        ;
+        thresholding
+        movdqa      xmm6,       xmm1              ;
+        mm6 = p0..p3
+        psubusw     xmm6,       xmm4              ;
+        mm6 = p0..p3 - p1..p4
+        psubusw     xmm4,       xmm1              ;
+        mm5 = p1..p4 - p0..p3
+        paddusw     xmm6,       xmm4              ;
+        mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6              ;
+        accumulate thresholds
+
+        paddusw     xmm3,       rd42              ;
+        mm3 += round value
+        psraw       xmm3,       3                 ;
+        mm3 /= 8
+
+        pand        xmm1,       xmm7              ;
+        mm1 select vals > thresh from source
+        pandn       xmm7,       xmm3              ;
+        mm7 select vals < thresh from blurred result
+        paddusw     xmm1,       xmm7              ;
+        combination
+
+        packuswb    xmm1,       xmm0              ;
+        pack to bytes
+        movq        QWORD PTR [edi+edx-8],  mm0   ;
+        store previous four bytes
+        movdq2q     mm0,        xmm1
+
+        add         edx,        8
+        cmp         edx,        cols
+        jl          acrossnextcol;
+
+        // last 8 pixels
+        movq        QWORD PTR [edi+edx-8],  mm0
+
+        // done with this rwo
+        add         esi, eax               ;
+        next line
+        mov         eax, dst_pixels_per_line ;
+        destination pitch?
+        add         edi, eax               ;
+        next destination
+        mov         eax, src_pixels_per_line ;
+        destination pitch?
+
+        dec         ecx                   ;
+        decrement count
+        jnz         nextrow               ;
+        next row
+    }
+}
+
+
+void vp8_mbpost_proc_down_mmx(unsigned char *dst, int pitch, int rows, int cols, int flimit)
+{
+    int c, i;
+    __declspec(align(16))
+    int flimit2[2];
+    __declspec(align(16))
+    unsigned char d[16][8];
+
+    flimit = vp8_q2mbl(flimit);
+
+    for (i = 0; i < 2; i++)
+        flimit2[i] = flimit;
+
+    rows += 8;
+
+    for (c = 0; c < cols; c += 4)
+    {
+        unsigned char *s = &dst[c];
+
+        __asm
+        {
+            mov         esi,        s           ;
+            pxor        mm0,        mm0     ;
+
+            mov         eax,        pitch       ;
+            neg         eax                                     // eax = -pitch
+
+            lea         esi,        [esi + eax*8];              // edi = s[-pitch*8]
+            neg         eax
+
+
+            pxor        mm5,        mm5
+            pxor        mm6,        mm6     ;
+
+            pxor        mm7,        mm7     ;
+            mov         edi,        esi
+
+            mov         ecx,        15          ;
+
+            loop_initvar:
+            movd        mm1,        DWORD PTR [edi];
+            punpcklbw   mm1,        mm0     ;
+
+            paddw       mm5,        mm1     ;
+            pmullw      mm1,        mm1     ;
+
+            movq        mm2,        mm1     ;
+            punpcklwd   mm1,        mm0     ;
+
+            punpckhwd   mm2,        mm0     ;
+            paddd       mm6,        mm1     ;
+
+            paddd       mm7,        mm2     ;
+            lea         edi,        [edi+eax]   ;
+
+            dec         ecx
+            jne         loop_initvar
+            //save the var and sum
+            xor         edx,        edx
+            loop_row:
+            movd        mm1,        DWORD PTR [esi]     // [s-pitch*8]
+            movd        mm2,        DWORD PTR [edi]     // [s+pitch*7]
+
+            punpcklbw   mm1,        mm0
+            punpcklbw   mm2,        mm0
+
+            paddw       mm5,        mm2
+            psubw       mm5,        mm1
+
+            pmullw      mm2,        mm2
+            movq        mm4,        mm2
+
+            punpcklwd   mm2,        mm0
+            punpckhwd   mm4,        mm0
+
+            paddd       mm6,        mm2
+            paddd       mm7,        mm4
+
+            pmullw      mm1,        mm1
+            movq        mm2,        mm1
+
+            punpcklwd   mm1,        mm0
+            psubd       mm6,        mm1
+
+            punpckhwd   mm2,        mm0
+            psubd       mm7,        mm2
+
+
+            movq        mm3,        mm6
+            pslld       mm3,        4
+
+            psubd       mm3,        mm6
+            movq        mm1,        mm5
+
+            movq        mm4,        mm5
+            pmullw      mm1,        mm1
+
+            pmulhw      mm4,        mm4
+            movq        mm2,        mm1
+
+            punpcklwd   mm1,        mm4
+            punpckhwd   mm2,        mm4
+
+            movq        mm4,        mm7
+            pslld       mm4,        4
+
+            psubd       mm4,        mm7
+
+            psubd       mm3,        mm1
+            psubd       mm4,        mm2
+
+            psubd       mm3,        flimit2
+            psubd       mm4,        flimit2
+
+            psrad       mm3,        31
+            psrad       mm4,        31
+
+            packssdw    mm3,        mm4
+            packsswb    mm3,        mm0
+
+            movd        mm1,        DWORD PTR [esi+eax*8]
+
+            movq        mm2,        mm1
+            punpcklbw   mm1,        mm0
+
+            paddw       mm1,        mm5
+            mov         ecx,        edx
+
+            and         ecx,        127
+            movq        mm4,        vp8_rv[ecx*2]
+
+            paddw       mm1,        mm4
+            //paddw     xmm1,       eight8s
+            psraw       mm1,        4
+
+            packuswb    mm1,        mm0
+            pand        mm1,        mm3
+
+            pandn       mm3,        mm2
+            por         mm1,        mm3
+
+            and         ecx,        15
+            movd        DWORD PTR  d[ecx*4], mm1
+
+            mov         ecx,        edx
+            sub         ecx,        8
+
+            and         ecx,        15
+            movd        mm1,        DWORD PTR d[ecx*4]
+
+            movd        [esi],      mm1
+            lea         esi,        [esi+eax]
+
+            lea         edi,        [edi+eax]
+            add         edx,        1
+
+            cmp         edx,        rows
+            jl          loop_row
+
+        }
+
+    }
+}
+
+void vp8_mbpost_proc_down_xmm(unsigned char *dst, int pitch, int rows, int cols, int flimit)
+{
+    int c, i;
+    __declspec(align(16))
+    int flimit4[4];
+    __declspec(align(16))
+    unsigned char d[16][8];
+
+    flimit = vp8_q2mbl(flimit);
+
+    for (i = 0; i < 4; i++)
+        flimit4[i] = flimit;
+
+    rows += 8;
+
+    for (c = 0; c < cols; c += 8)
+    {
+        unsigned char *s = &dst[c];
+
+        __asm
+        {
+            mov         esi,        s           ;
+            pxor        xmm0,       xmm0        ;
+
+            mov         eax,        pitch       ;
+            neg         eax                                     // eax = -pitch
+
+            lea         esi,        [esi + eax*8];              // edi = s[-pitch*8]
+            neg         eax
+
+
+            pxor        xmm5,       xmm5
+            pxor        xmm6,       xmm6        ;
+
+            pxor        xmm7,       xmm7        ;
+            mov         edi,        esi
+
+            mov         ecx,        15          ;
+
+            loop_initvar:
+            movq        xmm1,       QWORD PTR [edi];
+            punpcklbw   xmm1,       xmm0        ;
+
+            paddw       xmm5,       xmm1        ;
+            pmullw      xmm1,       xmm1        ;
+
+            movdqa      xmm2,       xmm1        ;
+            punpcklwd   xmm1,       xmm0        ;
+
+            punpckhwd   xmm2,       xmm0        ;
+            paddd       xmm6,       xmm1        ;
+
+            paddd       xmm7,       xmm2        ;
+            lea         edi,        [edi+eax]   ;
+
+            dec         ecx
+            jne         loop_initvar
+            //save the var and sum
+            xor         edx,        edx
+            loop_row:
+            movq        xmm1,       QWORD PTR [esi]     // [s-pitch*8]
+            movq        xmm2,       QWORD PTR [edi]     // [s+pitch*7]
+
+            punpcklbw   xmm1,       xmm0
+            punpcklbw   xmm2,       xmm0
+
+            paddw       xmm5,       xmm2
+            psubw       xmm5,       xmm1
+
+            pmullw      xmm2,       xmm2
+            movdqa      xmm4,       xmm2
+
+            punpcklwd   xmm2,       xmm0
+            punpckhwd   xmm4,       xmm0
+
+            paddd       xmm6,       xmm2
+            paddd       xmm7,       xmm4
+
+            pmullw      xmm1,       xmm1
+            movdqa      xmm2,       xmm1
+
+            punpcklwd   xmm1,       xmm0
+            psubd       xmm6,       xmm1
+
+            punpckhwd   xmm2,       xmm0
+            psubd       xmm7,       xmm2
+
+
+            movdqa      xmm3,       xmm6
+            pslld       xmm3,       4
+
+            psubd       xmm3,       xmm6
+            movdqa      xmm1,       xmm5
+
+            movdqa      xmm4,       xmm5
+            pmullw      xmm1,       xmm1
+
+            pmulhw      xmm4,       xmm4
+            movdqa      xmm2,       xmm1
+
+            punpcklwd   xmm1,       xmm4
+            punpckhwd   xmm2,       xmm4
+
+            movdqa      xmm4,       xmm7
+            pslld       xmm4,       4
+
+            psubd       xmm4,       xmm7
+
+            psubd       xmm3,       xmm1
+            psubd       xmm4,       xmm2
+
+            psubd       xmm3,       flimit4
+            psubd       xmm4,       flimit4
+
+            psrad       xmm3,       31
+            psrad       xmm4,       31
+
+            packssdw    xmm3,       xmm4
+            packsswb    xmm3,       xmm0
+
+            movq        xmm1,       QWORD PTR [esi+eax*8]
+
+            movq        xmm2,       xmm1
+            punpcklbw   xmm1,       xmm0
+
+            paddw       xmm1,       xmm5
+            mov         ecx,        edx
+
+            and         ecx,        127
+            movdqu      xmm4,       vp8_rv[ecx*2]
+
+            paddw       xmm1,       xmm4
+            //paddw     xmm1,       eight8s
+            psraw       xmm1,       4
+
+            packuswb    xmm1,       xmm0
+            pand        xmm1,       xmm3
+
+            pandn       xmm3,       xmm2
+            por         xmm1,       xmm3
+
+            and         ecx,        15
+            movq        QWORD PTR  d[ecx*8], xmm1
+
+            mov         ecx,        edx
+            sub         ecx,        8
+
+            and         ecx,        15
+            movq        mm0,        d[ecx*8]
+
+            movq        [esi],      mm0
+            lea         esi,        [esi+eax]
+
+            lea         edi,        [edi+eax]
+            add         edx,        1
+
+            cmp         edx,        rows
+            jl          loop_row
+
+        }
+
+    }
+}
+#if 0
+/****************************************************************************
+ *
+ *  ROUTINE       : plane_add_noise_wmt
+ *
+ *  INPUTS        : unsigned char *Start    starting address of buffer to add gaussian
+ *                                  noise to
+ *                  unsigned int Width    width of plane
+ *                  unsigned int Height   height of plane
+ *                  int  Pitch    distance between subsequent lines of frame
+ *                  int  q        quantizer used to determine amount of noise
+ *                                  to add
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void.
+ *
+ *  FUNCTION      : adds gaussian noise to a plane of pixels
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+void vp8_plane_add_noise_wmt(unsigned char *Start, unsigned int Width, unsigned int Height, int Pitch, int q, int a)
+{
+    unsigned int i;
+
+    __declspec(align(16)) unsigned char blackclamp[16];
+    __declspec(align(16)) unsigned char whiteclamp[16];
+    __declspec(align(16)) unsigned char bothclamp[16];
+    char char_dist[300];
+    char Rand[2048];
+    double sigma;
+//    return;
+    __asm emms
+    sigma = a + .5 + .6 * (63 - q) / 63.0;
+
+    // set up a lookup table of 256 entries that matches
+    // a gaussian distribution with sigma determined by q.
+    //
+    {
+        double i;
+        int next, j;
+
+        next = 0;
+
+        for (i = -32; i < 32; i++)
+        {
+            double g = 256 * vp8_gaussian(sigma, 0, 1.0 * i);
+            int a = (int)(g + .5);
+
+            if (a)
+            {
+                for (j = 0; j < a; j++)
+                {
+                    char_dist[next+j] = (char) i;
+                }
+
+                next = next + j;
+            }
+
+        }
+
+        for (next = next; next < 256; next++)
+            char_dist[next] = 0;
+
+    }
+
+    for (i = 0; i < 2048; i++)
+    {
+        Rand[i] = char_dist[rand() & 0xff];
+    }
+
+    for (i = 0; i < 16; i++)
+    {
+        blackclamp[i] = -char_dist[0];
+        whiteclamp[i] = -char_dist[0];
+        bothclamp[i] = -2 * char_dist[0];
+    }
+
+    for (i = 0; i < Height; i++)
+    {
+        unsigned char *Pos = Start + i * Pitch;
+        char  *Ref = Rand + (rand() & 0xff);
+
+        __asm
+        {
+            mov ecx, [Width]
+            mov esi, Pos
+            mov edi, Ref
+            xor         eax, eax
+
+            nextset:
+            movdqu      xmm1, [esi+eax]        // get the source
+
+            psubusb     xmm1, blackclamp       // clamp both sides so we don't outrange adding noise
+            paddusb     xmm1, bothclamp
+            psubusb     xmm1, whiteclamp
+
+            movdqu      xmm2, [edi+eax]        // get the noise for this line
+            paddb       xmm1, xmm2             // add it in
+            movdqu      [esi+eax], xmm1        // store the result
+
+            add         eax, 16                // move to the next line
+
+            cmp         eax, ecx
+            jl          nextset
+
+
+        }
+
+    }
+}
+#endif
+__declspec(align(16))
+static const int four8s[4] = { 8, 8, 8, 8};
+void vp8_mbpost_proc_across_ip_xmm(unsigned char *src, int pitch, int rows, int cols, int flimit)
+{
+    int r, i;
+    __declspec(align(16))
+    int flimit4[4];
+    unsigned char *s = src;
+    int sumsq;
+    int sum;
+
+
+    flimit = vp8_q2mbl(flimit);
+    flimit4[0] =
+        flimit4[1] =
+            flimit4[2] =
+                flimit4[3] = flimit;
+
+    for (r = 0; r < rows; r++)
+    {
+
+
+        sumsq = 0;
+        sum = 0;
+
+        for (i = -8; i <= 6; i++)
+        {
+            sumsq += s[i] * s[i];
+            sum   += s[i];
+        }
+
+        __asm
+        {
+            mov         eax,    sumsq
+            movd        xmm7,   eax
+
+            mov         eax,    sum
+            movd        xmm6,   eax
+
+            mov         esi,    s
+            xor         ecx,    ecx
+
+            mov         edx,    cols
+            add         edx,    8
+            pxor        mm0,    mm0
+            pxor        mm1,    mm1
+
+            pxor        xmm0,   xmm0
+            nextcol4:
+
+            movd        xmm1,   DWORD PTR [esi+ecx-8]   // -8 -7 -6 -5
+            movd        xmm2,   DWORD PTR [esi+ecx+7]   // +7 +8 +9 +10
+
+            punpcklbw   xmm1,   xmm0                    // expanding
+            punpcklbw   xmm2,   xmm0                    // expanding
+
+            punpcklwd   xmm1,   xmm0                    // expanding to dwords
+            punpcklwd   xmm2,   xmm0                    // expanding to dwords
+
+            psubd       xmm2,   xmm1                    // 7--8   8--7   9--6 10--5
+            paddd       xmm1,   xmm1                    // -8*2   -7*2   -6*2 -5*2
+
+            paddd       xmm1,   xmm2                    // 7+-8   8+-7   9+-6 10+-5
+            pmaddwd     xmm1,   xmm2                    // squared of 7+-8   8+-7   9+-6 10+-5
+
+            paddd       xmm6,   xmm2
+            paddd       xmm7,   xmm1
+
+            pshufd      xmm6,   xmm6,   0               // duplicate the last ones
+            pshufd      xmm7,   xmm7,   0               // duplicate the last ones
+
+            psrldq      xmm1,       4                   // 8--7   9--6 10--5  0000
+            psrldq      xmm2,       4                   // 8--7   9--6 10--5  0000
+
+            pshufd      xmm3,   xmm1,   3               // 0000  8--7   8--7   8--7 squared
+            pshufd      xmm4,   xmm2,   3               // 0000  8--7   8--7   8--7 squared
+
+            paddd       xmm6,   xmm4
+            paddd       xmm7,   xmm3
+
+            pshufd      xmm3,   xmm1,   01011111b       // 0000  0000   9--6   9--6 squared
+            pshufd      xmm4,   xmm2,   01011111b       // 0000  0000   9--6   9--6 squared
+
+            paddd       xmm7,   xmm3
+            paddd       xmm6,   xmm4
+
+            pshufd      xmm3,   xmm1,   10111111b       // 0000  0000   8--7   8--7 squared
+            pshufd      xmm4,   xmm2,   10111111b       // 0000  0000   8--7   8--7 squared
+
+            paddd       xmm7,   xmm3
+            paddd       xmm6,   xmm4
+
+            movdqa      xmm3,   xmm6
+            pmaddwd     xmm3,   xmm3
+
+            movdqa      xmm5,   xmm7
+            pslld       xmm5,   4
+
+            psubd       xmm5,   xmm7
+            psubd       xmm5,   xmm3
+
+            psubd       xmm5,   flimit4
+            psrad       xmm5,   31
+
+            packssdw    xmm5,   xmm0
+            packsswb    xmm5,   xmm0
+
+            movd        xmm1,   DWORD PTR [esi+ecx]
+            movq        xmm2,   xmm1
+
+            punpcklbw   xmm1,   xmm0
+            punpcklwd   xmm1,   xmm0
+
+            paddd       xmm1,   xmm6
+            paddd       xmm1,   four8s
+
+            psrad       xmm1,   4
+            packssdw    xmm1,   xmm0
+
+            packuswb    xmm1,   xmm0
+            pand        xmm1,   xmm5
+
+            pandn       xmm5,   xmm2
+            por         xmm5,   xmm1
+
+            movd        [esi+ecx-8],  mm0
+            movq        mm0,    mm1
+
+            movdq2q     mm1,    xmm5
+            psrldq      xmm7,   12
+
+            psrldq      xmm6,   12
+            add         ecx,    4
+
+            cmp         ecx,    edx
+            jl          nextcol4
+
+        }
+        s += pitch;
+    }
+}
+
+#if 0
+
+/****************************************************************************
+ *
+ *  ROUTINE       : plane_add_noise_mmx
+ *
+ *  INPUTS        : unsigned char *Start    starting address of buffer to add gaussian
+ *                                  noise to
+ *                  unsigned int Width    width of plane
+ *                  unsigned int Height   height of plane
+ *                  int  Pitch    distance between subsequent lines of frame
+ *                  int  q        quantizer used to determine amount of noise
+ *                                  to add
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void.
+ *
+ *  FUNCTION      : adds gaussian noise to a plane of pixels
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+void vp8_plane_add_noise_mmx(unsigned char *Start, unsigned int Width, unsigned int Height, int Pitch, int q, int a)
+{
+    unsigned int i;
+    int Pitch4 = Pitch * 4;
+    const int noise_amount = 2;
+    const int noise_adder = 2 * noise_amount + 1;
+
+    __declspec(align(16)) unsigned char blackclamp[16];
+    __declspec(align(16)) unsigned char whiteclamp[16];
+    __declspec(align(16)) unsigned char bothclamp[16];
+
+    char char_dist[300];
+    char Rand[2048];
+
+    double sigma;
+    __asm emms
+    sigma = a + .5 + .6 * (63 - q) / 63.0;
+
+    // set up a lookup table of 256 entries that matches
+    // a gaussian distribution with sigma determined by q.
+    //
+    {
+        double i, sum = 0;
+        int next, j;
+
+        next = 0;
+
+        for (i = -32; i < 32; i++)
+        {
+            int a = (int)(.5 + 256 * vp8_gaussian(sigma, 0, i));
+
+            if (a)
+            {
+                for (j = 0; j < a; j++)
+                {
+                    char_dist[next+j] = (char) i;
+                }
+
+                next = next + j;
+            }
+
+        }
+
+        for (next = next; next < 256; next++)
+            char_dist[next] = 0;
+
+    }
+
+    for (i = 0; i < 2048; i++)
+    {
+        Rand[i] = char_dist[rand() & 0xff];
+    }
+
+    for (i = 0; i < 16; i++)
+    {
+        blackclamp[i] = -char_dist[0];
+        whiteclamp[i] = -char_dist[0];
+        bothclamp[i] = -2 * char_dist[0];
+    }
+
+    for (i = 0; i < Height; i++)
+    {
+        unsigned char *Pos = Start + i * Pitch;
+        char  *Ref = Rand + (rand() & 0xff);
+
+        __asm
+        {
+            mov ecx, [Width]
+            mov esi, Pos
+            mov edi, Ref
+            xor         eax, eax
+
+            nextset:
+            movq        mm1, [esi+eax]        // get the source
+
+            psubusb     mm1, blackclamp       // clamp both sides so we don't outrange adding noise
+            paddusb     mm1, bothclamp
+            psubusb     mm1, whiteclamp
+
+            movq        mm2, [edi+eax]        // get the noise for this line
+            paddb       mm1, mm2             // add it in
+            movq        [esi+eax], mm1        // store the result
+
+            add         eax, 8                // move to the next line
+
+            cmp         eax, ecx
+            jl          nextset
+
+
+        }
+
+    }
+}
+#else
+extern char an[8][64][3072];
+extern int cd[8][64];
+
+void vp8_plane_add_noise_mmx(unsigned char *Start, unsigned int Width, unsigned int Height, int Pitch, int q, int a)
+{
+    unsigned int i;
+    __declspec(align(16)) unsigned char blackclamp[16];
+    __declspec(align(16)) unsigned char whiteclamp[16];
+    __declspec(align(16)) unsigned char bothclamp[16];
+
+
+    __asm emms
+
+    for (i = 0; i < 16; i++)
+    {
+        blackclamp[i] = -cd[a][q];
+        whiteclamp[i] = -cd[a][q];
+        bothclamp[i] = -2 * cd[a][q];
+    }
+
+    for (i = 0; i < Height; i++)
+    {
+        unsigned char *Pos = Start + i * Pitch;
+        char  *Ref = an[a][q] + (rand() & 0xff);
+
+        __asm
+        {
+            mov ecx, [Width]
+            mov esi, Pos
+            mov edi, Ref
+            xor         eax, eax
+
+            nextset:
+            movq        mm1, [esi+eax]        // get the source
+
+            psubusb     mm1, blackclamp       // clamp both sides so we don't outrange adding noise
+            paddusb     mm1, bothclamp
+            psubusb     mm1, whiteclamp
+
+            movq        mm2, [edi+eax]        // get the noise for this line
+            paddb       mm1, mm2             // add it in
+            movq        [esi+eax], mm1        // store the result
+
+            add         eax, 8                // move to the next line
+
+            cmp         eax, ecx
+            jl          nextset
+        }
+    }
+}
+
+
+void vp8_plane_add_noise_wmt(unsigned char *Start, unsigned int Width, unsigned int Height, int Pitch, int q, int a)
+{
+    unsigned int i;
+
+    __declspec(align(16)) unsigned char blackclamp[16];
+    __declspec(align(16)) unsigned char whiteclamp[16];
+    __declspec(align(16)) unsigned char bothclamp[16];
+
+    __asm emms
+
+    for (i = 0; i < 16; i++)
+    {
+        blackclamp[i] = -cd[a][q];
+        whiteclamp[i] = -cd[a][q];
+        bothclamp[i] = -2 * cd[a][q];
+    }
+
+    for (i = 0; i < Height; i++)
+    {
+        unsigned char *Pos = Start + i * Pitch;
+        char *Ref = an[a][q] + (rand() & 0xff);
+
+        __asm
+        {
+            mov ecx,    [Width]
+            mov esi,    Pos
+            mov edi,    Ref
+            xor         eax, eax
+
+            nextset:
+            movdqu      xmm1, [esi+eax]        // get the source
+
+            psubusb     xmm1, blackclamp       // clamp both sides so we don't outrange adding noise
+            paddusb     xmm1, bothclamp
+            psubusb     xmm1, whiteclamp
+
+            movdqu      xmm2, [edi+eax]        // get the noise for this line
+            paddb       xmm1, xmm2             // add it in
+            movdqu      [esi+eax], xmm1        // store the result
+
+            add         eax, 16                // move to the next line
+
+            cmp         eax, ecx
+            jl          nextset
+        }
+    }
+}
+
+#endif
diff --git a/vp8/common/x86/postproc_sse2.asm b/vp8/common/x86/postproc_sse2.asm
new file mode 100644
index 0000000..bfa36fa
--- /dev/null
+++ b/vp8/common/x86/postproc_sse2.asm
@@ -0,0 +1,688 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_post_proc_down_and_across_xmm
+;(
+;    unsigned char *src_ptr,
+;    unsigned char *dst_ptr,
+;    int src_pixels_per_line,
+;    int dst_pixels_per_line,
+;    int rows,
+;    int cols,
+;    int flimit
+;)
+global sym(vp8_post_proc_down_and_across_xmm)
+sym(vp8_post_proc_down_and_across_xmm):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+%if ABI_IS_32BIT=1 && CONFIG_PIC=1
+    ALIGN_STACK 16, rax
+    ; move the global rd onto the stack, since we don't have enough registers
+    ; to do PIC addressing
+    movdqa      xmm0, [rd42 GLOBAL]
+    sub         rsp, 16
+    movdqa      [rsp], xmm0
+%define RD42 [rsp]
+%else
+%define RD42 [rd42 GLOBAL]
+%endif
+
+
+        movd        xmm2,       dword ptr arg(6) ;flimit
+        punpcklwd   xmm2,       xmm2
+        punpckldq   xmm2,       xmm2
+        punpcklqdq  xmm2,       xmm2
+
+        mov         rsi,        arg(0) ;src_ptr
+        mov         rdi,        arg(1) ;dst_ptr
+
+        movsxd      rcx,        DWORD PTR arg(4) ;rows
+        movsxd      rax,        DWORD PTR arg(2) ;src_pixels_per_line ; destination pitch?
+        pxor        xmm0,       xmm0              ; mm0 = 00000000
+
+nextrow:
+
+        xor         rdx,        rdx       ; clear out rdx for use as loop counter
+nextcol:
+        movq        xmm3,       QWORD PTR [rsi]         ; mm4 = r0 p0..p7
+        punpcklbw   xmm3,       xmm0                    ; mm3 = p0..p3
+        movdqa      xmm1,       xmm3                    ; mm1 = p0..p3
+        psllw       xmm3,       2                       ;
+
+        movq        xmm5,       QWORD PTR [rsi + rax]   ; mm4 = r1 p0..p7
+        punpcklbw   xmm5,       xmm0                    ; mm5 = r1 p0..p3
+        paddusw     xmm3,       xmm5                    ; mm3 += mm6
+
+        ; thresholding
+        movdqa      xmm7,       xmm1                    ; mm7 = r0 p0..p3
+        psubusw     xmm7,       xmm5                    ; mm7 = r0 p0..p3 - r1 p0..p3
+        psubusw     xmm5,       xmm1                    ; mm5 = r1 p0..p3 - r0 p0..p3
+        paddusw     xmm7,       xmm5                    ; mm7 = abs(r0 p0..p3 - r1 p0..p3)
+        pcmpgtw     xmm7,       xmm2
+
+        movq        xmm5,       QWORD PTR [rsi + 2*rax] ; mm4 = r2 p0..p7
+        punpcklbw   xmm5,       xmm0                    ; mm5 = r2 p0..p3
+        paddusw     xmm3,       xmm5                    ; mm3 += mm5
+
+        ; thresholding
+        movdqa      xmm6,       xmm1                    ; mm6 = r0 p0..p3
+        psubusw     xmm6,       xmm5                    ; mm6 = r0 p0..p3 - r2 p0..p3
+        psubusw     xmm5,       xmm1                    ; mm5 = r2 p0..p3 - r2 p0..p3
+        paddusw     xmm6,       xmm5                    ; mm6 = abs(r0 p0..p3 - r2 p0..p3)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6                    ; accumulate thresholds
+
+
+        neg         rax
+        movq        xmm5,       QWORD PTR [rsi+2*rax]   ; mm4 = r-2 p0..p7
+        punpcklbw   xmm5,       xmm0                    ; mm5 = r-2 p0..p3
+        paddusw     xmm3,       xmm5                    ; mm3 += mm5
+
+        ; thresholding
+        movdqa      xmm6,       xmm1                    ; mm6 = r0 p0..p3
+        psubusw     xmm6,       xmm5                    ; mm6 = p0..p3 - r-2 p0..p3
+        psubusw     xmm5,       xmm1                    ; mm5 = r-2 p0..p3 - p0..p3
+        paddusw     xmm6,       xmm5                    ; mm6 = abs(r0 p0..p3 - r-2 p0..p3)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6                    ; accumulate thresholds
+
+        movq        xmm4,       QWORD PTR [rsi+rax]     ; mm4 = r-1 p0..p7
+        punpcklbw   xmm4,       xmm0                    ; mm4 = r-1 p0..p3
+        paddusw     xmm3,       xmm4                    ; mm3 += mm5
+
+        ; thresholding
+        movdqa      xmm6,       xmm1                    ; mm6 = r0 p0..p3
+        psubusw     xmm6,       xmm4                    ; mm6 = p0..p3 - r-2 p0..p3
+        psubusw     xmm4,       xmm1                    ; mm5 = r-1 p0..p3 - p0..p3
+        paddusw     xmm6,       xmm4                    ; mm6 = abs(r0 p0..p3 - r-1 p0..p3)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6                    ; accumulate thresholds
+
+
+        paddusw     xmm3,       RD42                    ; mm3 += round value
+        psraw       xmm3,       3                       ; mm3 /= 8
+
+        pand        xmm1,       xmm7                    ; mm1 select vals > thresh from source
+        pandn       xmm7,       xmm3                    ; mm7 select vals < thresh from blurred result
+        paddusw     xmm1,       xmm7                    ; combination
+
+        packuswb    xmm1,       xmm0                    ; pack to bytes
+        movq        QWORD PTR [rdi], xmm1             ;
+
+        neg         rax                   ; pitch is positive
+        add         rsi,        8
+        add         rdi,        8
+
+        add         rdx,        8
+        cmp         edx,        dword arg(5) ;cols
+
+        jl          nextcol
+
+        ; done with the all cols, start the across filtering in place
+        sub         rsi,        rdx
+        sub         rdi,        rdx
+
+        xor         rdx,        rdx
+        movq        mm0,        QWORD PTR [rdi-8];
+
+acrossnextcol:
+        movq        xmm7,       QWORD PTR [rdi +rdx -2]
+        movd        xmm4,       DWORD PTR [rdi +rdx +6]
+
+        pslldq      xmm4,       8
+        por         xmm4,       xmm7
+
+        movdqa      xmm3,       xmm4
+        psrldq      xmm3,       2
+        punpcklbw   xmm3,       xmm0              ; mm3 = p0..p3
+        movdqa      xmm1,       xmm3              ; mm1 = p0..p3
+        psllw       xmm3,       2
+
+
+        movdqa      xmm5,       xmm4
+        psrldq      xmm5,       3
+        punpcklbw   xmm5,       xmm0              ; mm5 = p1..p4
+        paddusw     xmm3,       xmm5              ; mm3 += mm6
+
+        ; thresholding
+        movdqa      xmm7,       xmm1              ; mm7 = p0..p3
+        psubusw     xmm7,       xmm5              ; mm7 = p0..p3 - p1..p4
+        psubusw     xmm5,       xmm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     xmm7,       xmm5              ; mm7 = abs(p0..p3 - p1..p4)
+        pcmpgtw     xmm7,       xmm2
+
+        movdqa      xmm5,       xmm4
+        psrldq      xmm5,       4
+        punpcklbw   xmm5,       xmm0              ; mm5 = p2..p5
+        paddusw     xmm3,       xmm5              ; mm3 += mm5
+
+        ; thresholding
+        movdqa      xmm6,       xmm1              ; mm6 = p0..p3
+        psubusw     xmm6,       xmm5              ; mm6 = p0..p3 - p1..p4
+        psubusw     xmm5,       xmm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     xmm6,       xmm5              ; mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6              ; accumulate thresholds
+
+
+        movdqa      xmm5,       xmm4              ; mm5 = p-2..p5
+        punpcklbw   xmm5,       xmm0              ; mm5 = p-2..p1
+        paddusw     xmm3,       xmm5              ; mm3 += mm5
+
+        ; thresholding
+        movdqa      xmm6,       xmm1              ; mm6 = p0..p3
+        psubusw     xmm6,       xmm5              ; mm6 = p0..p3 - p1..p4
+        psubusw     xmm5,       xmm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     xmm6,       xmm5              ; mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6              ; accumulate thresholds
+
+        psrldq      xmm4,       1                   ; mm4 = p-1..p5
+        punpcklbw   xmm4,       xmm0              ; mm4 = p-1..p2
+        paddusw     xmm3,       xmm4              ; mm3 += mm5
+
+        ; thresholding
+        movdqa      xmm6,       xmm1              ; mm6 = p0..p3
+        psubusw     xmm6,       xmm4              ; mm6 = p0..p3 - p1..p4
+        psubusw     xmm4,       xmm1              ; mm5 = p1..p4 - p0..p3
+        paddusw     xmm6,       xmm4              ; mm6 = abs(p0..p3 - p1..p4)
+        pcmpgtw     xmm6,       xmm2
+        por         xmm7,       xmm6              ; accumulate thresholds
+
+        paddusw     xmm3,       RD42              ; mm3 += round value
+        psraw       xmm3,       3                 ; mm3 /= 8
+
+        pand        xmm1,       xmm7              ; mm1 select vals > thresh from source
+        pandn       xmm7,       xmm3              ; mm7 select vals < thresh from blurred result
+        paddusw     xmm1,       xmm7              ; combination
+
+        packuswb    xmm1,       xmm0              ; pack to bytes
+        movq        QWORD PTR [rdi+rdx-8],  mm0   ; store previous four bytes
+        movdq2q     mm0,        xmm1
+
+        add         rdx,        8
+        cmp         edx,        dword arg(5) ;cols
+        jl          acrossnextcol;
+
+        ; last 8 pixels
+        movq        QWORD PTR [rdi+rdx-8],  mm0
+
+        ; done with this rwo
+        add         rsi,rax               ; next line
+        mov         eax, dword arg(3) ;dst_pixels_per_line ; destination pitch?
+        add         rdi,rax               ; next destination
+        mov         eax, dword arg(2) ;src_pixels_per_line ; destination pitch?
+
+        dec         rcx                   ; decrement count
+        jnz         nextrow               ; next row
+
+%if ABI_IS_32BIT=1 && CONFIG_PIC=1
+    add rsp,16
+    pop rsp
+%endif
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%undef RD42
+
+
+;void vp8_mbpost_proc_down_xmm(unsigned char *dst,
+;                            int pitch, int rows, int cols,int flimit)
+extern sym(vp8_rv)
+global sym(vp8_mbpost_proc_down_xmm)
+sym(vp8_mbpost_proc_down_xmm):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 128+16
+
+    ; unsigned char d[16][8] at [rsp]
+    ; create flimit2 at [rsp+128]
+    mov         eax, dword ptr arg(4) ;flimit
+    mov         [rsp+128], eax
+    mov         [rsp+128+4], eax
+    mov         [rsp+128+8], eax
+    mov         [rsp+128+12], eax
+%define flimit4 [rsp+128]
+
+%if ABI_IS_32BIT=0
+    lea         r8,       [sym(vp8_rv) GLOBAL]
+%endif
+
+    ;rows +=8;
+    add         dword arg(2), 8
+
+    ;for(c=0; c<cols; c+=8)
+loop_col:
+            mov         rsi,        arg(0) ; s
+            pxor        xmm0,       xmm0        ;
+
+            movsxd      rax,        dword ptr arg(1) ;pitch       ;
+            neg         rax                                     ; rax = -pitch
+
+            lea         rsi,        [rsi + rax*8];              ; rdi = s[-pitch*8]
+            neg         rax
+
+
+            pxor        xmm5,       xmm5
+            pxor        xmm6,       xmm6        ;
+
+            pxor        xmm7,       xmm7        ;
+            mov         rdi,        rsi
+
+            mov         rcx,        15          ;
+
+loop_initvar:
+            movq        xmm1,       QWORD PTR [rdi];
+            punpcklbw   xmm1,       xmm0        ;
+
+            paddw       xmm5,       xmm1        ;
+            pmullw      xmm1,       xmm1        ;
+
+            movdqa      xmm2,       xmm1        ;
+            punpcklwd   xmm1,       xmm0        ;
+
+            punpckhwd   xmm2,       xmm0        ;
+            paddd       xmm6,       xmm1        ;
+
+            paddd       xmm7,       xmm2        ;
+            lea         rdi,        [rdi+rax]   ;
+
+            dec         rcx
+            jne         loop_initvar
+            ;save the var and sum
+            xor         rdx,        rdx
+loop_row:
+            movq        xmm1,       QWORD PTR [rsi]     ; [s-pitch*8]
+            movq        xmm2,       QWORD PTR [rdi]     ; [s+pitch*7]
+
+            punpcklbw   xmm1,       xmm0
+            punpcklbw   xmm2,       xmm0
+
+            paddw       xmm5,       xmm2
+            psubw       xmm5,       xmm1
+
+            pmullw      xmm2,       xmm2
+            movdqa      xmm4,       xmm2
+
+            punpcklwd   xmm2,       xmm0
+            punpckhwd   xmm4,       xmm0
+
+            paddd       xmm6,       xmm2
+            paddd       xmm7,       xmm4
+
+            pmullw      xmm1,       xmm1
+            movdqa      xmm2,       xmm1
+
+            punpcklwd   xmm1,       xmm0
+            psubd       xmm6,       xmm1
+
+            punpckhwd   xmm2,       xmm0
+            psubd       xmm7,       xmm2
+
+
+            movdqa      xmm3,       xmm6
+            pslld       xmm3,       4
+
+            psubd       xmm3,       xmm6
+            movdqa      xmm1,       xmm5
+
+            movdqa      xmm4,       xmm5
+            pmullw      xmm1,       xmm1
+
+            pmulhw      xmm4,       xmm4
+            movdqa      xmm2,       xmm1
+
+            punpcklwd   xmm1,       xmm4
+            punpckhwd   xmm2,       xmm4
+
+            movdqa      xmm4,       xmm7
+            pslld       xmm4,       4
+
+            psubd       xmm4,       xmm7
+
+            psubd       xmm3,       xmm1
+            psubd       xmm4,       xmm2
+
+            psubd       xmm3,       flimit4
+            psubd       xmm4,       flimit4
+
+            psrad       xmm3,       31
+            psrad       xmm4,       31
+
+            packssdw    xmm3,       xmm4
+            packsswb    xmm3,       xmm0
+
+            movq        xmm1,       QWORD PTR [rsi+rax*8]
+
+            movq        xmm2,       xmm1
+            punpcklbw   xmm1,       xmm0
+
+            paddw       xmm1,       xmm5
+            mov         rcx,        rdx
+
+            and         rcx,        127
+%if ABI_IS_32BIT=1 && CONFIG_PIC=1
+            push        rax
+            lea         rax,        [sym(vp8_rv) GLOBAL]
+            movdqu      xmm4,       [rax + rcx*2] ;vp8_rv[rcx*2]
+            pop         rax
+%elif ABI_IS_32BIT=0
+            movdqu      xmm4,       [r8 + rcx*2] ;vp8_rv[rcx*2]
+%else
+            movdqu      xmm4,       [sym(vp8_rv) + rcx*2]
+%endif
+
+            paddw       xmm1,       xmm4
+            ;paddw     xmm1,       eight8s
+            psraw       xmm1,       4
+
+            packuswb    xmm1,       xmm0
+            pand        xmm1,       xmm3
+
+            pandn       xmm3,       xmm2
+            por         xmm1,       xmm3
+
+            and         rcx,        15
+            movq        QWORD PTR   [rsp + rcx*8], xmm1 ;d[rcx*8]
+
+            mov         rcx,        rdx
+            sub         rcx,        8
+
+            and         rcx,        15
+            movq        mm0,        [rsp + rcx*8] ;d[rcx*8]
+
+            movq        [rsi],      mm0
+            lea         rsi,        [rsi+rax]
+
+            lea         rdi,        [rdi+rax]
+            add         rdx,        1
+
+            cmp         edx,        dword arg(2) ;rows
+            jl          loop_row
+
+        add         dword arg(0), 8 ; s += 8
+        sub         dword arg(3), 8 ; cols -= 8
+        cmp         dword arg(3), 0
+        jg          loop_col
+
+    add         rsp, 128+16
+    pop         rsp
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%undef flimit4
+
+
+;void vp8_mbpost_proc_across_ip_xmm(unsigned char *src,
+;                                int pitch, int rows, int cols,int flimit)
+global sym(vp8_mbpost_proc_across_ip_xmm)
+sym(vp8_mbpost_proc_across_ip_xmm):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 16
+
+    ; create flimit4 at [rsp]
+    mov         eax, dword ptr arg(4) ;flimit
+    mov         [rsp], eax
+    mov         [rsp+4], eax
+    mov         [rsp+8], eax
+    mov         [rsp+12], eax
+%define flimit4 [rsp]
+
+
+    ;for(r=0;r<rows;r++)
+ip_row_loop:
+
+        xor         rdx,    rdx ;sumsq=0;
+        xor         rcx,    rcx ;sum=0;
+        mov         rsi,    arg(0); s
+        mov         rdi,    -8
+ip_var_loop:
+        ;for(i=-8;i<=6;i++)
+        ;{
+        ;    sumsq += s[i]*s[i];
+        ;    sum   += s[i];
+        ;}
+        movzx       eax, byte [rsi+rdi]
+        add         ecx, eax
+        mul         al
+        add         edx, eax
+        add         rdi, 1
+        cmp         rdi, 6
+        jle         ip_var_loop
+
+
+            ;mov         rax,    sumsq
+            ;movd        xmm7,   rax
+            movd        xmm7,   edx
+
+            ;mov         rax,    sum
+            ;movd        xmm6,   rax
+            movd        xmm6,   ecx
+
+            mov         rsi,    arg(0) ;s
+            xor         rcx,    rcx
+
+            movsxd      rdx,    dword arg(3) ;cols
+            add         rdx,    8
+            pxor        mm0,    mm0
+            pxor        mm1,    mm1
+
+            pxor        xmm0,   xmm0
+nextcol4:
+
+            movd        xmm1,   DWORD PTR [rsi+rcx-8]   ; -8 -7 -6 -5
+            movd        xmm2,   DWORD PTR [rsi+rcx+7]   ; +7 +8 +9 +10
+
+            punpcklbw   xmm1,   xmm0                    ; expanding
+            punpcklbw   xmm2,   xmm0                    ; expanding
+
+            punpcklwd   xmm1,   xmm0                    ; expanding to dwords
+            punpcklwd   xmm2,   xmm0                    ; expanding to dwords
+
+            psubd       xmm2,   xmm1                    ; 7--8   8--7   9--6 10--5
+            paddd       xmm1,   xmm1                    ; -8*2   -7*2   -6*2 -5*2
+
+            paddd       xmm1,   xmm2                    ; 7+-8   8+-7   9+-6 10+-5
+            pmaddwd     xmm1,   xmm2                    ; squared of 7+-8   8+-7   9+-6 10+-5
+
+            paddd       xmm6,   xmm2
+            paddd       xmm7,   xmm1
+
+            pshufd      xmm6,   xmm6,   0               ; duplicate the last ones
+            pshufd      xmm7,   xmm7,   0               ; duplicate the last ones
+
+            psrldq      xmm1,       4                   ; 8--7   9--6 10--5  0000
+            psrldq      xmm2,       4                   ; 8--7   9--6 10--5  0000
+
+            pshufd      xmm3,   xmm1,   3               ; 0000  8--7   8--7   8--7 squared
+            pshufd      xmm4,   xmm2,   3               ; 0000  8--7   8--7   8--7 squared
+
+            paddd       xmm6,   xmm4
+            paddd       xmm7,   xmm3
+
+            pshufd      xmm3,   xmm1,   01011111b       ; 0000  0000   9--6   9--6 squared
+            pshufd      xmm4,   xmm2,   01011111b       ; 0000  0000   9--6   9--6 squared
+
+            paddd       xmm7,   xmm3
+            paddd       xmm6,   xmm4
+
+            pshufd      xmm3,   xmm1,   10111111b       ; 0000  0000   8--7   8--7 squared
+            pshufd      xmm4,   xmm2,   10111111b       ; 0000  0000   8--7   8--7 squared
+
+            paddd       xmm7,   xmm3
+            paddd       xmm6,   xmm4
+
+            movdqa      xmm3,   xmm6
+            pmaddwd     xmm3,   xmm3
+
+            movdqa      xmm5,   xmm7
+            pslld       xmm5,   4
+
+            psubd       xmm5,   xmm7
+            psubd       xmm5,   xmm3
+
+            psubd       xmm5,   flimit4
+            psrad       xmm5,   31
+
+            packssdw    xmm5,   xmm0
+            packsswb    xmm5,   xmm0
+
+            movd        xmm1,   DWORD PTR [rsi+rcx]
+            movq        xmm2,   xmm1
+
+            punpcklbw   xmm1,   xmm0
+            punpcklwd   xmm1,   xmm0
+
+            paddd       xmm1,   xmm6
+            paddd       xmm1,   [four8s GLOBAL]
+
+            psrad       xmm1,   4
+            packssdw    xmm1,   xmm0
+
+            packuswb    xmm1,   xmm0
+            pand        xmm1,   xmm5
+
+            pandn       xmm5,   xmm2
+            por         xmm5,   xmm1
+
+            movd        [rsi+rcx-8],  mm0
+            movq        mm0,    mm1
+
+            movdq2q     mm1,    xmm5
+            psrldq      xmm7,   12
+
+            psrldq      xmm6,   12
+            add         rcx,    4
+
+            cmp         rcx,    rdx
+            jl          nextcol4
+
+        ;s+=pitch;
+        movsxd rax, dword arg(1)
+        add    arg(0), rax
+
+        sub dword arg(2), 1 ;rows-=1
+        cmp dword arg(2), 0
+        jg ip_row_loop
+
+    add         rsp, 16
+    pop         rsp
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+%undef flimit4
+
+
+;void vp8_plane_add_noise_wmt (unsigned char *Start, unsigned char *noise,
+;                            unsigned char blackclamp[16],
+;                            unsigned char whiteclamp[16],
+;                            unsigned char bothclamp[16],
+;                            unsigned int Width, unsigned int Height, int Pitch)
+extern sym(rand)
+global sym(vp8_plane_add_noise_wmt)
+sym(vp8_plane_add_noise_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+addnoise_loop:
+    call sym(rand) WRT_PLT
+    mov     rcx, arg(1) ;noise
+    and     rax, 0xff
+    add     rcx, rax
+
+    ; we rely on the fact that the clamping vectors are stored contiguously
+    ; in black/white/both order. Note that we have to reload this here because
+    ; rdx could be trashed by rand()
+    mov     rdx, arg(2) ; blackclamp
+
+
+            mov     rdi, rcx
+            movsxd  rcx, dword arg(5) ;[Width]
+            mov     rsi, arg(0) ;Pos
+            xor         rax,rax
+
+addnoise_nextset:
+            movdqu      xmm1,[rsi+rax]         ; get the source
+
+            psubusb     xmm1, [rdx]    ;blackclamp        ; clamp both sides so we don't outrange adding noise
+            paddusb     xmm1, [rdx+32] ;bothclamp
+            psubusb     xmm1, [rdx+16] ;whiteclamp
+
+            movdqu      xmm2,[rdi+rax]         ; get the noise for this line
+            paddb       xmm1,xmm2              ; add it in
+            movdqu      [rsi+rax],xmm1         ; store the result
+
+            add         rax,16                 ; move to the next line
+
+            cmp         rax, rcx
+            jl          addnoise_nextset
+
+    movsxd  rax, dword arg(7) ; Pitch
+    add     arg(0), rax ; Start += Pitch
+    sub     dword arg(6), 1   ; Height -= 1
+    jg      addnoise_loop
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+SECTION_RODATA
+align 16
+rd42:
+    times 8 dw 0x04
+four8s:
+    times 4 dd 8
diff --git a/vp8/common/x86/postproc_x86.h b/vp8/common/x86/postproc_x86.h
new file mode 100644
index 0000000..49a1907
--- /dev/null
+++ b/vp8/common/x86/postproc_x86.h
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef POSTPROC_X86_H
+#define POSTPROC_X86_H
+
+/* Note:
+ *
+ * This platform is commonly built for runtime CPU detection. If you modify
+ * any of the function mappings present in this file, be sure to also update
+ * them in the function pointer initialization code
+ */
+
+#if HAVE_MMX
+extern prototype_postproc_inplace(vp8_mbpost_proc_down_mmx);
+extern prototype_postproc(vp8_post_proc_down_and_across_mmx);
+extern prototype_postproc_addnoise(vp8_plane_add_noise_mmx);
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_postproc_down
+#define vp8_postproc_down vp8_mbpost_proc_down_mmx
+
+#undef  vp8_postproc_downacross
+#define vp8_postproc_downacross vp8_post_proc_down_and_across_mmx
+
+#undef  vp8_postproc_addnoise
+#define vp8_postproc_addnoise vp8_plane_add_noise_mmx
+
+#endif
+#endif
+
+
+#if HAVE_SSE2
+extern prototype_postproc_inplace(vp8_mbpost_proc_down_xmm);
+extern prototype_postproc_inplace(vp8_mbpost_proc_across_ip_xmm);
+extern prototype_postproc(vp8_post_proc_down_and_across_xmm);
+extern prototype_postproc_addnoise(vp8_plane_add_noise_wmt);
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_postproc_down
+#define vp8_postproc_down vp8_mbpost_proc_down_xmm
+
+#undef  vp8_postproc_across
+#define vp8_postproc_across vp8_mbpost_proc_across_ip_xmm
+
+#undef  vp8_postproc_downacross
+#define vp8_postproc_downacross vp8_post_proc_down_and_across_xmm
+
+#undef  vp8_postproc_addnoise
+#define vp8_postproc_addnoise vp8_plane_add_noise_wmt
+
+
+#endif
+#endif
+
+#endif
diff --git a/vp8/common/x86/recon_mmx.asm b/vp8/common/x86/recon_mmx.asm
new file mode 100644
index 0000000..ba60c5d
--- /dev/null
+++ b/vp8/common/x86/recon_mmx.asm
@@ -0,0 +1,320 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+;void vp8_recon_b_mmx(unsigned char *s, short *q, unsigned char *d, int stride)
+global sym(vp8_recon_b_mmx)
+sym(vp8_recon_b_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov       rsi, arg(0) ;s
+        mov       rdi, arg(2) ;d
+        mov       rdx, arg(1) ;q
+        movsxd    rax, dword ptr arg(3) ;stride
+        pxor      mm0, mm0
+
+        movd      mm1, [rsi]
+        punpcklbw mm1, mm0
+        paddsw    mm1, [rdx]
+        packuswb  mm1,  mm0              ; pack and unpack to saturate
+        movd      [rdi], mm1
+
+        movd      mm2, [rsi+16]
+        punpcklbw mm2, mm0
+        paddsw    mm2, [rdx+32]
+        packuswb  mm2, mm0              ; pack and unpack to saturate
+        movd      [rdi+rax], mm2
+
+        movd      mm3, [rsi+32]
+        punpcklbw mm3, mm0
+        paddsw    mm3, [rdx+64]
+        packuswb  mm3,  mm0              ; pack and unpack to saturate
+        movd      [rdi+2*rax], mm3
+
+        add       rdi, rax
+        movd      mm4, [rsi+48]
+        punpcklbw mm4, mm0
+        paddsw    mm4, [rdx+96]
+        packuswb  mm4, mm0              ; pack and unpack to saturate
+        movd      [rdi+2*rax], mm4
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void copy_mem8x8_mmx(
+;    unsigned char *src,
+;    int src_stride,
+;    unsigned char *dst,
+;    int dst_stride
+;    )
+global sym(vp8_copy_mem8x8_mmx)
+sym(vp8_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(vp8_copy_mem8x4_mmx)
+sym(vp8_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(vp8_copy_mem16x16_mmx)
+sym(vp8_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/vp8/common/x86/recon_sse2.asm b/vp8/common/x86/recon_sse2.asm
new file mode 100644
index 0000000..f2685a7
--- /dev/null
+++ b/vp8/common/x86/recon_sse2.asm
@@ -0,0 +1,228 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+;void vp8_recon2b_sse2(unsigned char *s, short *q, unsigned char *d, int stride)
+global sym(vp8_recon2b_sse2)
+sym(vp8_recon2b_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi,        arg(0) ;s
+        mov         rdi,        arg(2) ;d
+        mov         rdx,        arg(1) ;q
+        movsxd      rax,        dword ptr arg(3) ;stride
+        pxor        xmm0,       xmm0
+
+        movq        xmm1,       MMWORD PTR [rsi]
+        punpcklbw   xmm1,       xmm0
+        paddsw      xmm1,       XMMWORD PTR [rdx]
+        packuswb    xmm1,       xmm0              ; pack and unpack to saturate
+        movq        MMWORD PTR [rdi],   xmm1
+
+
+        movq        xmm2,       MMWORD PTR [rsi+8]
+        punpcklbw   xmm2,       xmm0
+        paddsw      xmm2,       XMMWORD PTR [rdx+16]
+        packuswb    xmm2,       xmm0              ; pack and unpack to saturate
+        movq        MMWORD PTR [rdi+rax],   xmm2
+
+
+        movq        xmm3,       MMWORD PTR [rsi+16]
+        punpcklbw   xmm3,       xmm0
+        paddsw      xmm3,       XMMWORD PTR [rdx+32]
+        packuswb    xmm3,       xmm0              ; pack and unpack to saturate
+        movq        MMWORD PTR [rdi+rax*2], xmm3
+
+        add         rdi, rax
+        movq        xmm4,       MMWORD PTR [rsi+24]
+        punpcklbw   xmm4,       xmm0
+        paddsw      xmm4,       XMMWORD PTR [rdx+48]
+        packuswb    xmm4,       xmm0              ; pack and unpack to saturate
+        movq        MMWORD PTR [rdi+rax*2], xmm4
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_recon4b_sse2(unsigned char *s, short *q, unsigned char *d, int stride)
+global sym(vp8_recon4b_sse2)
+sym(vp8_recon4b_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi,        arg(0) ;s
+        mov         rdi,        arg(2) ;d
+        mov         rdx,        arg(1) ;q
+        movsxd      rax,        dword ptr arg(3) ;stride
+        pxor        xmm0,       xmm0
+
+        movdqa      xmm1,       XMMWORD PTR [rsi]
+        movdqa      xmm5,       xmm1
+        punpcklbw   xmm1,       xmm0
+        punpckhbw   xmm5,       xmm0
+        paddsw      xmm1,       XMMWORD PTR [rdx]
+        paddsw      xmm5,       XMMWORD PTR [rdx+16]
+        packuswb    xmm1,       xmm5              ; pack and unpack to saturate
+        movdqa      XMMWORD PTR [rdi],  xmm1
+
+
+        movdqa      xmm2,       XMMWORD PTR [rsi+16]
+        movdqa      xmm6,       xmm2
+        punpcklbw   xmm2,       xmm0
+        punpckhbw   xmm6,       xmm0
+        paddsw      xmm2,       XMMWORD PTR [rdx+32]
+        paddsw      xmm6,       XMMWORD PTR [rdx+48]
+        packuswb    xmm2,       xmm6              ; pack and unpack to saturate
+        movdqa      XMMWORD PTR [rdi+rax],  xmm2
+
+
+        movdqa      xmm3,       XMMWORD PTR [rsi+32]
+        movdqa      xmm7,       xmm3
+        punpcklbw   xmm3,       xmm0
+        punpckhbw   xmm7,       xmm0
+        paddsw      xmm3,       XMMWORD PTR [rdx+64]
+        paddsw      xmm7,       XMMWORD PTR [rdx+80]
+        packuswb    xmm3,       xmm7              ; pack and unpack to saturate
+        movdqa      XMMWORD PTR [rdi+rax*2],    xmm3
+
+        add       rdi, rax
+        movdqa      xmm4,       XMMWORD PTR [rsi+48]
+        movdqa      xmm5,       xmm4
+        punpcklbw   xmm4,       xmm0
+        punpckhbw   xmm5,       xmm0
+        paddsw      xmm4,       XMMWORD PTR [rdx+96]
+        paddsw      xmm5,       XMMWORD PTR [rdx+112]
+        packuswb    xmm4,       xmm5              ; pack and unpack to saturate
+        movdqa      XMMWORD PTR [rdi+rax*2],    xmm4
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void copy_mem16x16_sse2(
+;    unsigned char *src,
+;    int src_stride,
+;    unsigned char *dst,
+;    int dst_stride
+;    )
+global sym(vp8_copy_mem16x16_sse2)
+sym(vp8_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/vp8/common/x86/recon_x86.h b/vp8/common/x86/recon_x86.h
new file mode 100644
index 0000000..c469778
--- /dev/null
+++ b/vp8/common/x86/recon_x86.h
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef RECON_X86_H
+#define RECON_X86_H
+
+/* Note:
+ *
+ * This platform is commonly built for runtime CPU detection. If you modify
+ * any of the function mappings present in this file, be sure to also update
+ * them in the function pointer initialization code
+ */
+
+#if HAVE_MMX
+extern prototype_recon_block(vp8_recon_b_mmx);
+extern prototype_copy_block(vp8_copy_mem8x8_mmx);
+extern prototype_copy_block(vp8_copy_mem8x4_mmx);
+extern prototype_copy_block(vp8_copy_mem16x16_mmx);
+
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_recon_recon
+#define vp8_recon_recon vp8_recon_b_mmx
+
+#undef  vp8_recon_copy8x8
+#define vp8_recon_copy8x8 vp8_copy_mem8x8_mmx
+
+#undef  vp8_recon_copy8x4
+#define vp8_recon_copy8x4 vp8_copy_mem8x4_mmx
+
+#undef  vp8_recon_copy16x16
+#define vp8_recon_copy16x16 vp8_copy_mem16x16_mmx
+
+#endif
+#endif
+
+#if HAVE_SSE2
+extern prototype_recon_block(vp8_recon2b_sse2);
+extern prototype_recon_block(vp8_recon4b_sse2);
+extern prototype_copy_block(vp8_copy_mem16x16_sse2);
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_recon_recon2
+#define vp8_recon_recon2 vp8_recon2b_sse2
+
+#undef  vp8_recon_recon4
+#define vp8_recon_recon4 vp8_recon4b_sse2
+
+#undef  vp8_recon_copy16x16
+#define vp8_recon_copy16x16 vp8_copy_mem16x16_sse2
+
+#endif
+#endif
+#endif
diff --git a/vp8/common/x86/subpixel_mmx.asm b/vp8/common/x86/subpixel_mmx.asm
new file mode 100644
index 0000000..c502118
--- /dev/null
+++ b/vp8/common/x86/subpixel_mmx.asm
@@ -0,0 +1,817 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+
+%define BLOCK_HEIGHT_WIDTH 4
+%define vp8_filter_weight 128
+%define VP8_FILTER_SHIFT  7
+
+
+;void vp8_filter_block1d_h6_mmx
+;(
+;    unsigned char   *src_ptr,
+;    unsigned short  *output_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned int    pixel_step,
+;    unsigned int    output_height,
+;    unsigned int    output_width,
+;    short           * vp8_filter
+;)
+global sym(vp8_filter_block1d_h6_mmx)
+sym(vp8_filter_block1d_h6_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rdx,    arg(6) ;vp8_filter
+
+        movq        mm1,    [rdx + 16]             ; do both the negative taps first!!!
+        movq        mm2,    [rdx + 32]         ;
+        movq        mm6,    [rdx + 48]        ;
+        movq        mm7,    [rdx + 64]        ;
+
+        mov         rdi,    arg(1) ;output_ptr
+        mov         rsi,    arg(0) ;src_ptr
+        movsxd      rcx,    dword ptr arg(4) ;output_height
+        movsxd      rax,    dword ptr arg(5) ;output_width      ; destination pitch?
+        pxor        mm0,    mm0              ; mm0 = 00000000
+
+nextrow:
+        movq        mm3,    [rsi-2]          ; mm3 = p-2..p5
+        movq        mm4,    mm3              ; mm4 = p-2..p5
+        psrlq       mm3,    8                ; mm3 = p-1..p5
+        punpcklbw   mm3,    mm0              ; mm3 = p-1..p2
+        pmullw      mm3,    mm1              ; mm3 *= kernel 1 modifiers.
+
+        movq        mm5,    mm4              ; mm5 = p-2..p5
+        punpckhbw   mm4,    mm0              ; mm5 = p2..p5
+        pmullw      mm4,    mm7              ; mm5 *= kernel 4 modifiers
+        paddsw      mm3,    mm4              ; mm3 += mm5
+
+        movq        mm4,    mm5              ; mm4 = p-2..p5;
+        psrlq       mm5,    16               ; mm5 = p0..p5;
+        punpcklbw   mm5,    mm0              ; mm5 = p0..p3
+        pmullw      mm5,    mm2              ; mm5 *= kernel 2 modifiers
+        paddsw      mm3,    mm5              ; mm3 += mm5
+
+        movq        mm5,    mm4              ; mm5 = p-2..p5
+        psrlq       mm4,    24               ; mm4 = p1..p5
+        punpcklbw   mm4,    mm0              ; mm4 = p1..p4
+        pmullw      mm4,    mm6              ; mm5 *= kernel 3 modifiers
+        paddsw      mm3,    mm4              ; mm3 += mm5
+
+        ; do outer positive taps
+        movd        mm4,    [rsi+3]
+        punpcklbw   mm4,    mm0              ; mm5 = p3..p6
+        pmullw      mm4,    [rdx+80]         ; mm5 *= kernel 0 modifiers
+        paddsw      mm3,    mm4              ; mm3 += mm5
+
+        punpcklbw   mm5,    mm0              ; mm5 = p-2..p1
+        pmullw      mm5,    [rdx]            ; mm5 *= kernel 5 modifiers
+        paddsw      mm3,    mm5              ; mm3 += mm5
+
+        paddsw      mm3,    [rd GLOBAL]               ; mm3 += round value
+        psraw       mm3,    VP8_FILTER_SHIFT     ; mm3 /= 128
+        packuswb    mm3,    mm0              ; pack and unpack to saturate
+        punpcklbw   mm3,    mm0              ;
+
+        movq        [rdi],  mm3              ; store the results in the destination
+
+%if ABI_IS_32BIT
+        add         rsi,    dword ptr arg(2) ;src_pixels_per_line ; next line
+        add         rdi,    rax;
+%else
+        movsxd      r8,     dword ptr arg(2) ;src_pixels_per_line
+        add         rdi,    rax;
+
+        add         rsi,    r8               ; next line
+%endif
+
+        dec         rcx                      ; decrement count
+        jnz         nextrow                  ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;
+; THIS FUNCTION APPEARS TO BE UNUSED
+;
+;void vp8_filter_block1d_v6_mmx
+;(
+;   short *src_ptr,
+;   unsigned char *output_ptr,
+;   unsigned int pixels_per_line,
+;   unsigned int pixel_step,
+;   unsigned int output_height,
+;   unsigned int output_width,
+;   short * vp8_filter
+;)
+global sym(vp8_filter_block1d_v6_mmx)
+sym(vp8_filter_block1d_v6_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        movq      mm5, [rd GLOBAL]
+        push        rbx
+        mov         rbx, arg(6) ;vp8_filter
+        movq      mm1, [rbx + 16]             ; do both the negative taps first!!!
+        movq      mm2, [rbx + 32]         ;
+        movq      mm6, [rbx + 48]        ;
+        movq      mm7, [rbx + 64]        ;
+
+        movsxd      rdx, dword ptr arg(2) ;pixels_per_line
+        mov         rdi, arg(1) ;output_ptr
+        mov         rsi, arg(0) ;src_ptr
+        sub         rsi, rdx
+        sub         rsi, rdx
+        movsxd      rcx, DWORD PTR arg(4) ;output_height
+        movsxd      rax, DWORD PTR arg(5) ;output_width      ; destination pitch?
+        pxor        mm0, mm0              ; mm0 = 00000000
+
+
+nextrow_v:
+        movq        mm3, [rsi+rdx]        ; mm3 = p0..p8  = row -1
+        pmullw      mm3, mm1              ; mm3 *= kernel 1 modifiers.
+
+
+        movq        mm4, [rsi + 4*rdx]      ; mm4 = p0..p3  = row 2
+        pmullw      mm4, mm7              ; mm4 *= kernel 4 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+        movq        mm4, [rsi + 2*rdx]           ; mm4 = p0..p3  = row 0
+        pmullw      mm4, mm2              ; mm4 *= kernel 2 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+        movq        mm4, [rsi]            ; mm4 = p0..p3  = row -2
+        pmullw      mm4, [rbx]            ; mm4 *= kernel 0 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+
+        add         rsi, rdx              ; move source forward 1 line to avoid 3 * pitch
+        movq        mm4, [rsi + 2*rdx]     ; mm4 = p0..p3  = row 1
+        pmullw      mm4, mm6              ; mm4 *= kernel 3 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+        movq        mm4, [rsi + 4*rdx]    ; mm4 = p0..p3  = row 3
+        pmullw      mm4, [rbx +80]        ; mm4 *= kernel 3 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+
+        paddsw      mm3, mm5               ; mm3 += round value
+        psraw       mm3, VP8_FILTER_SHIFT     ; mm3 /= 128
+        packuswb    mm3, mm0              ; pack and saturate
+
+        movd        [rdi],mm3             ; store the results in the destination
+
+        add         rdi,rax;
+
+        dec         rcx                   ; decrement count
+        jnz         nextrow_v             ; next row
+
+        pop         rbx
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_filter_block1dc_v6_mmx
+;(
+;   short *src_ptr,
+;   unsigned char *output_ptr,
+;    int output_pitch,
+;   unsigned int pixels_per_line,
+;   unsigned int pixel_step,
+;   unsigned int output_height,
+;   unsigned int output_width,
+;   short * vp8_filter
+;)
+global sym(vp8_filter_block1dc_v6_mmx)
+sym(vp8_filter_block1dc_v6_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        movq      mm5, [rd GLOBAL]
+        push        rbx
+        mov         rbx, arg(7) ;vp8_filter
+        movq      mm1, [rbx + 16]             ; do both the negative taps first!!!
+        movq      mm2, [rbx + 32]         ;
+        movq      mm6, [rbx + 48]        ;
+        movq      mm7, [rbx + 64]        ;
+
+        movsxd      rdx, dword ptr arg(3) ;pixels_per_line
+        mov         rdi, arg(1) ;output_ptr
+        mov         rsi, arg(0) ;src_ptr
+        sub         rsi, rdx
+        sub         rsi, rdx
+        movsxd      rcx, DWORD PTR arg(5) ;output_height
+        movsxd      rax, DWORD PTR arg(2) ;output_pitch      ; destination pitch?
+        pxor        mm0, mm0              ; mm0 = 00000000
+
+
+nextrow_cv:
+        movq        mm3, [rsi+rdx]        ; mm3 = p0..p8  = row -1
+        pmullw      mm3, mm1              ; mm3 *= kernel 1 modifiers.
+
+
+        movq        mm4, [rsi + 4*rdx]      ; mm4 = p0..p3  = row 2
+        pmullw      mm4, mm7              ; mm4 *= kernel 4 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+        movq        mm4, [rsi + 2*rdx]           ; mm4 = p0..p3  = row 0
+        pmullw      mm4, mm2              ; mm4 *= kernel 2 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+        movq        mm4, [rsi]            ; mm4 = p0..p3  = row -2
+        pmullw      mm4, [rbx]            ; mm4 *= kernel 0 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+
+        add         rsi, rdx              ; move source forward 1 line to avoid 3 * pitch
+        movq        mm4, [rsi + 2*rdx]     ; mm4 = p0..p3  = row 1
+        pmullw      mm4, mm6              ; mm4 *= kernel 3 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+        movq        mm4, [rsi + 4*rdx]    ; mm4 = p0..p3  = row 3
+        pmullw      mm4, [rbx +80]        ; mm4 *= kernel 3 modifiers.
+        paddsw      mm3, mm4              ; mm3 += mm4
+
+
+        paddsw      mm3, mm5               ; mm3 += round value
+        psraw       mm3, VP8_FILTER_SHIFT     ; mm3 /= 128
+        packuswb    mm3, mm0              ; pack and saturate
+
+        movd        [rdi],mm3             ; store the results in the destination
+        ; the subsequent iterations repeat 3 out of 4 of these reads.  Since the
+        ; recon block should be in cache this shouldn't cost much.  Its obviously
+        ; avoidable!!!.
+        lea         rdi,  [rdi+rax] ;
+        dec         rcx                   ; decrement count
+        jnz         nextrow_cv             ; next row
+
+        pop         rbx
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void bilinear_predict8x8_mmx
+;(
+;    unsigned char  *src_ptr,
+;    int   src_pixels_per_line,
+;    int  xoffset,
+;    int  yoffset,
+;   unsigned char *dst_ptr,
+;    int dst_pitch
+;)
+global sym(vp8_bilinear_predict8x8_mmx)
+sym(vp8_bilinear_predict8x8_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ;const short *HFilter = bilinear_filters_mmx[xoffset];
+    ;const short *VFilter = bilinear_filters_mmx[yoffset];
+
+        movsxd      rax,        dword ptr arg(2) ;xoffset
+        mov         rdi,        arg(4) ;dst_ptr           ;
+
+        shl         rax,        5 ; offset * 32
+        lea         rcx,        [sym(vp8_bilinear_filters_mmx) GLOBAL]
+
+        add         rax,        rcx ; HFilter
+        mov         rsi,        arg(0) ;src_ptr              ;
+
+        movsxd      rdx,        dword ptr arg(5) ;dst_pitch
+        movq        mm1,        [rax]               ;
+
+        movq        mm2,        [rax+16]            ;
+        movsxd      rax,        dword ptr arg(3) ;yoffset
+
+        pxor        mm0,        mm0                 ;
+
+        shl         rax,        5 ; offset*32
+        add         rax,        rcx ; VFilter
+
+        lea         rcx,        [rdi+rdx*8]          ;
+        movsxd      rdx,        dword ptr arg(1) ;src_pixels_per_line    ;
+
+
+
+        ; get the first horizontal line done       ;
+        movq        mm3,        [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movq        mm4,        mm3                 ; make a copy of current line
+
+        punpcklbw   mm3,        mm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   mm4,        mm0                 ;
+
+        pmullw      mm3,        mm1                 ;
+        pmullw      mm4,        mm1                 ;
+
+        movq        mm5,        [rsi+1]             ;
+        movq        mm6,        mm5                 ;
+
+        punpcklbw   mm5,        mm0                 ;
+        punpckhbw   mm6,        mm0                 ;
+
+        pmullw      mm5,        mm2                 ;
+        pmullw      mm6,        mm2                 ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm4,        mm6                 ;
+
+        paddw       mm3,        [rd GLOBAL]                  ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       mm4,        [rd GLOBAL]                  ;
+        psraw       mm4,        VP8_FILTER_SHIFT        ;
+
+        movq        mm7,        mm3                 ;
+        packuswb    mm7,        mm4                 ;
+
+        add         rsi,        rdx                 ; next line
+next_row_8x8:
+        movq        mm3,        [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movq        mm4,        mm3                 ; make a copy of current line
+
+        punpcklbw   mm3,        mm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   mm4,        mm0                 ;
+
+        pmullw      mm3,        mm1                 ;
+        pmullw      mm4,        mm1                 ;
+
+        movq        mm5,        [rsi+1]             ;
+        movq        mm6,        mm5                 ;
+
+        punpcklbw   mm5,        mm0                 ;
+        punpckhbw   mm6,        mm0                 ;
+
+        pmullw      mm5,        mm2                 ;
+        pmullw      mm6,        mm2                 ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm4,        mm6                 ;
+
+        movq        mm5,        mm7                 ;
+        movq        mm6,        mm7                 ;
+
+        punpcklbw   mm5,        mm0                 ;
+        punpckhbw   mm6,        mm0
+
+        pmullw      mm5,        [rax]               ;
+        pmullw      mm6,        [rax]               ;
+
+        paddw       mm3,        [rd GLOBAL]                  ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       mm4,        [rd GLOBAL]                  ;
+        psraw       mm4,        VP8_FILTER_SHIFT        ;
+
+        movq        mm7,        mm3                 ;
+        packuswb    mm7,        mm4                 ;
+
+
+        pmullw      mm3,        [rax+16]            ;
+        pmullw      mm4,        [rax+16]            ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm4,        mm6                 ;
+
+
+        paddw       mm3,        [rd GLOBAL]                  ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       mm4,        [rd GLOBAL]                  ;
+        psraw       mm4,        VP8_FILTER_SHIFT        ;
+
+        packuswb    mm3,        mm4
+
+        movq        [rdi],      mm3                 ; store the results in the destination
+
+%if ABI_IS_32BIT
+        add         rsi,        rdx                 ; next line
+        add         rdi,        dword ptr arg(5) ;dst_pitch                   ;
+%else
+        movsxd      r8,         dword ptr arg(5) ;dst_pitch
+        add         rsi,        rdx                 ; next line
+        add         rdi,        r8                  ;dst_pitch
+%endif
+        cmp         rdi,        rcx                 ;
+        jne         next_row_8x8
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void bilinear_predict8x4_mmx
+;(
+;    unsigned char  *src_ptr,
+;    int   src_pixels_per_line,
+;    int  xoffset,
+;    int  yoffset,
+;    unsigned char *dst_ptr,
+;    int dst_pitch
+;)
+global sym(vp8_bilinear_predict8x4_mmx)
+sym(vp8_bilinear_predict8x4_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ;const short *HFilter = bilinear_filters_mmx[xoffset];
+    ;const short *VFilter = bilinear_filters_mmx[yoffset];
+
+        movsxd      rax,        dword ptr arg(2) ;xoffset
+        mov         rdi,        arg(4) ;dst_ptr           ;
+
+        lea         rcx,        [sym(vp8_bilinear_filters_mmx) GLOBAL]
+        shl         rax,        5
+
+        mov         rsi,        arg(0) ;src_ptr              ;
+        add         rax,        rcx
+
+        movsxd      rdx,        dword ptr arg(5) ;dst_pitch
+        movq        mm1,        [rax]               ;
+
+        movq        mm2,        [rax+16]            ;
+        movsxd      rax,        dword ptr arg(3) ;yoffset
+
+        pxor        mm0,        mm0                 ;
+        shl         rax,        5
+
+        add         rax,        rcx
+        lea         rcx,        [rdi+rdx*4]          ;
+
+        movsxd      rdx,        dword ptr arg(1) ;src_pixels_per_line    ;
+
+        ; get the first horizontal line done       ;
+        movq        mm3,        [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movq        mm4,        mm3                 ; make a copy of current line
+
+        punpcklbw   mm3,        mm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   mm4,        mm0                 ;
+
+        pmullw      mm3,        mm1                 ;
+        pmullw      mm4,        mm1                 ;
+
+        movq        mm5,        [rsi+1]             ;
+        movq        mm6,        mm5                 ;
+
+        punpcklbw   mm5,        mm0                 ;
+        punpckhbw   mm6,        mm0                 ;
+
+        pmullw      mm5,        mm2                 ;
+        pmullw      mm6,        mm2                 ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm4,        mm6                 ;
+
+        paddw       mm3,        [rd GLOBAL]                  ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       mm4,        [rd GLOBAL]                  ;
+        psraw       mm4,        VP8_FILTER_SHIFT        ;
+
+        movq        mm7,        mm3                 ;
+        packuswb    mm7,        mm4                 ;
+
+        add         rsi,        rdx                 ; next line
+next_row_8x4:
+        movq        mm3,        [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movq        mm4,        mm3                 ; make a copy of current line
+
+        punpcklbw   mm3,        mm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   mm4,        mm0                 ;
+
+        pmullw      mm3,        mm1                 ;
+        pmullw      mm4,        mm1                 ;
+
+        movq        mm5,        [rsi+1]             ;
+        movq        mm6,        mm5                 ;
+
+        punpcklbw   mm5,        mm0                 ;
+        punpckhbw   mm6,        mm0                 ;
+
+        pmullw      mm5,        mm2                 ;
+        pmullw      mm6,        mm2                 ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm4,        mm6                 ;
+
+        movq        mm5,        mm7                 ;
+        movq        mm6,        mm7                 ;
+
+        punpcklbw   mm5,        mm0                 ;
+        punpckhbw   mm6,        mm0
+
+        pmullw      mm5,        [rax]               ;
+        pmullw      mm6,        [rax]               ;
+
+        paddw       mm3,        [rd GLOBAL]                  ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       mm4,        [rd GLOBAL]                  ;
+        psraw       mm4,        VP8_FILTER_SHIFT        ;
+
+        movq        mm7,        mm3                 ;
+        packuswb    mm7,        mm4                 ;
+
+
+        pmullw      mm3,        [rax+16]            ;
+        pmullw      mm4,        [rax+16]            ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm4,        mm6                 ;
+
+
+        paddw       mm3,        [rd GLOBAL]                  ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       mm4,        [rd GLOBAL]                  ;
+        psraw       mm4,        VP8_FILTER_SHIFT        ;
+
+        packuswb    mm3,        mm4
+
+        movq        [rdi],      mm3                 ; store the results in the destination
+
+%if ABI_IS_32BIT
+        add         rsi,        rdx                 ; next line
+        add         rdi,        dword ptr arg(5) ;dst_pitch                   ;
+%else
+        movsxd      r8,         dword ptr arg(5) ;dst_pitch
+        add         rsi,        rdx                 ; next line
+        add         rdi,        r8
+%endif
+        cmp         rdi,        rcx                 ;
+        jne         next_row_8x4
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void bilinear_predict4x4_mmx
+;(
+;    unsigned char  *src_ptr,
+;    int   src_pixels_per_line,
+;    int  xoffset,
+;    int  yoffset,
+;    unsigned char *dst_ptr,
+;    int dst_pitch
+;)
+global sym(vp8_bilinear_predict4x4_mmx)
+sym(vp8_bilinear_predict4x4_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ;const short *HFilter = bilinear_filters_mmx[xoffset];
+    ;const short *VFilter = bilinear_filters_mmx[yoffset];
+
+        movsxd      rax,        dword ptr arg(2) ;xoffset
+        mov         rdi,        arg(4) ;dst_ptr           ;
+
+        lea         rcx,        [sym(vp8_bilinear_filters_mmx) GLOBAL]
+        shl         rax,        5
+
+        add         rax,        rcx ; HFilter
+        mov         rsi,        arg(0) ;src_ptr              ;
+
+        movsxd      rdx,        dword ptr arg(5) ;ldst_pitch
+        movq        mm1,        [rax]               ;
+
+        movq        mm2,        [rax+16]            ;
+        movsxd      rax,        dword ptr arg(3) ;yoffset
+
+        pxor        mm0,        mm0                 ;
+        shl         rax,        5
+
+        add         rax,        rcx
+        lea         rcx,        [rdi+rdx*4]          ;
+
+        movsxd      rdx,        dword ptr arg(1) ;src_pixels_per_line    ;
+
+        ; get the first horizontal line done       ;
+        movd        mm3,        [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        punpcklbw   mm3,        mm0                 ; xx 00 01 02 03 04 05 06
+
+        pmullw      mm3,        mm1                 ;
+        movd        mm5,        [rsi+1]             ;
+
+        punpcklbw   mm5,        mm0                 ;
+        pmullw      mm5,        mm2                 ;
+
+        paddw       mm3,        mm5                 ;
+        paddw       mm3,        [rd GLOBAL]                  ; xmm3 += round value
+
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        movq        mm7,        mm3                 ;
+        packuswb    mm7,        mm0                 ;
+
+        add         rsi,        rdx                 ; next line
+next_row_4x4:
+        movd        mm3,        [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        punpcklbw   mm3,        mm0                 ; xx 00 01 02 03 04 05 06
+
+        pmullw      mm3,        mm1                 ;
+        movd        mm5,        [rsi+1]             ;
+
+        punpcklbw   mm5,        mm0                 ;
+        pmullw      mm5,        mm2                 ;
+
+        paddw       mm3,        mm5                 ;
+
+        movq        mm5,        mm7                 ;
+        punpcklbw   mm5,        mm0                 ;
+
+        pmullw      mm5,        [rax]               ;
+        paddw       mm3,        [rd GLOBAL]                  ; xmm3 += round value
+
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+        movq        mm7,        mm3                 ;
+
+        packuswb    mm7,        mm0                 ;
+
+        pmullw      mm3,        [rax+16]            ;
+        paddw       mm3,        mm5                 ;
+
+
+        paddw       mm3,        [rd GLOBAL]                  ; xmm3 += round value
+        psraw       mm3,        VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        packuswb    mm3,        mm0
+        movd        [rdi],      mm3                 ; store the results in the destination
+
+%if ABI_IS_32BIT
+        add         rsi,        rdx                 ; next line
+        add         rdi,        dword ptr arg(5) ;dst_pitch                   ;
+%else
+        movsxd      r8,         dword ptr arg(5) ;dst_pitch                   ;
+        add         rsi,        rdx                 ; next line
+        add         rdi,        r8
+%endif
+
+        cmp         rdi,        rcx                 ;
+        jne         next_row_4x4
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+SECTION_RODATA
+align 16
+rd:
+    times 4 dw 0x40
+
+align 16
+global sym(vp8_six_tap_mmx)
+sym(vp8_six_tap_mmx):
+    times 8 dw 0
+    times 8 dw 0
+    times 8 dw 128
+    times 8 dw 0
+    times 8 dw 0
+    times 8 dw 0
+
+    times 8 dw 0
+    times 8 dw -6
+    times 8 dw 123
+    times 8 dw 12
+    times 8 dw -1
+    times 8 dw 0
+
+    times 8 dw 2
+    times 8 dw -11
+    times 8 dw 108
+    times 8 dw 36
+    times 8 dw -8
+    times 8 dw 1
+
+    times 8 dw 0
+    times 8 dw -9
+    times 8 dw 93
+    times 8 dw 50
+    times 8 dw -6
+    times 8 dw 0
+
+    times 8 dw 3
+    times 8 dw -16
+    times 8 dw 77
+    times 8 dw 77
+    times 8 dw -16
+    times 8 dw 3
+
+    times 8 dw 0
+    times 8 dw -6
+    times 8 dw 50
+    times 8 dw 93
+    times 8 dw -9
+    times 8 dw 0
+
+    times 8 dw 1
+    times 8 dw -8
+    times 8 dw 36
+    times 8 dw 108
+    times 8 dw -11
+    times 8 dw 2
+
+    times 8 dw 0
+    times 8 dw -1
+    times 8 dw 12
+    times 8 dw 123
+    times 8 dw -6
+    times 8 dw 0
+
+
+align 16
+global sym(vp8_bilinear_filters_mmx)
+sym(vp8_bilinear_filters_mmx):
+    times 8 dw 128
+    times 8 dw 0
+
+    times 8 dw 112
+    times 8 dw 16
+
+    times 8 dw 96
+    times 8 dw 32
+
+    times 8 dw 80
+    times 8 dw 48
+
+    times 8 dw 64
+    times 8 dw 64
+
+    times 8 dw 48
+    times 8 dw 80
+
+    times 8 dw 32
+    times 8 dw 96
+
+    times 8 dw 16
+    times 8 dw 112
diff --git a/vp8/common/x86/subpixel_sse2.asm b/vp8/common/x86/subpixel_sse2.asm
new file mode 100644
index 0000000..dee04f2
--- /dev/null
+++ b/vp8/common/x86/subpixel_sse2.asm
@@ -0,0 +1,1032 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%define BLOCK_HEIGHT_WIDTH 4
+%define VP8_FILTER_WEIGHT 128
+%define VP8_FILTER_SHIFT  7
+
+
+;/************************************************************************************
+; Notes: filter_block1d_h6 applies a 6 tap filter horizontally to the input pixels. The
+; input pixel array has output_height rows. This routine assumes that output_height is an
+; even number. This function handles 8 pixels in horizontal direction, calculating ONE
+; rows each iteration to take advantage of the 128 bits operations.
+;*************************************************************************************/
+;void vp8_filter_block1d8_h6_sse2
+;(
+;    unsigned char  *src_ptr,
+;    unsigned short *output_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned int    pixel_step,
+;    unsigned int    output_height,
+;    unsigned int    output_width,
+;    short           *vp8_filter
+;)
+global sym(vp8_filter_block1d8_h6_sse2)
+sym(vp8_filter_block1d8_h6_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rdx,        arg(6) ;vp8_filter
+        mov         rsi,        arg(0) ;src_ptr
+
+        mov         rdi,        arg(1) ;output_ptr
+
+        movsxd      rcx,        dword ptr arg(4) ;output_height
+        movsxd      rax,        dword ptr arg(2) ;src_pixels_per_line            ; Pitch for Source
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(5) ;output_width
+%endif
+        pxor        xmm0,       xmm0                        ; clear xmm0 for unpack
+
+filter_block1d8_h6_rowloop:
+        movq        xmm3,       MMWORD PTR [rsi - 2]
+        movq        xmm1,       MMWORD PTR [rsi + 6]
+
+        prefetcht2  [rsi+rax-2]
+
+        pslldq      xmm1,       8
+        por         xmm1,       xmm3
+
+        movdqa      xmm4,       xmm1
+        movdqa      xmm5,       xmm1
+
+        movdqa      xmm6,       xmm1
+        movdqa      xmm7,       xmm1
+
+        punpcklbw   xmm3,       xmm0                        ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
+        psrldq      xmm4,       1                           ; xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1
+
+        pmullw      xmm3,       XMMWORD PTR [rdx]           ; x[-2] * H[-2]; Tap 1
+        punpcklbw   xmm4,       xmm0                        ; xx06 xx05 xx04 xx03 xx02 xx01 xx00 xx-1
+
+        psrldq      xmm5,       2                           ; xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
+        pmullw      xmm4,       XMMWORD PTR [rdx+16]        ; x[-1] * H[-1]; Tap 2
+
+
+        punpcklbw   xmm5,       xmm0                        ; xx07 xx06 xx05 xx04 xx03 xx02 xx01 xx00
+        psrldq      xmm6,       3                           ; xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01
+
+        pmullw      xmm5,       [rdx+32]                    ; x[ 0] * H[ 0]; Tap 3
+
+        punpcklbw   xmm6,       xmm0                        ; xx08 xx07 xx06 xx05 xx04 xx03 xx02 xx01
+        psrldq      xmm7,       4                           ; xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02
+
+        pmullw      xmm6,       [rdx+48]                    ; x[ 1] * h[ 1] ; Tap 4
+
+        punpcklbw   xmm7,       xmm0                        ; xx09 xx08 xx07 xx06 xx05 xx04 xx03 xx02
+        psrldq      xmm1,       5                           ; xx xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03
+
+
+        pmullw      xmm7,       [rdx+64]                    ; x[ 2] * h[ 2] ; Tap 5
+
+        punpcklbw   xmm1,       xmm0                        ; xx0a xx09 xx08 xx07 xx06 xx05 xx04 xx03
+        pmullw      xmm1,       [rdx+80]                    ; x[ 3] * h[ 3] ; Tap 6
+
+
+        paddsw      xmm4,       xmm7
+        paddsw      xmm4,       xmm5
+
+        paddsw      xmm4,       xmm3
+        paddsw      xmm4,       xmm6
+
+        paddsw      xmm4,       xmm1
+        paddsw      xmm4,       [rd GLOBAL]
+
+        psraw       xmm4,       7
+
+        packuswb    xmm4,       xmm0
+        punpcklbw   xmm4,       xmm0
+
+        movdqa      XMMWORD Ptr [rdi],         xmm4
+        lea         rsi,        [rsi + rax]
+
+%if ABI_IS_32BIT
+        add         rdi,        DWORD Ptr arg(5) ;[output_width]
+%else
+        add         rdi,        r8
+%endif
+        dec         rcx
+
+        jnz         filter_block1d8_h6_rowloop                ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_filter_block1d16_h6_sse2
+;(
+;    unsigned char  *src_ptr,
+;    unsigned short *output_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned int    pixel_step,
+;    unsigned int    output_height,
+;    unsigned int    output_width,
+;    short           *vp8_filter
+;)
+;/************************************************************************************
+; Notes: filter_block1d_h6 applies a 6 tap filter horizontally to the input pixels. The
+; input pixel array has output_height rows. This routine assumes that output_height is an
+; even number. This function handles 8 pixels in horizontal direction, calculating ONE
+; rows each iteration to take advantage of the 128 bits operations.
+;*************************************************************************************/
+global sym(vp8_filter_block1d16_h6_sse2)
+sym(vp8_filter_block1d16_h6_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rdx,        arg(6) ;vp8_filter
+        mov         rsi,        arg(0) ;src_ptr
+
+        mov         rdi,        arg(1) ;output_ptr
+
+        movsxd      rcx,        dword ptr arg(4) ;output_height
+        movsxd      rax,        dword ptr arg(2) ;src_pixels_per_line            ; Pitch for Source
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(5) ;output_width
+%endif
+
+        pxor        xmm0,       xmm0                        ; clear xmm0 for unpack
+
+filter_block1d16_h6_sse2_rowloop:
+        movq        xmm3,       MMWORD PTR [rsi - 2]
+        movq        xmm1,       MMWORD PTR [rsi + 6]
+
+        movq        xmm2,       MMWORD PTR [rsi +14]
+        pslldq      xmm2,       8
+
+        por         xmm2,       xmm1
+        prefetcht2  [rsi+rax-2]
+
+        pslldq      xmm1,       8
+        por         xmm1,       xmm3
+
+        movdqa      xmm4,       xmm1
+        movdqa      xmm5,       xmm1
+
+        movdqa      xmm6,       xmm1
+        movdqa      xmm7,       xmm1
+
+        punpcklbw   xmm3,       xmm0                        ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
+        psrldq      xmm4,       1                           ; xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1
+
+        pmullw      xmm3,       XMMWORD PTR [rdx]           ; x[-2] * H[-2]; Tap 1
+        punpcklbw   xmm4,       xmm0                        ; xx06 xx05 xx04 xx03 xx02 xx01 xx00 xx-1
+
+        psrldq      xmm5,       2                           ; xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
+        pmullw      xmm4,       XMMWORD PTR [rdx+16]        ; x[-1] * H[-1]; Tap 2
+
+
+        punpcklbw   xmm5,       xmm0                        ; xx07 xx06 xx05 xx04 xx03 xx02 xx01 xx00
+        psrldq      xmm6,       3                           ; xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01
+
+        pmullw      xmm5,       [rdx+32]                    ; x[ 0] * H[ 0]; Tap 3
+
+        punpcklbw   xmm6,       xmm0                        ; xx08 xx07 xx06 xx05 xx04 xx03 xx02 xx01
+        psrldq      xmm7,       4                           ; xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02
+
+        pmullw      xmm6,       [rdx+48]                    ; x[ 1] * h[ 1] ; Tap 4
+
+        punpcklbw   xmm7,       xmm0                        ; xx09 xx08 xx07 xx06 xx05 xx04 xx03 xx02
+        psrldq      xmm1,       5                           ; xx xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03
+
+
+        pmullw      xmm7,       [rdx+64]                    ; x[ 2] * h[ 2] ; Tap 5
+
+        punpcklbw   xmm1,       xmm0                        ; xx0a xx09 xx08 xx07 xx06 xx05 xx04 xx03
+        pmullw      xmm1,       [rdx+80]                    ; x[ 3] * h[ 3] ; Tap 6
+
+        paddsw      xmm4,       xmm7
+        paddsw      xmm4,       xmm5
+
+        paddsw      xmm4,       xmm3
+        paddsw      xmm4,       xmm6
+
+        paddsw      xmm4,       xmm1
+        paddsw      xmm4,       [rd GLOBAL]
+
+        psraw       xmm4,       7
+
+        packuswb    xmm4,       xmm0
+        punpcklbw   xmm4,       xmm0
+
+        movdqa      XMMWORD Ptr [rdi],         xmm4
+
+        movdqa      xmm3,       xmm2
+        movdqa      xmm4,       xmm2
+
+        movdqa      xmm5,       xmm2
+        movdqa      xmm6,       xmm2
+
+        movdqa      xmm7,       xmm2
+
+        punpcklbw   xmm3,       xmm0                        ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
+        psrldq      xmm4,       1                           ; xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1
+
+        pmullw      xmm3,       XMMWORD PTR [rdx]           ; x[-2] * H[-2]; Tap 1
+        punpcklbw   xmm4,       xmm0                        ; xx06 xx05 xx04 xx03 xx02 xx01 xx00 xx-1
+
+        psrldq      xmm5,       2                           ; xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
+        pmullw      xmm4,       XMMWORD PTR [rdx+16]        ; x[-1] * H[-1]; Tap 2
+
+
+        punpcklbw   xmm5,       xmm0                        ; xx07 xx06 xx05 xx04 xx03 xx02 xx01 xx00
+        psrldq      xmm6,       3                           ; xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01
+
+        pmullw      xmm5,       [rdx+32]                    ; x[ 0] * H[ 0]; Tap 3
+
+        punpcklbw   xmm6,       xmm0                        ; xx08 xx07 xx06 xx05 xx04 xx03 xx02 xx01
+        psrldq      xmm7,       4                           ; xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03 02
+
+        pmullw      xmm6,       [rdx+48]                    ; x[ 1] * h[ 1] ; Tap 4
+
+        punpcklbw   xmm7,       xmm0                        ; xx09 xx08 xx07 xx06 xx05 xx04 xx03 xx02
+        psrldq      xmm2,       5                           ; xx xx xx xx xx 0d 0c 0b 0a 09 08 07 06 05 04 03
+
+        pmullw      xmm7,       [rdx+64]                    ; x[ 2] * h[ 2] ; Tap 5
+
+        punpcklbw   xmm2,       xmm0                        ; xx0a xx09 xx08 xx07 xx06 xx05 xx04 xx03
+        pmullw      xmm2,       [rdx+80]                    ; x[ 3] * h[ 3] ; Tap 6
+
+
+        paddsw      xmm4,       xmm7
+        paddsw      xmm4,       xmm5
+
+        paddsw      xmm4,       xmm3
+        paddsw      xmm4,       xmm6
+
+        paddsw      xmm4,       xmm2
+        paddsw      xmm4,       [rd GLOBAL]
+
+        psraw       xmm4,       7
+
+        packuswb    xmm4,       xmm0
+        punpcklbw   xmm4,       xmm0
+
+        movdqa      XMMWORD Ptr [rdi+16],      xmm4
+
+        lea         rsi,        [rsi + rax]
+%if ABI_IS_32BIT
+        add         rdi,        DWORD Ptr arg(5) ;[output_width]
+%else
+        add         rdi,        r8
+%endif
+
+        dec         rcx
+        jnz         filter_block1d16_h6_sse2_rowloop                ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_filter_block1d8_v6_sse2
+;(
+;    short *src_ptr,
+;    unsigned char *output_ptr,
+;    int dst_ptich,
+;    unsigned int pixels_per_line,
+;    unsigned int pixel_step,
+;    unsigned int output_height,
+;    unsigned int output_width,
+;    short * vp8_filter
+;)
+;/************************************************************************************
+; Notes: filter_block1d8_v6 applies a 6 tap filter vertically to the input pixels. The
+; input pixel array has output_height rows.
+;*************************************************************************************/
+global sym(vp8_filter_block1d8_v6_sse2)
+sym(vp8_filter_block1d8_v6_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rax,        arg(7) ;vp8_filter
+        movsxd      rdx,        dword ptr arg(3) ;pixels_per_line
+
+        mov         rdi,        arg(1) ;output_ptr
+        mov         rsi,        arg(0) ;src_ptr
+
+        sub         rsi,        rdx
+        sub         rsi,        rdx
+
+        movsxd      rcx,        DWORD PTR arg(5) ;[output_height]
+        pxor        xmm0,       xmm0                        ; clear xmm0
+
+        movdqa      xmm7,       XMMWORD PTR [rd GLOBAL]
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(2) ; dst_ptich
+%endif
+
+vp8_filter_block1d8_v6_sse2_loop:
+        movdqa      xmm1,       XMMWORD PTR [rsi]
+        pmullw      xmm1,       [rax]
+
+        movdqa      xmm2,       XMMWORD PTR [rsi + rdx]
+        pmullw      xmm2,       [rax + 16]
+
+        movdqa      xmm3,       XMMWORD PTR [rsi + rdx * 2]
+        pmullw      xmm3,       [rax + 32]
+
+        movdqa      xmm5,       XMMWORD PTR [rsi + rdx * 4]
+        pmullw      xmm5,       [rax + 64]
+
+        add         rsi,        rdx
+        movdqa      xmm4,       XMMWORD PTR [rsi + rdx * 2]
+
+        pmullw      xmm4,       [rax + 48]
+        movdqa      xmm6,       XMMWORD PTR [rsi + rdx * 4]
+
+        pmullw      xmm6,       [rax + 80]
+
+        paddsw      xmm2,       xmm5
+        paddsw      xmm2,       xmm3
+
+        paddsw      xmm2,       xmm1
+        paddsw      xmm2,       xmm4
+
+        paddsw      xmm2,       xmm6
+        paddsw      xmm2,       xmm7
+
+        psraw       xmm2,       7
+        packuswb    xmm2,       xmm0              ; pack and saturate
+
+        movq        QWORD PTR [rdi], xmm2         ; store the results in the destination
+%if ABI_IS_32BIT
+        add         rdi,        DWORD PTR arg(2) ;[dst_ptich]
+%else
+        add         rdi,        r8
+%endif
+        dec         rcx         ; decrement count
+        jnz         vp8_filter_block1d8_v6_sse2_loop               ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_unpack_block1d16_h6_sse2
+;(
+;    unsigned char  *src_ptr,
+;    unsigned short *output_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned int    output_height,
+;    unsigned int    output_width
+;)
+global sym(vp8_unpack_block1d16_h6_sse2)
+sym(vp8_unpack_block1d16_h6_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi,        arg(0) ;src_ptr
+        mov         rdi,        arg(1) ;output_ptr
+
+        movsxd      rcx,        dword ptr arg(3) ;output_height
+        movsxd      rax,        dword ptr arg(2) ;src_pixels_per_line            ; Pitch for Source
+
+        pxor        xmm0,       xmm0                        ; clear xmm0 for unpack
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(4) ;output_width            ; Pitch for Source
+%endif
+
+unpack_block1d16_h6_sse2_rowloop:
+        movq        xmm1,       MMWORD PTR [rsi]            ; 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1 -2
+        movq        xmm3,       MMWORD PTR [rsi+8]          ; make copy of xmm1
+
+        punpcklbw   xmm3,       xmm0                        ; xx05 xx04 xx03 xx02 xx01 xx01 xx-1 xx-2
+        punpcklbw   xmm1,       xmm0
+
+        movdqa      XMMWORD Ptr [rdi],         xmm1
+        movdqa      XMMWORD Ptr [rdi + 16],    xmm3
+
+        lea         rsi,        [rsi + rax]
+%if ABI_IS_32BIT
+        add         rdi,        DWORD Ptr arg(4) ;[output_width]
+%else
+        add         rdi,        r8
+%endif
+        dec         rcx
+        jnz         unpack_block1d16_h6_sse2_rowloop                ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_unpack_block1d8_h6_sse2
+;(
+;    unsigned char  *src_ptr,
+;    unsigned short *output_ptr,
+;    unsigned int    src_pixels_per_line,
+;    unsigned int    output_height,
+;    unsigned int    output_width
+;)
+global sym(vp8_unpack_block1d8_h6_sse2)
+sym(vp8_unpack_block1d8_h6_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rsi,        arg(0) ;src_ptr
+        mov         rdi,        arg(1) ;output_ptr
+
+        movsxd      rcx,        dword ptr arg(3) ;output_height
+        movsxd      rax,        dword ptr arg(2) ;src_pixels_per_line            ; Pitch for Source
+
+        pxor        xmm0,       xmm0                        ; clear xmm0 for unpack
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(4) ;output_width            ; Pitch for Source
+%endif
+
+unpack_block1d8_h6_sse2_rowloop:
+        movq        xmm1,       MMWORD PTR [rsi]            ; 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 -1 -2
+        lea         rsi,        [rsi + rax]
+
+        punpcklbw   xmm1,       xmm0
+        movdqa      XMMWORD Ptr [rdi],         xmm1
+
+%if ABI_IS_32BIT
+        add         rdi,        DWORD Ptr arg(4) ;[output_width]
+%else
+        add         rdi,        r8
+%endif
+        dec         rcx
+        jnz         unpack_block1d8_h6_sse2_rowloop                ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_pack_block1d8_v6_sse2
+;(
+;    short *src_ptr,
+;    unsigned char *output_ptr,
+;    int dst_ptich,
+;    unsigned int pixels_per_line,
+;    unsigned int output_height,
+;    unsigned int output_width
+;)
+global sym(vp8_pack_block1d8_v6_sse2)
+sym(vp8_pack_block1d8_v6_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        movsxd      rdx,        dword ptr arg(3) ;pixels_per_line
+        mov         rdi,        arg(1) ;output_ptr
+
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rcx,        DWORD PTR arg(4) ;[output_height]
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(5) ;output_width            ; Pitch for Source
+%endif
+
+pack_block1d8_v6_sse2_loop:
+        movdqa      xmm0,       XMMWORD PTR [rsi]
+        packuswb    xmm0,       xmm0
+
+        movq        QWORD PTR [rdi], xmm0         ; store the results in the destination
+        lea         rsi,        [rsi+rdx]
+
+%if ABI_IS_32BIT
+        add         rdi,        DWORD Ptr arg(5) ;[output_width]
+%else
+        add         rdi,        r8
+%endif
+        dec         rcx         ; decrement count
+        jnz         pack_block1d8_v6_sse2_loop               ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_pack_block1d16_v6_sse2
+;(
+;    short *src_ptr,
+;    unsigned char *output_ptr,
+;    int dst_ptich,
+;    unsigned int pixels_per_line,
+;    unsigned int output_height,
+;    unsigned int output_width
+;)
+global sym(vp8_pack_block1d16_v6_sse2)
+sym(vp8_pack_block1d16_v6_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        movsxd      rdx,        dword ptr arg(3) ;pixels_per_line
+        mov         rdi,        arg(1) ;output_ptr
+
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rcx,        DWORD PTR arg(4) ;[output_height]
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(2) ;dst_pitch
+%endif
+
+pack_block1d16_v6_sse2_loop:
+        movdqa      xmm0,       XMMWORD PTR [rsi]
+        movdqa      xmm1,       XMMWORD PTR [rsi+16]
+
+        packuswb    xmm0,       xmm1
+        movdqa      XMMWORD PTR [rdi], xmm0         ; store the results in the destination
+
+        add         rsi,        rdx
+%if ABI_IS_32BIT
+        add         rdi,        DWORD Ptr arg(2) ;dst_pitch
+%else
+        add         rdi,        r8
+%endif
+        dec         rcx         ; decrement count
+        jnz         pack_block1d16_v6_sse2_loop               ; next row
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_bilinear_predict16x16_sse2
+;(
+;    unsigned char  *src_ptr,
+;    int   src_pixels_per_line,
+;    int  xoffset,
+;    int  yoffset,
+;    unsigned char *dst_ptr,
+;    int dst_pitch
+;)
+extern sym(vp8_bilinear_filters_mmx)
+global sym(vp8_bilinear_predict16x16_sse2)
+sym(vp8_bilinear_predict16x16_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ;const short *HFilter = bilinear_filters_mmx[xoffset]
+    ;const short *VFilter = bilinear_filters_mmx[yoffset]
+
+        lea         rcx,        [sym(vp8_bilinear_filters_mmx) GLOBAL]
+        movsxd      rax,        dword ptr arg(2) ;xoffset
+
+        cmp         rax,        0      ;skip first_pass filter if xoffset=0
+        je          b16x16_sp_only
+
+        shl         rax,        5
+        add         rax,        rcx    ;HFilter
+
+        mov         rdi,        arg(4) ;dst_ptr
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rdx,        dword ptr arg(5) ;dst_pitch
+
+        movdqa      xmm1,       [rax]
+        movdqa      xmm2,       [rax+16]
+
+        movsxd      rax,        dword ptr arg(3) ;yoffset
+
+        cmp         rax,        0      ;skip second_pass filter if yoffset=0
+        je          b16x16_fp_only
+
+        shl         rax,        5
+        add         rax,        rcx    ;VFilter
+
+        lea         rcx,        [rdi+rdx*8]
+        lea         rcx,        [rcx+rdx*8]
+        movsxd      rdx,        dword ptr arg(1) ;src_pixels_per_line
+
+        pxor        xmm0,       xmm0
+
+%if ABI_IS_32BIT=0
+        movsxd      r8,         dword ptr arg(5) ;dst_pitch
+%endif
+        ; get the first horizontal line done
+        movdqu      xmm3,       [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movdqa      xmm4,       xmm3                 ; make a copy of current line
+
+        punpcklbw   xmm3,       xmm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   xmm4,       xmm0
+
+        pmullw      xmm3,       xmm1
+        pmullw      xmm4,       xmm1
+
+        movdqu      xmm5,       [rsi+1]
+        movdqa      xmm6,       xmm5
+
+        punpcklbw   xmm5,       xmm0
+        punpckhbw   xmm6,       xmm0
+
+        pmullw      xmm5,       xmm2
+        pmullw      xmm6,       xmm2
+
+        paddw       xmm3,       xmm5
+        paddw       xmm4,       xmm6
+
+        paddw       xmm3,       [rd GLOBAL]         ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       xmm4,       [rd GLOBAL]
+        psraw       xmm4,       VP8_FILTER_SHIFT
+
+        movdqa      xmm7,       xmm3
+        packuswb    xmm7,       xmm4
+
+        add         rsi,        rdx                 ; next line
+next_row:
+        movdqu      xmm3,       [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movdqa      xmm4,       xmm3                 ; make a copy of current line
+
+        punpcklbw   xmm3,       xmm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   xmm4,       xmm0
+
+        pmullw      xmm3,       xmm1
+        pmullw      xmm4,       xmm1
+
+        movdqu      xmm5,       [rsi+1]
+        movdqa      xmm6,       xmm5
+
+        punpcklbw   xmm5,       xmm0
+        punpckhbw   xmm6,       xmm0
+
+        pmullw      xmm5,       xmm2
+        pmullw      xmm6,       xmm2
+
+        paddw       xmm3,       xmm5
+        paddw       xmm4,       xmm6
+
+        movdqa      xmm5,       xmm7
+        movdqa      xmm6,       xmm7
+
+        punpcklbw   xmm5,       xmm0
+        punpckhbw   xmm6,       xmm0
+
+        pmullw      xmm5,       [rax]
+        pmullw      xmm6,       [rax]
+
+        paddw       xmm3,       [rd GLOBAL]         ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       xmm4,       [rd GLOBAL]
+        psraw       xmm4,       VP8_FILTER_SHIFT
+
+        movdqa      xmm7,       xmm3
+        packuswb    xmm7,       xmm4
+
+        pmullw      xmm3,       [rax+16]
+        pmullw      xmm4,       [rax+16]
+
+        paddw       xmm3,       xmm5
+        paddw       xmm4,       xmm6
+
+        paddw       xmm3,       [rd GLOBAL]         ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       xmm4,       [rd GLOBAL]
+        psraw       xmm4,       VP8_FILTER_SHIFT
+
+        packuswb    xmm3,       xmm4
+        movdqa      [rdi],      xmm3                 ; store the results in the destination
+
+        add         rsi,        rdx                 ; next line
+%if ABI_IS_32BIT
+        add         rdi,        DWORD PTR arg(5) ;dst_pitch
+%else
+        add         rdi,        r8
+%endif
+
+        cmp         rdi,        rcx
+        jne         next_row
+
+        jmp         done
+
+b16x16_sp_only:
+        movsxd      rax,        dword ptr arg(3) ;yoffset
+        shl         rax,        5
+        add         rax,        rcx    ;VFilter
+
+        mov         rdi,        arg(4) ;dst_ptr
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rdx,        dword ptr arg(5) ;dst_pitch
+
+        movdqa      xmm1,       [rax]
+        movdqa      xmm2,       [rax+16]
+
+        lea         rcx,        [rdi+rdx*8]
+        lea         rcx,        [rcx+rdx*8]
+        movsxd      rax,        dword ptr arg(1) ;src_pixels_per_line
+
+        pxor        xmm0,       xmm0
+
+        ; get the first horizontal line done
+        movdqu      xmm7,       [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+
+        add         rsi,        rax                 ; next line
+next_row_spo:
+        movdqu      xmm3,       [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+
+        movdqa      xmm5,       xmm7
+        movdqa      xmm6,       xmm7
+
+        movdqa      xmm4,       xmm3                 ; make a copy of current line
+        movdqa      xmm7,       xmm3
+
+        punpcklbw   xmm5,       xmm0
+        punpckhbw   xmm6,       xmm0
+        punpcklbw   xmm3,       xmm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   xmm4,       xmm0
+
+        pmullw      xmm5,       xmm1
+        pmullw      xmm6,       xmm1
+        pmullw      xmm3,       xmm2
+        pmullw      xmm4,       xmm2
+
+        paddw       xmm3,       xmm5
+        paddw       xmm4,       xmm6
+
+        paddw       xmm3,       [rd GLOBAL]         ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       xmm4,       [rd GLOBAL]
+        psraw       xmm4,       VP8_FILTER_SHIFT
+
+        packuswb    xmm3,       xmm4
+        movdqa      [rdi],      xmm3                 ; store the results in the destination
+
+        add         rsi,        rax                 ; next line
+        add         rdi,        rdx                 ;dst_pitch
+        cmp         rdi,        rcx
+        jne         next_row_spo
+
+        jmp         done
+
+b16x16_fp_only:
+        lea         rcx,        [rdi+rdx*8]
+        lea         rcx,        [rcx+rdx*8]
+        movsxd      rax,        dword ptr arg(1) ;src_pixels_per_line
+        pxor        xmm0,       xmm0
+
+next_row_fpo:
+        movdqu      xmm3,       [rsi]               ; xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14
+        movdqa      xmm4,       xmm3                 ; make a copy of current line
+
+        punpcklbw   xmm3,       xmm0                 ; xx 00 01 02 03 04 05 06
+        punpckhbw   xmm4,       xmm0
+
+        pmullw      xmm3,       xmm1
+        pmullw      xmm4,       xmm1
+
+        movdqu      xmm5,       [rsi+1]
+        movdqa      xmm6,       xmm5
+
+        punpcklbw   xmm5,       xmm0
+        punpckhbw   xmm6,       xmm0
+
+        pmullw      xmm5,       xmm2
+        pmullw      xmm6,       xmm2
+
+        paddw       xmm3,       xmm5
+        paddw       xmm4,       xmm6
+
+        paddw       xmm3,       [rd GLOBAL]         ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        paddw       xmm4,       [rd GLOBAL]
+        psraw       xmm4,       VP8_FILTER_SHIFT
+
+        packuswb    xmm3,       xmm4
+        movdqa      [rdi],      xmm3                 ; store the results in the destination
+
+        add         rsi,        rax                 ; next line
+        add         rdi,        rdx                 ; dst_pitch
+        cmp         rdi,        rcx
+        jne         next_row_fpo
+
+done:
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_bilinear_predict8x8_sse2
+;(
+;    unsigned char  *src_ptr,
+;    int   src_pixels_per_line,
+;    int  xoffset,
+;    int  yoffset,
+;    unsigned char *dst_ptr,
+;    int dst_pitch
+;)
+extern sym(vp8_bilinear_filters_mmx)
+global sym(vp8_bilinear_predict8x8_sse2)
+sym(vp8_bilinear_predict8x8_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    ALIGN_STACK 16, rax
+    sub         rsp, 144                         ; reserve 144 bytes
+
+    ;const short *HFilter = bilinear_filters_mmx[xoffset]
+    ;const short *VFilter = bilinear_filters_mmx[yoffset]
+        lea         rcx,        [sym(vp8_bilinear_filters_mmx) GLOBAL]
+
+        mov         rsi,        arg(0) ;src_ptr
+        movsxd      rdx,        dword ptr arg(1) ;src_pixels_per_line
+
+    ;Read 9-line unaligned data in and put them on stack. This gives a big
+    ;performance boost.
+        movdqu      xmm0,       [rsi]
+        lea         rax,        [rdx + rdx*2]
+        movdqu      xmm1,       [rsi+rdx]
+        movdqu      xmm2,       [rsi+rdx*2]
+        add         rsi,        rax
+        movdqu      xmm3,       [rsi]
+        movdqu      xmm4,       [rsi+rdx]
+        movdqu      xmm5,       [rsi+rdx*2]
+        add         rsi,        rax
+        movdqu      xmm6,       [rsi]
+        movdqu      xmm7,       [rsi+rdx]
+
+        movdqa      XMMWORD PTR [rsp],            xmm0
+
+        movdqu      xmm0,       [rsi+rdx*2]
+
+        movdqa      XMMWORD PTR [rsp+16],         xmm1
+        movdqa      XMMWORD PTR [rsp+32],         xmm2
+        movdqa      XMMWORD PTR [rsp+48],         xmm3
+        movdqa      XMMWORD PTR [rsp+64],         xmm4
+        movdqa      XMMWORD PTR [rsp+80],         xmm5
+        movdqa      XMMWORD PTR [rsp+96],         xmm6
+        movdqa      XMMWORD PTR [rsp+112],        xmm7
+        movdqa      XMMWORD PTR [rsp+128],        xmm0
+
+        movsxd      rax,        dword ptr arg(2) ;xoffset
+        shl         rax,        5
+        add         rax,        rcx    ;HFilter
+
+        mov         rdi,        arg(4) ;dst_ptr
+        movsxd      rdx,        dword ptr arg(5) ;dst_pitch
+
+        movdqa      xmm1,       [rax]
+        movdqa      xmm2,       [rax+16]
+
+        movsxd      rax,        dword ptr arg(3) ;yoffset
+        shl         rax,        5
+        add         rax,        rcx    ;VFilter
+
+        lea         rcx,        [rdi+rdx*8]
+
+        movdqa      xmm5,       [rax]
+        movdqa      xmm6,       [rax+16]
+
+        pxor        xmm0,       xmm0
+
+        ; get the first horizontal line done
+        movdqa      xmm3,       XMMWORD PTR [rsp]
+        movdqa      xmm4,       xmm3                 ; make a copy of current line
+        psrldq      xmm4,       1
+
+        punpcklbw   xmm3,       xmm0                 ; 00 01 02 03 04 05 06 07
+        punpcklbw   xmm4,       xmm0                 ; 01 02 03 04 05 06 07 08
+
+        pmullw      xmm3,       xmm1
+        pmullw      xmm4,       xmm2
+
+        paddw       xmm3,       xmm4
+
+        paddw       xmm3,       [rd GLOBAL]         ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        movdqa      xmm7,       xmm3
+        add         rsp,        16                 ; next line
+next_row8x8:
+        movdqa      xmm3,       XMMWORD PTR [rsp]               ; 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
+        movdqa      xmm4,       xmm3                 ; make a copy of current line
+        psrldq      xmm4,       1
+
+        punpcklbw   xmm3,       xmm0                 ; 00 01 02 03 04 05 06 07
+        punpcklbw   xmm4,       xmm0                 ; 01 02 03 04 05 06 07 08
+
+        pmullw      xmm3,       xmm1
+        pmullw      xmm4,       xmm2
+
+        paddw       xmm3,       xmm4
+        pmullw      xmm7,       xmm5
+
+        paddw       xmm3,       [rd GLOBAL]         ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        movdqa      xmm4,       xmm3
+
+        pmullw      xmm3,       xmm6
+        paddw       xmm3,       xmm7
+
+        movdqa      xmm7,       xmm4
+
+        paddw       xmm3,       [rd GLOBAL]         ; xmm3 += round value
+        psraw       xmm3,       VP8_FILTER_SHIFT        ; xmm3 /= 128
+
+        packuswb    xmm3,       xmm0
+        movq        [rdi],      xmm3                 ; store the results in the destination
+
+        add         rsp,        16                 ; next line
+        add         rdi,        rdx
+
+        cmp         rdi,        rcx
+        jne         next_row8x8
+
+    ;add rsp, 144
+    pop rsp
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+SECTION_RODATA
+align 16
+rd:
+    times 8 dw 0x40
diff --git a/vp8/common/x86/subpixel_x86.h b/vp8/common/x86/subpixel_x86.h
new file mode 100644
index 0000000..efa7b2e
--- /dev/null
+++ b/vp8/common/x86/subpixel_x86.h
@@ -0,0 +1,88 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef SUBPIXEL_X86_H
+#define SUBPIXEL_X86_H
+
+/* Note:
+ *
+ * This platform is commonly built for runtime CPU detection. If you modify
+ * any of the function mappings present in this file, be sure to also update
+ * them in the function pointer initialization code
+ */
+
+#if HAVE_MMX
+extern prototype_subpixel_predict(vp8_sixtap_predict16x16_mmx);
+extern prototype_subpixel_predict(vp8_sixtap_predict8x8_mmx);
+extern prototype_subpixel_predict(vp8_sixtap_predict8x4_mmx);
+extern prototype_subpixel_predict(vp8_sixtap_predict4x4_mmx);
+extern prototype_subpixel_predict(vp8_bilinear_predict16x16_mmx);
+extern prototype_subpixel_predict(vp8_bilinear_predict8x8_mmx);
+extern prototype_subpixel_predict(vp8_bilinear_predict8x4_mmx);
+extern prototype_subpixel_predict(vp8_bilinear_predict4x4_mmx);
+
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_subpix_sixtap16x16
+#define vp8_subpix_sixtap16x16 vp8_sixtap_predict16x16_mmx
+
+#undef  vp8_subpix_sixtap8x8
+#define vp8_subpix_sixtap8x8 vp8_sixtap_predict8x8_mmx
+
+#undef  vp8_subpix_sixtap8x4
+#define vp8_subpix_sixtap8x4 vp8_sixtap_predict8x4_mmx
+
+#undef  vp8_subpix_sixtap4x4
+#define vp8_subpix_sixtap4x4 vp8_sixtap_predict4x4_mmx
+
+#undef  vp8_subpix_bilinear16x16
+#define vp8_subpix_bilinear16x16 vp8_bilinear_predict16x16_mmx
+
+#undef  vp8_subpix_bilinear8x8
+#define vp8_subpix_bilinear8x8 vp8_bilinear_predict8x8_mmx
+
+#undef  vp8_subpix_bilinear8x4
+#define vp8_subpix_bilinear8x4 vp8_bilinear_predict8x4_mmx
+
+#undef  vp8_subpix_bilinear4x4
+#define vp8_subpix_bilinear4x4 vp8_bilinear_predict4x4_mmx
+
+#endif
+#endif
+
+
+#if HAVE_SSE2
+extern prototype_subpixel_predict(vp8_sixtap_predict16x16_sse2);
+extern prototype_subpixel_predict(vp8_sixtap_predict8x8_sse2);
+extern prototype_subpixel_predict(vp8_sixtap_predict8x4_sse2);
+extern prototype_subpixel_predict(vp8_bilinear_predict16x16_sse2);
+extern prototype_subpixel_predict(vp8_bilinear_predict8x8_sse2);
+
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_subpix_sixtap16x16
+#define vp8_subpix_sixtap16x16 vp8_sixtap_predict16x16_sse2
+
+#undef  vp8_subpix_sixtap8x8
+#define vp8_subpix_sixtap8x8 vp8_sixtap_predict8x8_sse2
+
+#undef  vp8_subpix_sixtap8x4
+#define vp8_subpix_sixtap8x4 vp8_sixtap_predict8x4_sse2
+
+#undef  vp8_subpix_bilinear16x16
+#define vp8_subpix_bilinear16x16 vp8_bilinear_predict16x16_sse2
+
+#undef  vp8_subpix_bilinear8x8
+#define vp8_subpix_bilinear8x8 vp8_bilinear_predict8x8_sse2
+
+#endif
+#endif
+
+#endif
diff --git a/vp8/common/x86/vp8_asm_stubs.c b/vp8/common/x86/vp8_asm_stubs.c
new file mode 100644
index 0000000..68454f7
--- /dev/null
+++ b/vp8/common/x86/vp8_asm_stubs.c
@@ -0,0 +1,342 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "vpx_ports/mem.h"
+#include "subpixel.h"
+
+extern const short vp8_six_tap_mmx[8][6*8];
+extern const short vp8_bilinear_filters_mmx[8][2*8];
+
+extern void vp8_filter_block1d_h6_mmx
+(
+    unsigned char   *src_ptr,
+    unsigned short  *output_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned int    pixel_step,
+    unsigned int    output_height,
+    unsigned int    output_width,
+    const short      *vp8_filter
+);
+extern void vp8_filter_block1dc_v6_mmx
+(
+    unsigned short *src_ptr,
+    unsigned char  *output_ptr,
+    int             output_pitch,
+    unsigned int    pixels_per_line,
+    unsigned int    pixel_step,
+    unsigned int    output_height,
+    unsigned int    output_width,
+    const short    *vp8_filter
+);
+extern void vp8_filter_block1d8_h6_sse2
+(
+    unsigned char  *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned int    pixel_step,
+    unsigned int    output_height,
+    unsigned int    output_width,
+    const short    *vp8_filter
+);
+extern void vp8_filter_block1d16_h6_sse2
+(
+    unsigned char  *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned int    pixel_step,
+    unsigned int    output_height,
+    unsigned int    output_width,
+    const short    *vp8_filter
+);
+extern void vp8_filter_block1d8_v6_sse2
+(
+    unsigned short *src_ptr,
+    unsigned char *output_ptr,
+    int dst_ptich,
+    unsigned int pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const short    *vp8_filter
+);
+extern void vp8_unpack_block1d16_h6_sse2
+(
+    unsigned char  *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned int    output_height,
+    unsigned int    output_width
+);
+extern void vp8_unpack_block1d8_h6_sse2
+(
+    unsigned char  *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int    src_pixels_per_line,
+    unsigned int    output_height,
+    unsigned int    output_width
+);
+extern void vp8_pack_block1d8_v6_sse2
+(
+    unsigned short *src_ptr,
+    unsigned char *output_ptr,
+    int dst_ptich,
+    unsigned int pixels_per_line,
+    unsigned int output_height,
+    unsigned int output_width
+);
+extern void vp8_pack_block1d16_v6_sse2
+(
+    unsigned short *src_ptr,
+    unsigned char *output_ptr,
+    int dst_ptich,
+    unsigned int pixels_per_line,
+    unsigned int output_height,
+    unsigned int output_width
+);
+extern prototype_subpixel_predict(vp8_bilinear_predict8x8_mmx);
+
+
+#if HAVE_MMX
+void vp8_sixtap_predict4x4_mmx
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 16*16);  // Temp data bufffer used in filtering
+    const short *HFilter, *VFilter;
+    HFilter = vp8_six_tap_mmx[xoffset];
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line), FData2, src_pixels_per_line, 1, 9, 8, HFilter);
+    VFilter = vp8_six_tap_mmx[yoffset];
+    vp8_filter_block1dc_v6_mmx(FData2 + 8, dst_ptr, dst_pitch, 8, 4 , 4, 4, VFilter);
+
+}
+
+
+void vp8_sixtap_predict16x16_mmx
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 24*24);  // Temp data bufffer used in filtering
+
+    const short *HFilter, *VFilter;
+
+
+    HFilter = vp8_six_tap_mmx[xoffset];
+
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line),    FData2,   src_pixels_per_line, 1, 21, 32, HFilter);
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line) + 4,  FData2 + 4, src_pixels_per_line, 1, 21, 32, HFilter);
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line) + 8,  FData2 + 8, src_pixels_per_line, 1, 21, 32, HFilter);
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line) + 12, FData2 + 12, src_pixels_per_line, 1, 21, 32, HFilter);
+
+    VFilter = vp8_six_tap_mmx[yoffset];
+    vp8_filter_block1dc_v6_mmx(FData2 + 32, dst_ptr,   dst_pitch, 32, 16 , 16, 16, VFilter);
+    vp8_filter_block1dc_v6_mmx(FData2 + 36, dst_ptr + 4, dst_pitch, 32, 16 , 16, 16, VFilter);
+    vp8_filter_block1dc_v6_mmx(FData2 + 40, dst_ptr + 8, dst_pitch, 32, 16 , 16, 16, VFilter);
+    vp8_filter_block1dc_v6_mmx(FData2 + 44, dst_ptr + 12, dst_pitch, 32, 16 , 16, 16, VFilter);
+
+}
+
+
+void vp8_sixtap_predict8x8_mmx
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 256);    // Temp data bufffer used in filtering
+
+    const short *HFilter, *VFilter;
+
+    HFilter = vp8_six_tap_mmx[xoffset];
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line),    FData2,   src_pixels_per_line, 1, 13, 16, HFilter);
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line) + 4,  FData2 + 4, src_pixels_per_line, 1, 13, 16, HFilter);
+
+    VFilter = vp8_six_tap_mmx[yoffset];
+    vp8_filter_block1dc_v6_mmx(FData2 + 16, dst_ptr,   dst_pitch, 16, 8 , 8, 8, VFilter);
+    vp8_filter_block1dc_v6_mmx(FData2 + 20, dst_ptr + 4, dst_pitch, 16, 8 , 8, 8, VFilter);
+
+}
+
+
+void vp8_sixtap_predict8x4_mmx
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 256);    // Temp data bufffer used in filtering
+
+    const short *HFilter, *VFilter;
+
+    HFilter = vp8_six_tap_mmx[xoffset];
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line),    FData2,   src_pixels_per_line, 1, 9, 16, HFilter);
+    vp8_filter_block1d_h6_mmx(src_ptr - (2 * src_pixels_per_line) + 4,  FData2 + 4, src_pixels_per_line, 1, 9, 16, HFilter);
+
+    VFilter = vp8_six_tap_mmx[yoffset];
+    vp8_filter_block1dc_v6_mmx(FData2 + 16, dst_ptr,   dst_pitch, 16, 8 , 4, 8, VFilter);
+    vp8_filter_block1dc_v6_mmx(FData2 + 20, dst_ptr + 4, dst_pitch, 16, 8 , 4, 8, VFilter);
+
+}
+
+
+
+void vp8_bilinear_predict16x16_mmx
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    vp8_bilinear_predict8x8_mmx(src_ptr,   src_pixels_per_line, xoffset, yoffset, dst_ptr,   dst_pitch);
+    vp8_bilinear_predict8x8_mmx(src_ptr + 8, src_pixels_per_line, xoffset, yoffset, dst_ptr + 8, dst_pitch);
+    vp8_bilinear_predict8x8_mmx(src_ptr + 8 * src_pixels_per_line,   src_pixels_per_line, xoffset, yoffset, dst_ptr + dst_pitch * 8,   dst_pitch);
+    vp8_bilinear_predict8x8_mmx(src_ptr + 8 * src_pixels_per_line + 8, src_pixels_per_line, xoffset, yoffset, dst_ptr + dst_pitch * 8 + 8, dst_pitch);
+}
+#endif
+
+
+#if HAVE_SSE2
+void vp8_sixtap_predict16x16_sse2
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+
+)
+{
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 24*24);    // Temp data bufffer used in filtering
+
+    const short *HFilter, *VFilter;
+
+    if (xoffset)
+    {
+        HFilter = vp8_six_tap_mmx[xoffset];
+        vp8_filter_block1d16_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2,   src_pixels_per_line, 1, 21, 32, HFilter);
+    }
+    else
+    {
+        vp8_unpack_block1d16_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2,   src_pixels_per_line, 21, 32);
+    }
+
+    if (yoffset)
+    {
+        VFilter = vp8_six_tap_mmx[yoffset];
+        vp8_filter_block1d8_v6_sse2(FData2 + 32, dst_ptr,   dst_pitch, 32, 16 , 16, 16, VFilter);
+        vp8_filter_block1d8_v6_sse2(FData2 + 40, dst_ptr + 8, dst_pitch, 32, 16 , 16, 16, VFilter);
+    }
+    else
+    {
+        vp8_pack_block1d16_v6_sse2(FData2 + 32, dst_ptr,   dst_pitch, 32,  16, 16);
+    }
+}
+
+
+void vp8_sixtap_predict8x8_sse2
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 256);  // Temp data bufffer used in filtering
+    const short *HFilter, *VFilter;
+
+    if (xoffset)
+    {
+        HFilter = vp8_six_tap_mmx[xoffset];
+        vp8_filter_block1d8_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2,   src_pixels_per_line, 1, 13, 16, HFilter);
+    }
+    else
+    {
+        vp8_unpack_block1d8_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2,   src_pixels_per_line, 13, 16);
+    }
+
+    if (yoffset)
+    {
+        VFilter = vp8_six_tap_mmx[yoffset];
+        vp8_filter_block1d8_v6_sse2(FData2 + 16, dst_ptr,   dst_pitch, 16, 8 , 8, dst_pitch, VFilter);
+    }
+    else
+    {
+        vp8_pack_block1d8_v6_sse2(FData2 + 16, dst_ptr,   dst_pitch, 16,  8, dst_pitch);
+    }
+
+
+}
+
+
+void vp8_sixtap_predict8x4_sse2
+(
+    unsigned char  *src_ptr,
+    int   src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pitch
+)
+{
+    DECLARE_ALIGNED_ARRAY(16, unsigned short, FData2, 256);  // Temp data bufffer used in filtering
+    const short *HFilter, *VFilter;
+
+    if (xoffset)
+    {
+        HFilter = vp8_six_tap_mmx[xoffset];
+        vp8_filter_block1d8_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2,   src_pixels_per_line, 1, 9, 16, HFilter);
+    }
+    else
+    {
+        vp8_unpack_block1d8_h6_sse2(src_ptr - (2 * src_pixels_per_line), FData2,   src_pixels_per_line, 9, 16);
+    }
+
+    if (yoffset)
+    {
+        VFilter = vp8_six_tap_mmx[yoffset];
+        vp8_filter_block1d8_v6_sse2(FData2 + 16, dst_ptr,   dst_pitch, 16, 8 , 4, dst_pitch, VFilter);
+    }
+    else
+    {
+        vp8_pack_block1d8_v6_sse2(FData2 + 16, dst_ptr,   dst_pitch, 16,  4, dst_pitch);
+    }
+
+
+}
+#endif
diff --git a/vp8/common/x86/x86_systemdependent.c b/vp8/common/x86/x86_systemdependent.c
new file mode 100644
index 0000000..5312e06
--- /dev/null
+++ b/vp8/common/x86/x86_systemdependent.c
@@ -0,0 +1,117 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "vpx_ports/x86.h"
+#include "g_common.h"
+#include "subpixel.h"
+#include "loopfilter.h"
+#include "recon.h"
+#include "idct.h"
+#include "pragmas.h"
+#include "onyxc_int.h"
+
+void vp8_arch_x86_common_init(VP8_COMMON *ctx)
+{
+#if CONFIG_RUNTIME_CPU_DETECT
+    VP8_COMMON_RTCD *rtcd = &ctx->rtcd;
+    int flags = x86_simd_caps();
+    int mmx_enabled = flags & HAS_MMX;
+    int xmm_enabled = flags & HAS_SSE;
+    int wmt_enabled = flags & HAS_SSE2;
+
+    /* Note:
+     *
+     * This platform can be built without runtime CPU detection as well. If
+     * you modify any of the function mappings present in this file, be sure
+     * to also update them in static mapings (<arch>/filename_<arch>.h)
+     */
+
+    /* Override default functions with fastest ones for this CPU. */
+#if HAVE_MMX
+
+    if (mmx_enabled)
+    {
+        rtcd->idct.idct1        = vp8_short_idct4x4llm_1_mmx;
+        rtcd->idct.idct16       = vp8_short_idct4x4llm_mmx;
+        rtcd->idct.idct1_scalar = vp8_dc_only_idct_mmx;
+        rtcd->idct.iwalsh16     = vp8_short_inv_walsh4x4_mmx;
+        rtcd->idct.iwalsh1     = vp8_short_inv_walsh4x4_1_mmx;
+
+
+
+        rtcd->recon.recon       = vp8_recon_b_mmx;
+        rtcd->recon.copy8x8     = vp8_copy_mem8x8_mmx;
+        rtcd->recon.copy8x4     = vp8_copy_mem8x4_mmx;
+        rtcd->recon.copy16x16   = vp8_copy_mem16x16_mmx;
+
+        rtcd->subpix.sixtap16x16   = vp8_sixtap_predict16x16_mmx;
+        rtcd->subpix.sixtap8x8     = vp8_sixtap_predict8x8_mmx;
+        rtcd->subpix.sixtap8x4     = vp8_sixtap_predict8x4_mmx;
+        rtcd->subpix.sixtap4x4     = vp8_sixtap_predict4x4_mmx;
+        rtcd->subpix.bilinear16x16 = vp8_bilinear_predict16x16_mmx;
+        rtcd->subpix.bilinear8x8   = vp8_bilinear_predict8x8_mmx;
+        rtcd->subpix.bilinear8x4   = vp8_bilinear_predict8x4_mmx;
+        rtcd->subpix.bilinear4x4   = vp8_bilinear_predict4x4_mmx;
+
+        rtcd->loopfilter.normal_mb_v = vp8_loop_filter_mbv_mmx;
+        rtcd->loopfilter.normal_b_v  = vp8_loop_filter_bv_mmx;
+        rtcd->loopfilter.normal_mb_h = vp8_loop_filter_mbh_mmx;
+        rtcd->loopfilter.normal_b_h  = vp8_loop_filter_bh_mmx;
+        rtcd->loopfilter.simple_mb_v = vp8_loop_filter_mbvs_mmx;
+        rtcd->loopfilter.simple_b_v  = vp8_loop_filter_bvs_mmx;
+        rtcd->loopfilter.simple_mb_h = vp8_loop_filter_mbhs_mmx;
+        rtcd->loopfilter.simple_b_h  = vp8_loop_filter_bhs_mmx;
+
+#if CONFIG_POSTPROC
+        rtcd->postproc.down        = vp8_mbpost_proc_down_mmx;
+        //rtcd->postproc.across      = vp8_mbpost_proc_across_ip_c;
+        rtcd->postproc.downacross  = vp8_post_proc_down_and_across_mmx;
+        rtcd->postproc.addnoise    = vp8_plane_add_noise_mmx;
+#endif
+    }
+
+#endif
+#if HAVE_SSE2
+
+    if (wmt_enabled)
+    {
+        rtcd->recon.recon2      = vp8_recon2b_sse2;
+        rtcd->recon.recon4      = vp8_recon4b_sse2;
+        rtcd->recon.copy16x16   = vp8_copy_mem16x16_sse2;
+
+        rtcd->idct.iwalsh16     = vp8_short_inv_walsh4x4_sse2;
+
+        rtcd->subpix.sixtap16x16   = vp8_sixtap_predict16x16_sse2;
+        rtcd->subpix.sixtap8x8     = vp8_sixtap_predict8x8_sse2;
+        rtcd->subpix.sixtap8x4     = vp8_sixtap_predict8x4_sse2;
+        rtcd->subpix.bilinear16x16 = vp8_bilinear_predict16x16_sse2;
+        rtcd->subpix.bilinear8x8   = vp8_bilinear_predict8x8_sse2;
+
+        rtcd->loopfilter.normal_mb_v = vp8_loop_filter_mbv_sse2;
+        rtcd->loopfilter.normal_b_v  = vp8_loop_filter_bv_sse2;
+        rtcd->loopfilter.normal_mb_h = vp8_loop_filter_mbh_sse2;
+        rtcd->loopfilter.normal_b_h  = vp8_loop_filter_bh_sse2;
+        rtcd->loopfilter.simple_mb_v = vp8_loop_filter_mbvs_sse2;
+        rtcd->loopfilter.simple_b_v  = vp8_loop_filter_bvs_sse2;
+        rtcd->loopfilter.simple_mb_h = vp8_loop_filter_mbhs_sse2;
+        rtcd->loopfilter.simple_b_h  = vp8_loop_filter_bhs_sse2;
+
+#if CONFIG_POSTPROC
+        rtcd->postproc.down        = vp8_mbpost_proc_down_xmm;
+        rtcd->postproc.across      = vp8_mbpost_proc_across_ip_xmm;
+        rtcd->postproc.downacross  = vp8_post_proc_down_and_across_xmm;
+        rtcd->postproc.addnoise    = vp8_plane_add_noise_wmt;
+#endif
+    }
+
+#endif
+#endif
+}
diff --git a/vp8/decoder/arm/armv5/dequantize_v5.asm b/vp8/decoder/arm/armv5/dequantize_v5.asm
new file mode 100644
index 0000000..eb3f030
--- /dev/null
+++ b/vp8/decoder/arm/armv5/dequantize_v5.asm
@@ -0,0 +1,51 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_dequantize_b_armv5|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+q       RN  r0
+dqc     RN  r1
+cnt     RN  r2
+
+;void dequantize_b_armv5(short *Q, short *DQC)
+|vp8_dequantize_b_armv5| PROC
+    stmdb   sp!, {r4, lr}
+    ldr     r3, [q]
+    ldr     r4, [dqc], #8
+
+    mov     cnt, #4
+dequant_loop
+    smulbb  lr, r3, r4
+    smultt  r12, r3, r4
+
+    ldr     r3, [q, #4]
+    ldr     r4, [dqc, #-4]
+
+    strh    lr, [q], #2
+    strh    r12, [q], #2
+
+    smulbb  lr, r3, r4
+    smultt  r12, r3, r4
+
+    subs    cnt, cnt, #1
+    ldrne   r3, [q, #4]
+    ldrne   r4, [dqc], #8
+
+    strh    lr, [q], #2
+    strh    r12, [q], #2
+
+    bne     dequant_loop
+
+    ldmia   sp!, {r4, pc}
+    ENDP    ;|vp8_dequantize_b_arm|
+
+    END
diff --git a/vp8/decoder/arm/armv6/dboolhuff_v6.asm b/vp8/decoder/arm/armv6/dboolhuff_v6.asm
new file mode 100644
index 0000000..143e33e
--- /dev/null
+++ b/vp8/decoder/arm/armv6/dboolhuff_v6.asm
@@ -0,0 +1,162 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_decode_value_v6|
+    EXPORT  |vp8dx_start_decode_v6|
+    EXPORT  |vp8dx_stop_decode_v6|
+    EXPORT  |vp8dx_decode_bool_v6|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    INCLUDE vpx_asm_offsets.asm
+
+br      RN  r0
+prob    RN  r1
+bits    RN  r1
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+;   int z = 0;
+;   int bit;
+;   for ( bit=bits-1; bit>=0; bit-- )
+;   {
+;       z |= (vp8dx_decode_bool(br, 0x80)<<bit);
+;   }
+;   return z;
+
+;int vp8_decode_value_v6 ( BOOL_DECODER *br, int bits )
+|vp8_decode_value_v6| PROC
+    stmdb   sp!, {r4 - r6, lr}
+    mov     r4, br
+    mov     r5, bits
+    mov     r6, #0
+
+    subs    r5, r5, #1
+    bmi     decode_value_exit
+
+decode_value_loop
+    mov     prob, #0x80
+    mov     br, r4
+    bl      vp8dx_decode_bool_v6_internal     ; needed for conversion to s file
+    orr     r6, r6, r0, lsl r5
+    subs    r5, r5, #1
+    bpl     decode_value_loop
+
+decode_value_exit
+    mov     r0, r6
+    ldmia   sp!, {r4 - r6, pc}
+    ENDP    ; |vp8_decode_value_v6|
+
+
+;void vp8dx_start_decode_v6 ( BOOL_DECODER *br, unsigned char *source )
+|vp8dx_start_decode_v6| PROC
+    stmdb   sp!, {r4 - r5, lr}
+    mov     r2, #0
+    mov     r3, #255
+
+    str     r2, [br, #bool_decoder_lowvalue]
+    str     r3, [br, #bool_decoder_range]
+    str     r1, [br, #bool_decoder_buffer]
+
+    mov     r3, #8
+    mov     r2, #4
+    str     r3, [br, #bool_decoder_count]
+    str     r2, [br, #bool_decoder_pos]
+
+    ldrb    r2, [r1, #3]
+    ldrb    r3, [r1, #2]
+    ldrb    r4, [r1, #1]
+    ldrb    r5, [r1]
+
+    orr     r1, r2, r3, lsl #8
+    orr     r1, r1, r4, lsl #16
+    orr     r1, r1, r5, lsl #24
+
+    str     r1, [br, #bool_decoder_value]
+
+    ldmia   sp!, {r4 - r5, pc}
+    ENDP    ; |vp8dx_start_decode_v6|
+
+
+;void vp8dx_stop_decode_v6 ( BOOL_DECODER *bc );
+|vp8dx_stop_decode_v6| PROC
+    mov     pc, lr
+    ENDP    ; |vp8dx_stop_decode_v6|
+
+
+; bigsplit  RN  r1
+; buffer_v  RN  r1
+; count_v       RN  r4
+; range_v       RN  r2
+; value_v       RN  r3
+; pos_v     RN  r5
+; split     RN  r6
+; bit           RN  lr
+;int vp8dx_decode_bool_v6 ( BOOL_DECODER *br, int probability )
+|vp8dx_decode_bool_v6| PROC
+vp8dx_decode_bool_v6_internal
+    stmdb   sp!, {r4 - r6, lr}
+
+    ldr     r2, [br, #bool_decoder_range]
+    ldr     r3, [br, #bool_decoder_value]
+
+    mov     r6, r2, lsl #8
+    sub     r6, r6, #256                ;   split = 1 +  (((range-1) * probability) >> 8)
+    mov     r12, #1
+    smlawb  r6, r6, prob, r12
+
+    mov     lr, #0
+    subs    r5, r3, r6, lsl #24
+
+    ;cmp        r3, r1
+    movhs   lr, #1
+    movhs   r3, r5
+    subhs   r2, r2, r6
+    movlo   r2, r6
+
+    cmp     r2, #0x80
+    blt     range_less_0x80
+    ;strd   r2, r3, [br, #bool_decoder_range]
+    str     r2, [br, #bool_decoder_range]
+    str     r3, [br, #bool_decoder_value]
+    mov     r0, lr
+    ldmia   sp!, {r4 - r6, pc}
+
+range_less_0x80
+    ldr     r5, [br, #bool_decoder_pos]
+    ldr     r1, [br, #bool_decoder_buffer]
+    ldr     r4, [br, #bool_decoder_count]
+    add     r1, r1, r5
+
+    clz       r12, r2
+    sub       r12, r12, #24
+    subs      r4, r4, r12
+    ldrleb    r6, [r1], #1
+    mov       r2, r2, lsl r12
+    mov       r3, r3, lsl r12
+    addle     r4, r4, #8
+    rsble     r12, r4, #8
+    addle     r5, r5, #1
+    orrle     r3, r3, r6, lsl r12
+
+    ;strd       r2, r3, [br, #bool_decoder_range]
+    ;strd       r4, r5, [br, #bool_decoder_count]
+    str         r2, [br, #bool_decoder_range]
+    str         r3, [br, #bool_decoder_value]
+    str         r4, [br, #bool_decoder_count]
+    str         r5, [br, #bool_decoder_pos]
+
+    mov     r0, lr
+
+    ldmia   sp!, {r4 - r6, pc}
+    ENDP    ; |vp8dx_decode_bool_v6|
+
+    END
diff --git a/vp8/decoder/arm/armv6/dequantdcidct_v6.asm b/vp8/decoder/arm/armv6/dequantdcidct_v6.asm
new file mode 100644
index 0000000..3daa9b3
--- /dev/null
+++ b/vp8/decoder/arm/armv6/dequantdcidct_v6.asm
@@ -0,0 +1,202 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_dequant_dc_idct_v6|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+;void vp8_dequant_dc_idct_v6(short *input, short *dq, short *output, int pitch,int Dc)
+|vp8_dequant_dc_idct_v6| PROC
+    stmdb   sp!, {r4-r11, lr}
+
+    ldr     r6, [sp, #36]           ;load Dc
+
+    ldr     r4, [r0]                ;input
+    ldr     r5, [r1], #4            ;dq
+
+    sub     sp, sp, #4
+    str     r0, [sp]
+
+    smultt  r7, r4, r5
+
+    ldr     r4, [r0, #4]            ;input
+    ldr     r5, [r1], #4            ;dq
+
+    strh    r6, [r0], #2
+    strh    r7, [r0], #2
+
+    smulbb  r6, r4, r5
+    smultt  r7, r4, r5
+
+    ldr     r4, [r0, #4]            ;input
+    ldr     r5, [r1], #4            ;dq
+
+    strh    r6, [r0], #2
+    strh    r7, [r0], #2
+
+    mov     r12, #3
+
+dequant_dc_idct_loop
+    smulbb  r6, r4, r5
+    smultt  r7, r4, r5
+
+    ldr     r4, [r0, #4]            ;input
+    ldr     r5, [r1], #4            ;dq
+
+    strh    r6, [r0], #2
+    strh    r7, [r0], #2
+
+    smulbb  r6, r4, r5
+    smultt  r7, r4, r5
+
+    subs    r12, r12, #1
+
+    ldrne   r4, [r0, #4]
+    ldrne   r5, [r1], #4
+
+    strh    r6, [r0], #2
+    strh    r7, [r0], #2
+
+    bne     dequant_dc_idct_loop
+
+    sub     r0, r0, #32
+    mov     r1, r2
+    mov     r2, r3
+
+; short_idct4x4llm_v6_dual
+
+    mov r3, #0x00004E00 ;                   cos
+    orr r3, r3, #0x0000007B ; cospi8sqrt2minus1
+    mov r4, #0x00008A00 ;                       sin
+    orr r4, r4, #0x0000008C ; sinpi8sqrt2
+    mov r5, #0x2    ; i=2                           i
+loop1_dual_11
+    ldr r6, [r0, #(4*2)]    ; i5 | i4                               5|4
+    ldr r12, [r0, #(12*2)]  ; i13 | i12                                                     13|12
+    ldr r14, [r0, #(8*2)]   ; i9 | i8                                                               9|8
+
+    smulwt  r9, r3, r6  ; (ip[5] * cospi8sqrt2minus1) >> 16                                         5c
+    smulwb  r7, r3, r6  ; (ip[4] * cospi8sqrt2minus1) >> 16                                 4c
+    smulwt  r10, r4, r6 ; (ip[5] * sinpi8sqrt2) >> 16                                               5s
+    smulwb  r8, r4, r6  ; (ip[4] * sinpi8sqrt2) >> 16                                       4s
+    pkhbt   r7, r7, r9, lsl #16 ; 5c | 4c
+    smulwt  r11, r3, r12    ; (ip[13] * cospi8sqrt2minus1) >> 16                                                    13c
+    pkhbt   r8, r8, r10, lsl #16    ; 5s | 4s
+    uadd16  r6, r6, r7  ; 5c+5 | 4c+4
+    smulwt  r7, r4, r12 ; (ip[13] * sinpi8sqrt2) >> 16                                  13s
+    smulwb  r9, r3, r12 ; (ip[12] * cospi8sqrt2minus1) >> 16                                            12c
+    smulwb  r10, r4, r12    ; (ip[12] * sinpi8sqrt2) >> 16                                              12s
+    subs    r5, r5, #0x1    ; i--                           --
+    pkhbt   r9, r9, r11, lsl #16    ; 13c | 12c
+    ldr r11, [r0], #0x4 ; i1 | i0       ++                                          1|0
+    pkhbt   r10, r10, r7, lsl #16   ; 13s | 12s
+    uadd16  r7, r12, r9 ; 13c+13 | 12c+12
+    usub16  r7, r8, r7  ; c                                 c
+    uadd16  r6, r6, r10 ; d                             d
+    uadd16  r10, r11, r14   ; a                                             a
+    usub16  r8, r11, r14    ; b                                     b
+    uadd16  r9, r10, r6 ; a+d                                           a+d
+    usub16  r10, r10, r6    ; a-d                                               a-d
+    uadd16  r6, r8, r7  ; b+c                               b+c
+    usub16  r7, r8, r7  ; b-c                                   b-c
+    str r6, [r1, r2]    ; o5 | o4
+    add r6, r2, r2  ; pitch * 2                             p2
+    str r7, [r1, r6]    ; o9 | o8
+    add r6,  r6, r2 ; pitch * 3                             p3
+    str r10, [r1, r6]   ; o13 | o12
+    str r9, [r1], #0x4  ; o1 | o0           ++
+    bne loop1_dual_11   ;
+    mov r5, #0x2    ; i=2                           i
+    sub r0, r1, #8  ; reset input/output        i/o
+loop2_dual_22
+    ldr r6, [r0, r2]    ; i5 | i4                               5|4
+    ldr r1, [r0]    ; i1 | i0           1|0
+    ldr r12, [r0, #0x4] ; i3 | i2                                                       3|2
+    add r14, r2, #0x4   ; pitch + 2                                                             p+2
+    ldr r14, [r0, r14]  ; i7 | i6                                                               7|6
+    smulwt  r9, r3, r6  ; (ip[5] * cospi8sqrt2minus1) >> 16                                         5c
+    smulwt  r7, r3, r1  ; (ip[1] * cospi8sqrt2minus1) >> 16                                 1c
+    smulwt  r10, r4, r6 ; (ip[5] * sinpi8sqrt2) >> 16                                               5s
+    smulwt  r8, r4, r1  ; (ip[1] * sinpi8sqrt2) >> 16                                       1s
+    pkhbt   r11, r6, r1, lsl #16    ; i0 | i4                                                   0|4
+    pkhbt   r7, r9, r7, lsl #16 ; 1c | 5c
+    pkhbt   r8, r10, r8, lsl #16    ; 1s | 5s = temp1 ©                                     tc1
+    pkhtb   r1, r1, r6, asr #16 ; i1 | i5           1|5
+    uadd16  r1, r7, r1  ; 1c+1 | 5c+5 = temp2 (d)           td2
+    pkhbt   r9, r14, r12, lsl #16   ; i2 | i6                                           2|6
+    uadd16  r10, r11, r9    ; a                                             a
+    usub16  r9, r11, r9 ; b                                         b
+    pkhtb   r6, r12, r14, asr #16   ; i3 | i7                               3|7
+    subs    r5, r5, #0x1    ; i--                           --
+    smulwt  r7, r3, r6  ; (ip[3] * cospi8sqrt2minus1) >> 16                                 3c
+    smulwt  r11, r4, r6 ; (ip[3] * sinpi8sqrt2) >> 16                                                   3s
+    smulwb  r12, r3, r6 ; (ip[7] * cospi8sqrt2minus1) >> 16                                                     7c
+    smulwb  r14, r4, r6 ; (ip[7] * sinpi8sqrt2) >> 16                                                               7s
+
+    pkhbt   r7, r12, r7, lsl #16    ; 3c | 7c
+    pkhbt   r11, r14, r11, lsl #16  ; 3s | 7s = temp1 (d)                                                   td1
+    uadd16  r6, r7, r6  ; 3c+3 | 7c+7 = temp2  (c)                              tc2
+    usub16  r12, r8, r6 ; c (o1 | o5)                                                       c
+    uadd16  r6, r11, r1 ; d (o3 | o7)                               d
+    uadd16  r7, r10, r6 ; a+d                                   a+d
+    mov r8, #0x4    ; set up 4's                                        4
+    orr r8, r8, #0x40000    ;                                       4|4
+    usub16  r6, r10, r6 ; a-d                               a-d
+    uadd16  r6, r6, r8  ; a-d+4                             3|7
+    uadd16  r7, r7, r8  ; a+d+4                                 0|4
+    uadd16  r10, r9, r12    ; b+c                                               b+c
+    usub16  r1, r9, r12 ; b-c           b-c
+    uadd16  r10, r10, r8    ; b+c+4                                             1|5
+    uadd16  r1, r1, r8  ; b-c+4         2|6
+    mov r8, r10, asr #19    ; o1 >> 3
+    strh    r8, [r0, #2]    ; o1
+    mov r8, r1, asr #19 ; o2 >> 3
+    strh    r8, [r0, #4]    ; o2
+    mov r8, r6, asr #19 ; o3 >> 3
+    strh    r8, [r0, #6]    ; o3
+    mov r8, r7, asr #19 ; o0 >> 3
+    strh    r8, [r0], r2    ; o0        +p
+    sxth    r10, r10    ;
+    mov r8, r10, asr #3 ; o5 >> 3
+    strh    r8, [r0, #2]    ; o5
+    sxth    r1, r1  ;
+    mov r8, r1, asr #3  ; o6 >> 3
+    strh    r8, [r0, #4]    ; o6
+    sxth    r6, r6  ;
+    mov r8, r6, asr #3  ; o7 >> 3
+    strh    r8, [r0, #6]    ; o7
+    sxth    r7, r7  ;
+    mov r8, r7, asr #3  ; o4 >> 3
+    strh    r8, [r0], r2    ; o4        +p
+;;;;;   subs    r5, r5, #0x1    ; i--                           --
+    bne loop2_dual_22   ;
+
+
+;vpx_memset
+    ldr     r0, [sp]
+    add     sp, sp, #4
+
+    mov     r12, #0
+    str     r12, [r0]
+    str     r12, [r0, #4]
+    str     r12, [r0, #8]
+    str     r12, [r0, #12]
+    str     r12, [r0, #16]
+    str     r12, [r0, #20]
+    str     r12, [r0, #24]
+    str     r12, [r0, #28]
+
+    ldmia   sp!, {r4 - r11, pc} ; replace vars, return                      restore
+
+    ENDP    ;|vp8_dequant_dc_idct_v68|
+
+    END
diff --git a/vp8/decoder/arm/armv6/dequantidct_v6.asm b/vp8/decoder/arm/armv6/dequantidct_v6.asm
new file mode 100644
index 0000000..61bb48d
--- /dev/null
+++ b/vp8/decoder/arm/armv6/dequantidct_v6.asm
@@ -0,0 +1,183 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_dequant_idct_v6|
+    ; ARM
+    ; REQUIRE8
+    ; PRESERVE8
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+;void vp8_dequant_idct_v6(short *input, short *dq, short *output, int pitch)
+|vp8_dequant_idct_v6| PROC
+    stmdb   sp!, {r4-r11, lr}
+
+    ldr     r4, [r0]            ;input
+    ldr     r5, [r1], #4            ;dq
+
+    sub     sp, sp, #4
+    str     r0, [sp]
+
+    mov     r12, #4
+
+dequant_idct_loop
+    smulbb  r6, r4, r5
+    smultt  r7, r4, r5
+
+    ldr     r4, [r0, #4]            ;input
+    ldr     r5, [r1], #4        ;dq
+
+    strh    r6, [r0], #2
+    strh    r7, [r0], #2
+
+    smulbb  r6, r4, r5
+    smultt  r7, r4, r5
+
+    subs    r12, r12, #1
+
+    ldrne   r4, [r0, #4]
+    ldrne   r5, [r1], #4
+
+    strh    r6, [r0], #2
+    strh    r7, [r0], #2
+
+    bne     dequant_idct_loop
+
+    sub     r0, r0, #32
+    mov     r1, r2
+    mov     r2, r3
+
+; short_idct4x4llm_v6_dual
+
+    mov r3, #0x00004E00 ;                   cos
+    orr r3, r3, #0x0000007B ; cospi8sqrt2minus1
+    mov r4, #0x00008A00 ;                       sin
+    orr r4, r4, #0x0000008C ; sinpi8sqrt2
+    mov r5, #0x2    ; i=2                           i
+loop1_dual_1
+    ldr r6, [r0, #(4*2)]    ; i5 | i4                               5|4
+    ldr r12, [r0, #(12*2)]  ; i13 | i12                                                     13|12
+    ldr r14, [r0, #(8*2)]   ; i9 | i8                                                               9|8
+
+    smulwt  r9, r3, r6  ; (ip[5] * cospi8sqrt2minus1) >> 16                                         5c
+    smulwb  r7, r3, r6  ; (ip[4] * cospi8sqrt2minus1) >> 16                                 4c
+    smulwt  r10, r4, r6 ; (ip[5] * sinpi8sqrt2) >> 16                                               5s
+    smulwb  r8, r4, r6  ; (ip[4] * sinpi8sqrt2) >> 16                                       4s
+    pkhbt   r7, r7, r9, lsl #16 ; 5c | 4c
+    smulwt  r11, r3, r12    ; (ip[13] * cospi8sqrt2minus1) >> 16                                                    13c
+    pkhbt   r8, r8, r10, lsl #16    ; 5s | 4s
+    uadd16  r6, r6, r7  ; 5c+5 | 4c+4
+    smulwt  r7, r4, r12 ; (ip[13] * sinpi8sqrt2) >> 16                                  13s
+    smulwb  r9, r3, r12 ; (ip[12] * cospi8sqrt2minus1) >> 16                                            12c
+    smulwb  r10, r4, r12    ; (ip[12] * sinpi8sqrt2) >> 16                                              12s
+    subs    r5, r5, #0x1    ; i--                           --
+    pkhbt   r9, r9, r11, lsl #16    ; 13c | 12c
+    ldr r11, [r0], #0x4 ; i1 | i0       ++                                          1|0
+    pkhbt   r10, r10, r7, lsl #16   ; 13s | 12s
+    uadd16  r7, r12, r9 ; 13c+13 | 12c+12
+    usub16  r7, r8, r7  ; c                                 c
+    uadd16  r6, r6, r10 ; d                             d
+    uadd16  r10, r11, r14   ; a                                             a
+    usub16  r8, r11, r14    ; b                                     b
+    uadd16  r9, r10, r6 ; a+d                                           a+d
+    usub16  r10, r10, r6    ; a-d                                               a-d
+    uadd16  r6, r8, r7  ; b+c                               b+c
+    usub16  r7, r8, r7  ; b-c                                   b-c
+    str r6, [r1, r2]    ; o5 | o4
+    add r6, r2, r2  ; pitch * 2                             p2
+    str r7, [r1, r6]    ; o9 | o8
+    add r6,  r6, r2 ; pitch * 3                             p3
+    str r10, [r1, r6]   ; o13 | o12
+    str r9, [r1], #0x4  ; o1 | o0           ++
+    bne loop1_dual_1    ;
+    mov r5, #0x2    ; i=2                           i
+    sub r0, r1, #8  ; reset input/output        i/o
+loop2_dual_2
+    ldr r6, [r0, r2]    ; i5 | i4                               5|4
+    ldr r1, [r0]    ; i1 | i0           1|0
+    ldr r12, [r0, #0x4] ; i3 | i2                                                       3|2
+    add r14, r2, #0x4   ; pitch + 2                                                             p+2
+    ldr r14, [r0, r14]  ; i7 | i6                                                               7|6
+    smulwt  r9, r3, r6  ; (ip[5] * cospi8sqrt2minus1) >> 16                                         5c
+    smulwt  r7, r3, r1  ; (ip[1] * cospi8sqrt2minus1) >> 16                                 1c
+    smulwt  r10, r4, r6 ; (ip[5] * sinpi8sqrt2) >> 16                                               5s
+    smulwt  r8, r4, r1  ; (ip[1] * sinpi8sqrt2) >> 16                                       1s
+    pkhbt   r11, r6, r1, lsl #16    ; i0 | i4                                                   0|4
+    pkhbt   r7, r9, r7, lsl #16 ; 1c | 5c
+    pkhbt   r8, r10, r8, lsl #16    ; 1s | 5s = temp1 ©                                     tc1
+    pkhtb   r1, r1, r6, asr #16 ; i1 | i5           1|5
+    uadd16  r1, r7, r1  ; 1c+1 | 5c+5 = temp2 (d)           td2
+    pkhbt   r9, r14, r12, lsl #16   ; i2 | i6                                           2|6
+    uadd16  r10, r11, r9    ; a                                             a
+    usub16  r9, r11, r9 ; b                                         b
+    pkhtb   r6, r12, r14, asr #16   ; i3 | i7                               3|7
+    subs    r5, r5, #0x1    ; i--                           --
+    smulwt  r7, r3, r6  ; (ip[3] * cospi8sqrt2minus1) >> 16                                 3c
+    smulwt  r11, r4, r6 ; (ip[3] * sinpi8sqrt2) >> 16                                                   3s
+    smulwb  r12, r3, r6 ; (ip[7] * cospi8sqrt2minus1) >> 16                                                     7c
+    smulwb  r14, r4, r6 ; (ip[7] * sinpi8sqrt2) >> 16                                                               7s
+
+    pkhbt   r7, r12, r7, lsl #16    ; 3c | 7c
+    pkhbt   r11, r14, r11, lsl #16  ; 3s | 7s = temp1 (d)                                                   td1
+    uadd16  r6, r7, r6  ; 3c+3 | 7c+7 = temp2  (c)                              tc2
+    usub16  r12, r8, r6 ; c (o1 | o5)                                                       c
+    uadd16  r6, r11, r1 ; d (o3 | o7)                               d
+    uadd16  r7, r10, r6 ; a+d                                   a+d
+    mov r8, #0x4    ; set up 4's                                        4
+    orr r8, r8, #0x40000    ;                                       4|4
+    usub16  r6, r10, r6 ; a-d                               a-d
+    uadd16  r6, r6, r8  ; a-d+4                             3|7
+    uadd16  r7, r7, r8  ; a+d+4                                 0|4
+    uadd16  r10, r9, r12    ; b+c                                               b+c
+    usub16  r1, r9, r12 ; b-c           b-c
+    uadd16  r10, r10, r8    ; b+c+4                                             1|5
+    uadd16  r1, r1, r8  ; b-c+4         2|6
+    mov r8, r10, asr #19    ; o1 >> 3
+    strh    r8, [r0, #2]    ; o1
+    mov r8, r1, asr #19 ; o2 >> 3
+    strh    r8, [r0, #4]    ; o2
+    mov r8, r6, asr #19 ; o3 >> 3
+    strh    r8, [r0, #6]    ; o3
+    mov r8, r7, asr #19 ; o0 >> 3
+    strh    r8, [r0], r2    ; o0        +p
+    sxth    r10, r10    ;
+    mov r8, r10, asr #3 ; o5 >> 3
+    strh    r8, [r0, #2]    ; o5
+    sxth    r1, r1  ;
+    mov r8, r1, asr #3  ; o6 >> 3
+    strh    r8, [r0, #4]    ; o6
+    sxth    r6, r6  ;
+    mov r8, r6, asr #3  ; o7 >> 3
+    strh    r8, [r0, #6]    ; o7
+    sxth    r7, r7  ;
+    mov r8, r7, asr #3  ; o4 >> 3
+    strh    r8, [r0], r2    ; o4        +p
+;;;;;   subs    r5, r5, #0x1    ; i--                           --
+    bne loop2_dual_2    ;
+            ;
+
+;vpx_memset
+    ldr     r0, [sp]
+    add     sp, sp, #4
+
+    mov     r12, #0
+    str     r12, [r0]
+    str     r12, [r0, #4]
+    str     r12, [r0, #8]
+    str     r12, [r0, #12]
+    str     r12, [r0, #16]
+    str     r12, [r0, #20]
+    str     r12, [r0, #24]
+    str     r12, [r0, #28]
+
+    ldmia   sp!, {r4 - r11, pc} ; replace vars, return                      restore
+
+    ENDP    ;|vp8_dequant_idct_v6|
+
+    END
diff --git a/vp8/decoder/arm/armv6/dequantize_v6.asm b/vp8/decoder/arm/armv6/dequantize_v6.asm
new file mode 100644
index 0000000..95e3859
--- /dev/null
+++ b/vp8/decoder/arm/armv6/dequantize_v6.asm
@@ -0,0 +1,68 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_dequantize_b_loop_v6|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+;-------------------------------
+;void   vp8_dequantize_b_loop_v6(short *Q, short *DQC, short *DQ);
+; r0    short *Q,
+; r1    short *DQC
+; r2    short *DQ
+|vp8_dequantize_b_loop_v6| PROC
+    stmdb   sp!, {r4-r9, lr}
+
+    ldr     r3, [r0]                ;load Q
+    ldr     r4, [r1]                ;load DQC
+    ldr     r5, [r0, #4]
+    ldr     r6, [r1, #4]
+
+    mov     r12, #2                 ;loop counter
+
+dequant_loop
+    smulbb  r7, r3, r4              ;multiply
+    smultt  r8, r3, r4
+    smulbb  r9, r5, r6
+    smultt  lr, r5, r6
+
+    ldr     r3, [r0, #8]
+    ldr     r4, [r1, #8]
+    ldr     r5, [r0, #12]
+    ldr     r6, [r1, #12]
+
+    strh    r7, [r2], #2            ;store result
+    smulbb  r7, r3, r4              ;multiply
+    strh    r8, [r2], #2
+    smultt  r8, r3, r4
+    strh    r9, [r2], #2
+    smulbb  r9, r5, r6
+    strh    lr, [r2], #2
+    smultt  lr, r5, r6
+
+    subs    r12, r12, #1
+
+    add     r0, r0, #16
+    add     r1, r1, #16
+
+    ldrne       r3, [r0]
+    strh    r7, [r2], #2            ;store result
+    ldrne       r4, [r1]
+    strh    r8, [r2], #2
+    ldrne       r5, [r0, #4]
+    strh    r9, [r2], #2
+    ldrne       r6, [r1, #4]
+    strh    lr, [r2], #2
+
+    bne     dequant_loop
+
+    ldmia   sp!, {r4-r9, pc}
+    ENDP    ;|vp8_dequantize_b_loop_v6|
+
+    END
diff --git a/vp8/decoder/arm/dboolhuff_arm.h b/vp8/decoder/arm/dboolhuff_arm.h
new file mode 100644
index 0000000..495004f
--- /dev/null
+++ b/vp8/decoder/arm/dboolhuff_arm.h
@@ -0,0 +1,49 @@
+#ifndef DBOOLHUFF_ARM_H
+#define DBOOLHUFF_ARM_H
+
+/* JLK
+ * There are currently no arm-optimized versions of
+ * these functions. As they are implemented, they
+ * can be uncommented below and added to
+ * arm/dsystemdependent.c
+ *
+ * The existing asm code is likely so different as
+ * to be useless. However, its been left (for now)
+ * for reference.
+ */
+/*
+#if HAVE_ARMV6
+#undef vp8_dbool_start
+#define vp8_dbool_start vp8dx_start_decode_v6
+
+#undef vp8_dbool_stop
+#define vp8_dbool_stop vp8dx_stop_decode_v6
+
+#undef vp8_dbool_fill
+#define vp8_dbool_fill vp8_bool_decoder_fill_v6
+
+#undef vp8_dbool_debool
+#define vp8_dbool_debool vp8_decode_bool_v6
+
+#undef vp8_dbool_devalue
+#define vp8_dbool_devalue vp8_decode_value_v6
+#endif // HAVE_ARMV6
+
+#if HAVE_ARMV7
+#undef vp8_dbool_start
+#define vp8_dbool_start vp8dx_start_decode_neon
+
+#undef vp8_dbool_stop
+#define vp8_dbool_stop vp8dx_stop_decode_neon
+
+#undef vp8_dbool_fill
+#define vp8_dbool_fill vp8_bool_decoder_fill_neon
+
+#undef vp8_dbool_debool
+#define vp8_dbool_debool vp8_decode_bool_neon
+
+#undef vp8_dbool_devalue
+#define vp8_dbool_devalue vp8_decode_value_neon
+#endif // HAVE_ARMV7
+*/
+#endif // DBOOLHUFF_ARM_H
diff --git a/vp8/decoder/arm/dequantize_arm.c b/vp8/decoder/arm/dequantize_arm.c
new file mode 100644
index 0000000..54006a9
--- /dev/null
+++ b/vp8/decoder/arm/dequantize_arm.c
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "dequantize.h"
+#include "predictdc.h"
+#include "idct.h"
+#include "vpx_mem/vpx_mem.h"
+
+#if HAVE_ARMV7
+extern void vp8_dequantize_b_loop_neon(short *Q, short *DQC, short *DQ);
+#endif
+
+#if HAVE_ARMV6
+extern void vp8_dequantize_b_loop_v6(short *Q, short *DQC, short *DQ);
+#endif
+
+#if HAVE_ARMV7
+
+void vp8_dequantize_b_neon(BLOCKD *d)
+{
+    int i;
+    short *DQ  = d->dqcoeff;
+    short *Q   = d->qcoeff;
+    short *DQC = &d->dequant[0][0];
+
+    vp8_dequantize_b_loop_neon(Q, DQC, DQ);
+}
+#endif
+
+#if HAVE_ARMV6
+void vp8_dequantize_b_v6(BLOCKD *d)
+{
+    int i;
+    short *DQ  = d->dqcoeff;
+    short *Q   = d->qcoeff;
+    short *DQC = &d->dequant[0][0];
+
+    vp8_dequantize_b_loop_v6(Q, DQC, DQ);
+}
+#endif
diff --git a/vp8/decoder/arm/dequantize_arm.h b/vp8/decoder/arm/dequantize_arm.h
new file mode 100644
index 0000000..c8a61a4
--- /dev/null
+++ b/vp8/decoder/arm/dequantize_arm.h
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef DEQUANTIZE_ARM_H
+#define DEQUANTIZE_ARM_H
+
+#if HAVE_ARMV6
+extern prototype_dequant_block(vp8_dequantize_b_v6);
+extern prototype_dequant_idct(vp8_dequant_idct_v6);
+extern prototype_dequant_idct_dc(vp8_dequant_dc_idct_v6);
+
+#undef  vp8_dequant_block
+#define vp8_dequant_block vp8_dequantize_b_v6
+
+#undef  vp8_dequant_idct
+#define vp8_dequant_idct vp8_dequant_idct_v6
+
+#undef  vp8_dequant_idct_dc
+#define vp8_dequant_idct_dc vp8_dequant_dc_idct_v6
+#endif
+
+#if HAVE_ARMV7
+extern prototype_dequant_block(vp8_dequantize_b_neon);
+extern prototype_dequant_idct(vp8_dequant_idct_neon);
+extern prototype_dequant_idct_dc(vp8_dequant_dc_idct_neon);
+
+#undef  vp8_dequant_block
+#define vp8_dequant_block vp8_dequantize_b_neon
+
+#undef  vp8_dequant_idct
+#define vp8_dequant_idct vp8_dequant_idct_neon
+
+#undef  vp8_dequant_idct_dc
+#define vp8_dequant_idct_dc vp8_dequant_dc_idct_neon
+#endif
+
+#endif
diff --git a/vp8/decoder/arm/detokenizearm_sjl.c b/vp8/decoder/arm/detokenizearm_sjl.c
new file mode 100644
index 0000000..c714452
--- /dev/null
+++ b/vp8/decoder/arm/detokenizearm_sjl.c
@@ -0,0 +1,730 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "type_aliases.h"
+#include "blockd.h"
+#include "onyxd_int.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/mem.h"
+
+#define BR_COUNT 8
+#define BOOL_DATA UINT8
+
+#define OCB_X PREV_COEF_CONTEXTS * ENTROPY_NODES
+//ALIGN16 UINT16 onyx_coef_bands_x[16] = { 0, 1*OCB_X, 2*OCB_X, 3*OCB_X, 6*OCB_X, 4*OCB_X, 5*OCB_X, 6*OCB_X, 6*OCB_X, 6*OCB_X, 6*OCB_X, 6*OCB_X, 6*OCB_X, 6*OCB_X, 6*OCB_X, 7*OCB_X};
+DECLARE_ALIGNED(16, UINT8, vp8_coef_bands_x[16]) = { 0, 1 * OCB_X, 2 * OCB_X, 3 * OCB_X, 6 * OCB_X, 4 * OCB_X, 5 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 7 * OCB_X};
+
+#define EOB_CONTEXT_NODE            0
+#define ZERO_CONTEXT_NODE           1
+#define ONE_CONTEXT_NODE            2
+#define LOW_VAL_CONTEXT_NODE        3
+#define TWO_CONTEXT_NODE            4
+#define THREE_CONTEXT_NODE          5
+#define HIGH_LOW_CONTEXT_NODE       6
+#define CAT_ONE_CONTEXT_NODE        7
+#define CAT_THREEFOUR_CONTEXT_NODE  8
+#define CAT_THREE_CONTEXT_NODE      9
+#define CAT_FIVE_CONTEXT_NODE       10
+
+
+
+
+DECLARE_ALIGNED(16, static const TOKENEXTRABITS, vp8d_token_extra_bits2[MAX_ENTROPY_TOKENS]) =
+{
+    {  0, -1, { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },  //ZERO_TOKEN
+    {  1, 0, { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },   //ONE_TOKEN
+    {  2, 0, { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },   //TWO_TOKEN
+    {  3, 0, { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },   //THREE_TOKEN
+    {  4, 0, { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },   //FOUR_TOKEN
+    {  5, 0, { 159, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },  //DCT_VAL_CATEGORY1
+    {  7, 1, { 145, 165, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } }, //DCT_VAL_CATEGORY2
+    { 11, 2, { 140, 148, 173, 0,  0,  0,  0,  0,  0,  0,  0,  0   } }, //DCT_VAL_CATEGORY3
+    { 19, 3, { 135, 140, 155, 176, 0,  0,  0,  0,  0,  0,  0,  0   } }, //DCT_VAL_CATEGORY4
+    { 35, 4, { 130, 134, 141, 157, 180, 0,  0,  0,  0,  0,  0,  0   } }, //DCT_VAL_CATEGORY5
+    { 67, 10, { 129, 130, 133, 140, 153, 177, 196, 230, 243, 254, 254, 0   } }, //DCT_VAL_CATEGORY6
+    {  0, -1, { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },  // EOB TOKEN
+};
+
+/*
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+DECLARE_ALIGNED(16, const UINT8, vp8_block2context_leftabove[25*3]) =
+{
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, //end of vp8_block2context
+    0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 1, 1, 0, 0, 1, 1, 0, //end of vp8_block2left
+    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 0, 1, 0, 1, 0, 1, 0 //end of vp8_block2above
+};
+
+/*
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+
+void vp8_reset_mb_tokens_context(MACROBLOCKD *x)
+{
+    ENTROPY_CONTEXT **const A = x->above_context;
+    ENTROPY_CONTEXT(* const L)[4] = x->left_context;
+
+    ENTROPY_CONTEXT *a;
+    ENTROPY_CONTEXT *l;
+    int i;
+
+    for (i = 0; i < 24; i++)
+    {
+
+        a = A[ vp8_block2context[i] ] + vp8_block2above[i];
+        l = L[ vp8_block2context[i] ] + vp8_block2left[i];
+
+        *a = *l = 0;
+    }
+
+    if (x->mbmi.mode != B_PRED && x->mbmi.mode != SPLITMV)
+    {
+        a = A[Y2CONTEXT] + vp8_block2above[24];
+        l = L[Y2CONTEXT] + vp8_block2left[24];
+        *a = *l = 0;
+    }
+
+
+}
+
+#define ONYXBLOCK2CONTEXT_OFFSET    0
+#define ONYXBLOCK2LEFT_OFFSET       25
+#define ONYXBLOCK2ABOVE_OFFSET 50
+
+DECLARE_ALIGNED(16, const static unsigned char, norm[128]) =
+{
+    0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+/*
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+void init_detokenizer(VP8D_COMP *dx)
+{
+    const VP8_COMMON *const oc = & dx->common;
+    MACROBLOCKD *x = & dx->mb;
+
+    dx->detoken.norm_ptr = (unsigned char *)norm;
+    dx->detoken.vp8_coef_tree_ptr = (vp8_tree_index *)vp8_coef_tree;
+    dx->detoken.ptr_onyxblock2context_leftabove = (UINT8 *)vp8_block2context_leftabove;
+    dx->detoken.ptr_onyx_coef_bands_x = vp8_coef_bands_x;
+    dx->detoken.scan = (int *)vp8_default_zig_zag1d;
+    dx->detoken.teb_base_ptr = (TOKENEXTRABITS *)vp8d_token_extra_bits2;
+
+    dx->detoken.qcoeff_start_ptr = &x->qcoeff[0];
+
+
+    dx->detoken.coef_probs[0] = (unsigned char *)(oc->fc.coef_probs [0] [ 0 ] [0]);
+    dx->detoken.coef_probs[1] = (unsigned char *)(oc->fc.coef_probs [1] [ 0 ] [0]);
+    dx->detoken.coef_probs[2] = (unsigned char *)(oc->fc.coef_probs [2] [ 0 ] [0]);
+    dx->detoken.coef_probs[3] = (unsigned char *)(oc->fc.coef_probs [3] [ 0 ] [0]);
+
+}
+
+/*
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+
+
+//shift = norm[range]; \
+//      shift = norm_ptr[range]; \
+
+#define NORMALIZE \
+    /*if(range < 0x80)*/                            \
+    { \
+        shift = detoken->norm_ptr[range]; \
+        range <<= shift; \
+        value <<= shift; \
+        count -= shift; \
+        if(count <= 0) \
+        { \
+            count += BR_COUNT ; \
+            value |= (*bufptr) << (BR_COUNT-count); \
+            bufptr++; \
+        } \
+    }
+#if 1
+#define DECODE_AND_APPLYSIGN(value_to_sign) \
+    split = (range + 1) >> 1; \
+    if ( (value >> 24) < split ) \
+    { \
+        range = split; \
+        v= value_to_sign; \
+    } \
+    else \
+    { \
+        range = range-split; \
+        value = value-(split<<24); \
+        v = -value_to_sign; \
+    } \
+    range +=range;                   \
+    value +=value;                   \
+    if (!--count) \
+    { \
+        count = BR_COUNT; \
+        value |= *bufptr; \
+        bufptr++; \
+    }
+
+#define DECODE_AND_BRANCH_IF_ZERO(probability,branch) \
+    { \
+        split = 1 +  ((( probability*(range-1) ) )>> 8); \
+        if ( (value >> 24) < split ) \
+        { \
+            range = split; \
+            NORMALIZE \
+            goto branch; \
+        } \
+        value -= (split<<24); \
+        range = range - split; \
+        NORMALIZE \
+    }
+
+#define DECODE_AND_LOOP_IF_ZERO(probability,branch) \
+    { \
+        split = 1 + ((( probability*(range-1) ) ) >> 8); \
+        if ( (value >> 24) < split ) \
+        { \
+            range = split; \
+            NORMALIZE \
+            Prob = coef_probs; \
+            ++c; \
+            Prob += vp8_coef_bands_x[c]; \
+            goto branch; \
+        } \
+        value -= (split<<24); \
+        range = range - split; \
+        NORMALIZE \
+    }
+
+#define DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) \
+    DECODE_AND_APPLYSIGN(val) \
+    Prob = coef_probs + (ENTROPY_NODES*2); \
+    if(c < 15){\
+        qcoeff_ptr [ scan[c] ] = (INT16) v; \
+        ++c; \
+        goto DO_WHILE; }\
+    qcoeff_ptr [ scan[15] ] = (INT16) v; \
+    goto BLOCK_FINISHED;
+
+
+#define DECODE_EXTRABIT_AND_ADJUST_VAL(t,bits_count)\
+    split = 1 +  (((range-1) * vp8d_token_extra_bits2[t].Probs[bits_count]) >> 8); \
+    if(value >= (split<<24))\
+    {\
+        range = range-split;\
+        value = value-(split<<24);\
+        val += ((UINT16)1<<bits_count);\
+    }\
+    else\
+    {\
+        range = split;\
+    }\
+    NORMALIZE
+#endif
+
+#if 0
+int vp8_decode_mb_tokens(VP8D_COMP *dx, MACROBLOCKD *x)
+{
+    ENTROPY_CONTEXT **const A = x->above_context;
+    ENTROPY_CONTEXT(* const L)[4] = x->left_context;
+    const VP8_COMMON *const oc = & dx->common;
+
+    BOOL_DECODER *bc = x->current_bc;
+
+    ENTROPY_CONTEXT *a;
+    ENTROPY_CONTEXT *l;
+    int i;
+
+    int eobtotal = 0;
+
+    register int count;
+
+    BOOL_DATA *bufptr;
+    register unsigned int range;
+    register unsigned int value;
+    const int *scan;
+    register unsigned int shift;
+    UINT32 split;
+    INT16 *qcoeff_ptr;
+
+    UINT8 *coef_probs;
+    int type;
+    int stop;
+    INT16 val, bits_count;
+    INT16 c;
+    INT16 t;
+    INT16 v;
+    vp8_prob *Prob;
+
+    //int *scan;
+    type = 3;
+    i = 0;
+    stop = 16;
+
+    if (x->mbmi.mode != B_PRED && x->mbmi.mode != SPLITMV)
+    {
+        i = 24;
+        stop = 24;
+        type = 1;
+        qcoeff_ptr = &x->qcoeff[24*16];
+        scan = vp8_default_zig_zag1d;
+        eobtotal -= 16;
+    }
+    else
+    {
+        scan = vp8_default_zig_zag1d;
+        qcoeff_ptr = &x->qcoeff[0];
+    }
+
+    count   = bc->count;
+    range   = bc->range;
+    value   = bc->value;
+    bufptr  = &bc->buffer[bc->pos];
+
+
+    coef_probs = (unsigned char *)(oc->fc.coef_probs [type] [ 0 ] [0]);
+
+BLOCK_LOOP:
+    a = A[ vp8_block2context[i] ] + vp8_block2above[i];
+    l = L[ vp8_block2context[i] ] + vp8_block2left[i];
+    c = (INT16)(!type);
+
+    VP8_COMBINEENTROPYCONTEXTS(t, *a, *l);
+    Prob = coef_probs;
+    Prob += t * ENTROPY_NODES;
+
+DO_WHILE:
+    Prob += vp8_coef_bands_x[c];
+    DECODE_AND_BRANCH_IF_ZERO(Prob[EOB_CONTEXT_NODE], BLOCK_FINISHED);
+
+CHECK_0_:
+    DECODE_AND_LOOP_IF_ZERO(Prob[ZERO_CONTEXT_NODE], CHECK_0_);
+    DECODE_AND_BRANCH_IF_ZERO(Prob[ONE_CONTEXT_NODE], ONE_CONTEXT_NODE_0_);
+    DECODE_AND_BRANCH_IF_ZERO(Prob[LOW_VAL_CONTEXT_NODE], LOW_VAL_CONTEXT_NODE_0_);
+    DECODE_AND_BRANCH_IF_ZERO(Prob[HIGH_LOW_CONTEXT_NODE], HIGH_LOW_CONTEXT_NODE_0_);
+    DECODE_AND_BRANCH_IF_ZERO(Prob[CAT_THREEFOUR_CONTEXT_NODE], CAT_THREEFOUR_CONTEXT_NODE_0_);
+    DECODE_AND_BRANCH_IF_ZERO(Prob[CAT_FIVE_CONTEXT_NODE], CAT_FIVE_CONTEXT_NODE_0_);
+    val = vp8d_token_extra_bits2[DCT_VAL_CATEGORY6].min_val;
+    bits_count = vp8d_token_extra_bits2[DCT_VAL_CATEGORY6].Length;
+
+    do
+    {
+        DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY6, bits_count);
+        bits_count -- ;
+    }
+    while (bits_count >= 0);
+
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
+
+CAT_FIVE_CONTEXT_NODE_0_:
+    val = vp8d_token_extra_bits2[DCT_VAL_CATEGORY5].min_val;
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 4);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 3);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 2);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 1);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 0);
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
+
+CAT_THREEFOUR_CONTEXT_NODE_0_:
+    DECODE_AND_BRANCH_IF_ZERO(Prob[CAT_THREE_CONTEXT_NODE], CAT_THREE_CONTEXT_NODE_0_);
+    val = vp8d_token_extra_bits2[DCT_VAL_CATEGORY4].min_val;
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 3);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 2);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 1);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 0);
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
+
+CAT_THREE_CONTEXT_NODE_0_:
+    val = vp8d_token_extra_bits2[DCT_VAL_CATEGORY3].min_val;
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 2);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 1);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 0);
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
+
+HIGH_LOW_CONTEXT_NODE_0_:
+    DECODE_AND_BRANCH_IF_ZERO(Prob[CAT_ONE_CONTEXT_NODE], CAT_ONE_CONTEXT_NODE_0_);
+
+    val = vp8d_token_extra_bits2[DCT_VAL_CATEGORY2].min_val;
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 1);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 0);
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
+
+CAT_ONE_CONTEXT_NODE_0_:
+    val = vp8d_token_extra_bits2[DCT_VAL_CATEGORY1].min_val;
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY1, 0);
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
+
+LOW_VAL_CONTEXT_NODE_0_:
+    DECODE_AND_BRANCH_IF_ZERO(Prob[TWO_CONTEXT_NODE], TWO_CONTEXT_NODE_0_);
+    DECODE_AND_BRANCH_IF_ZERO(Prob[THREE_CONTEXT_NODE], THREE_CONTEXT_NODE_0_);
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(4);
+
+THREE_CONTEXT_NODE_0_:
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(3);
+
+TWO_CONTEXT_NODE_0_:
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(2);
+
+ONE_CONTEXT_NODE_0_:
+    DECODE_AND_APPLYSIGN(1);
+    Prob = coef_probs + ENTROPY_NODES;
+
+    if (c < 15)
+    {
+        qcoeff_ptr [ scan[c] ] = (INT16) v;
+        ++c;
+        goto DO_WHILE;
+    }
+
+    qcoeff_ptr [ scan[15] ] = (INT16) v;
+BLOCK_FINISHED:
+    t = ((x->Block[i].eob = c) != !type);   // any nonzero data?
+    eobtotal += x->Block[i].eob;
+    *a = *l = t;
+    qcoeff_ptr += 16;
+
+    i++;
+
+    if (i < stop)
+        goto BLOCK_LOOP;
+
+    if (i == 25)
+    {
+        scan = vp8_default_zig_zag1d;//x->scan_order1d;
+        type = 0;
+        i = 0;
+        stop = 16;
+        coef_probs = (unsigned char *)(oc->fc.coef_probs [type] [ 0 ] [0]);
+        qcoeff_ptr = &x->qcoeff[0];
+        goto BLOCK_LOOP;
+    }
+
+    if (i == 16)
+    {
+        type = 2;
+        coef_probs = (unsigned char *)(oc->fc.coef_probs [type] [ 0 ] [0]);
+        stop = 24;
+        goto BLOCK_LOOP;
+    }
+
+    bc->count = count;
+    bc->value = value;
+    bc->range = range;
+    bc->pos  = bufptr - bc->buffer;
+    return eobtotal;
+
+}
+//#endif
+#else
+/*
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+
+#if 0
+//uses relative offsets
+
+const vp8_tree_index vp8_coef_tree_x[ 22] =   /* corresponding _CONTEXT_NODEs */
+{
+    -DCT_EOB_TOKEN, 1,                             /* 0 = EOB */
+    -ZERO_TOKEN, 1,                               /* 1 = ZERO */
+    -ONE_TOKEN, 1,                               /* 2 = ONE */
+    2, 5,                                       /* 3 = LOW_VAL */
+    -TWO_TOKEN, 1,                         /* 4 = TWO */
+    -THREE_TOKEN, -FOUR_TOKEN,                /* 5 = THREE */
+    2, 3,                                  /* 6 = HIGH_LOW */
+    -DCT_VAL_CATEGORY1, -DCT_VAL_CATEGORY2,   /* 7 = CAT_ONE */
+    2, 3,                                 /* 8 = CAT_THREEFOUR */
+    -DCT_VAL_CATEGORY3, -DCT_VAL_CATEGORY4,  /* 9 = CAT_THREE */
+    -DCT_VAL_CATEGORY5, -DCT_VAL_CATEGORY6   /* 10 = CAT_FIVE */
+};
+#endif
+
+#define _SCALEDOWN 8 //16 //8
+
+int vp8_decode_mb_tokens_v5(DETOK *detoken, int type);
+
+int vp8_decode_mb_tokens_v5_c(DETOK *detoken, int type)
+{
+    BOOL_DECODER *bc = detoken->current_bc;
+
+    ENTROPY_CONTEXT *a;
+    ENTROPY_CONTEXT *l;
+    int i;
+
+    register int count;
+
+    BOOL_DATA *bufptr;
+    register unsigned int range;
+    register unsigned int value;
+    register unsigned int shift;
+    UINT32 split;
+    INT16 *qcoeff_ptr;
+
+    UINT8 *coef_probs;
+//  int type;
+    int stop;
+    INT16 c;
+    INT16 t;
+    INT16 v;
+    vp8_prob *Prob;
+
+
+
+//  type = 3;
+    i = 0;
+    stop = 16;
+    qcoeff_ptr = detoken->qcoeff_start_ptr;
+
+//  if( detoken->mode != B_PRED && detoken->mode != SPLITMV)
+    if (type == 1)
+    {
+        i += 24;
+        stop += 8; //24;
+//      type = 1;
+        qcoeff_ptr += 24 * 16;
+//      eobtotal-=16;
+    }
+
+    count   = bc->count;
+    range   = bc->range;
+    value   = bc->value;
+    bufptr  = &bc->buffer[bc->pos];
+
+
+    coef_probs = detoken->coef_probs[type]; //(unsigned char *)( oc->fc.coef_probs [type] [ 0 ] [0]);
+
+BLOCK_LOOP:
+    a = detoken->A[ detoken->ptr_onyxblock2context_leftabove[i] ];
+    l = detoken->L[ detoken->ptr_onyxblock2context_leftabove[i] ];
+    c = !type;
+    a += detoken->ptr_onyxblock2context_leftabove[i + ONYXBLOCK2ABOVE_OFFSET];
+    l += detoken->ptr_onyxblock2context_leftabove[i + ONYXBLOCK2LEFT_OFFSET];
+
+    //#define ONYX_COMBINEENTROPYCONTEXTS( Dest, A, B) \
+    //Dest = ((A)!=0) + ((B)!=0);
+
+    VP8_COMBINEENTROPYCONTEXTS(t, *a, *l);
+
+    Prob = coef_probs;
+    Prob += t * ENTROPY_NODES;
+    t = 0;
+
+    do
+    {
+
+        {
+//                  onyx_tree_index * onyx_coef_tree_ptr = onyx_coef_tree_x;
+
+            Prob += detoken->ptr_onyx_coef_bands_x[c];
+
+        GET_TOKEN_START:
+
+            do
+            {
+                split = 1 + (((range - 1) * (Prob[t>>1])) >> 8);
+
+                if (value >> 24 >= split)
+                {
+                    range = range - split;
+                    value = value - (split << 24);
+                    t += 1;
+
+                    //used to eliminate else branch
+                    split = range;
+                }
+
+                range = split;
+
+                t = detoken->vp8_coef_tree_ptr[ t ];
+
+                NORMALIZE
+
+            }
+            while (t  > 0) ;
+        }
+    GET_TOKEN_STOP:
+
+        if (t == -DCT_EOB_TOKEN)
+        {
+            break;
+        }
+
+        v = -t;
+
+        if (v > FOUR_TOKEN)
+        {
+            INT16 bits_count;
+            TOKENEXTRABITS *teb_ptr;
+
+//                      teb_ptr = &onyxd_token_extra_bits2[t];
+//                  teb_ptr = &onyxd_token_extra_bits2[v];
+            teb_ptr = &detoken->teb_base_ptr[v];
+
+
+            v = teb_ptr->min_val;
+            bits_count = teb_ptr->Length;
+
+            do
+            {
+                split = 1 + (((range - 1) * teb_ptr->Probs[bits_count]) >> _SCALEDOWN);
+
+                if ((value >> 24) >= split)
+                {
+                    range = range - split;
+                    value = value - (split << 24);
+                    v += ((UINT16)1 << bits_count);
+
+                    //used to eliminate else branch
+                    split = range;
+                }
+
+                range = split;
+
+                NORMALIZE
+
+                bits_count -- ;
+            }
+            while (bits_count >= 0);
+        }
+
+        Prob = coef_probs;
+
+        if (t)
+        {
+            split = 1 + (((range - 1) * vp8_prob_half) >> 8);
+
+            if ((value >> 24) >= split)
+            {
+                range = range - split;
+                value = value - (split << 24);
+                v = (v ^ -1) + 1;           /* negate w/out conditionals */
+
+                //used to eliminate else branch
+                split = range;
+            }
+
+            range = split;
+
+            NORMALIZE
+            Prob += ENTROPY_NODES;
+
+            if (t < -ONE_TOKEN)
+                Prob += ENTROPY_NODES;
+
+            t = -2;
+        }
+
+        //if t is zero, we will skip the eob table check
+        t += 2;
+        qcoeff_ptr [detoken->scan [c] ] = (INT16) v;
+
+    }
+    while (++c < 16);
+
+    if (t != -DCT_EOB_TOKEN)
+    {
+        --c;
+    }
+
+    t = ((detoken->eob[i] = c) != !type);   // any nonzero data?
+//  eobtotal += detoken->eob[i];
+    *a = *l = t;
+    qcoeff_ptr += 16;
+
+    i++;
+
+    if (i < stop)
+        goto BLOCK_LOOP;
+
+    if (i == 25)
+    {
+        type = 0;
+        i = 0;
+        stop = 16;
+//      coef_probs = (unsigned char *)(oc->fc.coef_probs [type] [ 0 ] [0]);
+        coef_probs = detoken->coef_probs[type]; //(unsigned char *)( oc->fc.coef_probs [type] [ 0 ] [0]);
+        qcoeff_ptr = detoken->qcoeff_start_ptr;
+        goto BLOCK_LOOP;
+    }
+
+    if (i == 16)
+    {
+        type = 2;
+//      coef_probs =(unsigned char *)( oc->fc.coef_probs [type] [ 0 ] [0]);
+        coef_probs = detoken->coef_probs[type]; //(unsigned char *)( oc->fc.coef_probs [type] [ 0 ] [0]);
+        stop = 24;
+        goto BLOCK_LOOP;
+    }
+
+    bc->count = count;
+    bc->value = value;
+    bc->range = range;
+    bc->pos  = bufptr - bc->buffer;
+    return 0;
+}
+//#if 0
+int vp8_decode_mb_tokens(VP8D_COMP *dx, MACROBLOCKD *x)
+{
+//  const ONYX_COMMON * const oc = & dx->common;
+    int eobtotal = 0;
+    int i, type;
+    /*
+        dx->detoken.norm_ptr = norm;
+        dx->detoken.onyx_coef_tree_ptr = onyx_coef_tree;
+        dx->detoken.ptr_onyxblock2context_leftabove = ONYXBLOCK2CONTEXT_LEFTABOVE;
+        dx->detoken.ptr_onyx_coef_bands_x = onyx_coef_bands_x;
+        dx->detoken.scan = default_zig_zag1d;
+        dx->detoken.teb_base_ptr = onyxd_token_extra_bits2;
+
+        dx->detoken.qcoeff_start_ptr = &x->qcoeff[0];
+
+        dx->detoken.A = x->above_context;
+        dx->detoken.L = x->left_context;
+
+        dx->detoken.coef_probs[0] = (unsigned char *)( oc->fc.coef_probs [0] [ 0 ] [0]);
+        dx->detoken.coef_probs[1] = (unsigned char *)( oc->fc.coef_probs [1] [ 0 ] [0]);
+        dx->detoken.coef_probs[2] = (unsigned char *)( oc->fc.coef_probs [2] [ 0 ] [0]);
+        dx->detoken.coef_probs[3] = (unsigned char *)( oc->fc.coef_probs [3] [ 0 ] [0]);
+    */
+
+    dx->detoken.current_bc = x->current_bc;
+    dx->detoken.A = x->above_context;
+    dx->detoken.L = x->left_context;
+
+    type = 3;
+
+    if (x->mbmi.mode != B_PRED && x->mbmi.mode != SPLITMV)
+    {
+        type = 1;
+        eobtotal -= 16;
+    }
+
+    vp8_decode_mb_tokens_v5(&dx->detoken, type);
+
+    for (i = 0; i < 25; i++)
+    {
+        x->Block[i].eob = dx->detoken.eob[i];
+        eobtotal += dx->detoken.eob[i];
+    }
+
+    return eobtotal;
+}
+#endif
diff --git a/vp8/decoder/arm/detokenizearm_v6.asm b/vp8/decoder/arm/detokenizearm_v6.asm
new file mode 100644
index 0000000..4d87ee5
--- /dev/null
+++ b/vp8/decoder/arm/detokenizearm_v6.asm
@@ -0,0 +1,364 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_decode_mb_tokens_v5|
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+    INCLUDE vpx_asm_offsets.asm
+
+l_qcoeff    EQU     0
+l_i         EQU     4
+l_type      EQU     8
+l_stop      EQU     12
+l_c         EQU     16
+l_l_ptr      EQU     20
+l_a_ptr      EQU     24
+l_bc        EQU     28
+l_coef_ptr   EQU     32
+l_stacksize EQU     64
+
+
+;; constant offsets -- these should be created at build time
+c_onyxblock2left_offset      EQU 25
+c_onyxblock2above_offset     EQU 50
+c_entropy_nodes              EQU 11
+c_dct_eob_token              EQU 11
+
+|vp8_decode_mb_tokens_v5| PROC
+    stmdb       sp!, {r4 - r11, lr}
+    sub         sp, sp, #l_stacksize
+    mov         r7, r1
+    mov         r9, r0                      ;DETOK *detoken
+
+    ldr         r1, [r9, #detok_current_bc]
+    ldr         r0, [r9, #detok_qcoeff_start_ptr]
+    mov         r11, #0
+    mov         r3, #0x10
+
+    cmp         r7, #1
+    addeq       r11, r11, #24
+    addeq       r3, r3, #8
+    addeq       r0, r0, #3, 24
+
+    str         r0, [sp, #l_qcoeff]
+    str         r11, [sp, #l_i]
+    str         r7, [sp, #l_type]
+    str         r3, [sp, #l_stop]
+    str         r1, [sp, #l_bc]
+
+    add         lr, r9, r7, lsl #2
+
+    ldr         r2, [r1, #bool_decoder_buffer]
+    ldr         r3, [r1, #bool_decoder_pos]
+
+    ldr         r10, [lr, #detok_coef_probs]
+    ldr         r5, [r1, #bool_decoder_count]
+    ldr         r6, [r1, #bool_decoder_range]
+    ldr         r4, [r1, #bool_decoder_value]
+    add         r8, r2, r3
+
+    str         r10, [sp, #l_coef_ptr]
+
+
+    ;align 4
+BLOCK_LOOP
+    ldr         r3, [r9, #detok_ptr_onyxblock2context_leftabove]
+    ldr         r2, [r9, #DETOK_A]
+    ldr         r1, [r9, #DETOK_L]
+    ldrb        r12, [r3, +r11]                                 ; detoken->ptr_onyxblock2context_leftabove[i]
+
+    cmp         r7, #0                                          ; check type
+    moveq       r7, #1
+    movne       r7, #0
+
+    ldr         r0, [r2, +r12, lsl #2]                          ; a
+    add         r1, r1, r12, lsl #4
+    add         r3, r3, r11
+
+    ldrb        r2, [r3, #c_onyxblock2above_offset]
+    ldrb        r3, [r3, #c_onyxblock2left_offset]
+    mov         lr, #c_entropy_nodes
+;;  ;++
+
+    ldr         r2, [r0, +r2, lsl #2]!
+    add         r3, r1, r3, lsl #2
+    str         r3, [sp, #l_l_ptr]
+    ldr         r3, [r3]
+
+    cmp         r2, #0
+    movne       r2, #1
+    cmp         r3, #0
+    addne       r2, r2, #1
+
+    str         r0, [sp, #l_a_ptr]
+    smlabb      r0, r2, lr, r10
+    mov         r1, #0                                          ; t = 0
+    str         r7, [sp, #l_c]
+
+    ;align 4
+COEFF_LOOP
+    ldr         r3, [r9, #detok_ptr_onyx_coef_bands_x]
+    ldr         lr, [r9, #detok_onyx_coef_tree_ptr]
+
+;;the following two lines are used if onyx_coef_bands_x is UINT16
+;;  add         r3, r3, r7, lsl #1
+;;  ldrh        r3, [r3]
+
+;;the following line is used if onyx_coef_bands_x is UINT8
+    ldrb        r3, [r7, +r3]
+
+
+;;  ;++
+;;  pld         [r8]
+    ;++
+    add         r0, r0, r3
+
+    ;align 4
+get_token_loop
+    ldrb        r2, [r0, +r1, asr #1]
+    mov         r3, r6, lsl #8
+    sub         r3, r3, #256                    ;split = 1 +  (((range-1) * probability) >> 8)
+    mov         r10, #1
+
+    smlawb      r2, r3, r2, r10
+    ldrb        r12, [r8]                       ;load cx data byte in stall slot
+    ;++
+
+    subs        r3, r4, r2, lsl #24             ;x = value-(split<<24)
+    addhs       r1, r1, #1                      ;t += 1
+    movhs       r4, r3                          ;update value
+    subhs       r2, r6, r2                      ;range = range - split
+    movlo       r6, r2
+
+;;; ldrsbhs     r1, [r1, +lr]
+    ldrsb     r1, [r1, +lr]
+
+
+;; use branch for short pipelines ???
+;;  cmp         r2, #0x80
+;;  bcs         |$LN22@decode_mb_to|
+
+    clz         r3, r2
+    sub         r3, r3, #24
+    subs        r5, r5, r3
+    mov         r6, r2, lsl r3
+    mov         r4, r4, lsl r3
+
+;; use branch for short pipelines ???
+;;  bgt         |$LN22@decode_mb_to|
+
+    addle         r5, r5, #8
+    rsble         r3, r5, #8
+    addle         r8, r8, #1
+    orrle         r4, r4, r12, lsl r3
+
+;;|$LN22@decode_mb_to|
+
+    cmp         r1, #0
+    bgt         get_token_loop
+
+    cmn         r1, #c_dct_eob_token             ;if(t == -DCT_EOB_TOKEN)
+    beq         END_OF_BLOCK
+
+    rsb         lr, r1, #0                      ;v = -t;
+
+    cmp         lr, #4                          ;if(v > FOUR_TOKEN)
+    ble         SKIP_EXTRABITS
+
+    ldr         r3, [r9, #detok_teb_base_ptr]
+    mov         r11, #1
+    add         r7, r3, lr, lsl #4
+
+    ldrsh       lr, [r7, #tokenextrabits_min_val];v = teb_ptr->min_val
+    ldrsh       r0, [r7, #tokenextrabits_length];bits_count = teb_ptr->Length
+
+extrabits_loop
+    add         r3, r0, r7
+
+    ldrb        r2, [r3, #4]
+    mov         r3, r6, lsl #8
+    sub         r3, r3, #256                    ;split = 1 +  (((range-1) * probability) >> 8)
+    mov         r10, #1
+
+    smlawb      r2, r3, r2, r10
+    ldrb        r12, [r8]
+    ;++
+
+    subs        r10, r4, r2, lsl #24            ;x = value-(split<<24)
+    movhs       r4, r10                         ;update value
+    subhs       r2, r6, r2                      ;range = range - split
+    addhs       lr, lr, r11, lsl r0             ;v += ((UINT16)1<<bits_count)
+    movlo       r6, r2                          ;range = split
+
+
+;; use branch for short pipelines ???
+;;  cmp         r2, #0x80
+;;  bcs         |$LN10@decode_mb_to|
+
+    clz         r3, r2
+    sub         r3, r3, #24
+    subs        r5, r5, r3
+    mov         r6, r2, lsl r3                  ;range
+    mov         r4, r4, lsl r3                  ;value
+
+    addle       r5, r5, #8
+    addle       r8, r8, #1
+    rsble       r3, r5, #8
+    orrle       r4, r4, r12, lsl r3
+
+;;|$LN10@decode_mb_to|
+    subs         r0, r0, #1
+    bpl         extrabits_loop
+
+
+SKIP_EXTRABITS
+    ldr         r11, [sp, #l_qcoeff]
+    ldr         r0, [sp, #l_coef_ptr]
+
+    cmp         r1, #0                          ;check for nonzero token
+    beq         SKIP_EOB_CHECK              ;if t is zero, we will skip the eob table chec
+
+    sub         r3, r6, #1                      ;range - 1
+    ;++
+    mov         r3, r3, lsl #7                  ; *= onyx_prob_half  (128)
+    ;++
+    mov         r3, r3, lsr #8
+    add         r2, r3, #1                      ;split
+
+    subs        r3, r4, r2, lsl #24             ;x = value-(split<<24)
+    movhs       r4, r3                          ;update value
+    subhs       r2, r6, r2                      ;range = range - split
+    mvnhs       r3, lr
+    addhs       lr, r3, #1                      ;v = (v ^ -1) + 1
+    movlo       r6, r2                          ;range = split
+
+;; use branch for short pipelines ???
+;;  cmp         r2, #0x80
+;;  bcs         |$LN6@decode_mb_to|
+
+    clz         r3, r2
+    sub         r3, r3, #24
+    subs        r5, r5, r3
+    mov         r6, r2, lsl r3
+    mov         r4, r4, lsl r3
+    ldrleb      r2, [r8], #1
+    addle       r5, r5, #8
+    rsble       r3, r5, #8
+    orrle       r4, r4, r2, lsl r3
+
+;;|$LN6@decode_mb_to|
+    add         r0, r0, #0xB
+
+    cmn         r1, #1
+
+    addlt       r0, r0, #0xB
+
+    mvn         r1, #1
+
+SKIP_EOB_CHECK
+    ldr         r7, [sp, #l_c]
+    ldr         r3, [r9, #detok_scan]
+    add         r1, r1, #2
+    cmp         r7, #(0x10 - 1)                     ;assume one less for now.... increment below
+
+    ldr         r3, [r3, +r7, lsl #2]
+    add         r7, r7, #1
+    add         r3, r11, r3, lsl #1
+
+    str         r7, [sp, #l_c]
+    strh        lr, [r3]
+
+    blt         COEFF_LOOP
+
+    sub         r7, r7, #1                          ;if(t != -DCT_EOB_TOKEN) --c
+
+END_OF_BLOCK
+    ldr         r3, [sp, #l_type]
+    ldr         r10, [sp, #l_coef_ptr]
+    ldr         r0, [sp, #l_qcoeff]
+    ldr         r11, [sp, #l_i]
+    ldr         r12, [sp, #l_stop]
+
+    cmp         r3, #0
+    moveq       r1, #1
+    movne       r1, #0
+    add         r3, r11, r9
+
+    cmp         r7, r1
+    strb        r7, [r3, #detok_eob]
+
+    ldr         r7, [sp, #l_l_ptr]
+    ldr         r2, [sp, #l_a_ptr]
+    movne       r3, #1
+    moveq       r3, #0
+
+    add         r0, r0, #0x20
+    add         r11, r11, #1
+    str         r3, [r7]
+    str         r3, [r2]
+    str         r0, [sp, #l_qcoeff]
+    str         r11, [sp, #l_i]
+
+    cmp         r11, r12                            ;i >= stop ?
+    ldr         r7, [sp, #l_type]
+    mov         lr, #0xB
+
+    blt         BLOCK_LOOP
+
+    cmp         r11, #0x19
+    bne         ln2_decode_mb_to
+
+    ldr         r12, [r9, #detok_qcoeff_start_ptr]
+    ldr         r10, [r9, #detok_coef_probs]
+    mov         r7, #0
+    mov         r3, #0x10
+    str         r12, [sp, #l_qcoeff]
+    str         r7, [sp, #l_i]
+    str         r7, [sp, #l_type]
+    str         r3, [sp, #l_stop]
+
+    str         r10, [sp, #l_coef_ptr]
+
+    b           BLOCK_LOOP
+
+ln2_decode_mb_to
+    cmp         r11, #0x10
+    bne         ln1_decode_mb_to
+
+    ldr         r10, [r9, #0x30]
+
+    mov         r7, #2
+    mov         r3, #0x18
+
+    str         r7, [sp, #l_type]
+    str         r3, [sp, #l_stop]
+
+    str         r10, [sp, #l_coef_ptr]
+    b           BLOCK_LOOP
+
+ln1_decode_mb_to
+    ldr         r2, [sp, #l_bc]
+    mov         r0, #0
+    nop
+
+    ldr         r3, [r2, #bool_decoder_buffer]
+    str         r5, [r2, #bool_decoder_count]
+    str         r4, [r2, #bool_decoder_value]
+    sub         r3, r8, r3
+    str         r3, [r2, #bool_decoder_pos]
+    str         r6, [r2, #bool_decoder_range]
+
+    add         sp, sp, #l_stacksize
+    ldmia       sp!, {r4 - r11, pc}
+
+    ENDP  ; |vp8_decode_mb_tokens_v5|
+
+    END
diff --git a/vp8/decoder/arm/dsystemdependent.c b/vp8/decoder/arm/dsystemdependent.c
new file mode 100644
index 0000000..455c83a
--- /dev/null
+++ b/vp8/decoder/arm/dsystemdependent.c
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "blockd.h"
+#include "pragmas.h"
+#include "postproc.h"
+#include "dboolhuff.h"
+#include "dequantize.h"
+#include "onyxd_int.h"
+
+void vp8_dmachine_specific_config(VP8D_COMP *pbi)
+{
+#if CONFIG_RUNTIME_CPU_DETECT
+    pbi->mb.rtcd         = &pbi->common.rtcd;
+#if HAVE_ARMV7
+    pbi->dequant.block   = vp8_dequantize_b_neon;
+    pbi->dequant.idct    = vp8_dequant_idct_neon;
+    pbi->dequant.idct_dc = vp8_dequant_dc_idct_neon;
+    pbi->dboolhuff.start = vp8dx_start_decode_c;
+    pbi->dboolhuff.stop  = vp8dx_stop_decode_c;
+    pbi->dboolhuff.fill  = vp8dx_bool_decoder_fill_c;
+    pbi->dboolhuff.debool = vp8dx_decode_bool_c;
+    pbi->dboolhuff.devalue = vp8dx_decode_value_c;
+
+#elif HAVE_ARMV6
+    pbi->dequant.block   = vp8_dequantize_b_v6;
+    pbi->dequant.idct    = vp8_dequant_idct_v6;
+    pbi->dequant.idct_dc = vp8_dequant_dc_idct_v6;
+    pbi->dboolhuff.start = vp8dx_start_decode_c;
+    pbi->dboolhuff.stop  = vp8dx_stop_decode_c;
+    pbi->dboolhuff.fill  = vp8dx_bool_decoder_fill_c;
+    pbi->dboolhuff.debool = vp8dx_decode_bool_c;
+    pbi->dboolhuff.devalue = vp8dx_decode_value_c;
+#endif
+#endif
+}
diff --git a/vp8/decoder/arm/neon/dboolhuff_neon.asm b/vp8/decoder/arm/neon/dboolhuff_neon.asm
new file mode 100644
index 0000000..7ec62a3
--- /dev/null
+++ b/vp8/decoder/arm/neon/dboolhuff_neon.asm
@@ -0,0 +1,159 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_decode_value_neon|
+    EXPORT  |vp8dx_start_decode_neon|
+    EXPORT  |vp8dx_stop_decode_neon|
+    EXPORT  |vp8dx_decode_bool_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    INCLUDE vpx_asm_offsets.asm
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+;   int z = 0;
+;   int bit;
+;   for ( bit=bits-1; bit>=0; bit-- )
+;   {
+;       z |= (vp8dx_decode_bool(br, 0x80)<<bit);
+;   }
+;   return z;
+
+;int vp8_decode_value_neon ( BOOL_DECODER *br, int bits )
+|vp8_decode_value_neon| PROC
+    stmdb   sp!, {r4 - r6, lr}
+    mov     r4, r0
+    mov     r5, r1
+    mov     r6, #0
+
+    subs    r5, r5, #1
+    bmi     decode_value_exit
+
+decode_value_loop
+    mov     r1, #0x80
+    mov     r0, r4
+    bl      vp8dx_decode_bool_neon_internal       ; needed for conversion to s file
+    orr     r6, r6, r0, lsl r5
+    subs    r5, r5, #1
+    bpl     decode_value_loop
+
+decode_value_exit
+    mov     r0, r6
+    ldmia   sp!, {r4 - r6, pc}
+    ENDP    ; |vp8_decode_value_neon|
+
+
+;void vp8dx_start_decode_neon ( BOOL_DECODER *br, unsigned char *source )
+|vp8dx_start_decode_neon| PROC
+    stmdb   sp!, {r4 - r5, lr}
+    mov     r2, #0
+    mov     r3, #255
+
+    str     r2, [r0, #bool_decoder_lowvalue]
+    str     r3, [r0, #bool_decoder_range]
+    str     r1, [r0, #bool_decoder_buffer]
+
+    mov     r3, #8
+    mov     r2, #4
+    str     r3, [r0, #bool_decoder_count]
+    str     r2, [r0, #bool_decoder_pos]
+
+    ldrb    r2, [r1, #3]
+    ldrb    r3, [r1, #2]
+    ldrb    r4, [r1, #1]
+    ldrb    r5, [r1]
+
+    orr     r1, r2, r3, lsl #8
+    orr     r1, r1, r4, lsl #16
+    orr     r1, r1, r5, lsl #24
+
+    str     r1, [r0, #bool_decoder_value]
+
+    ldmia   sp!, {r4 - r5, pc}
+    ENDP    ; |vp8dx_start_decode_neon|
+
+
+;void vp8dx_stop_decode_neon ( BOOL_DECODER *bc );
+|vp8dx_stop_decode_neon| PROC
+    mov     pc, lr
+    ENDP    ; |vp8dx_stop_decode_neon|
+
+
+; bigsplit  RN  r1
+; buffer_v  RN  r1
+; count_v       RN  r4
+; range_v       RN  r2
+; value_v       RN  r3
+; pos_v     RN  r5
+; split     RN  r6
+; bit           RN  lr
+;int vp8dx_decode_bool_neon ( BOOL_DECODER *br, int probability )
+|vp8dx_decode_bool_neon| PROC
+vp8dx_decode_bool_neon_internal
+;LDRD and STRD doubleword data transfers must be eight-byte aligned. Use ALIGN 8
+;before memory allocation
+    stmdb   sp!, {r4 - r5, lr}
+
+    ldr     r2, [r0, #bool_decoder_range]       ;load range (r2), value(r3)
+    ldr     r3, [r0, #bool_decoder_value]
+    ;ldrd   r2, r3, [r0, #bool_decoder_range]   ;ldrd costs 2 cycles
+    ;
+
+    mov     r4, r2, lsl #8
+    sub     r4, r4, #256
+    mov     r12, #1
+
+    smlawb  r4, r4, r1, r12         ;split = 1 +  (((range-1) * probability) >> 8)
+
+    mov     lr, r0
+    mov     r0, #0                  ;bit = 0
+    ;
+    subs    r5, r3, r4, lsl #24
+
+    subhs   r2, r2, r4              ;range = br->range-split
+    movlo   r2, r4                  ;range = split
+    movhs   r0, #1                  ;bit = 1
+    movhs   r3, r5                  ;value = value-bigsplit
+
+    cmp     r2, #0x80
+    blt     range_less_0x80
+    strd    r2, r3, [lr, #bool_decoder_range]   ;store result
+
+    ldmia   sp!, {r4 - r5, pc}
+
+range_less_0x80
+
+    ldrd    r4, r5, [lr, #bool_decoder_count]   ;load count, pos, buffer
+    ldr     r1, [lr, #bool_decoder_buffer]
+
+    clz     r12, r2
+    add     r1, r1, r5
+
+    sub     r12, r12, #24
+    subs    r4, r4, r12             ;count -= shift
+    mov     r2, r2, lsl r12         ;range <<= shift
+    mov     r3, r3, lsl r12         ;value <<= shift
+    addle   r4, r4, #8              ;count += 8
+    ldrleb  r12, [r1], #1           ;br->buffer[br->pos]
+
+    rsble   r1, r4, #8              ;-count
+    addle   r5, r5, #1              ;br->pos++
+    orrle   r3, r3, r12, lsl r1     ;value |= (br->buffer[br->pos]) << (-count)
+
+    strd    r2, r3, [lr, #bool_decoder_range]   ;store result
+    strd    r4, r5, [lr, #bool_decoder_count]
+
+    ldmia   sp!, {r4 - r5, pc}
+    ENDP    ; |vp8dx_decode_bool_neon|
+
+    END
diff --git a/vp8/decoder/arm/neon/dequantdcidct_neon.asm b/vp8/decoder/arm/neon/dequantdcidct_neon.asm
new file mode 100644
index 0000000..3392f2c
--- /dev/null
+++ b/vp8/decoder/arm/neon/dequantdcidct_neon.asm
@@ -0,0 +1,133 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_dequant_dc_idct_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;void vp8_dequant_dc_idct_c(short *input, short *dq, short *output, int pitch, int Dc);
+; r0    short *input,
+; r1    short *dq,
+; r2    short *output,
+; r3    int pitch,
+; (stack)   int Dc
+|vp8_dequant_dc_idct_neon| PROC
+    vld1.16         {q3, q4}, [r0]
+    vld1.16         {q5, q6}, [r1]
+
+    ldr             r1, [sp]                ;load Dc from stack
+
+    ldr             r12, _dcidct_coeff_
+
+    vmul.i16        q1, q3, q5              ;input for short_idct4x4llm_neon
+    vmul.i16        q2, q4, q6
+
+    vmov.16         d2[0], r1
+
+;|short_idct4x4llm_neon| PROC
+    vld1.16         {d0}, [r12]
+    vswp            d3, d4                  ;q2(vp[4] vp[12])
+
+    vqdmulh.s16     q3, q2, d0[2]
+    vqdmulh.s16     q4, q2, d0[0]
+
+    vqadd.s16       d12, d2, d3             ;a1
+    vqsub.s16       d13, d2, d3             ;b1
+
+    vshr.s16        q3, q3, #1
+    vshr.s16        q4, q4, #1
+
+    vqadd.s16       q3, q3, q2              ;modify since sinpi8sqrt2 > 65536/2 (negtive number)
+    vqadd.s16       q4, q4, q2
+
+    ;d6 - c1:temp1
+    ;d7 - d1:temp2
+    ;d8 - d1:temp1
+    ;d9 - c1:temp2
+
+    vqsub.s16       d10, d6, d9             ;c1
+    vqadd.s16       d11, d7, d8             ;d1
+
+    vqadd.s16       d2, d12, d11
+    vqadd.s16       d3, d13, d10
+    vqsub.s16       d4, d13, d10
+    vqsub.s16       d5, d12, d11
+
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+; memset(input, 0, 32) -- 32bytes
+    vmov.i16        q14, #0
+
+    vswp            d3, d4
+    vqdmulh.s16     q3, q2, d0[2]
+    vqdmulh.s16     q4, q2, d0[0]
+
+    vqadd.s16       d12, d2, d3             ;a1
+    vqsub.s16       d13, d2, d3             ;b1
+
+    vmov            q15, q14
+
+    vshr.s16        q3, q3, #1
+    vshr.s16        q4, q4, #1
+
+    vqadd.s16       q3, q3, q2              ;modify since sinpi8sqrt2 > 65536/2 (negtive number)
+    vqadd.s16       q4, q4, q2
+
+    vqsub.s16       d10, d6, d9             ;c1
+    vqadd.s16       d11, d7, d8             ;d1
+
+    vqadd.s16       d2, d12, d11
+    vqadd.s16       d3, d13, d10
+    vqsub.s16       d4, d13, d10
+    vqsub.s16       d5, d12, d11
+
+    vst1.16         {q14, q15}, [r0]
+
+    vrshr.s16       d2, d2, #3
+    vrshr.s16       d3, d3, #3
+    vrshr.s16       d4, d4, #3
+    vrshr.s16       d5, d5, #3
+
+    add             r1, r2, r3
+    add             r12, r1, r3
+    add             r0, r12, r3
+
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+    vst1.16         {d2}, [r2]
+    vst1.16         {d3}, [r1]
+    vst1.16         {d4}, [r12]
+    vst1.16         {d5}, [r0]
+
+    bx             lr
+
+    ENDP
+
+;-----------------
+    AREA    dcidct4x4_dat, DATA, READWRITE          ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_dcidct_coeff_
+    DCD     dcidct_coeff
+dcidct_coeff
+    DCD     0x4e7b4e7b, 0x8a8c8a8c
+
+;20091, 20091, 35468, 35468
+
+    END
diff --git a/vp8/decoder/arm/neon/dequantidct_neon.asm b/vp8/decoder/arm/neon/dequantidct_neon.asm
new file mode 100644
index 0000000..bba4d5d
--- /dev/null
+++ b/vp8/decoder/arm/neon/dequantidct_neon.asm
@@ -0,0 +1,128 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_dequant_idct_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;void vp8_dequant_idct_c(short *input, short *dq, short *output, int pitch);
+; r0    short *input,
+; r1    short *dq,
+; r2    short *output,
+; r3    int pitch,
+|vp8_dequant_idct_neon| PROC
+    vld1.16         {q3, q4}, [r0]
+    vld1.16         {q5, q6}, [r1]
+
+    ldr             r12, _didct_coeff_
+
+    vmul.i16        q1, q3, q5              ;input for short_idct4x4llm_neon
+    vmul.i16        q2, q4, q6
+
+;|short_idct4x4llm_neon| PROC
+    vld1.16         {d0}, [r12]
+    vswp            d3, d4                  ;q2(vp[4] vp[12])
+
+    vqdmulh.s16     q3, q2, d0[2]
+    vqdmulh.s16     q4, q2, d0[0]
+
+    vqadd.s16       d12, d2, d3             ;a1
+    vqsub.s16       d13, d2, d3             ;b1
+
+    vshr.s16        q3, q3, #1
+    vshr.s16        q4, q4, #1
+
+    vqadd.s16       q3, q3, q2              ;modify since sinpi8sqrt2 > 65536/2 (negtive number)
+    vqadd.s16       q4, q4, q2
+
+    ;d6 - c1:temp1
+    ;d7 - d1:temp2
+    ;d8 - d1:temp1
+    ;d9 - c1:temp2
+
+    vqsub.s16       d10, d6, d9             ;c1
+    vqadd.s16       d11, d7, d8             ;d1
+
+    vqadd.s16       d2, d12, d11
+    vqadd.s16       d3, d13, d10
+    vqsub.s16       d4, d13, d10
+    vqsub.s16       d5, d12, d11
+
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+; memset(input, 0, 32) -- 32bytes
+    vmov.i16        q14, #0
+
+    vswp            d3, d4
+    vqdmulh.s16     q3, q2, d0[2]
+    vqdmulh.s16     q4, q2, d0[0]
+
+    vqadd.s16       d12, d2, d3             ;a1
+    vqsub.s16       d13, d2, d3             ;b1
+
+    vmov            q15, q14
+
+    vshr.s16        q3, q3, #1
+    vshr.s16        q4, q4, #1
+
+    vqadd.s16       q3, q3, q2              ;modify since sinpi8sqrt2 > 65536/2 (negtive number)
+    vqadd.s16       q4, q4, q2
+
+    vqsub.s16       d10, d6, d9             ;c1
+    vqadd.s16       d11, d7, d8             ;d1
+
+    vqadd.s16       d2, d12, d11
+    vqadd.s16       d3, d13, d10
+    vqsub.s16       d4, d13, d10
+    vqsub.s16       d5, d12, d11
+
+    vst1.16         {q14, q15}, [r0]
+
+    vrshr.s16       d2, d2, #3
+    vrshr.s16       d3, d3, #3
+    vrshr.s16       d4, d4, #3
+    vrshr.s16       d5, d5, #3
+
+    add             r1, r2, r3
+    add             r12, r1, r3
+    add             r0, r12, r3
+
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+    vst1.16         {d2}, [r2]
+    vst1.16         {d3}, [r1]
+    vst1.16         {d4}, [r12]
+    vst1.16         {d5}, [r0]
+
+    bx             lr
+
+    ENDP
+
+;-----------------
+    AREA    didct4x4_dat, DATA, READWRITE           ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_didct_coeff_
+    DCD     didct_coeff
+didct_coeff
+    DCD     0x4e7b4e7b, 0x8a8c8a8c
+
+;20091, 20091, 35468, 35468
+
+    END
diff --git a/vp8/decoder/arm/neon/dequantizeb_neon.asm b/vp8/decoder/arm/neon/dequantizeb_neon.asm
new file mode 100644
index 0000000..1bde946
--- /dev/null
+++ b/vp8/decoder/arm/neon/dequantizeb_neon.asm
@@ -0,0 +1,33 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_dequantize_b_loop_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    short *Q,
+; r1    short *DQC
+; r2    short *DQ
+|vp8_dequantize_b_loop_neon| PROC
+    vld1.16         {q0, q1}, [r0]
+    vld1.16         {q2, q3}, [r1]
+
+    vmul.i16        q4, q0, q2
+    vmul.i16        q5, q1, q3
+
+    vst1.16         {q4, q5}, [r2]
+
+    bx             lr
+
+    ENDP
+
+    END
diff --git a/vp8/decoder/dboolhuff.c b/vp8/decoder/dboolhuff.c
new file mode 100644
index 0000000..442054e
--- /dev/null
+++ b/vp8/decoder/dboolhuff.c
@@ -0,0 +1,174 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "dboolhuff.h"
+#include "vpx_ports/mem.h"
+#include "vpx_mem/vpx_mem.h"
+
+DECLARE_ALIGNED(16, const unsigned int, vp8dx_bitreader_norm[256]) =
+{
+    0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+
+static void copy_in(BOOL_DECODER *br, unsigned int to_write)
+{
+    if (to_write > br->user_buffer_sz)
+        to_write = br->user_buffer_sz;
+
+    memcpy(br->write_ptr, br->user_buffer, to_write);
+    br->user_buffer += to_write;
+    br->user_buffer_sz -= to_write;
+    br->write_ptr = br_ptr_advance(br->write_ptr, to_write);
+}
+
+int vp8dx_start_decode_c(BOOL_DECODER *br, const unsigned char *source,
+                        unsigned int source_sz)
+{
+    br->lowvalue = 0;
+    br->range    = 255;
+    br->count    = 0;
+    br->user_buffer    = source;
+    br->user_buffer_sz = source_sz;
+
+    if (source_sz && !source)
+        return 1;
+
+    /* Allocate the ring buffer backing store with alignment equal to the
+     * buffer size*2 so that a single pointer can be used for wrapping rather
+     * than a pointer+offset.
+     */
+    br->decode_buffer  = vpx_memalign(VP8_BOOL_DECODER_SZ * 2,
+                                      VP8_BOOL_DECODER_SZ);
+
+    if (!br->decode_buffer)
+        return 1;
+
+    /* Populate the buffer */
+    br->read_ptr = br->decode_buffer;
+    br->write_ptr = br->decode_buffer;
+    copy_in(br, VP8_BOOL_DECODER_SZ);
+
+    /* Read the first byte */
+    br->value = (*br->read_ptr++) << 8;
+    return 0;
+}
+
+
+void vp8dx_bool_decoder_fill_c(BOOL_DECODER *br)
+{
+    int          left, right;
+
+    /* Find available room in the buffer */
+    left = 0;
+    right = br->read_ptr - br->write_ptr;
+
+    if (right < 0)
+    {
+        /* Read pointer is behind the write pointer. We can write from the
+         * write pointer to the end of the buffer.
+         */
+        right = VP8_BOOL_DECODER_SZ - (br->write_ptr - br->decode_buffer);
+        left = br->read_ptr - br->decode_buffer;
+    }
+
+    if (right + left < 128)
+        return;
+
+    if (right)
+        copy_in(br, right);
+
+    if (left)
+    {
+        br->write_ptr = br->decode_buffer;
+        copy_in(br, left);
+    }
+
+}
+
+
+void vp8dx_stop_decode_c(BOOL_DECODER *bc)
+{
+    vpx_free(bc->decode_buffer);
+    bc->decode_buffer = 0;
+}
+
+#if 0
+/*
+ * Until optimized versions of these functions are available, we
+ * keep the implementation in the header to allow inlining.
+ *
+ * The RTCD-style invocations are still in place so this can
+ * be switched by just uncommenting these functions here and
+ * the DBOOLHUFF_INVOKE calls in the header.
+ */
+int vp8dx_decode_bool_c(BOOL_DECODER *br, int probability)
+{
+    unsigned int bit=0;
+    unsigned int split;
+    unsigned int bigsplit;
+    register unsigned int range = br->range;
+    register unsigned int value = br->value;
+
+    split = 1 + (((range-1) * probability) >> 8);
+    bigsplit = (split<<8);
+
+    range = split;
+    if(value >= bigsplit)
+    {
+        range = br->range-split;
+        value = value-bigsplit;
+        bit = 1;
+    }
+
+    /*if(range>=0x80)
+    {
+        br->value = value;
+        br->range = range;
+        return bit;
+    }*/
+
+    {
+        int count = br->count;
+        register unsigned int shift = vp8dx_bitreader_norm[range];
+        range <<= shift;
+        value <<= shift;
+        count -= shift;
+        if(count <= 0)
+        {
+            value |= (*br->read_ptr) << (-count);
+            br->read_ptr = br_ptr_advance(br->read_ptr, 1);
+            count += 8 ;
+        }
+        br->count = count;
+    }
+    br->value = value;
+    br->range = range;
+    return bit;
+}
+
+int vp8dx_decode_value_c(BOOL_DECODER *br, int bits)
+{
+    int z = 0;
+    int bit;
+    for ( bit=bits-1; bit>=0; bit-- )
+    {
+        z |= (vp8dx_decode_bool(br, 0x80)<<bit);
+    }
+    return z;
+}
+#endif
diff --git a/vp8/decoder/dboolhuff.h b/vp8/decoder/dboolhuff.h
new file mode 100644
index 0000000..f5c9822
--- /dev/null
+++ b/vp8/decoder/dboolhuff.h
@@ -0,0 +1,226 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef DBOOLHUFF_H
+#define DBOOLHUFF_H
+#include "vpx_ports/config.h"
+#include "vpx_ports/mem.h"
+#include "vpx_ports/vpx_integer.h"
+
+/* Size of the bool decoder backing storage
+ *
+ * This size was chosen to be greater than the worst case encoding of a
+ * single macroblock. This was calcluated as follows (python):
+ *
+ *     def max_cost(prob):
+ *         return max(prob_costs[prob], prob_costs[255-prob]) / 256;
+ *
+ *     tree_nodes_cost = 7 * max_cost(255)
+ *     extra_bits_cost = sum([max_cost(bit) for bit in extra_bits])
+ *     sign_bit_cost = max_cost(128)
+ *     total_cost = tree_nodes_cost + extra_bits_cost + sign_bit_cost
+ *
+ * where the prob_costs table was taken from the C vp8_prob_cost table in
+ * boolhuff.c and the extra_bits table was taken from the 11 extrabits for
+ * a category 6 token as defined in vp8d_token_extra_bits2/detokenize.c
+ *
+ * This equation produced a maximum of 79 bits per coefficient. Scaling up
+ * to the macroblock level:
+ *
+ *     79 bits/coeff * 16 coeff/block * 25 blocks/macroblock = 31600 b/mb
+ *
+ *     4096 bytes = 32768 bits > 31600
+ */
+#define VP8_BOOL_DECODER_SZ       4096
+#define VP8_BOOL_DECODER_MASK     (VP8_BOOL_DECODER_SZ-1)
+#define VP8_BOOL_DECODER_PTR_MASK (~(uintptr_t)(VP8_BOOL_DECODER_SZ))
+
+struct vp8_dboolhuff_rtcd_vtable;
+
+typedef struct
+{
+    unsigned int         lowvalue;
+    unsigned int         range;
+    unsigned int         value;
+    int                  count;
+    const unsigned char *user_buffer;
+    unsigned int         user_buffer_sz;
+    unsigned char       *decode_buffer;
+    const unsigned char *read_ptr;
+    unsigned char       *write_ptr;
+#if CONFIG_RUNTIME_CPU_DETECT
+    struct vp8_dboolhuff_rtcd_vtable *rtcd;
+#endif
+} BOOL_DECODER;
+
+#define prototype_dbool_start(sym) int sym(BOOL_DECODER *br, \
+    const unsigned char *source, unsigned int source_sz)
+#define prototype_dbool_stop(sym) void sym(BOOL_DECODER *bc)
+#define prototype_dbool_fill(sym) void sym(BOOL_DECODER *br)
+#define prototype_dbool_debool(sym) int sym(BOOL_DECODER *br, int probability)
+#define prototype_dbool_devalue(sym) int sym(BOOL_DECODER *br, int bits);
+
+#if ARCH_ARM
+#include "arm/dboolhuff_arm.h"
+#endif
+
+#ifndef vp8_dbool_start
+#define vp8_dbool_start vp8dx_start_decode_c
+#endif
+
+#ifndef vp8_dbool_stop
+#define vp8_dbool_stop vp8dx_stop_decode_c
+#endif
+
+#ifndef vp8_dbool_fill
+#define vp8_dbool_fill vp8dx_bool_decoder_fill_c
+#endif
+
+#ifndef vp8_dbool_debool
+#define vp8_dbool_debool vp8dx_decode_bool_c
+#endif
+
+#ifndef vp8_dbool_devalue
+#define vp8_dbool_devalue vp8dx_decode_value_c
+#endif
+
+extern prototype_dbool_start(vp8_dbool_start);
+extern prototype_dbool_stop(vp8_dbool_stop);
+extern prototype_dbool_fill(vp8_dbool_fill);
+extern prototype_dbool_debool(vp8_dbool_debool);
+extern prototype_dbool_devalue(vp8_dbool_devalue);
+
+typedef prototype_dbool_start((*vp8_dbool_start_fn_t));
+typedef prototype_dbool_stop((*vp8_dbool_stop_fn_t));
+typedef prototype_dbool_fill((*vp8_dbool_fill_fn_t));
+typedef prototype_dbool_debool((*vp8_dbool_debool_fn_t));
+typedef prototype_dbool_devalue((*vp8_dbool_devalue_fn_t));
+
+typedef struct vp8_dboolhuff_rtcd_vtable {
+    vp8_dbool_start_fn_t   start;
+    vp8_dbool_stop_fn_t    stop;
+    vp8_dbool_fill_fn_t    fill;
+    vp8_dbool_debool_fn_t  debool;
+    vp8_dbool_devalue_fn_t devalue;
+} vp8_dboolhuff_rtcd_vtable_t;
+
+// There are no processor-specific versions of these
+// functions right now. Disable RTCD to avoid using
+// function pointers which gives a speed boost
+//#ifdef ENABLE_RUNTIME_CPU_DETECT
+//#define DBOOLHUFF_INVOKE(ctx,fn) (ctx)->fn
+//#define IF_RTCD(x) (x)
+//#else
+#define DBOOLHUFF_INVOKE(ctx,fn) vp8_dbool_##fn
+#define IF_RTCD(x) NULL
+//#endif
+
+static unsigned char *br_ptr_advance(const unsigned char *_ptr,
+                                     unsigned int n)
+{
+    uintptr_t  ptr = (uintptr_t)_ptr;
+
+    ptr += n;
+    ptr &= VP8_BOOL_DECODER_PTR_MASK;
+
+    return (void *)ptr;
+}
+
+DECLARE_ALIGNED(16, extern const unsigned int, vp8dx_bitreader_norm[256]);
+
+/* wrapper functions to hide RTCD. static means inline means hopefully no
+ * penalty
+ */
+static int vp8dx_start_decode(BOOL_DECODER *br,
+        struct vp8_dboolhuff_rtcd_vtable *rtcd,
+        const unsigned char *source, unsigned int source_sz) {
+#if CONFIG_RUNTIME_CPU_DETECT
+    br->rtcd = rtcd;
+#endif
+    return DBOOLHUFF_INVOKE(rtcd, start)(br, source, source_sz);
+}
+static void vp8dx_stop_decode(BOOL_DECODER *br) {
+    DBOOLHUFF_INVOKE(br->rtcd, stop)(br);
+}
+static void vp8dx_bool_decoder_fill(BOOL_DECODER *br) {
+    DBOOLHUFF_INVOKE(br->rtcd, fill)(br);
+}
+static int vp8dx_decode_bool(BOOL_DECODER *br, int probability) {
+  /*
+   * Until optimized versions of this function are available, we
+   * keep the implementation in the header to allow inlining.
+   *
+   *return DBOOLHUFF_INVOKE(br->rtcd, debool)(br, probability);
+   */
+    unsigned int bit = 0;
+    unsigned int split;
+    unsigned int bigsplit;
+    register unsigned int range = br->range;
+    register unsigned int value = br->value;
+
+    split = 1 + (((range - 1) * probability) >> 8);
+    bigsplit = (split << 8);
+
+    range = split;
+
+    if (value >= bigsplit)
+    {
+        range = br->range - split;
+        value = value - bigsplit;
+        bit = 1;
+    }
+
+    /*if(range>=0x80)
+    {
+        br->value = value;
+        br->range = range;
+        return bit
+    }*/
+
+    {
+        int count = br->count;
+        register unsigned int shift = vp8dx_bitreader_norm[range];
+        range <<= shift;
+        value <<= shift;
+        count -= shift;
+
+        if (count <= 0)
+        {
+            value |= (*br->read_ptr) << (-count);
+            br->read_ptr = br_ptr_advance(br->read_ptr, 1);
+            count += 8 ;
+        }
+
+        br->count = count;
+    }
+    br->value = value;
+    br->range = range;
+    return bit;
+}
+
+static int vp8_decode_value(BOOL_DECODER *br, int bits)
+{
+  /*
+   * Until optimized versions of this function are available, we
+   * keep the implementation in the header to allow inlining.
+   *
+   *return DBOOLHUFF_INVOKE(br->rtcd, devalue)(br, bits);
+   */
+    int z = 0;
+    int bit;
+
+    for (bit = bits - 1; bit >= 0; bit--)
+    {
+        z |= (vp8dx_decode_bool(br, 0x80) << bit);
+    }
+
+    return z;
+}
+#endif
diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c
new file mode 100644
index 0000000..6035f3e
--- /dev/null
+++ b/vp8/decoder/decodemv.c
@@ -0,0 +1,418 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "treereader.h"
+#include "entropymv.h"
+#include "entropymode.h"
+#include "onyxd_int.h"
+#include "findnearmv.h"
+#include "demode.h"
+#if CONFIG_DEBUG
+#include <assert.h>
+#endif
+
+static int read_mvcomponent(vp8_reader *r, const MV_CONTEXT *mvc)
+{
+    const vp8_prob *const p = (const vp8_prob *) mvc;
+    int x = 0;
+
+    if (vp8_read(r, p [mvpis_short]))  /* Large */
+    {
+        int i = 0;
+
+        do
+        {
+            x += vp8_read(r, p [MVPbits + i]) << i;
+        }
+        while (++i < 3);
+
+        i = mvlong_width - 1;  /* Skip bit 3, which is sometimes implicit */
+
+        do
+        {
+            x += vp8_read(r, p [MVPbits + i]) << i;
+        }
+        while (--i > 3);
+
+        if (!(x & 0xFFF0)  ||  vp8_read(r, p [MVPbits + 3]))
+            x += 8;
+    }
+    else   /* small */
+        x = vp8_treed_read(r, vp8_small_mvtree, p + MVPshort);
+
+    if (x  &&  vp8_read(r, p [MVPsign]))
+        x = -x;
+
+    return x;
+}
+
+static void read_mv(vp8_reader *r, MV *mv, const MV_CONTEXT *mvc)
+{
+    mv->row = (short)(read_mvcomponent(r,   mvc) << 1);
+    mv->col = (short)(read_mvcomponent(r, ++mvc) << 1);
+}
+
+
+static void read_mvcontexts(vp8_reader *bc, MV_CONTEXT *mvc)
+{
+    int i = 0;
+
+    do
+    {
+        const vp8_prob *up = vp8_mv_update_probs[i].prob;
+        vp8_prob *p = (vp8_prob *)(mvc + i);
+        vp8_prob *const pstop = p + MVPcount;
+
+        do
+        {
+            if (vp8_read(bc, *up++))
+            {
+                const vp8_prob x = (vp8_prob)vp8_read_literal(bc, 7);
+
+                *p = x ? x << 1 : 1;
+            }
+        }
+        while (++p < pstop);
+    }
+    while (++i < 2);
+}
+
+
+static MB_PREDICTION_MODE read_mv_ref(vp8_reader *bc, const vp8_prob *p)
+{
+    const int i = vp8_treed_read(bc, vp8_mv_ref_tree, p);
+
+    return (MB_PREDICTION_MODE)i;
+}
+
+static MB_PREDICTION_MODE sub_mv_ref(vp8_reader *bc, const vp8_prob *p)
+{
+    const int i = vp8_treed_read(bc, vp8_sub_mv_ref_tree, p);
+
+    return (MB_PREDICTION_MODE)i;
+}
+unsigned int vp8_mv_cont_count[5][4] =
+{
+    { 0, 0, 0, 0 },
+    { 0, 0, 0, 0 },
+    { 0, 0, 0, 0 },
+    { 0, 0, 0, 0 },
+    { 0, 0, 0, 0 }
+};
+
+void vp8_decode_mode_mvs(VP8D_COMP *pbi)
+{
+    const MV Zero = { 0, 0};
+
+    VP8_COMMON *const pc = & pbi->common;
+    vp8_reader *const bc = & pbi->bc;
+
+    MODE_INFO *mi = pc->mi, *ms;
+    const int mis = pc->mode_info_stride;
+
+    MV_CONTEXT *const mvc = pc->fc.mvc;
+
+    int mb_row = -1;
+
+    vp8_prob prob_intra;
+    vp8_prob prob_last;
+    vp8_prob prob_gf;
+    vp8_prob prob_skip_false = 0;
+
+    if (pc->mb_no_coeff_skip)
+        prob_skip_false = (vp8_prob)vp8_read_literal(bc, 8);
+
+    prob_intra = (vp8_prob)vp8_read_literal(bc, 8);
+    prob_last  = (vp8_prob)vp8_read_literal(bc, 8);
+    prob_gf    = (vp8_prob)vp8_read_literal(bc, 8);
+
+    ms = pc->mi - 1;
+
+    if (vp8_read_bit(bc))
+    {
+        int i = 0;
+
+        do
+        {
+            pc->fc.ymode_prob[i] = (vp8_prob) vp8_read_literal(bc, 8);
+        }
+        while (++i < 4);
+    }
+
+    if (vp8_read_bit(bc))
+    {
+        int i = 0;
+
+        do
+        {
+            pc->fc.uv_mode_prob[i] = (vp8_prob) vp8_read_literal(bc, 8);
+        }
+        while (++i < 3);
+    }
+
+    read_mvcontexts(bc, mvc);
+
+    while (++mb_row < pc->mb_rows)
+    {
+        int mb_col = -1;
+
+        while (++mb_col < pc->mb_cols)
+        {
+            MB_MODE_INFO *const mbmi = & mi->mbmi;
+            MV *const mv = & mbmi->mv.as_mv;
+            VP8_COMMON *const pc = &pbi->common;
+            MACROBLOCKD *xd = &pbi->mb;
+
+            vp8dx_bool_decoder_fill(bc);
+
+            // Distance of Mb to the various image edges.
+            // These specified to 8th pel as they are always compared to MV values that are in 1/8th pel units
+            xd->mb_to_left_edge = -((mb_col * 16) << 3);
+            xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
+            xd->mb_to_top_edge = -((mb_row * 16)) << 3;
+            xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
+
+            // If required read in new segmentation data for this MB
+            if (pbi->mb.update_mb_segmentation_map)
+                vp8_read_mb_features(bc, mbmi, &pbi->mb);
+
+            // Read the macroblock coeff skip flag if this feature is in use, else default to 0
+            if (pc->mb_no_coeff_skip)
+                mbmi->mb_skip_coeff = vp8_read(bc, prob_skip_false);
+            else
+                mbmi->mb_skip_coeff = 0;
+
+            mbmi->uv_mode = DC_PRED;
+
+            if ((mbmi->ref_frame = (MV_REFERENCE_FRAME) vp8_read(bc, prob_intra)))    /* inter MB */
+            {
+                int rct[4];
+                vp8_prob mv_ref_p [VP8_MVREFS-1];
+                MV nearest, nearby, best_mv;
+
+                if (vp8_read(bc, prob_last))
+                {
+                    mbmi->ref_frame = (MV_REFERENCE_FRAME)((int)mbmi->ref_frame + (int)(1 + vp8_read(bc, prob_gf)));
+                }
+
+                vp8_find_near_mvs(xd, mi, &nearest, &nearby, &best_mv, rct, mbmi->ref_frame, pbi->common.ref_frame_sign_bias);
+
+                vp8_mv_ref_probs(mv_ref_p, rct);
+
+                switch (mbmi->mode = read_mv_ref(bc, mv_ref_p))
+                {
+                case SPLITMV:
+                {
+                    const int s = mbmi->partitioning = vp8_treed_read(
+                                                           bc, vp8_mbsplit_tree, vp8_mbsplit_probs
+                                                       );
+                    const int num_p = vp8_mbsplit_count [s];
+                    const int *const  L = vp8_mbsplits [s];
+                    int j = 0;
+
+                    do  /* for each subset j */
+                    {
+                        B_MODE_INFO *const bmi = mbmi->partition_bmi + j;
+                        MV *const mv = & bmi->mv.as_mv;
+
+                        int k = -1;  /* first block in subset j */
+                        int mv_contz;
+
+                        while (j != L[++k])
+                            if (k >= 16)
+#if CONFIG_DEBUG
+                                assert(0);
+
+#else
+                                ;
+#endif
+
+                        mv_contz = vp8_mv_cont(&(vp8_left_bmi(mi, k)->mv.as_mv), &(vp8_above_bmi(mi, k, mis)->mv.as_mv));
+
+                        switch (bmi->mode = (B_PREDICTION_MODE) sub_mv_ref(bc, vp8_sub_mv_ref_prob2 [mv_contz])) //pc->fc.sub_mv_ref_prob))
+                        {
+                        case NEW4X4:
+                            read_mv(bc, mv, (const MV_CONTEXT *) mvc);
+                            mv->row += best_mv.row;
+                            mv->col += best_mv.col;
+#ifdef VPX_MODE_COUNT
+                            vp8_mv_cont_count[mv_contz][3]++;
+#endif
+                            break;
+                        case LEFT4X4:
+                            *mv = vp8_left_bmi(mi, k)->mv.as_mv;
+#ifdef VPX_MODE_COUNT
+                            vp8_mv_cont_count[mv_contz][0]++;
+#endif
+                            break;
+                        case ABOVE4X4:
+                            *mv = vp8_above_bmi(mi, k, mis)->mv.as_mv;
+#ifdef VPX_MODE_COUNT
+                            vp8_mv_cont_count[mv_contz][1]++;
+#endif
+                            break;
+                        case ZERO4X4:
+                            *mv = Zero;
+#ifdef VPX_MODE_COUNT
+                            vp8_mv_cont_count[mv_contz][2]++;
+#endif
+                            break;
+                        default:
+                            break;
+                        }
+
+                        /* Fill (uniform) modes, mvs of jth subset.
+                           Must do it here because ensuing subsets can
+                           refer back to us via "left" or "above". */
+                        do
+                            if (j == L[k])
+                                mi->bmi[k] = *bmi;
+
+                        while (++k < 16);
+                    }
+                    while (++j < num_p);
+                }
+
+                *mv = mi->bmi[15].mv.as_mv;
+
+                break;  /* done with SPLITMV */
+
+                case NEARMV:
+                    *mv = nearby;
+
+                    // Clip "next_nearest" so that it does not extend to far out of image
+                    if (mv->col < (xd->mb_to_left_edge - LEFT_TOP_MARGIN))
+                        mv->col = xd->mb_to_left_edge - LEFT_TOP_MARGIN;
+                    else if (mv->col > xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN)
+                        mv->col = xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN;
+
+                    if (mv->row < (xd->mb_to_top_edge - LEFT_TOP_MARGIN))
+                        mv->row = xd->mb_to_top_edge - LEFT_TOP_MARGIN;
+                    else if (mv->row > xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN)
+                        mv->row = xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN;
+
+                    goto propagate_mv;
+
+                case NEARESTMV:
+                    *mv = nearest;
+
+                    // Clip "next_nearest" so that it does not extend to far out of image
+                    if (mv->col < (xd->mb_to_left_edge - LEFT_TOP_MARGIN))
+                        mv->col = xd->mb_to_left_edge - LEFT_TOP_MARGIN;
+                    else if (mv->col > xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN)
+                        mv->col = xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN;
+
+                    if (mv->row < (xd->mb_to_top_edge - LEFT_TOP_MARGIN))
+                        mv->row = xd->mb_to_top_edge - LEFT_TOP_MARGIN;
+                    else if (mv->row > xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN)
+                        mv->row = xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN;
+
+                    goto propagate_mv;
+
+                case ZEROMV:
+                    *mv = Zero;
+                    goto propagate_mv;
+
+                case NEWMV:
+                    read_mv(bc, mv, (const MV_CONTEXT *) mvc);
+                    mv->row += best_mv.row;
+                    mv->col += best_mv.col;
+                    /* Encoder should not produce invalid motion vectors, but since
+                     * arbitrary length MVs can be parsed from the bitstream, we
+                     * need to clamp them here in case we're reading bad data to
+                     * avoid a crash.
+                     */
+#if CONFIG_DEBUG
+                    assert(mv->col >= (xd->mb_to_left_edge - LEFT_TOP_MARGIN));
+                    assert(mv->col <= (xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN));
+                    assert(mv->row >= (xd->mb_to_top_edge - LEFT_TOP_MARGIN));
+                    assert(mv->row <= (xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN));
+#endif
+
+                    if (mv->col < (xd->mb_to_left_edge - LEFT_TOP_MARGIN))
+                        mv->col = xd->mb_to_left_edge - LEFT_TOP_MARGIN;
+                    else if (mv->col > xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN)
+                        mv->col = xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN;
+
+                    if (mv->row < (xd->mb_to_top_edge - LEFT_TOP_MARGIN))
+                        mv->row = xd->mb_to_top_edge - LEFT_TOP_MARGIN;
+                    else if (mv->row > xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN)
+                        mv->row = xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN;
+
+                propagate_mv:  /* same MV throughout */
+                    {
+                        //int i=0;
+                        //do
+                        //{
+                        //  mi->bmi[i].mv.as_mv = *mv;
+                        //}
+                        //while( ++i < 16);
+
+                        mi->bmi[0].mv.as_mv = *mv;
+                        mi->bmi[1].mv.as_mv = *mv;
+                        mi->bmi[2].mv.as_mv = *mv;
+                        mi->bmi[3].mv.as_mv = *mv;
+                        mi->bmi[4].mv.as_mv = *mv;
+                        mi->bmi[5].mv.as_mv = *mv;
+                        mi->bmi[6].mv.as_mv = *mv;
+                        mi->bmi[7].mv.as_mv = *mv;
+                        mi->bmi[8].mv.as_mv = *mv;
+                        mi->bmi[9].mv.as_mv = *mv;
+                        mi->bmi[10].mv.as_mv = *mv;
+                        mi->bmi[11].mv.as_mv = *mv;
+                        mi->bmi[12].mv.as_mv = *mv;
+                        mi->bmi[13].mv.as_mv = *mv;
+                        mi->bmi[14].mv.as_mv = *mv;
+                        mi->bmi[15].mv.as_mv = *mv;
+                    }
+
+                    break;
+
+                default:;
+#if CONFIG_DEBUG
+                    assert(0);
+#endif
+                }
+
+            }
+            else
+            {
+                /* MB is intra coded */
+
+                int j = 0;
+
+                do
+                {
+                    mi->bmi[j].mv.as_mv = Zero;
+                }
+                while (++j < 16);
+
+                *mv = Zero;
+
+                if ((mbmi->mode = (MB_PREDICTION_MODE) vp8_read_ymode(bc, pc->fc.ymode_prob)) == B_PRED)
+                {
+                    int j = 0;
+
+                    do
+                    {
+                        mi->bmi[j].mode = (B_PREDICTION_MODE)vp8_read_bmode(bc, pc->fc.bmode_prob);
+                    }
+                    while (++j < 16);
+                }
+
+                mbmi->uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode(bc, pc->fc.uv_mode_prob);
+            }
+
+            mi++;       // next macroblock
+        }
+
+        mi++;           // skip left predictor each row
+    }
+}
diff --git a/vp8/decoder/decodemv.h b/vp8/decoder/decodemv.h
new file mode 100644
index 0000000..4030071
--- /dev/null
+++ b/vp8/decoder/decodemv.h
@@ -0,0 +1,13 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "onyxd_int.h"
+
+void vp8_decode_mode_mvs(VP8D_COMP *);
diff --git a/vp8/decoder/decoderthreading.h b/vp8/decoder/decoderthreading.h
new file mode 100644
index 0000000..ebc5c27
--- /dev/null
+++ b/vp8/decoder/decoderthreading.h
@@ -0,0 +1,24 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+
+
+
+#ifndef _DECODER_THREADING_H
+#define _DECODER_THREADING_H
+
+
+extern void vp8_mtdecode_mb_rows(VP8D_COMP *pbi,
+                                 MACROBLOCKD *xd);
+extern void vp8_stop_lfthread(VP8D_COMP *pbi);
+extern void vp8_start_lfthread(VP8D_COMP *pbi);
+extern void vp8_decoder_remove_threads(VP8D_COMP *pbi);
+extern void vp8_decoder_create_threads(VP8D_COMP *pbi);
+#endif
diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c
new file mode 100644
index 0000000..4edf4f6
--- /dev/null
+++ b/vp8/decoder/decodframe.c
@@ -0,0 +1,907 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "onyxd_int.h"
+#include "header.h"
+#include "reconintra.h"
+#include "reconintra4x4.h"
+#include "recon.h"
+#include "reconinter.h"
+#include "dequantize.h"
+#include "detokenize.h"
+#include "invtrans.h"
+#include "alloccommon.h"
+#include "entropymode.h"
+#include "quant_common.h"
+#include "segmentation_common.h"
+#include "setupintrarecon.h"
+#include "demode.h"
+#include "decodemv.h"
+#include "extend.h"
+#include "vpx_mem/vpx_mem.h"
+#include "idct.h"
+#include "dequantize.h"
+#include "predictdc.h"
+#include "threading.h"
+#include "decoderthreading.h"
+#include "dboolhuff.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+void vp8cx_init_de_quantizer(VP8D_COMP *pbi)
+{
+    int r, c;
+    int i;
+    int Q;
+    VP8_COMMON *const pc = & pbi->common;
+
+    for (Q = 0; Q < QINDEX_RANGE; Q++)
+    {
+        pc->Y1dequant[Q][0][0] = (short)vp8_dc_quant(Q, pc->y1dc_delta_q);
+        pc->Y2dequant[Q][0][0] = (short)vp8_dc2quant(Q, pc->y2dc_delta_q);
+        pc->UVdequant[Q][0][0] = (short)vp8_dc_uv_quant(Q, pc->uvdc_delta_q);
+
+        // all the ac values = ;
+        for (i = 1; i < 16; i++)
+        {
+            int rc = vp8_default_zig_zag1d[i];
+            r = (rc >> 2);
+            c = (rc & 3);
+
+            pc->Y1dequant[Q][r][c] = (short)vp8_ac_yquant(Q);
+            pc->Y2dequant[Q][r][c] = (short)vp8_ac2quant(Q, pc->y2ac_delta_q);
+            pc->UVdequant[Q][r][c] = (short)vp8_ac_uv_quant(Q, pc->uvac_delta_q);
+        }
+    }
+}
+
+static void mb_init_dequantizer(VP8D_COMP *pbi, MACROBLOCKD *xd)
+{
+    int i;
+    int QIndex;
+    MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
+    VP8_COMMON *const pc = & pbi->common;
+
+    // Decide whether to use the default or alternate baseline Q value.
+    if (xd->segmentation_enabled)
+    {
+        // Abs Value
+        if (xd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+            QIndex = xd->segment_feature_data[MB_LVL_ALT_Q][mbmi->segment_id];
+
+        // Delta Value
+        else
+        {
+            QIndex = pc->base_qindex + xd->segment_feature_data[MB_LVL_ALT_Q][mbmi->segment_id];
+            QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0;    // Clamp to valid range
+        }
+    }
+    else
+        QIndex = pc->base_qindex;
+
+    // Set up the block level dequant pointers
+    for (i = 0; i < 16; i++)
+    {
+        xd->block[i].dequant = pc->Y1dequant[QIndex];
+    }
+
+    for (i = 16; i < 24; i++)
+    {
+        xd->block[i].dequant = pc->UVdequant[QIndex];
+    }
+
+    xd->block[24].dequant = pc->Y2dequant[QIndex];
+
+}
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define RTCD_VTABLE(x) (&(pbi)->common.rtcd.x)
+#else
+#define RTCD_VTABLE(x) NULL
+#endif
+
+//skip_recon_mb() is Modified: Instead of writing the result to predictor buffer and then copying it
+// to dst buffer, we can write the result directly to dst buffer. This eliminates unnecessary copy.
+static void skip_recon_mb(VP8D_COMP *pbi, MACROBLOCKD *xd)
+{
+    if (xd->frame_type == KEY_FRAME  ||  xd->mbmi.ref_frame == INTRA_FRAME)
+    {
+
+        vp8_build_intra_predictors_mbuv_s(xd);
+        vp8_build_intra_predictors_mby_s_ptr(xd);
+
+    }
+    else
+    {
+        vp8_build_inter_predictors_mb_s(xd);
+    }
+}
+
+static void reconstruct_mb(VP8D_COMP *pbi, MACROBLOCKD *xd)
+{
+    if (xd->frame_type == KEY_FRAME  ||  xd->mbmi.ref_frame == INTRA_FRAME)
+    {
+        vp8_build_intra_predictors_mbuv(xd);
+
+        if (xd->mbmi.mode != B_PRED)
+        {
+            vp8_build_intra_predictors_mby_ptr(xd);
+            vp8_recon16x16mb(RTCD_VTABLE(recon), xd);
+        }
+        else
+        {
+            vp8_recon_intra4x4mb(RTCD_VTABLE(recon), xd);
+        }
+    }
+    else
+    {
+        vp8_build_inter_predictors_mb(xd);
+        vp8_recon16x16mb(RTCD_VTABLE(recon), xd);
+    }
+}
+
+
+static void de_quantand_idct(VP8D_COMP *pbi, MACROBLOCKD *xd)
+{
+    int i;
+    BLOCKD *b = &xd->block[24];
+
+
+    if (xd->mbmi.mode != B_PRED && xd->mbmi.mode != SPLITMV)
+    {
+        DEQUANT_INVOKE(&pbi->dequant, block)(b);
+
+        // do 2nd order transform on the dc block
+        if (b->eob > 1)
+        {
+            IDCT_INVOKE(RTCD_VTABLE(idct), iwalsh16)(&b->dqcoeff[0], b->diff);
+            ((int *)b->qcoeff)[0] = 0;
+            ((int *)b->qcoeff)[1] = 0;
+            ((int *)b->qcoeff)[2] = 0;
+            ((int *)b->qcoeff)[3] = 0;
+            ((int *)b->qcoeff)[4] = 0;
+            ((int *)b->qcoeff)[5] = 0;
+            ((int *)b->qcoeff)[6] = 0;
+            ((int *)b->qcoeff)[7] = 0;
+        }
+        else
+        {
+            IDCT_INVOKE(RTCD_VTABLE(idct), iwalsh1)(&b->dqcoeff[0], b->diff);
+            ((int *)b->qcoeff)[0] = 0;
+        }
+
+
+        for (i = 0; i < 16; i++)
+        {
+
+            b = &xd->block[i];
+
+            if (b->eob > 1)
+            {
+                DEQUANT_INVOKE(&pbi->dequant, idct_dc)(b->qcoeff, &b->dequant[0][0], b->diff, 32, xd->block[24].diff[i]);
+            }
+            else
+            {
+                IDCT_INVOKE(RTCD_VTABLE(idct), idct1_scalar)(xd->block[24].diff[i], b->diff, 32);
+            }
+        }
+
+        for (i = 16; i < 24; i++)
+        {
+            b = &xd->block[i];
+
+            if (b->eob > 1)
+            {
+                DEQUANT_INVOKE(&pbi->dequant, idct)(b->qcoeff, &b->dequant[0][0], b->diff, 16);
+            }
+            else
+            {
+                IDCT_INVOKE(RTCD_VTABLE(idct), idct1_scalar)(b->qcoeff[0] * b->dequant[0][0], b->diff, 16);
+                ((int *)b->qcoeff)[0] = 0;
+            }
+        }
+    }
+    else
+    {
+        for (i = 0; i < 24; i++)
+        {
+
+            b = &xd->block[i];
+
+            if (b->eob > 1)
+            {
+                DEQUANT_INVOKE(&pbi->dequant, idct)(b->qcoeff, &b->dequant[0][0], b->diff, (32 - (i & 16)));
+            }
+            else
+            {
+                IDCT_INVOKE(RTCD_VTABLE(idct), idct1_scalar)(b->qcoeff[0] * b->dequant[0][0], b->diff, (32 - (i & 16)));
+                ((int *)b->qcoeff)[0] = 0;
+            }
+        }
+    }
+}
+
+void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd)
+{
+    int eobtotal = 0;
+
+    if (xd->mbmi.mb_skip_coeff)
+    {
+        vp8_reset_mb_tokens_context(xd);
+    }
+    else
+    {
+        eobtotal = vp8_decode_mb_tokens(pbi, xd);
+    }
+
+    xd->mode_info_context->mbmi.dc_diff = 1;
+
+    if (xd->mbmi.mode != B_PRED && xd->mbmi.mode != SPLITMV && eobtotal == 0)
+    {
+        xd->mode_info_context->mbmi.dc_diff = 0;
+        skip_recon_mb(pbi, xd);
+        return;
+    }
+
+    if (xd->segmentation_enabled)
+        mb_init_dequantizer(pbi, xd);
+
+    de_quantand_idct(pbi, xd);
+    reconstruct_mb(pbi, xd);
+}
+
+static int get_delta_q(vp8_reader *bc, int prev, int *q_update)
+{
+    int ret_val = 0;
+
+    if (vp8_read_bit(bc))
+    {
+        ret_val = vp8_read_literal(bc, 4);
+
+        if (vp8_read_bit(bc))
+            ret_val = -ret_val;
+    }
+
+    /* Trigger a quantizer update if the delta-q value has changed */
+    if (ret_val != prev)
+        *q_update = 1;
+
+    return ret_val;
+}
+
+#ifdef PACKET_TESTING
+#include <stdio.h>
+FILE *vpxlog = 0;
+#endif
+
+
+
+void vp8_decode_mb_row(VP8D_COMP *pbi,
+                       VP8_COMMON *pc,
+                       int mb_row,
+                       MACROBLOCKD *xd)
+{
+
+    int i;
+    int recon_yoffset, recon_uvoffset;
+    int mb_col;
+    int recon_y_stride = pc->last_frame.y_stride;
+    int recon_uv_stride = pc->last_frame.uv_stride;
+
+    vpx_memset(pc->left_context, 0, sizeof(pc->left_context));
+    recon_yoffset = mb_row * recon_y_stride * 16;
+    recon_uvoffset = mb_row * recon_uv_stride * 8;
+    // reset above block coeffs
+
+    xd->above_context[Y1CONTEXT] = pc->above_context[Y1CONTEXT];
+    xd->above_context[UCONTEXT ] = pc->above_context[UCONTEXT];
+    xd->above_context[VCONTEXT ] = pc->above_context[VCONTEXT];
+    xd->above_context[Y2CONTEXT] = pc->above_context[Y2CONTEXT];
+    xd->up_available = (mb_row != 0);
+
+    xd->mb_to_top_edge = -((mb_row * 16)) << 3;
+    xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
+
+    for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
+    {
+        // Take a copy of the mode and Mv information for this macroblock into the xd->mbmi
+        vpx_memcpy(&xd->mbmi, &xd->mode_info_context->mbmi, 32); //sizeof(MB_MODE_INFO) );
+
+        if (xd->mbmi.mode == SPLITMV || xd->mbmi.mode == B_PRED)
+        {
+            for (i = 0; i < 16; i++)
+            {
+                BLOCKD *d = &xd->block[i];
+                vpx_memcpy(&d->bmi, &xd->mode_info_context->bmi[i], sizeof(B_MODE_INFO));
+            }
+        }
+
+        // Distance of Mb to the various image edges.
+        // These specified to 8th pel as they are always compared to values that are in 1/8th pel units
+        xd->mb_to_left_edge = -((mb_col * 16) << 3);
+        xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
+
+        xd->dst.y_buffer = pc->new_frame.y_buffer + recon_yoffset;
+        xd->dst.u_buffer = pc->new_frame.u_buffer + recon_uvoffset;
+        xd->dst.v_buffer = pc->new_frame.v_buffer + recon_uvoffset;
+
+        xd->left_available = (mb_col != 0);
+
+        // Select the appropriate reference frame for this MB
+        if (xd->mbmi.ref_frame == LAST_FRAME)
+        {
+            xd->pre.y_buffer = pc->last_frame.y_buffer + recon_yoffset;
+            xd->pre.u_buffer = pc->last_frame.u_buffer + recon_uvoffset;
+            xd->pre.v_buffer = pc->last_frame.v_buffer + recon_uvoffset;
+        }
+        else if (xd->mbmi.ref_frame == GOLDEN_FRAME)
+        {
+            // Golden frame reconstruction buffer
+            xd->pre.y_buffer = pc->golden_frame.y_buffer + recon_yoffset;
+            xd->pre.u_buffer = pc->golden_frame.u_buffer + recon_uvoffset;
+            xd->pre.v_buffer = pc->golden_frame.v_buffer + recon_uvoffset;
+        }
+        else
+        {
+            // Alternate reference frame reconstruction buffer
+            xd->pre.y_buffer = pc->alt_ref_frame.y_buffer + recon_yoffset;
+            xd->pre.u_buffer = pc->alt_ref_frame.u_buffer + recon_uvoffset;
+            xd->pre.v_buffer = pc->alt_ref_frame.v_buffer + recon_uvoffset;
+        }
+
+        vp8_build_uvmvs(xd, pc->full_pixel);
+
+        /*
+        if(pbi->common.current_video_frame==0 &&mb_col==1 && mb_row==0)
+        pbi->debugoutput =1;
+        else
+        pbi->debugoutput =0;
+        */
+        vp8dx_bool_decoder_fill(xd->current_bc);
+        vp8_decode_macroblock(pbi, xd);
+
+
+        recon_yoffset += 16;
+        recon_uvoffset += 8;
+
+        ++xd->mode_info_context;  /* next mb */
+
+        xd->gf_active_ptr++;      // GF useage flag for next MB
+
+        xd->above_context[Y1CONTEXT] += 4;
+        xd->above_context[UCONTEXT ] += 2;
+        xd->above_context[VCONTEXT ] += 2;
+        xd->above_context[Y2CONTEXT] ++;
+
+        pbi->current_mb_col_main = mb_col;
+    }
+
+    // adjust to the next row of mbs
+    vp8_extend_mb_row(
+        &pc->new_frame,
+        xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8
+    );
+
+    ++xd->mode_info_context;      /* skip prediction column */
+
+    pbi->last_mb_row_decoded = mb_row;
+}
+
+
+static unsigned int read_partition_size(const unsigned char *cx_size)
+{
+    const unsigned int size =
+        cx_size[0] + (cx_size[1] << 8) + (cx_size[2] << 16);
+    return size;
+}
+
+
+static void setup_token_decoder(VP8D_COMP *pbi,
+                                const unsigned char *cx_data)
+{
+    int num_part;
+    int i;
+    VP8_COMMON          *pc = &pbi->common;
+    const unsigned char *user_data_end = pbi->Source + pbi->source_sz;
+    vp8_reader          *bool_decoder;
+    const unsigned char *partition;
+
+    /* Parse number of token partitions to use */
+    pc->multi_token_partition = (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
+    num_part = 1 << pc->multi_token_partition;
+
+    /* Set up pointers to the first partition */
+    partition = cx_data;
+    bool_decoder = &pbi->bc2;
+
+    if (num_part > 1)
+    {
+        CHECK_MEM_ERROR(pbi->mbc, vpx_malloc(num_part * sizeof(vp8_reader)));
+        bool_decoder = pbi->mbc;
+        partition += 3 * (num_part - 1);
+    }
+
+    for (i = 0; i < num_part; i++)
+    {
+        const unsigned char *partition_size_ptr = cx_data + i * 3;
+        unsigned int         partition_size;
+
+        /* Calculate the length of this partition. The last partition
+         * size is implicit.
+         */
+        if (i < num_part - 1)
+        {
+            partition_size = read_partition_size(partition_size_ptr);
+        }
+        else
+        {
+            partition_size = user_data_end - partition;
+        }
+
+        if (partition + partition_size > user_data_end)
+            vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                               "Truncated packet or corrupt partition "
+                               "%d length", i + 1);
+
+        if (vp8dx_start_decode(bool_decoder, IF_RTCD(&pbi->dboolhuff),
+                               partition, partition_size))
+            vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+                               "Failed to allocate bool decoder %d", i + 1);
+
+        /* Advance to the next partition */
+        partition += partition_size;
+        bool_decoder++;
+    }
+
+    /* Clamp number of decoder threads */
+    if (pbi->decoding_thread_count > num_part - 1)
+        pbi->decoding_thread_count = num_part - 1;
+}
+
+
+static void stop_token_decoder(VP8D_COMP *pbi)
+{
+    int i;
+    VP8_COMMON *pc = &pbi->common;
+
+    if (pc->multi_token_partition != ONE_PARTITION)
+    {
+        int num_part = (1 << pc->multi_token_partition);
+
+        for (i = 0; i < num_part; i++)
+        {
+            vp8dx_stop_decode(&pbi->mbc[i]);
+        }
+
+        vpx_free(pbi->mbc);
+    }
+    else
+        vp8dx_stop_decode(& pbi->bc2);
+}
+
+static void init_frame(VP8D_COMP *pbi)
+{
+    VP8_COMMON *const pc = & pbi->common;
+    MACROBLOCKD *const xd  = & pbi->mb;
+
+    if (pc->frame_type == KEY_FRAME)
+    {
+        // Various keyframe initializations
+        vpx_memcpy(pc->fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context));
+
+        vp8_init_mbmode_probs(pc);
+
+        vp8_default_coef_probs(pc);
+        vp8_kf_default_bmode_probs(pc->kf_bmode_prob);
+
+        // reset the segment feature data to 0 with delta coding (Default state).
+        vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data));
+        xd->mb_segement_abs_delta = SEGMENT_DELTADATA;
+
+       // reset the mode ref deltasa for loop filter
+        vpx_memset(xd->ref_lf_deltas, 0, sizeof(xd->ref_lf_deltas));
+        vpx_memset(xd->mode_lf_deltas, 0, sizeof(xd->mode_lf_deltas));
+
+        // All buffers are implicitly updated on key frames.
+        pc->refresh_golden_frame = 1;
+        pc->refresh_alt_ref_frame = 1;
+        pc->copy_buffer_to_gf = 0;
+        pc->copy_buffer_to_arf = 0;
+
+        // Note that Golden and Altref modes cannot be used on a key frame so
+        // ref_frame_sign_bias[] is undefined and meaningless
+        pc->ref_frame_sign_bias[GOLDEN_FRAME] = 0;
+        pc->ref_frame_sign_bias[ALTREF_FRAME] = 0;
+    }
+    else
+    {
+        if (!pc->use_bilinear_mc_filter)
+            pc->mcomp_filter_type = SIXTAP;
+        else
+            pc->mcomp_filter_type = BILINEAR;
+
+        // To enable choice of different interploation filters
+        if (pc->mcomp_filter_type == SIXTAP)
+        {
+            xd->subpixel_predict      = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap4x4);
+            xd->subpixel_predict8x4   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x4);
+            xd->subpixel_predict8x8   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x8);
+            xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap16x16);
+        }
+        else
+        {
+            xd->subpixel_predict      = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear4x4);
+            xd->subpixel_predict8x4   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x4);
+            xd->subpixel_predict8x8   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8);
+            xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16);
+        }
+    }
+
+    xd->left_context = pc->left_context;
+    xd->mode_info_context = pc->mi;
+    xd->frame_type = pc->frame_type;
+    xd->mbmi.mode = DC_PRED;
+    xd->mode_info_stride = pc->mode_info_stride;
+}
+
+int vp8_decode_frame(VP8D_COMP *pbi)
+{
+    vp8_reader *const bc = & pbi->bc;
+    VP8_COMMON *const pc = & pbi->common;
+    MACROBLOCKD *const xd  = & pbi->mb;
+    const unsigned char *data = (const unsigned char *)pbi->Source;
+    const unsigned char *const data_end = data + pbi->source_sz;
+    int first_partition_length_in_bytes;
+
+    int mb_row;
+    int i, j, k, l;
+    const int *const mb_feature_data_bits = vp8_mb_feature_data_bits;
+
+    pc->frame_type = (FRAME_TYPE)(data[0] & 1);
+    pc->version = (data[0] >> 1) & 7;
+    pc->show_frame = (data[0] >> 4) & 1;
+    first_partition_length_in_bytes =
+        (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
+    data += 3;
+
+    if (data + first_partition_length_in_bytes > data_end)
+        vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                           "Truncated packet or corrupt partition 0 length");
+    vp8_setup_version(pc);
+
+    if (pc->frame_type == KEY_FRAME)
+    {
+        const int Width = pc->Width;
+        const int Height = pc->Height;
+
+        // vet via sync code
+        if (data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a)
+            vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
+                               "Invalid frame sync code");
+
+        pc->Width = (data[3] | (data[4] << 8)) & 0x3fff;
+        pc->horiz_scale = data[4] >> 6;
+        pc->Height = (data[5] | (data[6] << 8)) & 0x3fff;
+        pc->vert_scale = data[6] >> 6;
+        data += 7;
+
+        if (Width != pc->Width  ||  Height != pc->Height)
+        {
+            if (pc->Width <= 0)
+            {
+                pc->Width = Width;
+                vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                                   "Invalid frame width");
+            }
+
+            if (pc->Height <= 0)
+            {
+                pc->Height = Height;
+                vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                                   "Invalid frame height");
+            }
+
+            if (vp8_alloc_frame_buffers(&pbi->common, pc->Width, pc->Height))
+                vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+                                   "Failed to allocate frame buffers");
+        }
+    }
+
+    if (pc->Width == 0 || pc->Height == 0)
+    {
+        return -1;
+    }
+
+    init_frame(pbi);
+
+    if (vp8dx_start_decode(bc, IF_RTCD(&pbi->dboolhuff),
+                           data, data_end - data))
+        vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+                           "Failed to allocate bool decoder 0");
+    if (pc->frame_type == KEY_FRAME) {
+        pc->clr_type    = (YUV_TYPE)vp8_read_bit(bc);
+        pc->clamp_type  = (CLAMP_TYPE)vp8_read_bit(bc);
+    }
+
+    // Is segmentation enabled
+    xd->segmentation_enabled = (unsigned char)vp8_read_bit(bc);
+
+    if (xd->segmentation_enabled)
+    {
+        // Signal whether or not the segmentation map is being explicitly updated this frame.
+        xd->update_mb_segmentation_map = (unsigned char)vp8_read_bit(bc);
+        xd->update_mb_segmentation_data = (unsigned char)vp8_read_bit(bc);
+
+        if (xd->update_mb_segmentation_data)
+        {
+            xd->mb_segement_abs_delta = (unsigned char)vp8_read_bit(bc);
+
+            vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data));
+
+            // For each segmentation feature (Quant and loop filter level)
+            for (i = 0; i < MB_LVL_MAX; i++)
+            {
+                for (j = 0; j < MAX_MB_SEGMENTS; j++)
+                {
+                    // Frame level data
+                    if (vp8_read_bit(bc))
+                    {
+                        xd->segment_feature_data[i][j] = (signed char)vp8_read_literal(bc, mb_feature_data_bits[i]);
+
+                        if (vp8_read_bit(bc))
+                            xd->segment_feature_data[i][j] = -xd->segment_feature_data[i][j];
+                    }
+                    else
+                        xd->segment_feature_data[i][j] = 0;
+                }
+            }
+        }
+
+        if (xd->update_mb_segmentation_map)
+        {
+            // Which macro block level features are enabled
+            vpx_memset(xd->mb_segment_tree_probs, 255, sizeof(xd->mb_segment_tree_probs));
+
+            // Read the probs used to decode the segment id for each macro block.
+            for (i = 0; i < MB_FEATURE_TREE_PROBS; i++)
+            {
+                // If not explicitly set value is defaulted to 255 by memset above
+                if (vp8_read_bit(bc))
+                    xd->mb_segment_tree_probs[i] = (vp8_prob)vp8_read_literal(bc, 8);
+            }
+        }
+    }
+
+    // Read the loop filter level and type
+    pc->filter_type = (LOOPFILTERTYPE) vp8_read_bit(bc);
+    pc->filter_level = vp8_read_literal(bc, 6);
+    pc->sharpness_level = vp8_read_literal(bc, 3);
+
+    // Read in loop filter deltas applied at the MB level based on mode or ref frame.
+    xd->mode_ref_lf_delta_update = 0;
+    xd->mode_ref_lf_delta_enabled = (unsigned char)vp8_read_bit(bc);
+
+    if (xd->mode_ref_lf_delta_enabled)
+    {
+        // Do the deltas need to be updated
+        xd->mode_ref_lf_delta_update = (unsigned char)vp8_read_bit(bc);
+
+        if (xd->mode_ref_lf_delta_update)
+        {
+            // Send update
+            for (i = 0; i < MAX_REF_LF_DELTAS; i++)
+            {
+                if (vp8_read_bit(bc))
+                {
+                    //sign = vp8_read_bit( bc );
+                    xd->ref_lf_deltas[i] = (signed char)vp8_read_literal(bc, 6);
+
+                    if (vp8_read_bit(bc))        // Apply sign
+                        xd->ref_lf_deltas[i] = xd->ref_lf_deltas[i] * -1;
+                }
+            }
+
+            // Send update
+            for (i = 0; i < MAX_MODE_LF_DELTAS; i++)
+            {
+                if (vp8_read_bit(bc))
+                {
+                    //sign = vp8_read_bit( bc );
+                    xd->mode_lf_deltas[i] = (signed char)vp8_read_literal(bc, 6);
+
+                    if (vp8_read_bit(bc))        // Apply sign
+                        xd->mode_lf_deltas[i] = xd->mode_lf_deltas[i] * -1;
+                }
+            }
+        }
+    }
+
+    setup_token_decoder(pbi, data + first_partition_length_in_bytes);
+    xd->current_bc = &pbi->bc2;
+
+    // Read the default quantizers.
+    {
+        int Q, q_update;
+
+        Q = vp8_read_literal(bc, 7);  // AC 1st order Q = default
+        pc->base_qindex = Q;
+        q_update = 0;
+        pc->y1dc_delta_q = get_delta_q(bc, pc->y1dc_delta_q, &q_update);
+        pc->y2dc_delta_q = get_delta_q(bc, pc->y2dc_delta_q, &q_update);
+        pc->y2ac_delta_q = get_delta_q(bc, pc->y2ac_delta_q, &q_update);
+        pc->uvdc_delta_q = get_delta_q(bc, pc->uvdc_delta_q, &q_update);
+        pc->uvac_delta_q = get_delta_q(bc, pc->uvac_delta_q, &q_update);
+
+        if (q_update)
+            vp8cx_init_de_quantizer(pbi);
+
+        // MB level dequantizer setup
+        mb_init_dequantizer(pbi, &pbi->mb);
+    }
+
+    // Determine if the golden frame or ARF buffer should be updated and how.
+    // For all non key frames the GF and ARF refresh flags and sign bias
+    // flags must be set explicitly.
+    if (pc->frame_type != KEY_FRAME)
+    {
+        // Should the GF or ARF be updated from the current frame
+        pc->refresh_golden_frame = vp8_read_bit(bc);
+        pc->refresh_alt_ref_frame = vp8_read_bit(bc);
+
+        // Buffer to buffer copy flags.
+        pc->copy_buffer_to_gf = 0;
+
+        if (!pc->refresh_golden_frame)
+            pc->copy_buffer_to_gf = vp8_read_literal(bc, 2);
+
+        pc->copy_buffer_to_arf = 0;
+
+        if (!pc->refresh_alt_ref_frame)
+            pc->copy_buffer_to_arf = vp8_read_literal(bc, 2);
+
+        pc->ref_frame_sign_bias[GOLDEN_FRAME] = vp8_read_bit(bc);
+        pc->ref_frame_sign_bias[ALTREF_FRAME] = vp8_read_bit(bc);
+    }
+
+    pc->refresh_entropy_probs = vp8_read_bit(bc);
+    if (pc->refresh_entropy_probs == 0)
+    {
+        vpx_memcpy(&pc->lfc, &pc->fc, sizeof(pc->fc));
+    }
+
+    pc->refresh_last_frame = pc->frame_type == KEY_FRAME  ||  vp8_read_bit(bc);
+
+    if (0)
+    {
+        FILE *z = fopen("decodestats.stt", "a");
+        fprintf(z, "%6d F:%d,G:%d,A:%d,L:%d,Q:%d\n",
+                pc->current_video_frame,
+                pc->frame_type,
+                pc->refresh_golden_frame,
+                pc->refresh_alt_ref_frame,
+                pc->refresh_last_frame,
+                pc->base_qindex);
+        fclose(z);
+    }
+
+
+    vp8dx_bool_decoder_fill(bc);
+    {
+        // read coef probability tree
+
+        for (i = 0; i < BLOCK_TYPES; i++)
+            for (j = 0; j < COEF_BANDS; j++)
+                for (k = 0; k < PREV_COEF_CONTEXTS; k++)
+                    for (l = 0; l < MAX_ENTROPY_TOKENS - 1; l++)
+                    {
+
+                        vp8_prob *const p = pc->fc.coef_probs [i][j][k] + l;
+
+                        if (vp8_read(bc, vp8_coef_update_probs [i][j][k][l]))
+                        {
+                            *p = (vp8_prob)vp8_read_literal(bc, 8);
+
+                        }
+                    }
+    }
+
+    vpx_memcpy(&xd->pre, &pc->last_frame, sizeof(YV12_BUFFER_CONFIG));
+    vpx_memcpy(&xd->dst, &pc->new_frame, sizeof(YV12_BUFFER_CONFIG));
+
+    // set up frame new frame for intra coded blocks
+    vp8_setup_intra_recon(&pc->new_frame);
+
+    vp8_setup_block_dptrs(xd);
+
+    vp8_build_block_doffsets(xd);
+
+    // clear out the coeff buffer
+    vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
+
+    // Read the mb_no_coeff_skip flag
+    pc->mb_no_coeff_skip = (int)vp8_read_bit(bc);
+
+    if (pc->frame_type == KEY_FRAME)
+        vp8_kfread_modes(pbi);
+    else
+        vp8_decode_mode_mvs(pbi);
+
+    // reset since these guys are used as iterators
+    vpx_memset(pc->above_context[Y1CONTEXT], 0, sizeof(ENTROPY_CONTEXT) * pc->mb_cols * 4);
+    vpx_memset(pc->above_context[UCONTEXT ], 0, sizeof(ENTROPY_CONTEXT) * pc->mb_cols * 2);
+    vpx_memset(pc->above_context[VCONTEXT ], 0, sizeof(ENTROPY_CONTEXT) * pc->mb_cols * 2);
+    vpx_memset(pc->above_context[Y2CONTEXT], 0, sizeof(ENTROPY_CONTEXT) * pc->mb_cols);
+
+    xd->gf_active_ptr = (signed char *)pc->gf_active_flags;     // Point to base of GF active flags data structure
+
+
+    vpx_memcpy(&xd->block[0].bmi, &xd->mode_info_context->bmi[0], sizeof(B_MODE_INFO));
+
+
+    if (pbi->b_multithreaded_lf && pbi->common.filter_level != 0)
+        vp8_start_lfthread(pbi);
+
+    if (pbi->b_multithreaded_rd && pbi->common.multi_token_partition != ONE_PARTITION)
+    {
+        vp8_mtdecode_mb_rows(pbi, xd);
+    }
+    else
+    {
+        int ibc = 0;
+        int num_part = 1 << pbi->common.multi_token_partition;
+
+        // Decode the individual macro block
+        for (mb_row = 0; mb_row < pc->mb_rows; mb_row++)
+        {
+
+            if (num_part > 1)
+            {
+                xd->current_bc = & pbi->mbc[ibc];
+                ibc++;
+
+                if (ibc == num_part)
+                    ibc = 0;
+            }
+
+            vp8_decode_mb_row(pbi, pc, mb_row, xd);
+        }
+
+        pbi->last_mb_row_decoded = mb_row;
+    }
+
+
+    stop_token_decoder(pbi);
+
+    vp8dx_stop_decode(bc);
+
+    // vpx_log("Decoder: Frame Decoded, Size Roughly:%d bytes  \n",bc->pos+pbi->bc2.pos);
+
+    // If this was a kf or Gf note the Q used
+    if ((pc->frame_type == KEY_FRAME) || (pc->refresh_golden_frame) || pbi->common.refresh_alt_ref_frame)
+        pc->last_kf_gf_q = pc->base_qindex;
+
+    if (pc->refresh_entropy_probs == 0)
+    {
+        vpx_memcpy(&pc->fc, &pc->lfc, sizeof(pc->fc));
+    }
+
+#ifdef PACKET_TESTING
+    {
+        FILE *f = fopen("decompressor.VP8", "ab");
+        unsigned int size = pbi->bc2.pos + pbi->bc.pos + 8;
+        fwrite((void *) &size, 4, 1, f);
+        fwrite((void *) pbi->Source, size, 1, f);
+        fclose(f);
+    }
+#endif
+
+    return 0;
+}
diff --git a/vp8/decoder/demode.c b/vp8/decoder/demode.c
new file mode 100644
index 0000000..fd05e6d
--- /dev/null
+++ b/vp8/decoder/demode.c
@@ -0,0 +1,149 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "onyxd_int.h"
+#include "entropymode.h"
+#include "findnearmv.h"
+
+
+int vp8_read_bmode(vp8_reader *bc, const vp8_prob *p)
+{
+    const int i = vp8_treed_read(bc, vp8_bmode_tree, p);
+
+    return i;
+}
+
+
+int vp8_read_ymode(vp8_reader *bc, const vp8_prob *p)
+{
+    const int i = vp8_treed_read(bc, vp8_ymode_tree, p);
+
+    return i;
+}
+
+int vp8_kfread_ymode(vp8_reader *bc, const vp8_prob *p)
+{
+    const int i = vp8_treed_read(bc, vp8_kf_ymode_tree, p);
+
+    return i;
+}
+
+
+
+int vp8_read_uv_mode(vp8_reader *bc, const vp8_prob *p)
+{
+    const int i = vp8_treed_read(bc, vp8_uv_mode_tree, p);
+
+    return i;
+}
+
+void vp8_read_mb_features(vp8_reader *r, MB_MODE_INFO *mi, MACROBLOCKD *x)
+{
+    // Is segmentation enabled
+    if (x->segmentation_enabled && x->update_mb_segmentation_map)
+    {
+        // If so then read the segment id.
+        if (vp8_read(r, x->mb_segment_tree_probs[0]))
+            mi->segment_id = (unsigned char)(2 + vp8_read(r, x->mb_segment_tree_probs[2]));
+        else
+            mi->segment_id = (unsigned char)(vp8_read(r, x->mb_segment_tree_probs[1]));
+    }
+}
+
+void vp8_kfread_modes(VP8D_COMP *pbi)
+{
+    VP8_COMMON *const cp = & pbi->common;
+    vp8_reader *const bc = & pbi->bc;
+
+    MODE_INFO *m = cp->mi;
+    const int ms = cp->mode_info_stride;
+
+    int mb_row = -1;
+    vp8_prob prob_skip_false = 0;
+
+    if (cp->mb_no_coeff_skip)
+        prob_skip_false = (vp8_prob)(vp8_read_literal(bc, 8));
+
+    while (++mb_row < cp->mb_rows)
+    {
+        int mb_col = -1;
+
+        while (++mb_col < cp->mb_cols)
+        {
+            MB_PREDICTION_MODE y_mode;
+
+            vp8dx_bool_decoder_fill(bc);
+            // Read the Macroblock segmentation map if it is being updated explicitly this frame (reset to 0 above by default)
+            // By default on a key frame reset all MBs to segment 0
+            m->mbmi.segment_id = 0;
+
+            if (pbi->mb.update_mb_segmentation_map)
+                vp8_read_mb_features(bc, &m->mbmi, &pbi->mb);
+
+            // Read the macroblock coeff skip flag if this feature is in use, else default to 0
+            if (cp->mb_no_coeff_skip)
+                m->mbmi.mb_skip_coeff = vp8_read(bc, prob_skip_false);
+            else
+                m->mbmi.mb_skip_coeff = 0;
+
+            y_mode = (MB_PREDICTION_MODE) vp8_kfread_ymode(bc, cp->kf_ymode_prob);
+
+            m->mbmi.ref_frame = INTRA_FRAME;
+
+            if ((m->mbmi.mode = y_mode) == B_PRED)
+            {
+                int i = 0;
+
+                do
+                {
+                    const B_PREDICTION_MODE A = vp8_above_bmi(m, i, ms)->mode;
+                    const B_PREDICTION_MODE L = vp8_left_bmi(m, i)->mode;
+
+                    m->bmi[i].mode = (B_PREDICTION_MODE) vp8_read_bmode(bc, cp->kf_bmode_prob [A] [L]);
+                }
+                while (++i < 16);
+            }
+            else
+            {
+                int BMode;
+                int i = 0;
+
+                switch (y_mode)
+                {
+                case DC_PRED:
+                    BMode = B_DC_PRED;
+                    break;
+                case V_PRED:
+                    BMode = B_VE_PRED;
+                    break;
+                case H_PRED:
+                    BMode = B_HE_PRED;
+                    break;
+                case TM_PRED:
+                    BMode = B_TM_PRED;
+                    break;
+                default:
+                    BMode = B_DC_PRED;
+                    break;
+                }
+
+                do
+                {
+                    m->bmi[i].mode = (B_PREDICTION_MODE)BMode;
+                }
+                while (++i < 16);
+            }
+
+            (m++)->mbmi.uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode(bc, cp->kf_uv_mode_prob);
+        }
+
+        m++; // skip the border
+    }
+}
diff --git a/vp8/decoder/demode.h b/vp8/decoder/demode.h
new file mode 100644
index 0000000..51bbc5e
--- /dev/null
+++ b/vp8/decoder/demode.h
@@ -0,0 +1,32 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "onyxd_int.h"
+
+/* Read (intra) modes for all blocks in a keyframe */
+
+void vp8_kfread_modes(VP8D_COMP *pbi);
+
+/* Intra mode for a Y subblock */
+
+int vp8_read_bmode(vp8_reader *, const vp8_prob *);
+
+/* MB intra Y mode trees differ for key and inter frames. */
+
+int   vp8_read_ymode(vp8_reader *, const vp8_prob *);
+int vp8_kfread_ymode(vp8_reader *, const vp8_prob *);
+
+/* MB intra UV mode trees are the same for key and inter frames. */
+
+int vp8_read_uv_mode(vp8_reader *, const vp8_prob *);
+
+/* Read any macroblock-level features that may be present. */
+
+void vp8_read_mb_features(vp8_reader *, MB_MODE_INFO *, MACROBLOCKD *);
diff --git a/vp8/decoder/dequantize.c b/vp8/decoder/dequantize.c
new file mode 100644
index 0000000..14798d9
--- /dev/null
+++ b/vp8/decoder/dequantize.c
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "dequantize.h"
+#include "predictdc.h"
+#include "idct.h"
+#include "vpx_mem/vpx_mem.h"
+
+extern void vp8_short_idct4x4llm_c(short *input, short *output, int pitch) ;
+extern void vp8_short_idct4x4llm_1_c(short *input, short *output, int pitch);
+
+
+void vp8_dequantize_b_c(BLOCKD *d)
+{
+    int i;
+    short *DQ  = d->dqcoeff;
+    short *Q   = d->qcoeff;
+    short *DQC = &d->dequant[0][0];
+
+    for (i = 0; i < 16; i++)
+    {
+        DQ[i] = Q[i] * DQC[i];
+    }
+}
+
+void vp8_dequant_idct_c(short *input, short *dq, short *output, int pitch)
+{
+    int i;
+
+    for (i = 0; i < 16; i++)
+    {
+        input[i] = dq[i] * input[i];
+    }
+
+    vp8_short_idct4x4llm_c(input, output, pitch);
+    vpx_memset(input, 0, 32);
+}
+
+void vp8_dequant_dc_idct_c(short *input, short *dq, short *output, int pitch, int Dc)
+{
+    int i;
+
+    input[0] = (short)Dc;
+
+    for (i = 1; i < 16; i++)
+    {
+        input[i] = dq[i] * input[i];
+    }
+
+    vp8_short_idct4x4llm_c(input, output, pitch);
+    vpx_memset(input, 0, 32);
+}
diff --git a/vp8/decoder/dequantize.h b/vp8/decoder/dequantize.h
new file mode 100644
index 0000000..d16b02e
--- /dev/null
+++ b/vp8/decoder/dequantize.h
@@ -0,0 +1,64 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef DEQUANTIZE_H
+#define DEQUANTIZE_H
+#include "blockd.h"
+
+#define prototype_dequant_block(sym) \
+    void sym(BLOCKD *x)
+
+#define prototype_dequant_idct(sym) \
+    void sym(short *input, short *dq, short *output, int pitch)
+
+#define prototype_dequant_idct_dc(sym) \
+    void sym(short *input, short *dq, short *output, int pitch, int dc)
+
+#if ARCH_X86 || ARCH_X86_64
+#include "x86/dequantize_x86.h"
+#endif
+
+#if ARCH_ARM
+#include "arm/dequantize_arm.h"
+#endif
+
+#ifndef vp8_dequant_block
+#define vp8_dequant_block vp8_dequantize_b_c
+#endif
+extern prototype_dequant_block(vp8_dequant_block);
+
+#ifndef vp8_dequant_idct
+#define vp8_dequant_idct vp8_dequant_idct_c
+#endif
+extern prototype_dequant_idct(vp8_dequant_idct);
+
+#ifndef vp8_dequant_idct_dc
+#define vp8_dequant_idct_dc vp8_dequant_dc_idct_c
+#endif
+extern prototype_dequant_idct_dc(vp8_dequant_idct_dc);
+
+
+typedef prototype_dequant_block((*vp8_dequant_block_fn_t));
+typedef prototype_dequant_idct((*vp8_dequant_idct_fn_t));
+typedef prototype_dequant_idct_dc((*vp8_dequant_idct_dc_fn_t));
+typedef struct
+{
+    vp8_dequant_block_fn_t    block;
+    vp8_dequant_idct_fn_t     idct;
+    vp8_dequant_idct_dc_fn_t  idct_dc;
+} vp8_dequant_rtcd_vtable_t;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define DEQUANT_INVOKE(ctx,fn) (ctx)->fn
+#else
+#define DEQUANT_INVOKE(ctx,fn) vp8_dequant_##fn
+#endif
+
+#endif
diff --git a/vp8/decoder/detokenize.c b/vp8/decoder/detokenize.c
new file mode 100644
index 0000000..a42f18d
--- /dev/null
+++ b/vp8/decoder/detokenize.c
@@ -0,0 +1,374 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "type_aliases.h"
+#include "blockd.h"
+#include "onyxd_int.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/mem.h"
+
+#define BR_COUNT 8
+#define BOOL_DATA UINT8
+
+#define OCB_X PREV_COEF_CONTEXTS * ENTROPY_NODES
+DECLARE_ALIGNED(16, UINT16, vp8_coef_bands_x[16]) = { 0, 1 * OCB_X, 2 * OCB_X, 3 * OCB_X, 6 * OCB_X, 4 * OCB_X, 5 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 6 * OCB_X, 7 * OCB_X};
+#define EOB_CONTEXT_NODE            0
+#define ZERO_CONTEXT_NODE           1
+#define ONE_CONTEXT_NODE            2
+#define LOW_VAL_CONTEXT_NODE        3
+#define TWO_CONTEXT_NODE            4
+#define THREE_CONTEXT_NODE          5
+#define HIGH_LOW_CONTEXT_NODE       6
+#define CAT_ONE_CONTEXT_NODE        7
+#define CAT_THREEFOUR_CONTEXT_NODE  8
+#define CAT_THREE_CONTEXT_NODE      9
+#define CAT_FIVE_CONTEXT_NODE       10
+
+/*
+//the definition is put in "onyxd_int.h"
+typedef struct
+{
+    INT16         min_val;
+    INT16         Length;
+    UINT8 Probs[12];
+} TOKENEXTRABITS;
+*/
+
+DECLARE_ALIGNED(16, static const TOKENEXTRABITS, vp8d_token_extra_bits2[MAX_ENTROPY_TOKENS]) =
+{
+    {  0, -1, { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },  //ZERO_TOKEN
+    {  1, 0, { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },   //ONE_TOKEN
+    {  2, 0, { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },   //TWO_TOKEN
+    {  3, 0, { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },   //THREE_TOKEN
+    {  4, 0, { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },   //FOUR_TOKEN
+    {  5, 0, { 159, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },  //DCT_VAL_CATEGORY1
+    {  7, 1, { 145, 165, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } }, //DCT_VAL_CATEGORY2
+    { 11, 2, { 140, 148, 173, 0,  0,  0,  0,  0,  0,  0,  0,  0   } }, //DCT_VAL_CATEGORY3
+    { 19, 3, { 135, 140, 155, 176, 0,  0,  0,  0,  0,  0,  0,  0   } }, //DCT_VAL_CATEGORY4
+    { 35, 4, { 130, 134, 141, 157, 180, 0,  0,  0,  0,  0,  0,  0   } }, //DCT_VAL_CATEGORY5
+    { 67, 10, { 129, 130, 133, 140, 153, 177, 196, 230, 243, 254, 254, 0   } }, //DCT_VAL_CATEGORY6
+    {  0, -1, { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   } },  // EOB TOKEN
+};
+
+
+void vp8_reset_mb_tokens_context(MACROBLOCKD *x)
+{
+    ENTROPY_CONTEXT **const A = x->above_context;
+    ENTROPY_CONTEXT(* const L)[4] = x->left_context;
+
+    ENTROPY_CONTEXT *a;
+    ENTROPY_CONTEXT *l;
+    int i;
+
+    for (i = 0; i < 24; i++)
+    {
+
+        a = A[ vp8_block2context[i] ] + vp8_block2above[i];
+        l = L[ vp8_block2context[i] ] + vp8_block2left[i];
+
+        *a = *l = 0;
+    }
+
+    if (x->mbmi.mode != B_PRED && x->mbmi.mode != SPLITMV)
+    {
+        a = A[Y2CONTEXT] + vp8_block2above[24];
+        l = L[Y2CONTEXT] + vp8_block2left[24];
+        *a = *l = 0;
+    }
+
+
+}
+DECLARE_ALIGNED(16, extern const unsigned int, vp8dx_bitreader_norm[256]);
+#define NORMALIZE \
+    /*if(range < 0x80)*/                            \
+    { \
+        shift = vp8dx_bitreader_norm[range]; \
+        range <<= shift; \
+        value <<= shift; \
+        count -= shift; \
+        if(count <= 0) \
+        { \
+            count += BR_COUNT ; \
+            value |= (*bufptr) << (BR_COUNT-count); \
+            bufptr = br_ptr_advance(bufptr, 1); \
+        } \
+    }
+
+#define DECODE_AND_APPLYSIGN(value_to_sign) \
+    split = (range + 1) >> 1; \
+    if ( (value >> 8) < split ) \
+    { \
+        range = split; \
+        v= value_to_sign; \
+    } \
+    else \
+    { \
+        range = range-split; \
+        value = value-(split<<8); \
+        v = -value_to_sign; \
+    } \
+    range +=range;                   \
+    value +=value;                   \
+    if (!--count) \
+    { \
+        count = BR_COUNT; \
+        value |= *bufptr; \
+        bufptr = br_ptr_advance(bufptr, 1); \
+    }
+
+#define DECODE_AND_BRANCH_IF_ZERO(probability,branch) \
+    { \
+        split = 1 +  ((( probability*(range-1) ) )>> 8); \
+        if ( (value >> 8) < split ) \
+        { \
+            range = split; \
+            NORMALIZE \
+            goto branch; \
+        } \
+        value -= (split<<8); \
+        range = range - split; \
+        NORMALIZE \
+    }
+
+#define DECODE_AND_LOOP_IF_ZERO(probability,branch) \
+    { \
+        split = 1 + ((( probability*(range-1) ) ) >> 8); \
+        if ( (value >> 8) < split ) \
+        { \
+            range = split; \
+            NORMALIZE \
+            Prob = coef_probs; \
+            if(c<15) {\
+            ++c; \
+            Prob += vp8_coef_bands_x[c]; \
+            goto branch; \
+            } goto BLOCK_FINISHED; /*for malformed input */\
+        } \
+        value -= (split<<8); \
+        range = range - split; \
+        NORMALIZE \
+    }
+
+#define DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) \
+    DECODE_AND_APPLYSIGN(val) \
+    Prob = coef_probs + (ENTROPY_NODES*2); \
+    if(c < 15){\
+        qcoeff_ptr [ scan[c] ] = (INT16) v; \
+        ++c; \
+        goto DO_WHILE; }\
+    qcoeff_ptr [ scan[15] ] = (INT16) v; \
+    goto BLOCK_FINISHED;
+
+
+#define DECODE_EXTRABIT_AND_ADJUST_VAL(t,bits_count)\
+    split = 1 +  (((range-1) * vp8d_token_extra_bits2[t].Probs[bits_count]) >> 8); \
+    if(value >= (split<<8))\
+    {\
+        range = range-split;\
+        value = value-(split<<8);\
+        val += ((UINT16)1<<bits_count);\
+    }\
+    else\
+    {\
+        range = split;\
+    }\
+    NORMALIZE
+
+int vp8_decode_mb_tokens(VP8D_COMP *dx, MACROBLOCKD *x)
+{
+    ENTROPY_CONTEXT **const A = x->above_context;
+    ENTROPY_CONTEXT(* const L)[4] = x->left_context;
+    const VP8_COMMON *const oc = & dx->common;
+
+    BOOL_DECODER *bc = x->current_bc;
+
+    ENTROPY_CONTEXT *a;
+    ENTROPY_CONTEXT *l;
+    int i;
+
+    int eobtotal = 0;
+
+    register int count;
+
+    const BOOL_DATA *bufptr;
+    register unsigned int range;
+    register unsigned int value;
+    const int *scan;
+    register unsigned int shift;
+    UINT32 split;
+    INT16 *qcoeff_ptr;
+
+    const vp8_prob *coef_probs;
+    int type;
+    int stop;
+    INT16 val, bits_count;
+    INT16 c;
+    INT16 t;
+    INT16 v;
+    const vp8_prob *Prob;
+
+    //int *scan;
+    type = 3;
+    i = 0;
+    stop = 16;
+
+    if (x->mbmi.mode != B_PRED && x->mbmi.mode != SPLITMV)
+    {
+        i = 24;
+        stop = 24;
+        type = 1;
+        qcoeff_ptr = &x->qcoeff[24*16];
+        scan = vp8_default_zig_zag1d;
+        eobtotal -= 16;
+    }
+    else
+    {
+        scan = vp8_default_zig_zag1d;
+        qcoeff_ptr = &x->qcoeff[0];
+    }
+
+    count   = bc->count;
+    range   = bc->range;
+    value   = bc->value;
+    bufptr  = bc->read_ptr;
+
+
+    coef_probs = oc->fc.coef_probs [type] [ 0 ] [0];
+
+BLOCK_LOOP:
+    a = A[ vp8_block2context[i] ] + vp8_block2above[i];
+    l = L[ vp8_block2context[i] ] + vp8_block2left[i];
+    c = (INT16)(!type);
+
+    VP8_COMBINEENTROPYCONTEXTS(t, *a, *l);
+    Prob = coef_probs;
+    Prob += t * ENTROPY_NODES;
+
+DO_WHILE:
+    Prob += vp8_coef_bands_x[c];
+    DECODE_AND_BRANCH_IF_ZERO(Prob[EOB_CONTEXT_NODE], BLOCK_FINISHED);
+
+CHECK_0_:
+    DECODE_AND_LOOP_IF_ZERO(Prob[ZERO_CONTEXT_NODE], CHECK_0_);
+    DECODE_AND_BRANCH_IF_ZERO(Prob[ONE_CONTEXT_NODE], ONE_CONTEXT_NODE_0_);
+    DECODE_AND_BRANCH_IF_ZERO(Prob[LOW_VAL_CONTEXT_NODE], LOW_VAL_CONTEXT_NODE_0_);
+    DECODE_AND_BRANCH_IF_ZERO(Prob[HIGH_LOW_CONTEXT_NODE], HIGH_LOW_CONTEXT_NODE_0_);
+    DECODE_AND_BRANCH_IF_ZERO(Prob[CAT_THREEFOUR_CONTEXT_NODE], CAT_THREEFOUR_CONTEXT_NODE_0_);
+    DECODE_AND_BRANCH_IF_ZERO(Prob[CAT_FIVE_CONTEXT_NODE], CAT_FIVE_CONTEXT_NODE_0_);
+    val = vp8d_token_extra_bits2[DCT_VAL_CATEGORY6].min_val;
+    bits_count = vp8d_token_extra_bits2[DCT_VAL_CATEGORY6].Length;
+
+    do
+    {
+        DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY6, bits_count);
+        bits_count -- ;
+    }
+    while (bits_count >= 0);
+
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
+
+CAT_FIVE_CONTEXT_NODE_0_:
+    val = vp8d_token_extra_bits2[DCT_VAL_CATEGORY5].min_val;
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 4);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 3);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 2);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 1);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 0);
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
+
+CAT_THREEFOUR_CONTEXT_NODE_0_:
+    DECODE_AND_BRANCH_IF_ZERO(Prob[CAT_THREE_CONTEXT_NODE], CAT_THREE_CONTEXT_NODE_0_);
+    val = vp8d_token_extra_bits2[DCT_VAL_CATEGORY4].min_val;
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 3);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 2);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 1);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 0);
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
+
+CAT_THREE_CONTEXT_NODE_0_:
+    val = vp8d_token_extra_bits2[DCT_VAL_CATEGORY3].min_val;
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 2);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 1);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 0);
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
+
+HIGH_LOW_CONTEXT_NODE_0_:
+    DECODE_AND_BRANCH_IF_ZERO(Prob[CAT_ONE_CONTEXT_NODE], CAT_ONE_CONTEXT_NODE_0_);
+
+    val = vp8d_token_extra_bits2[DCT_VAL_CATEGORY2].min_val;
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 1);
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 0);
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
+
+CAT_ONE_CONTEXT_NODE_0_:
+    val = vp8d_token_extra_bits2[DCT_VAL_CATEGORY1].min_val;
+    DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY1, 0);
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val);
+
+LOW_VAL_CONTEXT_NODE_0_:
+    DECODE_AND_BRANCH_IF_ZERO(Prob[TWO_CONTEXT_NODE], TWO_CONTEXT_NODE_0_);
+    DECODE_AND_BRANCH_IF_ZERO(Prob[THREE_CONTEXT_NODE], THREE_CONTEXT_NODE_0_);
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(4);
+
+THREE_CONTEXT_NODE_0_:
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(3);
+
+TWO_CONTEXT_NODE_0_:
+    DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(2);
+
+ONE_CONTEXT_NODE_0_:
+    DECODE_AND_APPLYSIGN(1);
+    Prob = coef_probs + ENTROPY_NODES;
+
+    if (c < 15)
+    {
+        qcoeff_ptr [ scan[c] ] = (INT16) v;
+        ++c;
+        goto DO_WHILE;
+    }
+
+    qcoeff_ptr [ scan[15] ] = (INT16) v;
+BLOCK_FINISHED:
+    t = ((x->block[i].eob = c) != !type);   // any nonzero data?
+    eobtotal += x->block[i].eob;
+    *a = *l = t;
+    qcoeff_ptr += 16;
+
+    i++;
+
+    if (i < stop)
+        goto BLOCK_LOOP;
+
+    if (i == 25)
+    {
+        scan = vp8_default_zig_zag1d;//x->scan_order1d;
+        type = 0;
+        i = 0;
+        stop = 16;
+        coef_probs = oc->fc.coef_probs [type] [ 0 ] [0];
+        qcoeff_ptr = &x->qcoeff[0];
+        goto BLOCK_LOOP;
+    }
+
+    if (i == 16)
+    {
+        type = 2;
+        coef_probs = oc->fc.coef_probs [type] [ 0 ] [0];
+        stop = 24;
+        goto BLOCK_LOOP;
+    }
+
+    bc->count = count;
+    bc->value = value;
+    bc->range = range;
+    bc->read_ptr = bufptr;
+    return eobtotal;
+
+}
diff --git a/vp8/decoder/detokenize.h b/vp8/decoder/detokenize.h
new file mode 100644
index 0000000..6a9a476
--- /dev/null
+++ b/vp8/decoder/detokenize.h
@@ -0,0 +1,19 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef detokenize_h
+#define detokenize_h 1
+
+#include "onyxd_int.h"
+
+void vp8_reset_mb_tokens_context(MACROBLOCKD *x);
+int vp8_decode_mb_tokens(VP8D_COMP *, MACROBLOCKD *);
+
+#endif /* detokenize_h */
diff --git a/vp8/decoder/generic/dsystemdependent.c b/vp8/decoder/generic/dsystemdependent.c
new file mode 100644
index 0000000..302b64b
--- /dev/null
+++ b/vp8/decoder/generic/dsystemdependent.c
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "dequantize.h"
+#include "onyxd_int.h"
+
+extern void vp8_arch_x86_decode_init(VP8D_COMP *pbi);
+
+void vp8_dmachine_specific_config(VP8D_COMP *pbi)
+{
+    // Pure C:
+#if CONFIG_RUNTIME_CPU_DETECT
+    pbi->mb.rtcd         = &pbi->common.rtcd;
+    pbi->dequant.block   = vp8_dequantize_b_c;
+    pbi->dequant.idct    = vp8_dequant_idct_c;
+    pbi->dequant.idct_dc = vp8_dequant_dc_idct_c;
+    pbi->dboolhuff.start = vp8dx_start_decode_c;
+    pbi->dboolhuff.stop  = vp8dx_stop_decode_c;
+    pbi->dboolhuff.fill  = vp8dx_bool_decoder_fill_c;
+#if 0 //For use with RTCD, when implemented
+    pbi->dboolhuff.debool = vp8dx_decode_bool_c;
+    pbi->dboolhuff.devalue = vp8dx_decode_value_c;
+#endif
+#endif
+
+#if ARCH_X86 || ARCH_X86_64
+    vp8_arch_x86_decode_init(pbi);
+#endif
+}
diff --git a/vp8/decoder/onyxd_if.c b/vp8/decoder/onyxd_if.c
new file mode 100644
index 0000000..6875585
--- /dev/null
+++ b/vp8/decoder/onyxd_if.c
@@ -0,0 +1,451 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "onyxc_int.h"
+#if CONFIG_POSTPROC
+#include "postproc.h"
+#endif
+#include "onyxd.h"
+#include "onyxd_int.h"
+#include "vpx_mem/vpx_mem.h"
+#include "alloccommon.h"
+#include "vpx_scale/yv12extend.h"
+#include "loopfilter.h"
+#include "swapyv12buffer.h"
+#include "g_common.h"
+#include "threading.h"
+#include "decoderthreading.h"
+#include <stdio.h>
+#include "segmentation_common.h"
+#include "quant_common.h"
+#include "vpx_scale/vpxscale.h"
+#include "systemdependent.h"
+#include "vpx_ports/vpx_timer.h"
+
+
+extern void vp8_init_loop_filter(VP8_COMMON *cm);
+
+extern void vp8cx_init_de_quantizer(VP8D_COMP *pbi);
+
+// DEBUG code
+#if CONFIG_DEBUG
+void vp8_recon_write_yuv_frame(unsigned char *name, YV12_BUFFER_CONFIG *s)
+{
+    FILE *yuv_file = fopen((char *)name, "ab");
+    unsigned char *src = s->y_buffer;
+    int h = s->y_height;
+
+    do
+    {
+        fwrite(src, s->y_width, 1,  yuv_file);
+        src += s->y_stride;
+    }
+    while (--h);
+
+    src = s->u_buffer;
+    h = s->uv_height;
+
+    do
+    {
+        fwrite(src, s->uv_width, 1,  yuv_file);
+        src += s->uv_stride;
+    }
+    while (--h);
+
+    src = s->v_buffer;
+    h = s->uv_height;
+
+    do
+    {
+        fwrite(src, s->uv_width, 1, yuv_file);
+        src += s->uv_stride;
+    }
+    while (--h);
+
+    fclose(yuv_file);
+}
+#endif
+
+void vp8dx_initialize()
+{
+    static int init_done = 0;
+
+    if (!init_done)
+    {
+        vp8_initialize_common();
+        vp8_scale_machine_specific_config();
+        init_done = 1;
+    }
+}
+
+
+VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
+{
+    VP8D_COMP *pbi = vpx_memalign(32, sizeof(VP8D_COMP));
+
+    if (!pbi)
+        return NULL;
+
+    vpx_memset(pbi, 0, sizeof(VP8D_COMP));
+
+    if (setjmp(pbi->common.error.jmp))
+    {
+        pbi->common.error.setjmp = 0;
+        vp8dx_remove_decompressor(pbi);
+        return 0;
+    }
+
+    pbi->common.error.setjmp = 1;
+    vp8dx_initialize();
+
+    vp8_create_common(&pbi->common);
+    vp8_dmachine_specific_config(pbi);
+
+    pbi->common.current_video_frame = 0;
+    pbi->ready_for_new_data = 1;
+
+    pbi->CPUFreq = 0; //vp8_get_processor_freq();
+    pbi->max_threads = oxcf->max_threads;
+    vp8_decoder_create_threads(pbi);
+
+    //vp8cx_init_de_quantizer() is first called here. Add check in frame_init_dequantizer() to avoid
+    // unnecessary calling of vp8cx_init_de_quantizer() for every frame.
+    vp8cx_init_de_quantizer(pbi);
+
+    {
+        VP8_COMMON *cm = &pbi->common;
+
+        vp8_init_loop_filter(cm);
+        cm->last_frame_type = KEY_FRAME;
+        cm->last_filter_type = cm->filter_type;
+        cm->last_sharpness_level = cm->sharpness_level;
+    }
+
+    pbi->common.error.setjmp = 0;
+    return (VP8D_PTR) pbi;
+}
+
+
+void vp8dx_remove_decompressor(VP8D_PTR ptr)
+{
+    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
+
+    if (!pbi)
+        return;
+
+    vp8_decoder_remove_threads(pbi);
+    vp8_remove_common(&pbi->common);
+    vpx_free(pbi);
+}
+
+
+void vp8dx_set_setting(VP8D_PTR comp, VP8D_SETTING oxst, int x)
+{
+    VP8D_COMP *pbi = (VP8D_COMP *) comp;
+
+    (void) pbi;
+    (void) x;
+
+    switch (oxst)
+    {
+    case VP8D_OK:
+        break;
+    }
+}
+
+int vp8dx_get_setting(VP8D_PTR comp, VP8D_SETTING oxst)
+{
+    VP8D_COMP *pbi = (VP8D_COMP *) comp;
+
+    (void) pbi;
+
+    switch (oxst)
+    {
+    case VP8D_OK:
+        break;
+    }
+
+    return -1;
+}
+
+int vp8dx_get_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
+{
+    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
+    VP8_COMMON *cm = &pbi->common;
+
+    if (ref_frame_flag == VP8_LAST_FLAG)
+        vp8_yv12_copy_frame_ptr(&cm->last_frame, sd);
+
+    else if (ref_frame_flag == VP8_GOLD_FLAG)
+        vp8_yv12_copy_frame_ptr(&cm->golden_frame, sd);
+
+    else if (ref_frame_flag == VP8_ALT_FLAG)
+        vp8_yv12_copy_frame_ptr(&cm->alt_ref_frame, sd);
+
+    else
+        return -1;
+
+    return 0;
+}
+int vp8dx_set_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
+{
+    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
+    VP8_COMMON *cm = &pbi->common;
+
+    if (ref_frame_flag == VP8_LAST_FLAG)
+        vp8_yv12_copy_frame_ptr(sd, &cm->last_frame);
+
+    else if (ref_frame_flag == VP8_GOLD_FLAG)
+        vp8_yv12_copy_frame_ptr(sd, &cm->golden_frame);
+
+    else if (ref_frame_flag == VP8_ALT_FLAG)
+        vp8_yv12_copy_frame_ptr(sd, &cm->alt_ref_frame);
+
+    else
+        return -1;
+
+    return 0;
+}
+
+//For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.
+#if HAVE_ARMV7
+extern void vp8_push_neon(INT64 *store);
+extern void vp8_pop_neon(INT64 *store);
+static INT64 dx_store_reg[8];
+#endif
+int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsigned char *source, INT64 time_stamp)
+{
+    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
+    VP8_COMMON *cm = &pbi->common;
+    int retcode = 0;
+
+    struct vpx_usec_timer timer;
+
+//  if(pbi->ready_for_new_data == 0)
+//      return -1;
+
+    if (ptr == 0)
+    {
+        return -1;
+    }
+
+    pbi->common.error.error_code = VPX_CODEC_OK;
+
+    if (setjmp(pbi->common.error.jmp))
+    {
+        pbi->common.error.setjmp = 0;
+        return -1;
+    }
+
+    pbi->common.error.setjmp = 1;
+
+#if HAVE_ARMV7
+    vp8_push_neon(dx_store_reg);
+#endif
+
+    vpx_usec_timer_start(&timer);
+
+    //cm->current_video_frame++;
+    pbi->Source = source;
+    pbi->source_sz = size;
+
+    retcode = vp8_decode_frame(pbi);
+
+    if (retcode < 0)
+    {
+#if HAVE_ARMV7
+        vp8_pop_neon(dx_store_reg);
+#endif
+        pbi->common.error.error_code = VPX_CODEC_ERROR;
+        pbi->common.error.setjmp = 0;
+        return retcode;
+    }
+
+    // Update the GF useage maps.
+    vp8_update_gf_useage_maps(cm, &pbi->mb);
+
+    if (pbi->b_multithreaded_lf && pbi->common.filter_level != 0)
+        vp8_stop_lfthread(pbi);
+
+    if (cm->refresh_last_frame)
+    {
+        vp8_swap_yv12_buffer(&cm->last_frame, &cm->new_frame);
+
+        cm->frame_to_show = &cm->last_frame;
+    }
+    else
+    {
+        cm->frame_to_show = &cm->new_frame;
+    }
+
+    if (!pbi->b_multithreaded_lf)
+    {
+        struct vpx_usec_timer lpftimer;
+        vpx_usec_timer_start(&lpftimer);
+        // Apply the loop filter if appropriate.
+
+        if (cm->filter_level > 0)
+        {
+            vp8_loop_filter_frame(cm, &pbi->mb, cm->filter_level);
+            cm->last_frame_type = cm->frame_type;
+            cm->last_filter_type = cm->filter_type;
+            cm->last_sharpness_level = cm->sharpness_level;
+
+        }
+
+        vpx_usec_timer_mark(&lpftimer);
+        pbi->time_loop_filtering += vpx_usec_timer_elapsed(&lpftimer);
+    }
+
+    vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);
+
+#if 0
+    // DEBUG code
+    //vp8_recon_write_yuv_frame("recon.yuv", cm->frame_to_show);
+    if (cm->current_video_frame <= 5)
+        write_dx_frame_to_file(cm->frame_to_show, cm->current_video_frame);
+#endif
+
+    // If any buffer copy / swaping is signalled it should be done here.
+    if (cm->copy_buffer_to_arf)
+    {
+        if (cm->copy_buffer_to_arf == 1)
+        {
+            if (cm->refresh_last_frame)
+                vp8_yv12_copy_frame_ptr(&cm->new_frame, &cm->alt_ref_frame);
+            else
+                vp8_yv12_copy_frame_ptr(&cm->last_frame, &cm->alt_ref_frame);
+        }
+        else if (cm->copy_buffer_to_arf == 2)
+            vp8_yv12_copy_frame_ptr(&cm->golden_frame, &cm->alt_ref_frame);
+    }
+
+    if (cm->copy_buffer_to_gf)
+    {
+        if (cm->copy_buffer_to_gf == 1)
+        {
+            if (cm->refresh_last_frame)
+                vp8_yv12_copy_frame_ptr(&cm->new_frame, &cm->golden_frame);
+            else
+                vp8_yv12_copy_frame_ptr(&cm->last_frame, &cm->golden_frame);
+        }
+        else if (cm->copy_buffer_to_gf == 2)
+            vp8_yv12_copy_frame_ptr(&cm->alt_ref_frame, &cm->golden_frame);
+    }
+
+    // Should the golden or alternate reference frame be refreshed?
+    if (cm->refresh_golden_frame || cm->refresh_alt_ref_frame)
+    {
+        if (cm->refresh_golden_frame)
+            vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cm->golden_frame);
+
+        if (cm->refresh_alt_ref_frame)
+            vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cm->alt_ref_frame);
+
+        //vpx_log("Decoder: recovery frame received \n");
+
+        // Update data structures that monitors GF useage
+        vpx_memset(cm->gf_active_flags, 1, (cm->mb_rows * cm->mb_cols));
+        cm->gf_active_count = cm->mb_rows * cm->mb_cols;
+    }
+
+    vp8_clear_system_state();
+
+    vpx_usec_timer_mark(&timer);
+    pbi->decode_microseconds = vpx_usec_timer_elapsed(&timer);
+
+    pbi->time_decoding += pbi->decode_microseconds;
+
+//  vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, cm->current_video_frame);
+
+    if (cm->show_frame)
+        cm->current_video_frame++;
+
+    pbi->ready_for_new_data = 0;
+    pbi->last_time_stamp = time_stamp;
+
+#if 0
+    {
+        int i;
+        INT64 earliest_time = pbi->dr[0].time_stamp;
+        INT64 latest_time = pbi->dr[0].time_stamp;
+        INT64 time_diff = 0;
+        int bytes = 0;
+
+        pbi->dr[pbi->common.current_video_frame&0xf].size = pbi->bc.pos + pbi->bc2.pos + 4;;
+        pbi->dr[pbi->common.current_video_frame&0xf].time_stamp = time_stamp;
+
+        for (i = 0; i < 16; i++)
+        {
+
+            bytes += pbi->dr[i].size;
+
+            if (pbi->dr[i].time_stamp < earliest_time)
+                earliest_time = pbi->dr[i].time_stamp;
+
+            if (pbi->dr[i].time_stamp > latest_time)
+                latest_time = pbi->dr[i].time_stamp;
+        }
+
+        time_diff = latest_time - earliest_time;
+
+        if (time_diff > 0)
+        {
+            pbi->common.bitrate = 80000.00 * bytes / time_diff  ;
+            pbi->common.framerate = 160000000.00 / time_diff ;
+        }
+
+    }
+#endif
+
+#if HAVE_ARMV7
+    vp8_pop_neon(dx_store_reg);
+#endif
+    pbi->common.error.setjmp = 0;
+    return retcode;
+}
+int vp8dx_get_raw_frame(VP8D_PTR ptr, YV12_BUFFER_CONFIG *sd, INT64 *time_stamp, INT64 *time_end_stamp, int deblock_level,  int noise_level, int flags)
+{
+    int ret = -1;
+    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
+
+    if (pbi->ready_for_new_data == 1)
+        return ret;
+
+    // ie no raw frame to show!!!
+    if (pbi->common.show_frame == 0)
+        return ret;
+
+    pbi->ready_for_new_data = 1;
+    *time_stamp = pbi->last_time_stamp;
+    *time_end_stamp = 0;
+
+    sd->clrtype = pbi->common.clr_type;
+#if CONFIG_POSTPROC
+    ret = vp8_post_proc_frame(&pbi->common, sd, deblock_level, noise_level, flags);
+#else
+
+    if (pbi->common.frame_to_show)
+    {
+        *sd = *pbi->common.frame_to_show;
+        sd->y_width = pbi->common.Width;
+        sd->y_height = pbi->common.Height;
+        sd->uv_height = pbi->common.Height / 2;
+        ret = 0;
+    }
+    else
+    {
+        ret = -1;
+    }
+
+#endif //!CONFIG_POSTPROC
+    vp8_clear_system_state();
+    return ret;
+}
diff --git a/vp8/decoder/onyxd_if_sjl.c b/vp8/decoder/onyxd_if_sjl.c
new file mode 100644
index 0000000..363ad5d
--- /dev/null
+++ b/vp8/decoder/onyxd_if_sjl.c
@@ -0,0 +1,398 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "onyxc_int.h"
+#include "postproc.h"
+#include "onyxd.h"
+#include "onyxd_int.h"
+#include "vpx_mem/vpx_mem.h"
+#include "alloccommon.h"
+#include "vpx_scale/yv12extend.h"
+#include "loopfilter.h"
+#include "swapyv12buffer.h"
+#include "g_common.h"
+#include "threading.h"
+#include "decoderthreading.h"
+#include <stdio.h>
+#include "segmentation_common.h"
+#include "quant_common.h"
+#include "vpx_scale/vpxscale.h"
+#include "systemdependent.h"
+#include "vpx_ports/vpx_timer.h"
+
+
+#ifndef VPX_NO_GLOBALS
+static int init_ct = 0;
+#else
+# include "vpx_global_handling.h"
+# define init_ct ((int)vpxglobalm(onyxd,init_ct))
+#endif
+
+extern void vp8_init_loop_filter(VP8_COMMON *cm);
+
+extern void vp8cx_init_de_quantizer(VP8D_COMP *pbi);
+extern void init_detokenizer(VP8D_COMP *dx);
+
+// DEBUG code
+void vp8_recon_write_yuv_frame(unsigned char *name, YV12_BUFFER_CONFIG *s)
+{
+    FILE *yuv_file = fopen((char *)name, "ab");
+    unsigned char *src = s->y_buffer;
+    int h = s->y_height;
+
+    do
+    {
+        fwrite(src, s->y_width, 1,  yuv_file);
+        src += s->y_stride;
+    }
+    while (--h);
+
+    src = s->u_buffer;
+    h = s->uv_height;
+
+    do
+    {
+        fwrite(src, s->uv_width, 1,  yuv_file);
+        src += s->uv_stride;
+    }
+    while (--h);
+
+    src = s->v_buffer;
+    h = s->uv_height;
+
+    do
+    {
+        fwrite(src, s->uv_width, 1, yuv_file);
+        src += s->uv_stride;
+    }
+    while (--h);
+
+    fclose(yuv_file);
+}
+
+void vp8dx_initialize()
+{
+    if (!init_ct++)
+    {
+        vp8_initialize_common();
+        vp8_scale_machine_specific_config();
+    }
+}
+
+void vp8dx_shutdown()
+{
+    if (!--init_ct)
+    {
+        vp8_shutdown_common();
+    }
+}
+
+
+VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
+{
+    VP8D_COMP *pbi = vpx_memalign(32, sizeof(VP8D_COMP));
+
+    if (!pbi)
+        return NULL;
+
+    vpx_memset(pbi, 0, sizeof(VP8D_COMP));
+
+    vp8dx_initialize();
+
+    vp8_create_common(&pbi->common);
+    vp8_dmachine_specific_config(pbi);
+
+    pbi->common.current_video_frame = 0;
+    pbi->ready_for_new_data = 1;
+
+    pbi->CPUFreq = 0; //vp8_get_processor_freq();
+    pbi->max_threads = oxcf->max_threads;
+    vp8_decoder_create_threads(pbi);
+
+    //vp8cx_init_de_quantizer() is first called here. Add check in frame_init_dequantizer() to avoid
+    // unnecessary calling of vp8cx_init_de_quantizer() for every frame.
+    vp8cx_init_de_quantizer(pbi);
+
+    {
+        VP8_COMMON *cm = &pbi->common;
+
+        vp8_init_loop_filter(cm);
+        cm->last_frame_type = KEY_FRAME;
+        cm->last_filter_type = cm->filter_type;
+        cm->last_sharpness_level = cm->sharpness_level;
+    }
+
+    init_detokenizer(pbi);
+
+    return (VP8D_PTR) pbi;
+}
+void vp8dx_remove_decompressor(VP8D_PTR ptr)
+{
+    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
+
+    if (!pbi)
+        return;
+
+    vp8_decoder_remove_threads(pbi);
+    vp8_remove_common(&pbi->common);
+    vpx_free(pbi);
+    vp8dx_shutdown();
+
+}
+
+void vp8dx_set_setting(VP8D_PTR comp, VP8D_SETTING oxst, int x)
+{
+    VP8D_COMP *pbi = (VP8D_COMP *) comp;
+
+    (void) pbi;
+    (void) x;
+
+    switch (oxst)
+    {
+    case VP8D_OK:
+        break;
+    }
+}
+
+int vp8dx_get_setting(VP8D_PTR comp, VP8D_SETTING oxst)
+{
+    VP8D_COMP *pbi = (VP8D_COMP *) comp;
+
+    (void) pbi;
+
+    switch (oxst)
+    {
+    case VP8D_OK:
+        break;
+    }
+
+    return -1;
+}
+
+int vp8dx_get_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
+{
+    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
+    VP8_COMMON *cm = &pbi->common;
+
+    if (ref_frame_flag == VP8_LAST_FLAG)
+        vp8_yv12_copy_frame_ptr(&cm->last_frame, sd);
+
+    else if (ref_frame_flag == VP8_GOLD_FLAG)
+        vp8_yv12_copy_frame_ptr(&cm->golden_frame, sd);
+
+    else if (ref_frame_flag == VP8_ALT_FLAG)
+        vp8_yv12_copy_frame_ptr(&cm->alt_ref_frame, sd);
+
+    else
+        return -1;
+
+    return 0;
+}
+int vp8dx_set_reference(VP8D_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
+{
+    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
+    VP8_COMMON *cm = &pbi->common;
+
+    if (ref_frame_flag == VP8_LAST_FLAG)
+        vp8_yv12_copy_frame_ptr(sd, &cm->last_frame);
+
+    else if (ref_frame_flag == VP8_GOLD_FLAG)
+        vp8_yv12_copy_frame_ptr(sd, &cm->golden_frame);
+
+    else if (ref_frame_flag == VP8_ALT_FLAG)
+        vp8_yv12_copy_frame_ptr(sd, &cm->alt_ref_frame);
+
+    else
+        return -1;
+
+    return 0;
+}
+int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, char *source, INT64 time_stamp)
+{
+    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
+    VP8_COMMON *cm = &pbi->common;
+    int retcode = 0;
+
+    struct vpx_usec_timer timer;
+    (void) size;
+
+//  if(pbi->ready_for_new_data == 0)
+//      return -1;
+
+    vpx_usec_timer_start(&timer);
+
+    if (ptr == 0)
+    {
+        return -1;
+    }
+
+    //cm->current_video_frame++;
+    pbi->Source = source;
+
+    retcode = vp8_decode_frame(pbi);
+
+    if (retcode < 0)
+        return retcode;
+
+    // Update the GF useage maps.
+    vp8_update_gf_useage_maps(cm, &pbi->mb);
+
+    if (pbi->b_multithreaded)
+        vp8_stop_lfthread(pbi);
+
+    if (cm->refresh_last_frame)
+    {
+        vp8_swap_yv12_buffer(&cm->last_frame, &cm->new_frame);
+
+        cm->frame_to_show = &cm->last_frame;
+    }
+    else
+    {
+        cm->frame_to_show = &cm->new_frame;
+    }
+
+    if (!pbi->b_multithreaded)
+    {
+        struct vpx_usec_timer lpftimer;
+        vpx_usec_timer_start(&lpftimer);
+        // Apply the loop filter if appropriate.
+
+        if (cm->filter_level > 0)
+        {
+            vp8_loop_filter_frame(cm, &pbi->mb, cm->filter_level);
+            cm->last_frame_type = cm->frame_type;
+            cm->last_filter_type = cm->filter_type;
+            cm->last_sharpness_level = cm->sharpness_level;
+
+        }
+
+        vpx_usec_timer_mark(&lpftimer);
+        pbi->time_loop_filtering += vpx_usec_timer_elapsed(&lpftimer);
+    }
+
+    vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);
+
+#if 0
+    // DEBUG code
+    //vp8_recon_write_yuv_frame("recon.yuv", cm->frame_to_show);
+    if (cm->current_video_frame <= 5)
+        write_dx_frame_to_file(cm->frame_to_show, cm->current_video_frame);
+#endif
+
+    // If any buffer copy / swaping is signalled it should be done here.
+    if (cm->copy_buffer_to_arf)
+    {
+        if (cm->copy_buffer_to_arf == 1)
+        {
+            if (cm->refresh_last_frame)
+                vp8_yv12_copy_frame_ptr(&cm->new_frame, &cm->alt_ref_frame);
+            else
+                vp8_yv12_copy_frame_ptr(&cm->last_frame, &cm->alt_ref_frame);
+        }
+        else if (cm->copy_buffer_to_arf == 2)
+            vp8_yv12_copy_frame_ptr(&cm->golden_frame, &cm->alt_ref_frame);
+    }
+
+    if (cm->copy_buffer_to_gf)
+    {
+        if (cm->copy_buffer_to_gf == 1)
+        {
+            if (cm->refresh_last_frame)
+                vp8_yv12_copy_frame_ptr(&cm->new_frame, &cm->golden_frame);
+            else
+                vp8_yv12_copy_frame_ptr(&cm->last_frame, &cm->golden_frame);
+        }
+        else if (cm->copy_buffer_to_gf == 2)
+            vp8_yv12_copy_frame_ptr(&cm->alt_ref_frame, &cm->golden_frame);
+    }
+
+    // Should the golden or alternate reference frame be refreshed?
+    if (cm->refresh_golden_frame || cm->refresh_alt_ref_frame)
+    {
+        if (cm->refresh_golden_frame)
+            vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cm->golden_frame);
+
+        if (cm->refresh_alt_ref_frame)
+            vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cm->alt_ref_frame);
+
+        //vpx_log("Decoder: recovery frame received \n");
+
+        // Update data structures that monitors GF useage
+        vpx_memset(cm->gf_active_flags, 1, (cm->mb_rows * cm->mb_cols));
+        cm->gf_active_count = cm->mb_rows * cm->mb_cols;
+    }
+
+    vp8_clear_system_state();
+
+    vpx_usec_timer_mark(&timer);
+    pbi->decode_microseconds = vpx_usec_timer_elapsed(&timer);
+
+    pbi->time_decoding += pbi->decode_microseconds;
+
+//  vp8_print_modes_and_motion_vectors( cm->mi, cm->mb_rows,cm->mb_cols, cm->current_video_frame);
+
+    cm->current_video_frame++;
+    pbi->ready_for_new_data = 0;
+    pbi->last_time_stamp = time_stamp;
+
+    {
+        int i;
+        INT64 earliest_time = pbi->dr[0].time_stamp;
+        INT64 latest_time = pbi->dr[0].time_stamp;
+        INT64 time_diff = 0;
+        int bytes = 0;
+
+        pbi->dr[pbi->common.current_video_frame&0xf].size = pbi->bc.pos + pbi->bc2.pos + 4;;
+        pbi->dr[pbi->common.current_video_frame&0xf].time_stamp = time_stamp;
+
+        for (i = 0; i < 16; i++)
+        {
+
+            bytes += pbi->dr[i].size;
+
+            if (pbi->dr[i].time_stamp < earliest_time)
+                earliest_time = pbi->dr[i].time_stamp;
+
+            if (pbi->dr[i].time_stamp > latest_time)
+                latest_time = pbi->dr[i].time_stamp;
+        }
+
+        time_diff = latest_time - earliest_time;
+
+        if (time_diff > 0)
+        {
+            pbi->common.bitrate = 80000.00 * bytes / time_diff  ;
+            pbi->common.framerate = 160000000.00 / time_diff ;
+        }
+
+    }
+    return retcode;
+}
+int vp8dx_get_raw_frame(VP8D_PTR ptr, YV12_BUFFER_CONFIG *sd, INT64 *time_stamp, INT64 *time_end_stamp, int deblock_level,  int noise_level, int flags)
+{
+    int ret = -1;
+    VP8D_COMP *pbi = (VP8D_COMP *) ptr;
+
+    if (pbi->ready_for_new_data == 1)
+        return ret;
+
+    // ie no raw frame to show!!!
+    if (pbi->common.show_frame == 0)
+        return ret;
+
+    pbi->ready_for_new_data = 1;
+    *time_stamp = pbi->last_time_stamp;
+    *time_end_stamp = 0;
+
+    sd->clrtype = pbi->common.clr_type;
+    ret = vp8_post_proc_frame(&pbi->common, sd, deblock_level, noise_level, flags);
+    vp8_clear_system_state();
+    return ret;
+}
diff --git a/vp8/decoder/onyxd_int.h b/vp8/decoder/onyxd_int.h
new file mode 100644
index 0000000..fa4fa48
--- /dev/null
+++ b/vp8/decoder/onyxd_int.h
@@ -0,0 +1,149 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_VP8D_INT_H
+#define __INC_VP8D_INT_H
+#include "vpx_ports/config.h"
+#include "onyxd.h"
+#include "treereader.h"
+#include "onyxc_int.h"
+#include "threading.h"
+#include "dequantize.h"
+
+typedef struct
+{
+    int ithread;
+    void *ptr1;
+    void *ptr2;
+} DECODETHREAD_DATA;
+
+typedef struct
+{
+    MACROBLOCKD  mbd;
+    int mb_row;
+    int current_mb_col;
+    short *coef_ptr;
+} MB_ROW_DEC;
+
+typedef struct
+{
+    INT64 time_stamp;
+    int size;
+} DATARATE;
+
+typedef struct
+{
+    INT16         min_val;
+    INT16         Length;
+    UINT8 Probs[12];
+} TOKENEXTRABITS;
+
+typedef struct
+{
+    int *scan;
+    UINT8 *ptr_onyxblock2context_leftabove;
+    vp8_tree_index *vp8_coef_tree_ptr;  //onyx_coef_tree_ptr; ???
+    TOKENEXTRABITS *teb_base_ptr;
+    unsigned char *norm_ptr;
+//  UINT16 *ptr_onyx_coef_bands_x;
+    UINT8 *ptr_onyx_coef_bands_x;
+
+    ENTROPY_CONTEXT   **A;
+    ENTROPY_CONTEXT(*L)[4];
+
+    INT16 *qcoeff_start_ptr;
+    BOOL_DECODER *current_bc;
+
+    UINT8 *coef_probs[4];
+
+    UINT8 eob[25];
+
+} DETOK;
+
+typedef struct VP8Decompressor
+{
+    DECLARE_ALIGNED(16, MACROBLOCKD, mb);
+
+    DECLARE_ALIGNED(16, VP8_COMMON, common);
+
+    vp8_reader bc, bc2;
+
+    VP8D_CONFIG oxcf;
+
+
+    const unsigned char *Source;
+    unsigned int   source_sz;
+
+
+    unsigned int CPUFreq;
+    unsigned int decode_microseconds;
+    unsigned int time_decoding;
+    unsigned int time_loop_filtering;
+
+    volatile int b_multithreaded_rd;
+    volatile int b_multithreaded_lf;
+    int max_threads;
+    int last_mb_row_decoded;
+    int current_mb_col_main;
+    int decoding_thread_count;
+    int allocated_decoding_thread_count;
+
+    // variable for threading
+    DECLARE_ALIGNED(16, MACROBLOCKD, lpfmb);
+#if CONFIG_MULTITHREAD
+    pthread_t           h_thread_lpf;         // thread for postprocessing
+    sem_t               h_event_lpf;          // Event for post_proc completed
+    sem_t               h_event_start_lpf;
+#endif
+    MB_ROW_DEC           *mb_row_di;
+    DECODETHREAD_DATA   *de_thread_data;
+#if CONFIG_MULTITHREAD
+    pthread_t           *h_decoding_thread;
+    sem_t               *h_event_mbrdecoding;
+    sem_t               h_event_main;
+    // end of threading data
+#endif
+    vp8_reader *mbc;
+    INT64 last_time_stamp;
+    int   ready_for_new_data;
+
+    DATARATE dr[16];
+
+    DETOK detoken;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+    vp8_dequant_rtcd_vtable_t        dequant;
+    struct vp8_dboolhuff_rtcd_vtable dboolhuff;
+#endif
+
+} VP8D_COMP;
+
+int vp8_decode_frame(VP8D_COMP *cpi);
+void vp8_dmachine_specific_config(VP8D_COMP *pbi);
+
+
+#if CONFIG_DEBUG
+#define CHECK_MEM_ERROR(lval,expr) do {\
+        lval = (expr); \
+        if(!lval) \
+            vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,\
+                               "Failed to allocate "#lval" at %s:%d", \
+                               __FILE__,__LINE__);\
+    } while(0)
+#else
+#define CHECK_MEM_ERROR(lval,expr) do {\
+        lval = (expr); \
+        if(!lval) \
+            vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,\
+                               "Failed to allocate "#lval);\
+    } while(0)
+#endif
+
+#endif
diff --git a/vp8/decoder/threading.c b/vp8/decoder/threading.c
new file mode 100644
index 0000000..e35d175
--- /dev/null
+++ b/vp8/decoder/threading.c
@@ -0,0 +1,596 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef WIN32
+# include <unistd.h>
+#endif
+#include "onyxd_int.h"
+#include "vpx_mem/vpx_mem.h"
+#include "threading.h"
+
+#include "loopfilter.h"
+#include "extend.h"
+#include "vpx_ports/vpx_timer.h"
+
+extern void vp8_decode_mb_row(VP8D_COMP *pbi,
+                              VP8_COMMON *pc,
+                              int mb_row,
+                              MACROBLOCKD *xd);
+
+extern void vp8_build_uvmvs(MACROBLOCKD *x, int fullpixel);
+extern void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd);
+
+void vp8_setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_DEC *mbrd, int count)
+{
+
+
+
+#if CONFIG_MULTITHREAD
+    VP8_COMMON *const pc = & pbi->common;
+    int i, j;
+
+    for (i = 0; i < count; i++)
+    {
+        MACROBLOCKD *mbd = &mbrd[i].mbd;
+#if CONFIG_RUNTIME_CPU_DETECT
+        mbd->rtcd = xd->rtcd;
+#endif
+
+
+        mbd->subpixel_predict        = xd->subpixel_predict;
+        mbd->subpixel_predict8x4     = xd->subpixel_predict8x4;
+        mbd->subpixel_predict8x8     = xd->subpixel_predict8x8;
+        mbd->subpixel_predict16x16   = xd->subpixel_predict16x16;
+        mbd->gf_active_ptr            = xd->gf_active_ptr;
+
+        mbd->mode_info        = pc->mi - 1;
+        mbd->mode_info_context = pc->mi   + pc->mode_info_stride * (i + 1);
+        mbd->mode_info_stride  = pc->mode_info_stride;
+
+        mbd->frame_type = pc->frame_type;
+        mbd->frames_since_golden      = pc->frames_since_golden;
+        mbd->frames_till_alt_ref_frame  = pc->frames_till_alt_ref_frame;
+
+        mbd->pre = pc->last_frame;
+        mbd->dst = pc->new_frame;
+
+
+
+
+        vp8_setup_block_dptrs(mbd);
+        vp8_build_block_doffsets(mbd);
+        mbd->segmentation_enabled    = xd->segmentation_enabled;
+        mbd->mb_segement_abs_delta     = xd->mb_segement_abs_delta;
+        vpx_memcpy(mbd->segment_feature_data, xd->segment_feature_data, sizeof(xd->segment_feature_data));
+
+        mbd->mbmi.mode = DC_PRED;
+        mbd->mbmi.uv_mode = DC_PRED;
+
+        mbd->current_bc = &pbi->bc2;
+
+        for (j = 0; j < 25; j++)
+        {
+            mbd->block[j].dequant = xd->block[j].dequant;
+        }
+    }
+
+#else
+    (void) pbi;
+    (void) xd;
+    (void) mbrd;
+    (void) count;
+#endif
+}
+
+
+THREAD_FUNCTION vp8_thread_decoding_proc(void *p_data)
+{
+#if CONFIG_MULTITHREAD
+    int ithread = ((DECODETHREAD_DATA *)p_data)->ithread;
+    VP8D_COMP *pbi = (VP8D_COMP *)(((DECODETHREAD_DATA *)p_data)->ptr1);
+    MB_ROW_DEC *mbrd = (MB_ROW_DEC *)(((DECODETHREAD_DATA *)p_data)->ptr2);
+    ENTROPY_CONTEXT mb_row_left_context[4][4];
+
+    while (1)
+    {
+        if (pbi->b_multithreaded_rd == 0)
+            break;
+
+        //if(WaitForSingleObject(pbi->h_event_mbrdecoding[ithread], INFINITE) == WAIT_OBJECT_0)
+        if (sem_wait(&pbi->h_event_mbrdecoding[ithread]) == 0)
+        {
+            if (pbi->b_multithreaded_rd == 0)
+                break;
+            else
+            {
+                VP8_COMMON *pc = &pbi->common;
+                int mb_row       = mbrd->mb_row;
+                MACROBLOCKD *xd = &mbrd->mbd;
+
+                //printf("ithread:%d mb_row %d\n", ithread, mb_row);
+                int i;
+                int recon_yoffset, recon_uvoffset;
+                int mb_col;
+                int recon_y_stride = pc->last_frame.y_stride;
+                int recon_uv_stride = pc->last_frame.uv_stride;
+
+                volatile int *last_row_current_mb_col;
+
+                if (ithread > 0)
+                    last_row_current_mb_col = &pbi->mb_row_di[ithread-1].current_mb_col;
+                else
+                    last_row_current_mb_col = &pbi->current_mb_col_main;
+
+                recon_yoffset = mb_row * recon_y_stride * 16;
+                recon_uvoffset = mb_row * recon_uv_stride * 8;
+                // reset above block coeffs
+
+                xd->above_context[Y1CONTEXT] = pc->above_context[Y1CONTEXT];
+                xd->above_context[UCONTEXT ] = pc->above_context[UCONTEXT];
+                xd->above_context[VCONTEXT ] = pc->above_context[VCONTEXT];
+                xd->above_context[Y2CONTEXT] = pc->above_context[Y2CONTEXT];
+                xd->left_context = mb_row_left_context;
+                vpx_memset(mb_row_left_context, 0, sizeof(mb_row_left_context));
+                xd->up_available = (mb_row != 0);
+
+                xd->mb_to_top_edge = -((mb_row * 16)) << 3;
+                xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
+
+                for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
+                {
+
+                    while (mb_col > (*last_row_current_mb_col - 1) && *last_row_current_mb_col != pc->mb_cols - 1)
+                    {
+                        x86_pause_hint();
+                        thread_sleep(0);
+                    }
+
+                    // Take a copy of the mode and Mv information for this macroblock into the xd->mbmi
+                    vpx_memcpy(&xd->mbmi, &xd->mode_info_context->mbmi, 32); //sizeof(MB_MODE_INFO) );
+
+                    if (xd->mbmi.mode == SPLITMV || xd->mbmi.mode == B_PRED)
+                    {
+                        for (i = 0; i < 16; i++)
+                        {
+                            BLOCKD *d = &xd->block[i];
+                            vpx_memcpy(&d->bmi, &xd->mode_info_context->bmi[i], sizeof(B_MODE_INFO));
+                        }
+                    }
+
+                    // Distance of Mb to the various image edges.
+                    // These specified to 8th pel as they are always compared to values that are in 1/8th pel units
+                    xd->mb_to_left_edge = -((mb_col * 16) << 3);
+                    xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
+
+                    xd->dst.y_buffer = pc->new_frame.y_buffer + recon_yoffset;
+                    xd->dst.u_buffer = pc->new_frame.u_buffer + recon_uvoffset;
+                    xd->dst.v_buffer = pc->new_frame.v_buffer + recon_uvoffset;
+
+                    xd->left_available = (mb_col != 0);
+
+                    // Select the appropriate reference frame for this MB
+                    if (xd->mbmi.ref_frame == LAST_FRAME)
+                    {
+                        xd->pre.y_buffer = pc->last_frame.y_buffer + recon_yoffset;
+                        xd->pre.u_buffer = pc->last_frame.u_buffer + recon_uvoffset;
+                        xd->pre.v_buffer = pc->last_frame.v_buffer + recon_uvoffset;
+                    }
+                    else if (xd->mbmi.ref_frame == GOLDEN_FRAME)
+                    {
+                        // Golden frame reconstruction buffer
+                        xd->pre.y_buffer = pc->golden_frame.y_buffer + recon_yoffset;
+                        xd->pre.u_buffer = pc->golden_frame.u_buffer + recon_uvoffset;
+                        xd->pre.v_buffer = pc->golden_frame.v_buffer + recon_uvoffset;
+                    }
+                    else
+                    {
+                        // Alternate reference frame reconstruction buffer
+                        xd->pre.y_buffer = pc->alt_ref_frame.y_buffer + recon_yoffset;
+                        xd->pre.u_buffer = pc->alt_ref_frame.u_buffer + recon_uvoffset;
+                        xd->pre.v_buffer = pc->alt_ref_frame.v_buffer + recon_uvoffset;
+                    }
+
+                    vp8_build_uvmvs(xd, pc->full_pixel);
+
+                    vp8dx_bool_decoder_fill(xd->current_bc);
+                    vp8_decode_macroblock(pbi, xd);
+
+
+                    recon_yoffset += 16;
+                    recon_uvoffset += 8;
+
+                    ++xd->mode_info_context;  /* next mb */
+
+                    xd->gf_active_ptr++;      // GF useage flag for next MB
+
+                    xd->above_context[Y1CONTEXT] += 4;
+                    xd->above_context[UCONTEXT ] += 2;
+                    xd->above_context[VCONTEXT ] += 2;
+                    xd->above_context[Y2CONTEXT] ++;
+                    pbi->mb_row_di[ithread].current_mb_col = mb_col;
+
+                }
+
+                // adjust to the next row of mbs
+                vp8_extend_mb_row(
+                    &pc->new_frame,
+                    xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8
+                );
+
+                ++xd->mode_info_context;      /* skip prediction column */
+
+                // since we have multithread
+                xd->mode_info_context += xd->mode_info_stride * pbi->decoding_thread_count;
+
+                //memcpy(&pbi->lpfmb, &pbi->mb, sizeof(pbi->mb));
+                if ((mb_row & 1) == 1)
+                {
+                    pbi->last_mb_row_decoded = mb_row;
+                    //printf("S%d", pbi->last_mb_row_decoded);
+                }
+
+                if (ithread == (pbi->decoding_thread_count - 1) || mb_row == pc->mb_rows - 1)
+                {
+                    //SetEvent(pbi->h_event_main);
+                    sem_post(&pbi->h_event_main);
+
+                }
+            }
+        }
+    }
+
+#else
+    (void) p_data;
+#endif
+
+    return 0 ;
+}
+
+THREAD_FUNCTION vp8_thread_loop_filter(void *p_data)
+{
+#if CONFIG_MULTITHREAD
+    VP8D_COMP *pbi = (VP8D_COMP *)p_data;
+
+    while (1)
+    {
+        if (pbi->b_multithreaded_lf == 0)
+            break;
+
+        //printf("before waiting for start_lpf\n");
+
+        //if(WaitForSingleObject(pbi->h_event_start_lpf, INFINITE) == WAIT_OBJECT_0)
+        if (sem_wait(&pbi->h_event_start_lpf) == 0)
+        {
+            if (pbi->b_multithreaded_lf == 0) // we're shutting down
+                break;
+            else
+            {
+
+                VP8_COMMON *cm  = &pbi->common;
+                MACROBLOCKD *mbd = &pbi->lpfmb;
+                int default_filt_lvl = pbi->common.filter_level;
+
+                YV12_BUFFER_CONFIG *post = &cm->new_frame;
+                loop_filter_info *lfi = cm->lf_info;
+
+                int mb_row;
+                int mb_col;
+
+
+                int baseline_filter_level[MAX_MB_SEGMENTS];
+                int filter_level;
+                int alt_flt_enabled = mbd->segmentation_enabled;
+
+                int i;
+                unsigned char *y_ptr, *u_ptr, *v_ptr;
+
+                volatile int *last_mb_row_decoded = &pbi->last_mb_row_decoded;
+
+                //MODE_INFO * this_mb_mode_info = cm->mi;
+                mbd->mode_info_context = cm->mi;          // Point at base of Mb MODE_INFO list
+
+                // Note the baseline filter values for each segment
+                if (alt_flt_enabled)
+                {
+                    for (i = 0; i < MAX_MB_SEGMENTS; i++)
+                    {
+                        if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+                            baseline_filter_level[i] = mbd->segment_feature_data[MB_LVL_ALT_LF][i];
+                        else
+                        {
+                            baseline_filter_level[i] = default_filt_lvl + mbd->segment_feature_data[MB_LVL_ALT_LF][i];
+                            baseline_filter_level[i] = (baseline_filter_level[i] >= 0) ? ((baseline_filter_level[i] <= MAX_LOOP_FILTER) ? baseline_filter_level[i] : MAX_LOOP_FILTER) : 0;  // Clamp to valid range
+                        }
+                    }
+                }
+                else
+                {
+                    for (i = 0; i < MAX_MB_SEGMENTS; i++)
+                        baseline_filter_level[i] = default_filt_lvl;
+                }
+
+                // Initialize the loop filter for this frame.
+                vp8_init_loop_filter(cm);
+
+                // Set up the buffer pointers
+                y_ptr = post->y_buffer;
+                u_ptr = post->u_buffer;
+                v_ptr = post->v_buffer;
+
+                // vp8_filter each macro block
+                for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+                {
+
+                    while (mb_row >= *last_mb_row_decoded)
+                    {
+                        x86_pause_hint();
+                        thread_sleep(0);
+                    }
+
+                    //printf("R%d", mb_row);
+                    for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+                    {
+                        int Segment = (alt_flt_enabled) ? mbd->mode_info_context->mbmi.segment_id : 0;
+
+                        filter_level = baseline_filter_level[Segment];
+
+                        // Apply any context driven MB level adjustment
+                        vp8_adjust_mb_lf_value(mbd, &filter_level);
+
+                        if (filter_level)
+                        {
+                            if (mb_col > 0)
+                                cm->lf_mbv(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
+
+                            if (mbd->mode_info_context->mbmi.dc_diff > 0)
+                                cm->lf_bv(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
+
+                            // don't apply across umv border
+                            if (mb_row > 0)
+                                cm->lf_mbh(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
+
+                            if (mbd->mode_info_context->mbmi.dc_diff > 0)
+                                cm->lf_bh(y_ptr, u_ptr, v_ptr, post->y_stride, post->uv_stride, &lfi[filter_level], cm->simpler_lpf);
+                        }
+
+                        y_ptr += 16;
+                        u_ptr += 8;
+                        v_ptr += 8;
+
+                        mbd->mode_info_context++;     // step to next MB
+
+                    }
+
+                    y_ptr += post->y_stride  * 16 - post->y_width;
+                    u_ptr += post->uv_stride *  8 - post->uv_width;
+                    v_ptr += post->uv_stride *  8 - post->uv_width;
+
+                    mbd->mode_info_context++;         // Skip border mb
+                }
+
+                //printf("R%d\n", mb_row);
+                // When done, signal main thread that ME is finished
+                //SetEvent(pbi->h_event_lpf);
+                sem_post(&pbi->h_event_lpf);
+            }
+
+        }
+    }
+
+#else
+    (void) p_data;
+#endif
+    return 0;
+}
+
+void vp8_decoder_create_threads(VP8D_COMP *pbi)
+{
+#if CONFIG_MULTITHREAD
+    int core_count = 0;
+    int ithread;
+
+    pbi->b_multithreaded_rd = 0;
+    pbi->b_multithreaded_lf = 0;
+    pbi->allocated_decoding_thread_count = 0;
+    core_count = (pbi->max_threads > 16) ? 16 : pbi->max_threads; //vp8_get_proc_core_count();
+    if (core_count > 1)
+    {
+        sem_init(&pbi->h_event_lpf, 0, 0);
+        sem_init(&pbi->h_event_start_lpf, 0, 0);
+        pbi->b_multithreaded_lf = 1;
+        pthread_create(&pbi->h_thread_lpf, 0, vp8_thread_loop_filter, (pbi));
+    }
+
+    if (core_count > 1)
+    {
+        pbi->b_multithreaded_rd = 1;
+        pbi->decoding_thread_count = core_count - 1;
+
+        CHECK_MEM_ERROR(pbi->h_decoding_thread, vpx_malloc(sizeof(pthread_t) * pbi->decoding_thread_count));
+        CHECK_MEM_ERROR(pbi->h_event_mbrdecoding, vpx_malloc(sizeof(sem_t) * pbi->decoding_thread_count));
+        CHECK_MEM_ERROR(pbi->mb_row_di, vpx_memalign(32, sizeof(MB_ROW_DEC) * pbi->decoding_thread_count));
+        vpx_memset(pbi->mb_row_di, 0, sizeof(MB_ROW_DEC) * pbi->decoding_thread_count);
+        CHECK_MEM_ERROR(pbi->de_thread_data, vpx_malloc(sizeof(DECODETHREAD_DATA) * pbi->decoding_thread_count));
+
+        for (ithread = 0; ithread < pbi->decoding_thread_count; ithread++)
+        {
+            sem_init(&pbi->h_event_mbrdecoding[ithread], 0, 0);
+
+            pbi->de_thread_data[ithread].ithread  = ithread;
+            pbi->de_thread_data[ithread].ptr1     = (void *)pbi;
+            pbi->de_thread_data[ithread].ptr2     = (void *) &pbi->mb_row_di[ithread];
+
+            pthread_create(&pbi->h_decoding_thread[ithread], 0, vp8_thread_decoding_proc, (&pbi->de_thread_data[ithread]));
+
+        }
+
+        sem_init(&pbi->h_event_main, 0, 0);
+        pbi->allocated_decoding_thread_count = pbi->decoding_thread_count;
+    }
+
+#else
+    (void) pbi;
+#endif
+}
+
+void vp8_decoder_remove_threads(VP8D_COMP *pbi)
+{
+#if CONFIG_MULTITHREAD
+
+    if (pbi->b_multithreaded_lf)
+    {
+        pbi->b_multithreaded_lf = 0;
+        sem_post(&pbi->h_event_start_lpf);
+        pthread_join(pbi->h_thread_lpf, 0);
+        sem_destroy(&pbi->h_event_start_lpf);
+    }
+
+    //shutdown MB Decoding thread;
+    if (pbi->b_multithreaded_rd)
+    {
+        pbi->b_multithreaded_rd = 0;
+        // allow all threads to exit
+        {
+            int i;
+
+            for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
+            {
+
+                sem_post(&pbi->h_event_mbrdecoding[i]);
+                pthread_join(pbi->h_decoding_thread[i], NULL);
+            }
+        }
+        {
+
+            int i;
+            for (i = 0; i < pbi->allocated_decoding_thread_count; i++)
+            {
+                sem_destroy(&pbi->h_event_mbrdecoding[i]);
+            }
+
+
+        }
+
+        sem_destroy(&pbi->h_event_main);
+
+        if (pbi->h_decoding_thread)
+        {
+            vpx_free(pbi->h_decoding_thread);
+            pbi->h_decoding_thread = NULL;
+        }
+
+        if (pbi->h_event_mbrdecoding)
+        {
+            vpx_free(pbi->h_event_mbrdecoding);
+            pbi->h_event_mbrdecoding = NULL;
+        }
+
+        if (pbi->mb_row_di)
+        {
+            vpx_free(pbi->mb_row_di);
+            pbi->mb_row_di = NULL ;
+        }
+
+        if (pbi->de_thread_data)
+        {
+            vpx_free(pbi->de_thread_data);
+            pbi->de_thread_data = NULL;
+        }
+    }
+
+#else
+    (void) pbi;
+#endif
+}
+
+
+void vp8_start_lfthread(VP8D_COMP *pbi)
+{
+#if CONFIG_MULTITHREAD
+    memcpy(&pbi->lpfmb, &pbi->mb, sizeof(pbi->mb));
+    pbi->last_mb_row_decoded = 0;
+    sem_post(&pbi->h_event_start_lpf);
+#else
+    (void) pbi;
+#endif
+}
+
+void vp8_stop_lfthread(VP8D_COMP *pbi)
+{
+#if CONFIG_MULTITHREAD
+    struct vpx_usec_timer timer;
+
+    vpx_usec_timer_start(&timer);
+
+    sem_wait(&pbi->h_event_lpf);
+
+    vpx_usec_timer_mark(&timer);
+    pbi->time_loop_filtering += vpx_usec_timer_elapsed(&timer);
+#else
+    (void) pbi;
+#endif
+}
+
+
+void vp8_mtdecode_mb_rows(VP8D_COMP *pbi,
+                          MACROBLOCKD *xd)
+{
+#if CONFIG_MULTITHREAD
+    int mb_row;
+    VP8_COMMON *pc = &pbi->common;
+
+    int ibc = 0;
+    int num_part = 1 << pbi->common.multi_token_partition;
+
+    vp8_setup_decoding_thread_data(pbi, xd, pbi->mb_row_di, pbi->decoding_thread_count);
+
+    for (mb_row = 0; mb_row < pc->mb_rows; mb_row += (pbi->decoding_thread_count + 1))
+    {
+        int i;
+        pbi->current_mb_col_main = -1;
+
+        xd->current_bc = &pbi->mbc[ibc];
+        ibc++ ;
+
+        if (ibc == num_part)
+            ibc = 0;
+
+        for (i = 0; i < pbi->decoding_thread_count; i++)
+        {
+            if ((mb_row + i + 1) >= pc->mb_rows)
+                break;
+
+            pbi->mb_row_di[i].mb_row = mb_row + i + 1;
+            pbi->mb_row_di[i].mbd.current_bc =  &pbi->mbc[ibc];
+            ibc++;
+
+            if (ibc == num_part)
+                ibc = 0;
+
+            pbi->mb_row_di[i].current_mb_col = -1;
+            sem_post(&pbi->h_event_mbrdecoding[i]);
+        }
+
+        vp8_decode_mb_row(pbi, pc, mb_row, xd);
+
+        xd->mode_info_context += xd->mode_info_stride * pbi->decoding_thread_count;
+
+        if (mb_row < pc->mb_rows - 1)
+        {
+            sem_wait(&pbi->h_event_main);
+        }
+    }
+
+    pbi->last_mb_row_decoded = mb_row;
+#else
+    (void) pbi;
+    (void) xd;
+#endif
+}
diff --git a/vp8/decoder/treereader.h b/vp8/decoder/treereader.h
new file mode 100644
index 0000000..eb10e24
--- /dev/null
+++ b/vp8/decoder/treereader.h
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef tree_reader_h
+#define tree_reader_h 1
+
+#include "treecoder.h"
+
+#include "dboolhuff.h"
+
+typedef BOOL_DECODER vp8_reader;
+
+#define vp8_read vp8dx_decode_bool
+#define vp8_read_literal vp8_decode_value
+#define vp8_read_bit( R) vp8_read( R, vp8_prob_half)
+
+
+/* Intent of tree data structure is to make decoding trivial. */
+
+static int vp8_treed_read(
+    vp8_reader *const r,        /* !!! must return a 0 or 1 !!! */
+    vp8_tree t,
+    const vp8_prob *const p
+)
+{
+    register vp8_tree_index i = 0;
+
+    while ((i = t[ i + vp8_read(r, p[i>>1])]) > 0) ;
+
+    return -i;
+}
+
+
+/* Variant reads a binary number given distributions on each bit.
+   Note that tree is arbitrary; probability of decoding a zero
+   may or may not depend on previously decoded bits. */
+
+static int vp8_treed_read_num(
+    vp8_reader *const r,        /* !!! must return a 0 or 1 !!! */
+    vp8_tree t,
+    const vp8_prob *const p
+)
+{
+    vp8_tree_index i = 0;
+    int v = 0, b;
+
+    do
+    {
+        b = vp8_read(r, p[i>>1]);
+        v = (v << 1) + b;
+    }
+    while ((i = t[i+b]) > 0);
+
+    return v;
+}
+#endif /* tree_reader_h */
diff --git a/vp8/decoder/x86/dequantize_mmx.asm b/vp8/decoder/x86/dequantize_mmx.asm
new file mode 100644
index 0000000..02be487
--- /dev/null
+++ b/vp8/decoder/x86/dequantize_mmx.asm
@@ -0,0 +1,410 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+
+;void vp8_dequantize_b_impl_mmx(short *sq, short *dq, short *q)
+global sym(vp8_dequantize_b_impl_mmx)
+sym(vp8_dequantize_b_impl_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov       rsi, arg(0) ;sq
+        mov       rdi, arg(1) ;dq
+        mov       rax, arg(2) ;q
+
+        movq      mm1, [rsi]
+        pmullw    mm1, [rax+0]            ; mm4 *= kernel 0 modifiers.
+        movq      [rdi], mm1
+
+        movq      mm1, [rsi+8]
+        pmullw    mm1, [rax+8]            ; mm4 *= kernel 0 modifiers.
+        movq      [rdi+8], mm1
+
+        movq      mm1, [rsi+16]
+        pmullw    mm1, [rax+16]            ; mm4 *= kernel 0 modifiers.
+        movq      [rdi+16], mm1
+
+        movq      mm1, [rsi+24]
+        pmullw    mm1, [rax+24]            ; mm4 *= kernel 0 modifiers.
+        movq      [rdi+24], mm1
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void dequant_idct_mmx(short *input, short *dq, short *output, int pitch)
+global sym(vp8_dequant_idct_mmx)
+sym(vp8_dequant_idct_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rax,    arg(0) ;input
+        mov         rdx,    arg(1) ;dq
+
+
+        movq        mm0,    [rax   ]
+        pmullw      mm0,    [rdx]
+
+        movq        mm1,    [rax +8]
+        pmullw      mm1,    [rdx +8]
+
+        movq        mm2,    [rax+16]
+        pmullw      mm2,    [rdx+16]
+
+        movq        mm3,    [rax+24]
+        pmullw      mm3,    [rdx+24]
+
+        mov         rdx,    arg(2) ;output
+        pxor        mm7,    mm7
+
+
+        movq        [rax],   mm7
+        movq        [rax+8], mm7
+
+        movq        [rax+16],mm7
+        movq        [rax+24],mm7
+
+
+        movsxd      rax,            dword ptr arg(3) ;pitch
+
+        psubw       mm0,            mm2             ; b1= 0-2
+        paddw       mm2,            mm2             ;
+
+        movq        mm5,            mm1
+        paddw       mm2,            mm0             ; a1 =0+2
+
+        pmulhw      mm5,            [x_s1sqr2 GLOBAL];
+        paddw       mm5,            mm1             ; ip1 * sin(pi/8) * sqrt(2)
+
+        movq        mm7,            mm3             ;
+        pmulhw      mm7,            [x_c1sqr2less1 GLOBAL];
+
+        paddw       mm7,            mm3             ; ip3 * cos(pi/8) * sqrt(2)
+        psubw       mm7,            mm5             ; c1
+
+        movq        mm5,            mm1
+        movq        mm4,            mm3
+
+        pmulhw      mm5,            [x_c1sqr2less1 GLOBAL]
+        paddw       mm5,            mm1
+
+        pmulhw      mm3,            [x_s1sqr2 GLOBAL]
+        paddw       mm3,            mm4
+
+        paddw       mm3,            mm5             ; d1
+        movq        mm6,            mm2             ; a1
+
+        movq        mm4,            mm0             ; b1
+        paddw       mm2,            mm3             ;0
+
+        paddw       mm4,            mm7             ;1
+        psubw       mm0,            mm7             ;2
+
+        psubw       mm6,            mm3             ;3
+
+        movq        mm1,            mm2             ; 03 02 01 00
+        movq        mm3,            mm4             ; 23 22 21 20
+
+        punpcklwd   mm1,            mm0             ; 11 01 10 00
+        punpckhwd   mm2,            mm0             ; 13 03 12 02
+
+        punpcklwd   mm3,            mm6             ; 31 21 30 20
+        punpckhwd   mm4,            mm6             ; 33 23 32 22
+
+        movq        mm0,            mm1             ; 11 01 10 00
+        movq        mm5,            mm2             ; 13 03 12 02
+
+        punpckldq   mm0,            mm3             ; 30 20 10 00
+        punpckhdq   mm1,            mm3             ; 31 21 11 01
+
+        punpckldq   mm2,            mm4             ; 32 22 12 02
+        punpckhdq   mm5,            mm4             ; 33 23 13 03
+
+        movq        mm3,            mm5             ; 33 23 13 03
+
+        psubw       mm0,            mm2             ; b1= 0-2
+        paddw       mm2,            mm2             ;
+
+        movq        mm5,            mm1
+        paddw       mm2,            mm0             ; a1 =0+2
+
+        pmulhw      mm5,            [x_s1sqr2 GLOBAL];
+        paddw       mm5,            mm1             ; ip1 * sin(pi/8) * sqrt(2)
+
+        movq        mm7,            mm3             ;
+        pmulhw      mm7,            [x_c1sqr2less1 GLOBAL];
+
+        paddw       mm7,            mm3             ; ip3 * cos(pi/8) * sqrt(2)
+        psubw       mm7,            mm5             ; c1
+
+        movq        mm5,            mm1
+        movq        mm4,            mm3
+
+        pmulhw      mm5,            [x_c1sqr2less1 GLOBAL]
+        paddw       mm5,            mm1
+
+        pmulhw      mm3,            [x_s1sqr2 GLOBAL]
+        paddw       mm3,            mm4
+
+        paddw       mm3,            mm5             ; d1
+        paddw       mm0,            [fours GLOBAL]
+
+        paddw       mm2,            [fours GLOBAL]
+        movq        mm6,            mm2             ; a1
+
+        movq        mm4,            mm0             ; b1
+        paddw       mm2,            mm3             ;0
+
+        paddw       mm4,            mm7             ;1
+        psubw       mm0,            mm7             ;2
+
+        psubw       mm6,            mm3             ;3
+        psraw       mm2,            3
+
+        psraw       mm0,            3
+        psraw       mm4,            3
+
+        psraw       mm6,            3
+
+        movq        mm1,            mm2             ; 03 02 01 00
+        movq        mm3,            mm4             ; 23 22 21 20
+
+        punpcklwd   mm1,            mm0             ; 11 01 10 00
+        punpckhwd   mm2,            mm0             ; 13 03 12 02
+
+        punpcklwd   mm3,            mm6             ; 31 21 30 20
+        punpckhwd   mm4,            mm6             ; 33 23 32 22
+
+        movq        mm0,            mm1             ; 11 01 10 00
+        movq        mm5,            mm2             ; 13 03 12 02
+
+        punpckldq   mm0,            mm3             ; 30 20 10 00
+        punpckhdq   mm1,            mm3             ; 31 21 11 01
+
+        punpckldq   mm2,            mm4             ; 32 22 12 02
+        punpckhdq   mm5,            mm4             ; 33 23 13 03
+
+        movq        [rdx],          mm0
+
+        movq        [rdx+rax],      mm1
+        movq        [rdx+rax*2],    mm2
+
+        add         rdx,            rax
+        movq        [rdx+rax*2],    mm5
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void dequant_dc_idct_mmx(short *input, short *dq, short *output, int pitch, int Dc)
+global sym(vp8_dequant_dc_idct_mmx)
+sym(vp8_dequant_dc_idct_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    GET_GOT     rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov         rax,    arg(0) ;input
+        mov         rdx,    arg(1) ;dq
+
+        movsxd      rcx,    dword ptr arg(4) ;Dc
+
+        movq        mm0,    [rax   ]
+        pmullw      mm0,    [rdx]
+
+        movq        mm1,    [rax +8]
+        pmullw      mm1,    [rdx +8]
+
+        movq        mm2,    [rax+16]
+        pmullw      mm2,    [rdx+16]
+
+        movq        mm3,    [rax+24]
+        pmullw      mm3,    [rdx+24]
+
+        mov         rdx,    arg(2) ;output
+        pxor        mm7,    mm7
+
+
+        movq        [rax],   mm7
+        movq        [rax+8], mm7
+
+        movq        [rax+16],mm7
+        movq        [rax+24],mm7
+
+        pinsrw      mm0,    rcx,  0
+        movsxd      rax,            dword ptr arg(3) ;pitch
+
+        psubw       mm0,            mm2             ; b1= 0-2
+        paddw       mm2,            mm2             ;
+
+        movq        mm5,            mm1
+        paddw       mm2,            mm0             ; a1 =0+2
+
+        pmulhw      mm5,            [x_s1sqr2 GLOBAL];
+        paddw       mm5,            mm1             ; ip1 * sin(pi/8) * sqrt(2)
+
+        movq        mm7,            mm3             ;
+        pmulhw      mm7,            [x_c1sqr2less1 GLOBAL];
+
+        paddw       mm7,            mm3             ; ip3 * cos(pi/8) * sqrt(2)
+        psubw       mm7,            mm5             ; c1
+
+        movq        mm5,            mm1
+        movq        mm4,            mm3
+
+        pmulhw      mm5,            [x_c1sqr2less1 GLOBAL]
+        paddw       mm5,            mm1
+
+        pmulhw      mm3,            [x_s1sqr2 GLOBAL]
+        paddw       mm3,            mm4
+
+        paddw       mm3,            mm5             ; d1
+        movq        mm6,            mm2             ; a1
+
+        movq        mm4,            mm0             ; b1
+        paddw       mm2,            mm3             ;0
+
+        paddw       mm4,            mm7             ;1
+        psubw       mm0,            mm7             ;2
+
+        psubw       mm6,            mm3             ;3
+
+        movq        mm1,            mm2             ; 03 02 01 00
+        movq        mm3,            mm4             ; 23 22 21 20
+
+        punpcklwd   mm1,            mm0             ; 11 01 10 00
+        punpckhwd   mm2,            mm0             ; 13 03 12 02
+
+        punpcklwd   mm3,            mm6             ; 31 21 30 20
+        punpckhwd   mm4,            mm6             ; 33 23 32 22
+
+        movq        mm0,            mm1             ; 11 01 10 00
+        movq        mm5,            mm2             ; 13 03 12 02
+
+        punpckldq   mm0,            mm3             ; 30 20 10 00
+        punpckhdq   mm1,            mm3             ; 31 21 11 01
+
+        punpckldq   mm2,            mm4             ; 32 22 12 02
+        punpckhdq   mm5,            mm4             ; 33 23 13 03
+
+        movq        mm3,            mm5             ; 33 23 13 03
+
+        psubw       mm0,            mm2             ; b1= 0-2
+        paddw       mm2,            mm2             ;
+
+        movq        mm5,            mm1
+        paddw       mm2,            mm0             ; a1 =0+2
+
+        pmulhw      mm5,            [x_s1sqr2 GLOBAL];
+        paddw       mm5,            mm1             ; ip1 * sin(pi/8) * sqrt(2)
+
+        movq        mm7,            mm3             ;
+        pmulhw      mm7,            [x_c1sqr2less1 GLOBAL];
+
+        paddw       mm7,            mm3             ; ip3 * cos(pi/8) * sqrt(2)
+        psubw       mm7,            mm5             ; c1
+
+        movq        mm5,            mm1
+        movq        mm4,            mm3
+
+        pmulhw      mm5,            [x_c1sqr2less1 GLOBAL]
+        paddw       mm5,            mm1
+
+        pmulhw      mm3,            [x_s1sqr2 GLOBAL]
+        paddw       mm3,            mm4
+
+        paddw       mm3,            mm5             ; d1
+        paddw       mm0,            [fours GLOBAL]
+
+        paddw       mm2,            [fours GLOBAL]
+        movq        mm6,            mm2             ; a1
+
+        movq        mm4,            mm0             ; b1
+        paddw       mm2,            mm3             ;0
+
+        paddw       mm4,            mm7             ;1
+        psubw       mm0,            mm7             ;2
+
+        psubw       mm6,            mm3             ;3
+        psraw       mm2,            3
+
+        psraw       mm0,            3
+        psraw       mm4,            3
+
+        psraw       mm6,            3
+
+        movq        mm1,            mm2             ; 03 02 01 00
+        movq        mm3,            mm4             ; 23 22 21 20
+
+        punpcklwd   mm1,            mm0             ; 11 01 10 00
+        punpckhwd   mm2,            mm0             ; 13 03 12 02
+
+        punpcklwd   mm3,            mm6             ; 31 21 30 20
+        punpckhwd   mm4,            mm6             ; 33 23 32 22
+
+        movq        mm0,            mm1             ; 11 01 10 00
+        movq        mm5,            mm2             ; 13 03 12 02
+
+        punpckldq   mm0,            mm3             ; 30 20 10 00
+        punpckhdq   mm1,            mm3             ; 31 21 11 01
+
+        punpckldq   mm2,            mm4             ; 32 22 12 02
+        punpckhdq   mm5,            mm4             ; 33 23 13 03
+
+        movq        [rdx],          mm0
+
+        movq        [rdx+rax],      mm1
+        movq        [rdx+rax*2],    mm2
+
+        add         rdx,            rax
+        movq        [rdx+rax*2],    mm5
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+SECTION_RODATA
+align 16
+x_s1sqr2:
+    times 4 dw 0x8A8C
+align 16
+x_c1sqr2less1:
+    times 4 dw 0x4E7B
+align 16
+fours:
+    times 4 dw 0x0004
diff --git a/vp8/decoder/x86/dequantize_x86.h b/vp8/decoder/x86/dequantize_x86.h
new file mode 100644
index 0000000..5def406
--- /dev/null
+++ b/vp8/decoder/x86/dequantize_x86.h
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef DEQUANTIZE_X86_H
+#define DEQUANTIZE_X86_H
+
+
+/* Note:
+ *
+ * This platform is commonly built for runtime CPU detection. If you modify
+ * any of the function mappings present in this file, be sure to also update
+ * them in the function pointer initialization code
+ */
+#if HAVE_MMX
+extern prototype_dequant_block(vp8_dequantize_b_mmx);
+extern prototype_dequant_idct(vp8_dequant_idct_mmx);
+extern prototype_dequant_idct_dc(vp8_dequant_dc_idct_mmx);
+
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_dequant_block
+#define vp8_dequant_block vp8_dequantize_b_mmx
+
+#undef  vp8_dequant_idct
+#define vp8_dequant_idct vp8_dequant_idct_mmx
+
+#undef  vp8_dequant_idct_dc
+#define vp8_dequant_idct_dc vp8_dequant_dc_idct_mmx
+
+#endif
+#endif
+
+#endif
diff --git a/vp8/decoder/x86/onyxdxv.c b/vp8/decoder/x86/onyxdxv.c
new file mode 100644
index 0000000..75a676a
--- /dev/null
+++ b/vp8/decoder/x86/onyxdxv.c
@@ -0,0 +1,1079 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/****************************************************************************
+*
+*   Module Title :     onyxdxv.c
+*
+*   Description  :     VP80 interface to DXV.
+*
+*****************************************************************************
+*/
+/****************************************************************************
+*  Header Files
+****************************************************************************/
+#include <math.h>   // For Abs()
+#include "pragmas.h"
+
+#include "vpxdxv.h"
+#include "vpxdxv_plugin.h"
+
+#include "onyxd_int.h"
+#include "onyx.h"
+#include "codec_common_interface.h"
+#include "vpx_scale/vpxscale.h"
+#include "vpx_mem/vpx_mem.h"
+#include "postproc.h"
+#include "vpxblit.h"
+#include "g_common.h"
+#include "vpx_scale/yv12extend.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include "scale_mode.h"
+#include "onyx_pb_interface.h"
+
+/****************************************************************************
+*  Macros
+****************************************************************************/
+
+#define VP8_FOURCC DXL_MKFOURCC( 'V', 'P', '8', '0')
+
+extern void vp8_blit_text(const char *msg, unsigned char *address, const int pitch);
+
+
+/****************************************************************************
+*  Typedefs
+****************************************************************************/
+
+typedef struct  // YUV buffer configuration structure
+{
+    int   y_width;
+    int   y_height;
+    int   y_stride;
+
+    int   uv_width;
+    int   uv_height;
+    int   uv_stride;
+
+    char *y_buffer;
+    char *u_buffer;
+    char *v_buffer;
+
+    char *uv_start;
+    int   uv_dst_area;
+    int   uv_used_area;
+
+    unsigned char *y_ptr_scrn;
+    unsigned char *u_ptr_scrn;
+    unsigned char *v_ptr_scrn;
+
+
+} DXV_YUV_BUFFER_CONFIG;
+
+
+typedef void ((*vp8blit_func)(unsigned char *, int, YUV_BUFFER_CONFIG *));
+
+/* define an x_image structure based on the core x_image struct */
+typedef struct t_ximage_codec
+{
+    DXV_YUV_BUFFER_CONFIG frame_buffer;
+    VP8D_COMP *my_pbi;
+    VP8_COMMON *common;
+    int owned;
+    int decompressed_once;
+
+    int sizeof_pixel;
+    vp8blit_func blitter;
+
+    unsigned int ppl_tag;
+    unsigned int bd_tag;
+    unsigned int *supported_output_format_list;
+
+    int cpu_free;
+    int postproc;
+    int add_noise;
+    int deinterlace;
+
+    int post_proc2time;
+    int post_proc4time;
+
+    int hs;
+    int hr;
+    int vs;
+    int vr;
+    YV12_BUFFER_CONFIG this_buffer;
+    YV12_BUFFER_CONFIG scaled_buffer;
+    YV12_BUFFER_CONFIG *passed_in_buffer;
+
+    int avgq;
+    int ppcount;
+
+
+} VP8_XIMAGE, *VP8_XIMAGE_HANDLE;
+
+
+/****************************************************************************
+*  Modul Statics
+****************************************************************************/
+static unsigned int g_vp8_preferred_output_format_list[] =
+{
+    VPXDXV_YUY2,
+    VPXDXV_UYVY,
+    VPXDXV_RGB8888,
+    VPXDXV_RGB888,
+    VPXDXV_RGB555,
+    VPXDXV_RGB565,
+    VPXDXV_YV12,
+    VPXDXV_I420,
+
+//    VPXDXV_YV12,
+//    VPXDXV_YUY2,
+//    VPXDXV_RGB565,
+//    VPXDXV_UYVY,
+    0
+};
+
+/****************************************************************************
+*  Forward declarationss
+****************************************************************************/
+void onyx_set_parameter(XIMAGE_HANDLE src, int Command, unsigned int Parameter);
+
+static int onyx_get_output_format(XIMAGE_HANDLE src, unsigned int *bd_tag);
+static int onyx_set_output_format(XIMAGE_HANDLE src, unsigned int bd_tag);
+
+static int vpx_get_size_of_pixel(unsigned int bd);
+
+/****************************************************************************
+*  Imports
+****************************************************************************/
+
+#define __Clamp255(x)   (unsigned char) ( (x) < 0 ? 0 : ( (x) <= 255 ? (x) : 255 ) )
+
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+void
+convert_yv12_buffer_types(YV12_BUFFER_CONFIG *source, DXV_YUV_BUFFER_CONFIG *dest)
+{
+    dest->y_buffer = (char *)source->y_buffer;
+    dest->u_buffer = (char *)source->u_buffer;
+    dest->v_buffer = (char *)source->v_buffer;
+    dest->y_width  = source->y_width;
+    dest->y_height = source->y_height;
+    dest->y_stride = source->y_stride;
+    dest->uv_width  = source->uv_width;
+    dest->uv_height = source->uv_height;
+    dest->uv_stride = source->uv_stride;
+}
+
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+
+
+int onyx_blit
+(
+    XIMAGE_HANDLE src,
+    VSCREEN_HANDLE v_screen,
+    DXV_YUV_BUFFER_CONFIG *frame_buffer,
+    int x,
+    int y
+)
+{
+    VP8_XIMAGE_HANDLE tab = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
+    VP8D_COMP *pbi;
+    VP8_COMMON *common = tab->common;
+    pbi = tab->my_pbi;
+
+    if (v_screen) /* if there is a v_screen, blit to it */
+    {
+        unsigned char *ptr_scrn;
+        int this_pitch, vs_height, vs_width;
+        unsigned int start_tick, stop_tick;
+
+        vpxdxv_get_vscreen_attributes(v_screen, (void **)&ptr_scrn,  &vs_width, &vs_height, &this_pitch);
+
+        if (ptr_scrn)
+        {
+            int w, h;
+
+            int p_size;
+            int view_x, view_y, view_w;
+            int hs, hr, vs, vr;
+            int neww, newh;
+            int cw, ch;
+            int microseconds_available = (int)(1000000 / 30);
+
+            microseconds_available = microseconds_available * tab->cpu_free / 100;
+
+            if (pbi)
+            {
+                microseconds_available -= pbi->decode_microseconds;
+
+                if (tab->cpu_free == 0)
+                    microseconds_available = INT_MAX;
+
+                if (tab->post_proc2time == 0)
+                    tab->post_proc2time = pbi->decode_microseconds * 1 / 2;
+
+                if (tab->post_proc4time == 0)
+                    tab->post_proc4time = pbi->decode_microseconds;
+            }
+
+
+            if (tab->ppcount == 0)
+            {
+                tab->post_proc2time = 0;
+                tab->post_proc4time = 0;
+                tab->ppcount = 64;
+            }
+            else
+            {
+                tab->ppcount --;
+            }
+
+            vpxdxv_get_vscreen_view(v_screen, &view_x, &view_y, &view_w, NULL);
+
+            Scale2Ratio(common->horiz_scale, &hr, &hs);
+            Scale2Ratio(common->vert_scale, &vr, &vs);
+
+            if (tab->postproc && tab->passed_in_buffer == 0)
+            {
+                int show_text = 0;
+
+                unsigned char message[512];
+
+                int pp = tab->postproc;
+                int q = (tab->avgq + 4) / 8;
+                int noise = 0;
+
+                vp8_clear_system_state();
+
+                if (pp >= 1000)
+                {
+                    pp -= 1000;
+                    noise = pp / 100;
+                    pp = pp - noise * 100;
+                }
+
+                if (pp >= 300)
+                {
+                    pp -= 300;
+                    show_text = 3;
+                }
+                else if (pp >= 200)
+                {
+                    pp -= 200;
+                    show_text = 2;
+                }
+                else if (pp >= 100)
+                {
+                    pp -= 100;
+                    show_text = 1;
+                }
+
+                if (pbi && (pbi->mb.segmentation_enabled & SEGMENT_PF) && tab->deinterlace)
+                {
+                    de_interlace(common->frame_to_show->y_buffer, common->post_proc_buffer.y_buffer,
+                                 common->post_proc_buffer.y_width, common->post_proc_buffer.y_height,
+                                 common->post_proc_buffer.y_stride);
+
+                    de_interlace(common->frame_to_show->u_buffer, common->post_proc_buffer.u_buffer,
+                                 common->post_proc_buffer.uv_width, common->post_proc_buffer.uv_height,
+                                 common->post_proc_buffer.uv_stride);
+                    de_interlace(common->frame_to_show->v_buffer, common->post_proc_buffer.v_buffer,
+                                 common->post_proc_buffer.uv_width, common->post_proc_buffer.uv_height,
+                                 common->post_proc_buffer.uv_stride);
+                }
+                else
+                {
+                    if (pp >= 10 && pp <= 20)
+                    {
+                        q = q + (pp - 15) * 10;
+
+                        if (q < 0)
+                            q = 0;
+                    }
+
+                    start_tick = vp8_get_high_res_timer_tick();
+
+                    if (pp > 3 && tab->post_proc4time < microseconds_available)
+                    {
+                        vp8_deblock_and_de_macro_block(common->frame_to_show, &common->post_proc_buffer, q, 1, 0);
+
+                        stop_tick = vp8_get_high_res_timer_tick();
+
+                        if (pbi)
+                            tab->post_proc4time = vp8_get_time_in_micro_sec(start_tick, stop_tick);
+                    }
+
+                    else if (pp > 0 && tab->post_proc2time < microseconds_available)
+                    {
+                        vp8_deblock(common->frame_to_show, &common->post_proc_buffer, q , 1,  0);
+                        stop_tick = vp8_get_high_res_timer_tick();
+
+                        if (pbi)
+                            tab->post_proc2time = vp8_get_time_in_micro_sec(start_tick, stop_tick);
+                    }
+                    else
+                    {
+                        vp8_yv12_copy_frame(common->frame_to_show, &common->post_proc_buffer);
+                    }
+
+                }
+
+                vp8_clear_system_state();
+
+                if (tab->add_noise == 1)
+                {
+
+                    vp8_plane_add_noise(common->post_proc_buffer.y_buffer,
+                                        common->post_proc_buffer.y_width, common->post_proc_buffer.y_height,
+                                        common->post_proc_buffer.y_stride, 63 - q, noise);
+                }
+
+
+                if (show_text == 1)
+                {
+#ifdef PACKET_TESTING
+                    {
+                        VP8_HEADER *oh2 = (VP8_HEADER *) pbi->Source;
+                        sprintf(message, "%8d %d%d%d%d%d size:%d\n",
+                        oh2->frame_number ,
+                        oh2->update_gold  ,
+                        oh2->update_last  ,
+                        oh2->uses_gold    ,
+                        oh2->uses_last    ,
+                        oh2->type,
+                        vpxdxv_get_ximage_csize(src));
+                    }
+#else
+                    sprintf(message, "F:%1ldG:%1ldQ:%3ldF:%3ld,%3ldP:%d_s:%6ld,N:%d,",
+                            (common->frame_type == KEY_FRAME),
+                            common->refresh_golden_frame,
+                            common->base_qindex,
+                            common->filter_level,
+                            q,
+                            tab->postproc,
+                            vpxdxv_get_ximage_csize(src), noise);
+#endif
+
+                    vp8_blit_text(message, common->post_proc_buffer.y_buffer, common->post_proc_buffer.y_stride);
+
+                }
+                else if (show_text == 2)
+                {
+                    int i, j;
+                    unsigned char *y_ptr;
+                    YV12_BUFFER_CONFIG *post = &common->post_proc_buffer;
+                    int mb_rows = post->y_height >> 4;
+                    int mb_cols = post->y_width  >> 4;
+                    int mb_index = 0;
+                    MODE_INFO *mi = common->mi;
+
+                    y_ptr = post->y_buffer + 4 * post->y_stride + 4;
+
+                    // vp8_filter each macro block
+                    for (i = 0; i < mb_rows; i++)
+                    {
+                        for (j = 0; j < mb_cols; j++)
+                        {
+                            char zz[4];
+
+                            if (pp == 4)
+                                sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
+                            else
+                                sprintf(zz, "%c", mi[mb_index].mbmi.ref_frame + 'a');
+
+                            vp8_blit_text(zz, y_ptr, post->y_stride);
+                            mb_index ++;
+                            y_ptr += 16;
+                        }
+
+                        mb_index ++; //border
+                        y_ptr += post->y_stride  * 16 - post->y_width;
+
+                    }
+                }
+                else if (show_text == 3)
+                {
+                    int i, j;
+                    unsigned char *y_ptr;
+                    YV12_BUFFER_CONFIG *post = &common->post_proc_buffer;
+                    int mb_rows = post->y_height >> 4;
+                    int mb_cols = post->y_width  >> 4;
+                    int mb_index = 0;
+                    MODE_INFO *mi = common->mi;
+
+                    y_ptr = post->y_buffer + 4 * post->y_stride + 4;
+
+                    // vp8_filter each macro block
+                    for (i = 0; i < mb_rows; i++)
+                    {
+                        for (j = 0; j < mb_cols; j++)
+                        {
+                            char zz[4];
+
+                            if (j == 0)
+                                sprintf(zz, "%c", '0' + i % 10);
+                            else
+                                sprintf(zz, "%c", '0' + j % 10);
+
+                            vp8_blit_text(zz, y_ptr, post->y_stride);
+                            mb_index ++;
+                            y_ptr += 16;
+                        }
+
+                        y_ptr += post->y_stride  * 16 - post->y_width;
+
+                    }
+                }
+
+                vpx_memcpy(&tab->this_buffer, &common->post_proc_buffer, sizeof(YV12_BUFFER_CONFIG));
+            }
+            else
+            {
+                vpx_memcpy(&tab->this_buffer, common->frame_to_show, sizeof(YV12_BUFFER_CONFIG));
+            }
+
+
+            /* get a frame pointer to the scaled and postprocessed reconstructed buffer */
+            if (tab->passed_in_buffer == 0)
+            {
+                if (common->horiz_scale != NORMAL || common->vert_scale != NORMAL)
+                {
+                    neww = hs * tab->this_buffer.y_width / hr;
+                    newh = vs * tab->this_buffer.y_height / vr;
+
+                    neww += neww & 1;
+
+                    if (tab->hs != hs || tab->hr != hr || tab->vs != vs || tab->vr != vr)
+                    {
+                        vp8_yv12_alloc_frame_buffer(&tab->scaled_buffer, neww, newh , 8);
+                    }
+
+                    vp8_yv12_scale_or_center(&tab->this_buffer,
+                                             &tab->scaled_buffer,
+                                             neww, newh, SCALE_TO_FIT, hs, hr, vs, vr);
+
+                    convert_yv12_buffer_types(&tab->scaled_buffer, frame_buffer);
+
+                    cw = hs * common->Width / hr;
+                    ch = vs * common->Height / vr;
+
+                }
+                else
+                {
+                    convert_yv12_buffer_types(&tab->this_buffer, frame_buffer);
+
+                    cw = common->Width;
+                    ch = common->Height;
+                }
+            }
+            else
+            {
+                convert_yv12_buffer_types(tab->passed_in_buffer, frame_buffer);
+                cw = common->Width;
+                ch = common->Height;
+                tab->passed_in_buffer = 0;
+            }
+
+            frame_buffer->y_width = cw;
+            frame_buffer->y_height = ch;
+            frame_buffer->uv_width = cw / 2;
+            frame_buffer->uv_height = ch / 2;
+
+            p_size = vpx_get_size_of_pixel(tab->bd_tag);
+
+            /* remember to offset if requested */
+            y += view_y;
+            x += view_x ;
+
+            /* for planar destinations */
+            w = view_w;
+            h = vs_height;
+
+            if (w < frame_buffer->y_width)
+            {
+                frame_buffer->y_width = w;
+                frame_buffer->uv_width = (w + 1) / 2;
+            }
+
+            if (h < frame_buffer->y_height)
+            {
+                frame_buffer->y_height = h;
+                frame_buffer->uv_height = (h + 1) / 2;
+            }
+
+            if (frame_buffer->y_width < view_w)
+                x += (view_w - frame_buffer->y_width) / 2;
+
+            if (x & 1)
+                x -= 1;
+
+            if (frame_buffer->y_height < vs_height)
+                y += (vs_height - frame_buffer->y_height) / 2;
+
+
+            ptr_scrn += (x * p_size) + (y * this_pitch);
+
+            frame_buffer->y_stride *= -1;
+            frame_buffer->uv_stride *= -1;
+
+            if (tab->bd_tag == VPXDXV_YV12 || tab->bd_tag == VPXDXV_I420)
+            {
+                if (this_pitch < 0)
+                {
+                    frame_buffer->uv_start = (char *)(ptr_scrn + abs(this_pitch) + abs(this_pitch) * h / 4 + this_pitch / 2);
+                    frame_buffer->uv_dst_area = abs((this_pitch * h) / 4);
+                    frame_buffer->uv_used_area = 0;
+                }
+                else
+                {
+                    frame_buffer->uv_start = (char *)(ptr_scrn + (this_pitch * h));
+                    frame_buffer->uv_dst_area = (((this_pitch + 1) / 2) * ((h + 1) / 2));
+                    frame_buffer->uv_used_area = (((this_pitch + 1) / 2) * frame_buffer->uv_height);
+                }
+            }
+
+            if ((pbi->mb.segmentation_enabled & SEGMENT_PF) && (tab->bd_tag != VPXDXV_YV12 && tab->bd_tag != VPXDXV_I420))
+            {
+                int ypitch = frame_buffer->y_stride;
+                int uvpitch = frame_buffer->uv_stride;
+
+                frame_buffer->y_stride <<= 1;
+                frame_buffer->y_height >>= 1;
+                frame_buffer->uv_stride <<= 1;
+                frame_buffer->uv_height >>= 1;
+
+                ptr_scrn += this_pitch;
+                frame_buffer->y_buffer -= ypitch;
+                frame_buffer->u_buffer -= uvpitch;
+                frame_buffer->v_buffer -= uvpitch;
+                tab->blitter(ptr_scrn, 2 * this_pitch, (YUV_BUFFER_CONFIG *)(&tab->frame_buffer));
+
+                ptr_scrn -= this_pitch;
+                frame_buffer->y_buffer += ypitch;
+                frame_buffer->u_buffer += uvpitch;
+                frame_buffer->v_buffer += uvpitch;
+                tab->blitter(ptr_scrn, 2 * this_pitch, (YUV_BUFFER_CONFIG *)(&tab->frame_buffer));
+
+            }
+            else
+            {
+                /* blit the screen */
+                tab->blitter(ptr_scrn, this_pitch, (YUV_BUFFER_CONFIG *)(&tab->frame_buffer));
+                vpx_log("Decoder: Frame shown \n");
+            }
+
+        }
+        else
+            vpx_log("Decoder: Frame not shown scrn pointer 0\n");
+    }
+    else
+        vpx_log("Decoder: Frame not shown vscreen 0\n");
+
+    return DXV_OK;
+}
+/****************************************************************************
+ *
+ *  ROUTINE       :     onyx_decompress
+ *
+ *  INPUTS        :     None
+ *
+ *  OUTPUTS       :     None
+ *
+ *  RETURNS       :     None.
+ *
+ *  FUNCTION      :
+ *
+ *  SPECIAL NOTES :
+ *
+ ****************************************************************************/
+static
+int onyx_decompress(XIMAGE_HANDLE src, VSCREEN_HANDLE v_screen)
+{
+    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
+    unsigned char *c_addr;
+    unsigned int c_size;
+    int w, h, x, y;
+    int vp8_rv;
+
+    c_addr = vpxdxv_get_ximage_cdata_addr(src);
+    c_size = vpxdxv_get_ximage_csize(src);
+    vpxdxv_get_ximage_xywh(src, &x, &y, &w, &h);
+
+    // if we have a compressed frame decompress it ( otherwise we'll just redo
+    // the scaling and postprocessing from the last frame )
+    if (c_addr)
+    {
+        if (c_size != 0)
+        {
+            int flags;
+            int ret_val;
+
+            int f;
+
+            // decode the frame
+            ret_val = vp8d_decompress_frame((VP8D_PTR) this_algorithm_base->my_pbi,
+                                            c_size,
+                                            (char *) c_addr,
+                                            &this_algorithm_base->this_buffer,
+                                            &flags);
+
+
+            f = this_algorithm_base->my_pbi->common.filter_level * 10 / 6;
+
+            if (this_algorithm_base->my_pbi->common.frame_type == KEY_FRAME)
+                this_algorithm_base->avgq = 8 * f;
+            else
+                this_algorithm_base->avgq = this_algorithm_base->avgq * 7 / 8 + f;
+
+
+
+            if (ret_val != 0)
+            {
+                if (ret_val == -1)
+                    return DXV_VERSION_CONFLICT;
+                else
+                    return DXV_BAD_DATA;
+            }
+
+        }
+    }
+
+
+    vp8_rv = onyx_blit(src, v_screen, &this_algorithm_base->frame_buffer, x, y);
+
+
+    return vp8_rv;
+}
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+static
+int vp8_ximagedestroy(XIMAGE_HANDLE src)
+{
+    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
+
+    if (this_algorithm_base)
+    {
+
+        vp8_yv12_de_alloc_frame_buffer(&this_algorithm_base->scaled_buffer);
+
+        /* safety check in case stopdecode was not called */
+        if (this_algorithm_base->owned)
+            vp8dx_remove_decompressor((VP8D_PTR)(this_algorithm_base->my_pbi));
+
+        duck_free(this_algorithm_base);
+    }
+
+    return DXV_OK;
+}
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+static int
+onyx_get_post_proc(XIMAGE_HANDLE src, unsigned int *ppl)
+{
+    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
+
+    if (this_algorithm_base)
+    {
+        *ppl = this_algorithm_base->ppl_tag;
+
+        return DXV_OK;
+    }
+
+    return DXV_NULL_BASE;
+}
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+static int
+onyx_set_post_proc(XIMAGE_HANDLE src, unsigned int ppl)
+{
+    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
+
+    if (this_algorithm_base)
+    {
+        this_algorithm_base->ppl_tag = ppl;
+
+        return DXV_OK;
+    }
+
+    return DXV_NULL_BASE;
+}
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+static
+int vp8_ximagestop_decode(XIMAGE_HANDLE src)
+{
+    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
+
+    if (this_algorithm_base)
+    {
+
+        vp8_yv12_de_alloc_frame_buffer(&this_algorithm_base->scaled_buffer);
+
+        if (this_algorithm_base->owned)
+            vp8dx_remove_decompressor((VP8D_PTR)(this_algorithm_base->my_pbi));
+
+        this_algorithm_base->owned = 0;
+    }
+
+    return DXV_OK;
+}
+
+
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+static
+int vp8_ximagestart_decode
+(
+    XIMAGE_HANDLE src
+)
+{
+    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
+    XIMAGE_INFO_PTR xinfo = vpxdxv_get_ximage_info(src);
+    VP8D_CONFIG ocf;
+
+    if (xinfo)
+    {
+        ocf.Width = xinfo->width;
+        ocf.Height = xinfo->height;
+    }
+
+    if (this_algorithm_base->common == 0)
+    {
+        this_algorithm_base->my_pbi = (VP8D_COMP *) vp8dx_create_decompressor(&ocf);
+        this_algorithm_base->owned = 1;
+        this_algorithm_base->common = &this_algorithm_base->my_pbi->common;
+        this_algorithm_base->avgq = 0;
+
+    }
+
+    this_algorithm_base->passed_in_buffer = 0;
+    this_algorithm_base->post_proc2time = 0;
+    this_algorithm_base->post_proc4time = 0;
+    this_algorithm_base->ppcount = 64;
+
+    return DXV_OK;
+}
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+static
+DXV_HANDLE vp8_ximagecreate(XIMAGE_HANDLE src)
+{
+    VP8_XIMAGE_HANDLE this_algorithm_base;
+
+    /* create a new algorithm base container */
+    this_algorithm_base = (VP8_XIMAGE_HANDLE)duck_calloc(1, sizeof(VP8_XIMAGE), DMEM_GENERAL);
+
+    if (this_algorithm_base == NULL)
+        return NULL;
+
+    vp8_scale_machine_specific_config();
+
+    vpxdxv_register_ximage_start_decode(src, vp8_ximagestart_decode);
+
+    vpxdxv_register_ximage_stop_decode(src, vp8_ximagestop_decode);
+
+    vpxdxv_register_ximage_destroy(src, vp8_ximagedestroy);
+
+    vpxdxv_register_ximage_dx(src, onyx_decompress);
+
+    vpxdxv_register_ximage_set_parameter(src, onyx_set_parameter);
+
+    vpxdxv_register_ximage_output_format_func(src,
+            onyx_get_output_format,
+            onyx_set_output_format);
+
+    vpxdxv_register_ximage_post_proc_level_func(src,
+            onyx_get_post_proc,
+            onyx_set_post_proc);
+
+    return (DXV_HANDLE)this_algorithm_base;
+}
+
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+
+static int store_output_list(unsigned int supported, int count,
+                             unsigned int *outlist)
+{
+    int i = 0, j = 0,
+        ret = DXV_OK;
+
+    while (i < count)
+    {
+        while (supported && !(supported & 0x01))
+        {
+            supported >>= 1;
+            ++j;
+        }
+
+        *(outlist + i) = g_vp8_preferred_output_format_list[j];
+        ++i;
+        ++j;
+        supported >>= 1;
+    }
+
+
+    return ret;
+}
+
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+static int onyx_get_output_list(XIMAGE_INFO_PTR xinfo, unsigned int *outlist,
+                                unsigned int *size)
+{
+    int i,
+        ret = DXV_INVALID_REQUEST;
+    unsigned int supported = 0,
+                 count = 0;
+    (void)xinfo;
+
+    if (size)
+    {
+        for (i = 0; i < sizeof(g_vp8_preferred_output_format_list) / sizeof(unsigned int) && i < 32; ++i)
+        {
+            if (vpx_get_blitter(g_vp8_preferred_output_format_list[i]) != (void *)0xffffffff)
+            {
+                supported |= (1 << i);
+                ++count;
+            }
+        }
+
+        if (outlist)
+        {
+            if (count && ((count + 1) == (*size / sizeof(int))))
+                ret = store_output_list(supported, count, outlist);
+            else
+                *outlist = 0;
+        }
+        else
+        {
+            *size = (count + 1) * sizeof(int);
+            ret = DXV_OK;
+        }
+    }
+
+    return ret;
+}
+
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+int onyx_init(void)
+{
+    int vp8_rv;
+
+    /* register VPX blitters based on cpu */
+    vpx_set_blit();
+
+    vp8_rv = vpxdxv_register_ximage(vp8_ximagecreate, onyx_get_output_list, VP8_FOURCC);
+    return vp8_rv;
+
+    return DXV_OK;
+}
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+int onyx_exit(void)
+{
+
+    vpxdxv_un_register_ximage(VP8_FOURCC);
+
+    return DXV_OK;
+}
+/****************************************************************************
+ *
+ *  ROUTINE       :  onyx_set_parameter
+ *
+ *  INPUTS        :  XIMAGE_HANDLE src   :
+ *                   int Command             :
+ *                   unsigned long Parameter :
+ *
+ *  OUTPUTS       :  None.
+ *
+ *  RETURNS       :  void
+ *
+ *  FUNCTION      :
+ *
+ *
+ *  SPECIAL NOTES :  None.
+ *
+ ****************************************************************************/
+void onyx_set_parameter(XIMAGE_HANDLE src, int Command, unsigned int Parameter)
+{
+    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
+
+    switch (Command)
+    {
+    case PBC_SET_CPUFREE:
+        this_algorithm_base->cpu_free  = Parameter;
+        break;
+    case PBC_SET_POSTPROC:
+        this_algorithm_base->postproc = Parameter;
+        break;
+
+    case PBC_SET_BLITBUFF:
+        this_algorithm_base->passed_in_buffer = (YV12_BUFFER_CONFIG *) Parameter;
+        break;
+
+    case PBC_SET_REFERENCEFRAME:
+    {
+        VP8_XIMAGE_HANDLE tab = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
+        VP8D_COMP *pbi;
+        pbi = tab->my_pbi;
+        vp8_yv12_copy_frame((YV12_BUFFER_CONFIG *) Parameter, &pbi->common.last_frame);
+    }
+    break;
+
+    case PBC_SET_COMMON:
+
+        if (Parameter)
+        {
+            this_algorithm_base->common = (VP8_COMMON *)Parameter;
+        }
+
+        break;
+    case PBC_SET_ADDNOISE:
+        this_algorithm_base->add_noise = Parameter;
+        break;
+    case PBC_SET_DEINTERLACEMODE:
+        this_algorithm_base->deinterlace = Parameter;
+        break;
+
+    }
+}
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+static int
+onyx_get_output_format(XIMAGE_HANDLE src, unsigned int *format_tag)
+{
+    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
+
+    if (this_algorithm_base)
+    {
+        *format_tag = this_algorithm_base->bd_tag;
+        return DXV_OK;
+    }
+
+    return DXV_NULL_BASE;
+}
+
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+static int
+onyx_set_output_format(XIMAGE_HANDLE src, unsigned int bd_tag)
+{
+    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
+    int i;
+    unsigned int bd_tag_found;
+
+    if (this_algorithm_base)
+    {
+        i = 0;
+        bd_tag_found = 0;
+
+        while (g_vp8_preferred_output_format_list[i] != 0)
+        {
+            if (g_vp8_preferred_output_format_list[i] == bd_tag)
+            {
+                bd_tag_found = 1;
+                break;
+            }
+
+            i++;
+        }
+
+        if (bd_tag_found)
+        {
+            this_algorithm_base->blitter = (vp8blit_func)vpx_get_blitter(bd_tag);
+            this_algorithm_base->bd_tag = bd_tag;
+            return DXV_OK;
+        }
+
+        return DXV_INVALID_BLIT;
+    }
+
+    return DXV_NULL_BASE;
+}
+
+/*
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*/
+int
+vpx_get_size_of_pixel(unsigned int bd)
+{
+    int vp8_rv;
+
+    switch (bd)
+    {
+    case VPXDXV_YV12:
+    case VPXDXV_I420:
+        vp8_rv = 1;
+        break;
+
+#ifdef _ENABLE_SPLIT_PIXEL_
+    case VPXDXV_SPLIT565:
+#endif
+    case VPXDXV_RGB555:
+    case VPXDXV_RGB565:
+    case VPXDXV_YUY2:
+    case VPXDXV_UYVY:
+    case VPXDXV_YVYU:
+        vp8_rv = 2;
+        break;
+
+    case VPXDXV_RGB888:
+        vp8_rv = 3;
+        break;
+
+    case VPXDXV_RGB8888:
+        vp8_rv = 4;
+        break;
+
+    default:
+        vp8_rv = -1;
+        break;
+    }
+
+    return vp8_rv;
+}
diff --git a/vp8/decoder/x86/x86_dsystemdependent.c b/vp8/decoder/x86/x86_dsystemdependent.c
new file mode 100644
index 0000000..6d7cc36
--- /dev/null
+++ b/vp8/decoder/x86/x86_dsystemdependent.c
@@ -0,0 +1,51 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "vpx_ports/x86.h"
+#include "onyxd_int.h"
+
+
+#if HAVE_MMX
+void vp8_dequantize_b_impl_mmx(short *sq, short *dq, short *q);
+
+void vp8_dequantize_b_mmx(BLOCKD *d)
+{
+    short *sq = (short *) d->qcoeff;
+    short *dq = (short *) d->dqcoeff;
+    short *q = (short *) d->dequant;
+    vp8_dequantize_b_impl_mmx(sq, dq, q);
+}
+#endif
+
+void vp8_arch_x86_decode_init(VP8D_COMP *pbi)
+{
+    int flags = x86_simd_caps();
+
+    /* Note:
+     *
+     * This platform can be built without runtime CPU detection as well. If
+     * you modify any of the function mappings present in this file, be sure
+     * to also update them in static mapings (<arch>/filename_<arch>.h)
+     */
+#if CONFIG_RUNTIME_CPU_DETECT
+    /* Override default functions with fastest ones for this CPU. */
+#if HAVE_MMX
+
+    if (flags & HAS_MMX)
+    {
+        pbi->dequant.block   = vp8_dequantize_b_mmx;
+        pbi->dequant.idct    = vp8_dequant_idct_mmx;
+        pbi->dequant.idct_dc = vp8_dequant_dc_idct_mmx;
+    }
+
+#endif
+#endif
+}
diff --git a/vp8/decoder/xprintf.c b/vp8/decoder/xprintf.c
new file mode 100644
index 0000000..cb2221c
--- /dev/null
+++ b/vp8/decoder/xprintf.c
@@ -0,0 +1,163 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/****************************************************************************
+*
+*   Module Title :     xprintf.cpp
+*
+*   Description  :     Display a printf style message on the current video frame.
+*
+****************************************************************************/
+
+/****************************************************************************
+*  Header Files
+****************************************************************************/
+
+#include <stdio.h>
+#include <stdarg.h>
+#ifdef _WIN32_WCE
+#include <windows.h>
+#endif
+#include "xprintf.h"
+
+/****************************************************************************
+ *
+ *  ROUTINE       : xprintf
+ *
+ *  INPUTS        : const PB_INSTANCE *ppbi : Pointer to decoder instance.
+ *                  long n_pixel             : Offset into buffer to write text.
+ *                  const char *format      : Format string for print.
+ *                  ...                     : Variable length argument list.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : int: Size (in bytes) of the formatted text.
+ *
+ *  FUNCTION      : Display a printf style message on the current video frame.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+int onyx_xprintf(unsigned char *ppbuffer, long n_pixel, long n_size, long n_stride, const char *format, ...)
+{
+    BOOL b_rc;
+    va_list arglist;
+    HFONT hfont, hfonto;
+
+    int rc = 0;
+    char sz_formatted[256] = "";
+    unsigned char *p_dest = &ppbuffer[n_pixel];
+
+#ifdef _WIN32_WCE
+    //  Set up temporary bitmap
+    HDC hdc_memory   = NULL;
+    HBITMAP hbm_temp = NULL;
+    HBITMAP hbm_orig = NULL;
+
+    RECT rect;
+
+    //  Copy bitmap to video frame
+    long x;
+    long y;
+
+    //  Format text
+    va_start(arglist, format);
+    _vsnprintf(sz_formatted, sizeof(sz_formatted), format, arglist);
+    va_end(arglist);
+
+    rect.left   = 0;
+    rect.top    = 0;
+    rect.right  = 8 * strlen(sz_formatted);
+    rect.bottom = 8;
+
+    hdc_memory = create_compatible_dc(NULL);
+
+    if (hdc_memory == NULL)
+        goto Exit;
+
+    hbm_temp = create_bitmap(rect.right, rect.bottom, 1, 1, NULL);
+
+    if (hbm_temp == NULL)
+        goto Exit;
+
+    hbm_orig = (HBITMAP)(select_object(hdc_memory, hbm_temp));
+
+    if (!hbm_orig)
+        goto Exit;
+
+    //  Write text into bitmap
+    //  font?
+    hfont = create_font(8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VARIABLE_PITCH | FF_SWISS, "");
+
+    if (hfont == NULL)
+        goto Exit;
+
+    hfonto = (HFONT)(select_object(hdc_memory, hbm_temp));
+
+    if (!hfonto)
+        goto Exit;
+
+    select_object(hdc_memory, hfont);
+    set_text_color(hdc_memory, 1);
+    set_bk_color(hdc_memory, 0);
+    set_bk_mode(hdc_memory, TRANSPARENT);
+
+    b_rc = bit_blt(hdc_memory, rect.left, rect.top, rect.right, rect.bottom, hdc_memory, rect.left, rect.top, BLACKNESS);
+
+    if (!b_rc)
+        goto Exit;
+
+    b_rc = ext_text_out(hdc_memory, 0, 0, ETO_CLIPPED, &rect, sz_formatted, strlen(sz_formatted), NULL);
+
+    if (!b_rc)
+        goto Exit;
+
+    for (y = rect.top; y < rect.bottom; ++y)
+    {
+        for (x = rect.left; x < rect.right; ++x)
+        {
+            if (get_pixel(hdc_memory, x, rect.bottom - 1 - y))
+                p_dest[x] = 255;
+        }
+
+        p_dest += n_stride;
+    }
+
+    rc = strlen(sz_formatted);
+
+Exit:
+
+    if (hbm_temp != NULL)
+    {
+        if (hbm_orig != NULL)
+        {
+            select_object(hdc_memory, hbm_orig);
+        }
+
+        delete_object(hbm_temp);
+    }
+
+    if (hfont != NULL)
+    {
+        if (hfonto != NULL)
+            select_object(hdc_memory, hfonto);
+
+        delete_object(hfont);
+    }
+
+    if (hdc_memory != NULL)
+        delete_dc(hdc_memory);
+
+    hdc_memory = 0;
+
+#endif
+
+    return rc;
+}
diff --git a/vp8/decoder/xprintf.h b/vp8/decoder/xprintf.h
new file mode 100644
index 0000000..2f175e9
--- /dev/null
+++ b/vp8/decoder/xprintf.h
@@ -0,0 +1,32 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/****************************************************************************
+*
+*   Module Title :     xprintf.h
+*
+*   Description  :     Debug print interface header file.
+*
+****************************************************************************/
+#ifndef __INC_XPRINTF_H
+#define __INC_XPRINTF_H
+
+/****************************************************************************
+*  Header Files
+****************************************************************************/
+
+/****************************************************************************
+*  Functions
+****************************************************************************/
+
+// Display a printf style message on the current video frame
+extern int onyx_xprintf(unsigned char *ppbuffer, long n_pixel, long n_size, long n_stride, const char *format, ...);
+
+#endif
diff --git a/vp8/encoder/arm/armv6/walsh_v6.asm b/vp8/encoder/arm/armv6/walsh_v6.asm
new file mode 100644
index 0000000..608c9ae
--- /dev/null
+++ b/vp8/encoder/arm/armv6/walsh_v6.asm
@@ -0,0 +1,144 @@
+;
+;  Copyright (c) 2010 The VP8 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 |vp8_short_walsh4x4_armv6|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY  ; name this block of code
+
+;short vp8_short_walsh4x4_armv6(short *input, short *output, int pitch)
+|vp8_short_walsh4x4_armv6| PROC
+
+    stmdb       sp!, {r4 - r11, lr}
+
+    mov         r12, r2              ; ugh. not clean
+    ldr         r2, [r0]             ; [1  |  0]
+    ldr         r3, [r0, #4]         ; [3  |  2]
+    ldr         r4, [r0, r12]!       ; [5  |  4]
+    ldr         r5, [r0, #4]         ; [7  |  6]
+    ldr         r6, [r0, r12]!       ; [9  |  8]
+    ldr         r7, [r0, #4]         ; [11 | 10]
+    ldr         r8, [r0, r12]!       ; [13 | 12]
+    ldr         r9, [r0, #4]         ; [15 | 14]
+
+    qsubaddx    r10, r2, r3          ; [c1|a1] [1-2   |   0+3]
+    qaddsubx    r11, r2, r3          ; [b1|d1] [1+2   |   0-3]
+    qsubaddx    r12, r4, r5          ; [c1|a1] [5-6   |   4+7]
+    qaddsubx    lr, r4, r5           ; [b1|d1] [5+6   |   4-7]
+
+    qaddsubx    r2, r10, r11         ; [1 | 2] [c1+d1 | a1-b1]
+    qaddsubx    r3, r11, r10         ; [0 | 3] [b1+a1 | d1-c1]
+    qaddsubx    r4, r12, lr          ; [5 | 6] [c1+d1 | a1-b1]
+    qaddsubx    r5, lr, r12          ; [4 | 7] [b1+a1 | d1-c1]
+
+    qsubaddx    r10, r6, r7          ; [c1|a1] [9-10  |  8+11]
+    qaddsubx    r11, r6, r7          ; [b1|d1] [9+10  |  8-11]
+    qsubaddx    r12, r8, r9          ; [c1|a1] [13-14 | 12+15]
+    qaddsubx    lr, r8, r9           ; [b1|d1] [13+14 | 12-15]
+
+    qaddsubx    r6, r10, r11         ; [9 |10] [c1+d1 | a1-b1]
+    qaddsubx    r7, r11, r10         ; [8 |11] [b1+a1 | d1-c1]
+    qaddsubx    r8, r12, lr          ; [13|14] [c1+d1 | a1-b1]
+    qaddsubx    r9, lr, r12          ; [12|15] [b1+a1 | d1-c1]
+
+    ; first transform complete
+
+    qadd16      r10, r3, r9          ; a1 [0+12  |  3+15]
+    qadd16      r11, r5, r7          ; b1 [4+8   |  7+11]
+    qsub16      r12, r5, r7          ; c1 [4-8   |  7-11]
+    qsub16      lr, r3, r9           ; d1 [0-12  |  3-15]
+
+    qadd16      r3, r10, r11         ; a2 [a1+b1] [0 | 3]
+    qadd16      r5, r12, lr          ; b2 [c1+d1] [4 | 7]
+    qsub16      r7, r10, r11         ; c2 [a1-b1] [8 |11]
+    qsub16      r9, lr, r12          ; d2 [d1-c1] [12|15]
+
+    qadd16      r10, r2, r8          ; a1 [1+13  |  2+14]
+    qadd16      r11, r4, r6          ; b1 [5+9   |  6+10]
+    qsub16      r12, r4, r6          ; c1 [5-9   |  6-10]
+    qsub16      lr, r2, r8           ; d1 [1-13  |  2-14]
+
+    qadd16      r2, r10, r11         ; a2 [a1+b1] [1 | 2]
+    qadd16      r4, r12, lr          ; b2 [c1+d1] [5 | 6]
+    qsub16      r6, r10, r11         ; c2 [a1-b1] [9 |10]
+    qsub16      r8, lr, r12          ; d2 [d1-c1] [13|14]
+
+    ; [a-d]2 += ([a-d]2 > 0)
+
+    asrs        r10, r3, #16
+    addpl       r10, r10, #1         ; [~0]
+    asrs        r11, r2, #16
+    addpl       r11, r11, #1         ; [~1]
+    lsl         r11, r11, #15        ; [1  |  x]
+    pkhtb       r10, r11, r10, asr #1; [1  |  0]
+    str         r10, [r1], #4
+
+    lsls        r11, r2, #16
+    addpl       r11, r11, #0x10000   ; [~2]
+    lsls        r12, r3, #16
+    addpl       r12, r12, #0x10000   ; [~3]
+    asr         r12, r12, #1         ; [3  |  x]
+    pkhtb       r11, r12, r11, asr #17; [3  |  2]
+    str         r11, [r1], #4
+
+    asrs        r2, r5, #16
+    addpl       r2, r2, #1           ; [~4]
+    asrs        r3, r4, #16
+    addpl       r3, r3, #1           ; [~5]
+    lsl         r3, r3, #15          ; [5  |  x]
+    pkhtb       r2, r3, r2, asr #1   ; [5  |  4]
+    str         r2, [r1], #4
+
+    lsls        r2, r4, #16
+    addpl       r2, r2, #0x10000     ; [~6]
+    lsls        r3, r5, #16
+    addpl       r3, r3, #0x10000     ; [~7]
+    asr         r3, r3, #1           ; [7  |  x]
+    pkhtb       r2, r3, r2, asr #17  ; [7  |  6]
+    str         r2, [r1], #4
+
+    asrs        r2, r7, #16
+    addpl       r2, r2, #1           ; [~8]
+    asrs        r3, r6, #16
+    addpl       r3, r3, #1           ; [~9]
+    lsl         r3, r3, #15          ; [9  |  x]
+    pkhtb       r2, r3, r2, asr #1   ; [9  |  8]
+    str         r2, [r1], #4
+
+    lsls        r2, r6, #16
+    addpl       r2, r2, #0x10000     ; [~10]
+    lsls        r3, r7, #16
+    addpl       r3, r3, #0x10000     ; [~11]
+    asr         r3, r3, #1           ; [11 |  x]
+    pkhtb       r2, r3, r2, asr #17  ; [11 | 10]
+    str         r2, [r1], #4
+
+    asrs        r2, r9, #16
+    addpl       r2, r2, #1           ; [~12]
+    asrs        r3, r8, #16
+    addpl       r3, r3, #1           ; [~13]
+    lsl         r3, r3, #15          ; [13 |  x]
+    pkhtb       r2, r3, r2, asr #1   ; [13 | 12]
+    str         r2, [r1], #4
+
+    lsls        r2, r8, #16
+    addpl       r2, r2, #0x10000     ; [~14]
+    lsls        r3, r9, #16
+    addpl       r3, r3, #0x10000     ; [~15]
+    asr         r3, r3, #1           ; [15 |  x]
+    pkhtb       r2, r3, r2, asr #17  ; [15 | 14]
+    str         r2, [r1]
+
+    ldmia       sp!, {r4 - r11, pc}
+    ENDP        ; |vp8_short_walsh4x4_armv6|
+
+    END
diff --git a/vp8/encoder/arm/boolhuff_arm.c b/vp8/encoder/arm/boolhuff_arm.c
new file mode 100644
index 0000000..e70b3ad
--- /dev/null
+++ b/vp8/encoder/arm/boolhuff_arm.c
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "boolhuff.h"
+#include "blockd.h"
+
+const unsigned int vp8_prob_cost[256] =
+{
+    2047, 2047, 1791, 1641, 1535, 1452, 1385, 1328, 1279, 1235, 1196, 1161, 1129, 1099, 1072, 1046,
+    1023, 1000,  979,  959,  940,  922,  905,  889,  873,  858,  843,  829,  816,  803,  790,  778,
+    767,  755,  744,  733,  723,  713,  703,  693,  684,  675,  666,  657,  649,  641,  633,  625,
+    617,  609,  602,  594,  587,  580,  573,  567,  560,  553,  547,  541,  534,  528,  522,  516,
+    511,  505,  499,  494,  488,  483,  477,  472,  467,  462,  457,  452,  447,  442,  437,  433,
+    428,  424,  419,  415,  410,  406,  401,  397,  393,  389,  385,  381,  377,  373,  369,  365,
+    361,  357,  353,  349,  346,  342,  338,  335,  331,  328,  324,  321,  317,  314,  311,  307,
+    304,  301,  297,  294,  291,  288,  285,  281,  278,  275,  272,  269,  266,  263,  260,  257,
+    255,  252,  249,  246,  243,  240,  238,  235,  232,  229,  227,  224,  221,  219,  216,  214,
+    211,  208,  206,  203,  201,  198,  196,  194,  191,  189,  186,  184,  181,  179,  177,  174,
+    172,  170,  168,  165,  163,  161,  159,  156,  154,  152,  150,  148,  145,  143,  141,  139,
+    137,  135,  133,  131,  129,  127,  125,  123,  121,  119,  117,  115,  113,  111,  109,  107,
+    105,  103,  101,   99,   97,   95,   93,   92,   90,   88,   86,   84,   82,   81,   79,   77,
+    75,   73,   72,   70,   68,   66,   65,   63,   61,   60,   58,   56,   55,   53,   51,   50,
+    48,   46,   45,   43,   41,   40,   38,   37,   35,   33,   32,   30,   29,   27,   25,   24,
+    22,   21,   19,   18,   16,   15,   13,   12,   10,    9,    7,    6,    4,    3,    1,   1
+};
+
diff --git a/vp8/encoder/arm/csystemdependent.c b/vp8/encoder/arm/csystemdependent.c
new file mode 100644
index 0000000..0039796
--- /dev/null
+++ b/vp8/encoder/arm/csystemdependent.c
@@ -0,0 +1,159 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "variance.h"
+#include "onyx_int.h"
+
+void (*vp8_yv12_copy_partial_frame_ptr)(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc, int Fraction);
+extern void vp8_yv12_copy_partial_frame(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc, int Fraction);
+extern void vpxyv12_copy_partial_frame_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc, int Fraction);
+
+void vp8_cmachine_specific_config(VP8_COMP *cpi)
+{
+#if CONFIG_RUNTIME_CPU_DETECT
+    cpi->rtcd.common                         = &cpi->common.rtcd;
+
+#if HAVE_ARMV7
+    cpi->rtcd.variance.sad16x16              = vp8_sad16x16_neon;
+    cpi->rtcd.variance.sad16x8               = vp8_sad16x8_neon;
+    cpi->rtcd.variance.sad8x16               = vp8_sad8x16_neon;
+    cpi->rtcd.variance.sad8x8                = vp8_sad8x8_neon;
+    cpi->rtcd.variance.sad4x4                = vp8_sad4x4_neon;
+
+    cpi->rtcd.variance.var4x4                = vp8_variance4x4_c;
+    cpi->rtcd.variance.var8x8                = vp8_variance8x8_neon;
+    cpi->rtcd.variance.var8x16               = vp8_variance8x16_neon;
+    cpi->rtcd.variance.var16x8               = vp8_variance16x8_neon;
+    cpi->rtcd.variance.var16x16              = vp8_variance16x16_neon;
+
+    cpi->rtcd.variance.subpixvar4x4          = vp8_sub_pixel_variance4x4_c;
+    cpi->rtcd.variance.subpixvar8x8          = vp8_sub_pixel_variance8x8_neon;
+    cpi->rtcd.variance.subpixvar8x16         = vp8_sub_pixel_variance8x16_c;
+    cpi->rtcd.variance.subpixvar16x8         = vp8_sub_pixel_variance16x8_c;
+    cpi->rtcd.variance.subpixvar16x16        = vp8_sub_pixel_variance16x16_neon;
+
+    cpi->rtcd.variance.mse16x16              = vp8_mse16x16_neon;
+    cpi->rtcd.variance.getmbss               = vp8_get_mb_ss_c;
+
+    cpi->rtcd.variance.get16x16prederror     = vp8_get16x16pred_error_neon;
+    cpi->rtcd.variance.get8x8var             = vp8_get8x8var_c;
+    cpi->rtcd.variance.get16x16var           = vp8_get16x16var_c;;
+    cpi->rtcd.variance.get4x4sse_cs          = vp8_get4x4sse_cs_neon;
+
+    cpi->rtcd.fdct.short4x4                  = vp8_short_fdct4x4_neon;
+    cpi->rtcd.fdct.short8x4                  = vp8_short_fdct8x4_neon;
+    cpi->rtcd.fdct.fast4x4                   = vp8_fast_fdct4x4_neon;
+    cpi->rtcd.fdct.fast8x4                   = vp8_fast_fdct8x4_neon;
+    cpi->rtcd.fdct.walsh_short4x4            = vp8_short_walsh4x4_neon;
+
+    cpi->rtcd.encodemb.berr                  = vp8_block_error_c;
+    cpi->rtcd.encodemb.mberr                 = vp8_mbblock_error_c;
+    cpi->rtcd.encodemb.mbuverr               = vp8_mbuverror_c;
+    cpi->rtcd.encodemb.subb                  = vp8_subtract_b_neon;
+    cpi->rtcd.encodemb.submby                = vp8_subtract_mby_neon;
+    cpi->rtcd.encodemb.submbuv               = vp8_subtract_mbuv_neon;
+
+    cpi->rtcd.quantize.quantb                = vp8_regular_quantize_b;
+    cpi->rtcd.quantize.fastquantb            = vp8_fast_quantize_b_neon;
+#elif HAVE_ARMV6
+    cpi->rtcd.variance.sad16x16              = vp8_sad16x16_c;
+    cpi->rtcd.variance.sad16x8               = vp8_sad16x8_c;
+    cpi->rtcd.variance.sad8x16               = vp8_sad8x16_c;
+    cpi->rtcd.variance.sad8x8                = vp8_sad8x8_c;
+    cpi->rtcd.variance.sad4x4                = vp8_sad4x4_c;
+
+    cpi->rtcd.variance.var4x4                = vp8_variance4x4_c;
+    cpi->rtcd.variance.var8x8                = vp8_variance8x8_c;
+    cpi->rtcd.variance.var8x16               = vp8_variance8x16_c;
+    cpi->rtcd.variance.var16x8               = vp8_variance16x8_c;
+    cpi->rtcd.variance.var16x16              = vp8_variance16x16_c;
+
+    cpi->rtcd.variance.subpixvar4x4          = vp8_sub_pixel_variance4x4_c;
+    cpi->rtcd.variance.subpixvar8x8          = vp8_sub_pixel_variance8x8_c;
+    cpi->rtcd.variance.subpixvar8x16         = vp8_sub_pixel_variance8x16_c;
+    cpi->rtcd.variance.subpixvar16x8         = vp8_sub_pixel_variance16x8_c;
+    cpi->rtcd.variance.subpixvar16x16        = vp8_sub_pixel_variance16x16_c;
+
+    cpi->rtcd.variance.mse16x16              = vp8_mse16x16_c;
+    cpi->rtcd.variance.getmbss               = vp8_get_mb_ss_c;
+
+    cpi->rtcd.variance.get16x16prederror     = vp8_get16x16pred_error_c;
+    cpi->rtcd.variance.get8x8var             = vp8_get8x8var_c;
+    cpi->rtcd.variance.get16x16var           = vp8_get16x16var_c;;
+    cpi->rtcd.variance.get4x4sse_cs          = vp8_get4x4sse_cs_c;
+
+    cpi->rtcd.fdct.short4x4                  = vp8_short_fdct4x4_c;
+    cpi->rtcd.fdct.short8x4                  = vp8_short_fdct8x4_c;
+    cpi->rtcd.fdct.fast4x4                   = vp8_fast_fdct4x4_c;
+    cpi->rtcd.fdct.fast8x4                   = vp8_fast_fdct8x4_c;
+    cpi->rtcd.fdct.walsh_short4x4            = vp8_short_walsh4x4_armv6;
+
+    cpi->rtcd.encodemb.berr                  = vp8_block_error_c;
+    cpi->rtcd.encodemb.mberr                 = vp8_mbblock_error_c;
+    cpi->rtcd.encodemb.mbuverr               = vp8_mbuverror_c;
+    cpi->rtcd.encodemb.subb                  = vp8_subtract_b_c;
+    cpi->rtcd.encodemb.submby                = vp8_subtract_mby_c;
+    cpi->rtcd.encodemb.submbuv               = vp8_subtract_mbuv_c;
+
+    cpi->rtcd.quantize.quantb                = vp8_regular_quantize_b;
+    cpi->rtcd.quantize.fastquantb            = vp8_fast_quantize_b_c;
+#else
+    //pure c
+    cpi->rtcd.variance.sad16x16              = vp8_sad16x16_c;
+    cpi->rtcd.variance.sad16x8               = vp8_sad16x8_c;
+    cpi->rtcd.variance.sad8x16               = vp8_sad8x16_c;
+    cpi->rtcd.variance.sad8x8                = vp8_sad8x8_c;
+    cpi->rtcd.variance.sad4x4                = vp8_sad4x4_c;
+
+    cpi->rtcd.variance.var4x4                = vp8_variance4x4_c;
+    cpi->rtcd.variance.var8x8                = vp8_variance8x8_c;
+    cpi->rtcd.variance.var8x16               = vp8_variance8x16_c;
+    cpi->rtcd.variance.var16x8               = vp8_variance16x8_c;
+    cpi->rtcd.variance.var16x16              = vp8_variance16x16_c;
+
+    cpi->rtcd.variance.subpixvar4x4          = vp8_sub_pixel_variance4x4_c;
+    cpi->rtcd.variance.subpixvar8x8          = vp8_sub_pixel_variance8x8_c;
+    cpi->rtcd.variance.subpixvar8x16         = vp8_sub_pixel_variance8x16_c;
+    cpi->rtcd.variance.subpixvar16x8         = vp8_sub_pixel_variance16x8_c;
+    cpi->rtcd.variance.subpixvar16x16        = vp8_sub_pixel_variance16x16_c;
+
+    cpi->rtcd.variance.mse16x16              = vp8_mse16x16_c;
+    cpi->rtcd.variance.getmbss               = vp8_get_mb_ss_c;
+
+    cpi->rtcd.variance.get16x16prederror     = vp8_get16x16pred_error_c;
+    cpi->rtcd.variance.get8x8var             = vp8_get8x8var_c;
+    cpi->rtcd.variance.get16x16var           = vp8_get16x16var_c;;
+    cpi->rtcd.variance.get4x4sse_cs          = vp8_get4x4sse_cs_c;
+
+    cpi->rtcd.fdct.short4x4                  = vp8_short_fdct4x4_c;
+    cpi->rtcd.fdct.short8x4                  = vp8_short_fdct8x4_c;
+    cpi->rtcd.fdct.fast4x4                   = vp8_fast_fdct4x4_c;
+    cpi->rtcd.fdct.fast8x4                   = vp8_fast_fdct8x4_c;
+    cpi->rtcd.fdct.walsh_short4x4            = vp8_short_walsh4x4_c;
+
+    cpi->rtcd.encodemb.berr                  = vp8_block_error_c;
+    cpi->rtcd.encodemb.mberr                 = vp8_mbblock_error_c;
+    cpi->rtcd.encodemb.mbuverr               = vp8_mbuverror_c;
+    cpi->rtcd.encodemb.subb                  = vp8_subtract_b_c;
+    cpi->rtcd.encodemb.submby                = vp8_subtract_mby_c;
+    cpi->rtcd.encodemb.submbuv               = vp8_subtract_mbuv_c;
+
+    cpi->rtcd.quantize.quantb                = vp8_regular_quantize_b;
+    cpi->rtcd.quantize.fastquantb            = vp8_fast_quantize_b_c;
+#endif
+#endif
+
+#if HAVE_ARMV7
+    vp8_yv12_copy_partial_frame_ptr = vpxyv12_copy_partial_frame_neon;
+#else
+    vp8_yv12_copy_partial_frame_ptr = vp8_yv12_copy_partial_frame;
+#endif
+}
diff --git a/vp8/encoder/arm/dct_arm.h b/vp8/encoder/arm/dct_arm.h
new file mode 100644
index 0000000..a671862
--- /dev/null
+++ b/vp8/encoder/arm/dct_arm.h
@@ -0,0 +1,45 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef DCT_ARM_H
+#define DCT_ARM_H
+
+#if HAVE_ARMV6
+extern prototype_fdct(vp8_short_walsh4x4_armv6);
+
+#undef  vp8_fdct_walsh_short4x4
+#define vp8_fdct_walsh_short4x4 vp8_short_walsh4x4_armv6
+#endif
+
+#if HAVE_ARMV7
+extern prototype_fdct(vp8_short_fdct4x4_neon);
+extern prototype_fdct(vp8_short_fdct8x4_neon);
+extern prototype_fdct(vp8_fast_fdct4x4_neon);
+extern prototype_fdct(vp8_fast_fdct8x4_neon);
+extern prototype_fdct(vp8_short_walsh4x4_neon);
+
+#undef  vp8_fdct_short4x4
+#define vp8_fdct_short4x4 vp8_short_fdct4x4_neon
+
+#undef  vp8_fdct_short8x4
+#define vp8_fdct_short8x4 vp8_short_fdct8x4_neon
+
+#undef  vp8_fdct_fast4x4
+#define vp8_fdct_fast4x4 vp8_fast_fdct4x4_neon
+
+#undef  vp8_fdct_fast8x4
+#define vp8_fdct_fast8x4 vp8_fast_fdct8x4_neon
+
+#undef  vp8_fdct_walsh_short4x4
+#define vp8_fdct_walsh_short4x4 vp8_short_walsh4x4_neon
+
+#endif
+
+#endif
diff --git a/vp8/encoder/arm/encodemb_arm.c b/vp8/encoder/arm/encodemb_arm.c
new file mode 100644
index 0000000..3f1d053
--- /dev/null
+++ b/vp8/encoder/arm/encodemb_arm.c
@@ -0,0 +1,30 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "encodemb.h"
+#include "reconinter.h"
+#include "quantize.h"
+#include "invtrans.h"
+#include "recon.h"
+#include "reconintra.h"
+#include "dct.h"
+#include "vpx_mem/vpx_mem.h"
+
+extern void vp8_subtract_b_neon_func(short *diff, unsigned char *src, unsigned char *pred, int stride, int pitch);
+
+void vp8_subtract_b_neon(BLOCK *be, BLOCKD *bd, int pitch)
+{
+    unsigned char *src_ptr = (*(be->base_src) + be->src);
+    short *diff_ptr = be->src_diff;
+    unsigned char *pred_ptr = bd->predictor;
+    int src_stride = be->src_stride;
+
+    vp8_subtract_b_neon_func(diff_ptr, src_ptr, pred_ptr, src_stride, pitch);
+}
diff --git a/vp8/encoder/arm/encodemb_arm.h b/vp8/encoder/arm/encodemb_arm.h
new file mode 100644
index 0000000..28f9e5c
--- /dev/null
+++ b/vp8/encoder/arm/encodemb_arm.h
@@ -0,0 +1,43 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef ENCODEMB_ARM_H
+#define ENCODEMB_ARM_H
+
+#if HAVE_ARMV7
+//extern prototype_berr(vp8_block_error_c);
+//extern prototype_mberr(vp8_mbblock_error_c);
+//extern prototype_mbuverr(vp8_mbuverror_c);
+
+extern prototype_subb(vp8_subtract_b_neon);
+extern prototype_submby(vp8_subtract_mby_neon);
+extern prototype_submbuv(vp8_subtract_mbuv_neon);
+
+//#undef  vp8_encodemb_berr
+//#define vp8_encodemb_berr vp8_block_error_c
+
+//#undef  vp8_encodemb_mberr
+//#define vp8_encodemb_mberr vp8_mbblock_error_c
+
+//#undef  vp8_encodemb_mbuverr
+//#define vp8_encodemb_mbuverr vp8_mbuverror_c
+
+#undef  vp8_encodemb_subb
+#define vp8_encodemb_subb vp8_subtract_b_neon
+
+#undef  vp8_encodemb_submby
+#define vp8_encodemb_submby vp8_subtract_mby_neon
+
+#undef  vp8_encodemb_submbuv
+#define vp8_encodemb_submbuv vp8_subtract_mbuv_neon
+
+#endif
+
+#endif
diff --git a/vp8/encoder/arm/mcomp_arm.c b/vp8/encoder/arm/mcomp_arm.c
new file mode 100644
index 0000000..07f2186
--- /dev/null
+++ b/vp8/encoder/arm/mcomp_arm.c
@@ -0,0 +1,1662 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "mcomp.h"
+#include "vpx_mem/vpx_mem.h"
+
+#include <stdio.h>
+#include <limits.h>
+#include <math.h>
+
+#ifdef ENTROPY_STATS
+static int mv_ref_ct [31] [4] [2];
+static int mv_mode_cts [4] [2];
+#endif
+
+static int mv_bits_sadcost[256];
+
+extern unsigned int vp8_sub_pixel_variance16x16s_neon
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+);
+extern unsigned int vp8_sub_pixel_variance16x16s_4_0_neon
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+);
+extern unsigned int vp8_sub_pixel_variance16x16s_0_4_neon
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+);
+extern unsigned int vp8_sub_pixel_variance16x16s_4_4_neon
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+);
+
+void vp8cx_init_mv_bits_sadcost()
+{
+    int i;
+
+    for (i = 0; i < 256; i++)
+    {
+        mv_bits_sadcost[i] = (int)sqrt(i * 16);
+    }
+}
+
+
+int vp8_mv_bit_cost(MV *mv, MV *ref, int *mvcost[2], int Weight)
+{
+    // MV costing is based on the distribution of vectors in the previous frame and as such will tend to
+    // over state the cost of vectors. In addition coding a new vector can have a knock on effect on the
+    // cost of subsequent vectors and the quality of prediction from NEAR and NEAREST for subsequent blocks.
+    // The "Weight" parameter allows, to a limited extent, for some account to be taken of these factors.
+    return ((mvcost[0][(mv->row - ref->row) >> 1] + mvcost[1][(mv->col - ref->col) >> 1]) * Weight) >> 7;
+}
+
+int vp8_mv_err_cost(MV *mv, MV *ref, int *mvcost[2], int error_per_bit)
+{
+    //int i;
+    //return ((mvcost[0][(mv->row - ref->row)>>1] + mvcost[1][(mv->col - ref->col)>>1] + 128) * error_per_bit) >> 8;
+    //return ( (vp8_mv_bit_cost(mv,  ref, mvcost, 100) + 128) * error_per_bit) >> 8;
+
+    //i = (vp8_mv_bit_cost(mv,  ref, mvcost, 100) * error_per_bit + 128) >> 8;
+    return ((mvcost[0][(mv->row - ref->row) >> 1] + mvcost[1][(mv->col - ref->col) >> 1]) * error_per_bit + 128) >> 8;
+    //return (vp8_mv_bit_cost(mv,  ref, mvcost, 128) * error_per_bit + 128) >> 8;
+}
+
+
+static int mv_bits(MV *mv, MV *ref, int *mvcost[2])
+{
+    // get the estimated number of bits for a motion vector, to be used for costing in SAD based
+    // motion estimation
+    return ((mvcost[0][(mv->row - ref->row) >> 1]  +  mvcost[1][(mv->col - ref->col)>> 1]) + 128) >> 8;
+}
+
+void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride)
+{
+    int Len;
+    int search_site_count = 0;
+
+
+    // Generate offsets for 4 search sites per step.
+    Len = MAX_FIRST_STEP;
+    x->ss[search_site_count].mv.col = 0;
+    x->ss[search_site_count].mv.row = 0;
+    x->ss[search_site_count].offset = 0;
+    search_site_count++;
+
+    while (Len > 0)
+    {
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = 0;
+        x->ss[search_site_count].mv.row = -Len;
+        x->ss[search_site_count].offset = -Len * stride;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = 0;
+        x->ss[search_site_count].mv.row = Len;
+        x->ss[search_site_count].offset = Len * stride;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = -Len;
+        x->ss[search_site_count].mv.row = 0;
+        x->ss[search_site_count].offset = -Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = Len;
+        x->ss[search_site_count].mv.row = 0;
+        x->ss[search_site_count].offset = Len;
+        search_site_count++;
+
+        // Contract.
+        Len /= 2;
+    }
+
+    x->ss_count = search_site_count;
+    x->searches_per_step = 4;
+}
+
+void vp8_init3smotion_compensation(MACROBLOCK *x, int stride)
+{
+    int Len;
+    int search_site_count = 0;
+
+    // Generate offsets for 8 search sites per step.
+    Len = MAX_FIRST_STEP;
+    x->ss[search_site_count].mv.col = 0;
+    x->ss[search_site_count].mv.row = 0;
+    x->ss[search_site_count].offset = 0;
+    search_site_count++;
+
+    while (Len > 0)
+    {
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = 0;
+        x->ss[search_site_count].mv.row = -Len;
+        x->ss[search_site_count].offset = -Len * stride;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = 0;
+        x->ss[search_site_count].mv.row = Len;
+        x->ss[search_site_count].offset = Len * stride;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = -Len;
+        x->ss[search_site_count].mv.row = 0;
+        x->ss[search_site_count].offset = -Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = Len;
+        x->ss[search_site_count].mv.row = 0;
+        x->ss[search_site_count].offset = Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = -Len;
+        x->ss[search_site_count].mv.row = -Len;
+        x->ss[search_site_count].offset = -Len * stride - Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = Len;
+        x->ss[search_site_count].mv.row = -Len;
+        x->ss[search_site_count].offset = -Len * stride + Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = -Len;
+        x->ss[search_site_count].mv.row = Len;
+        x->ss[search_site_count].offset = Len * stride - Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = Len;
+        x->ss[search_site_count].mv.row = Len;
+        x->ss[search_site_count].offset = Len * stride + Len;
+        search_site_count++;
+
+
+        // Contract.
+        Len /= 2;
+    }
+
+    x->ss_count = search_site_count;
+    x->searches_per_step = 8;
+}
+
+
+#define MVC(r,c) (((mvcost[0][(r)-rr] + mvcost[1][(c) - rc]) * error_per_bit + 128 )>>8 ) // estimated cost of a motion vector (r,c)
+#define PRE(r,c) (*(d->base_pre) + d->pre + ((r)>>2) * d->pre_stride + ((c)>>2)) // pointer to predictor base of a motionvector
+#define SP(x) (((x)&3)<<1) // convert motion vector component to offset for svf calc
+#define DIST(r,c) svf( PRE(r,c), d->pre_stride, SP(c),SP(r), z,b->src_stride,&sse) // returns subpixel variance error function.
+#define IFMVCV(r,c,s,e) if ( c >= minc && c <= maxc && r >= minr && r <= maxr) s else e;
+#define ERR(r,c) (MVC(r,c)+DIST(r,c)) // returns distortion + motion vector cost
+#define CHECK_BETTER(v,r,c) IFMVCV(r,c,{if((v = ERR(r,c)) < besterr) { besterr = v; br=r; bc=c; }}, v=INT_MAX;)// checks if (r,c) has better score than previous best
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#define MAX(x,y) (((x)>(y))?(x):(y))
+
+//#define CHECK_BETTER(v,r,c) if((v = ERR(r,c)) < besterr) { besterr = v; br=r; bc=c; }
+
+int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d, MV *bestmv, MV *ref_mv, int error_per_bit, vp8_subpixvariance_fn_t svf, vp8_variance_fn_t vf, int *mvcost[2])
+{
+    unsigned char *y = *(d->base_pre) + d->pre + (bestmv->row) * d->pre_stride + bestmv->col;
+    unsigned char *z = (*(b->base_src) + b->src);
+
+    int rr = ref_mv->row >> 1, rc = ref_mv->col >> 1;
+    int br = bestmv->row << 2, bc = bestmv->col << 2;
+    int tr = br, tc = bc;
+    unsigned int besterr = INT_MAX;
+    unsigned int left, right, up, down, diag;
+    unsigned int sse;
+    unsigned int whichdir;
+    unsigned int halfiters = 4;
+    unsigned int quarteriters = 4;
+
+    int minc = MAX(x->mv_col_min << 2, (ref_mv->col >> 1) - ((1 << mvlong_width) - 1));
+    int maxc = MIN(x->mv_col_max << 2, (ref_mv->col >> 1) + ((1 << mvlong_width) - 1));
+    int minr = MAX(x->mv_row_min << 2, (ref_mv->row >> 1) - ((1 << mvlong_width) - 1));
+    int maxr = MIN(x->mv_row_max << 2, (ref_mv->row >> 1) + ((1 << mvlong_width) - 1));
+
+    // central mv
+    bestmv->row <<= 3;
+    bestmv->col <<= 3;
+
+    // calculate central point error
+    besterr = vf(y, d->pre_stride, z, b->src_stride, &sse);
+    besterr += vp8_mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
+
+    // TODO: Each subsequent iteration checks at least one point in common with the last iteration could be 2 ( if diag selected)
+    while (--halfiters)
+    {
+        // 1/2 pel
+        CHECK_BETTER(left, tr, tc - 2);
+        CHECK_BETTER(right, tr, tc + 2);
+        CHECK_BETTER(up, tr - 2, tc);
+        CHECK_BETTER(down, tr + 2, tc);
+
+        whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+
+        switch (whichdir)
+        {
+        case 0:
+            CHECK_BETTER(diag, tr - 2, tc - 2);
+            break;
+        case 1:
+            CHECK_BETTER(diag, tr - 2, tc + 2);
+            break;
+        case 2:
+            CHECK_BETTER(diag, tr + 2, tc - 2);
+            break;
+        case 3:
+            CHECK_BETTER(diag, tr + 2, tc + 2);
+            break;
+        }
+
+        // no reason to check the same one again.
+        if (tr == br && tc == bc)
+            break;
+
+        tr = br;
+        tc = bc;
+    }
+
+    // TODO: Each subsequent iteration checks at least one point in common with the last iteration could be 2 ( if diag selected)
+    // 1/4 pel
+    while (--quarteriters)
+    {
+        CHECK_BETTER(left, tr, tc - 1);
+        CHECK_BETTER(right, tr, tc + 1);
+        CHECK_BETTER(up, tr - 1, tc);
+        CHECK_BETTER(down, tr + 1, tc);
+
+        whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+
+        switch (whichdir)
+        {
+        case 0:
+            CHECK_BETTER(diag, tr - 1, tc - 1);
+            break;
+        case 1:
+            CHECK_BETTER(diag, tr - 1, tc + 1);
+            break;
+        case 2:
+            CHECK_BETTER(diag, tr + 1, tc - 1);
+            break;
+        case 3:
+            CHECK_BETTER(diag, tr + 1, tc + 1);
+            break;
+        }
+
+        // no reason to check the same one again.
+        if (tr == br && tc == bc)
+            break;
+
+        tr = br;
+        tc = bc;
+    }
+
+    bestmv->row = br << 1;
+    bestmv->col = bc << 1;
+
+    if ((abs(bestmv->col - ref_mv->col) > MAX_FULL_PEL_VAL) || (abs(bestmv->row - ref_mv->row) > MAX_FULL_PEL_VAL))
+        return INT_MAX;
+
+    return besterr;
+}
+#undef MVC
+#undef PRE
+#undef SP
+#undef DIST
+#undef ERR
+#undef CHECK_BETTER
+#undef MIN
+#undef MAX
+int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, MV *bestmv, MV *ref_mv, int error_per_bit, vp8_subpixvariance_fn_t svf, vp8_variance_fn_t vf, int *mvcost[2])
+{
+    int bestmse = INT_MAX;
+    MV startmv;
+    //MV this_mv;
+    MV this_mv;
+    unsigned char *y = *(d->base_pre) + d->pre + (bestmv->row) * d->pre_stride + bestmv->col;
+    unsigned char *z = (*(b->base_src) + b->src);
+    int left, right, up, down, diag;
+    unsigned int sse;
+    int whichdir ;
+
+
+    // Trap uncodable vectors
+    if ((abs((bestmv->col << 3) - ref_mv->col) > MAX_FULL_PEL_VAL) || (abs((bestmv->row << 3) - ref_mv->row) > MAX_FULL_PEL_VAL))
+    {
+        bestmv->row <<= 3;
+        bestmv->col <<= 3;
+        return INT_MAX;
+    }
+
+    // central mv
+    bestmv->row <<= 3;
+    bestmv->col <<= 3;
+    startmv = *bestmv;
+
+    // calculate central point error
+    bestmse = vf(y, d->pre_stride, z, b->src_stride, &sse);
+    bestmse += vp8_mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
+
+    // go left then right and check error
+    this_mv.row = startmv.row;
+    this_mv.col = ((startmv.col - 8) | 4);
+    left = vp8_sub_pixel_variance16x16s_4_0_neon(y - 1, d->pre_stride, z, b->src_stride, &sse);
+    left += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (left < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = left;
+    }
+
+    this_mv.col += 8;
+    right = vp8_sub_pixel_variance16x16s_4_0_neon(y, d->pre_stride, z, b->src_stride, &sse);
+    right += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (right < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = right;
+    }
+
+    // go up then down and check error
+    this_mv.col = startmv.col;
+    this_mv.row = ((startmv.row - 8) | 4);
+    up = vp8_sub_pixel_variance16x16s_0_4_neon(y - d->pre_stride, d->pre_stride, z, b->src_stride, &sse);
+    up += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (up < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = up;
+    }
+
+    this_mv.row += 8;
+    down = vp8_sub_pixel_variance16x16s_0_4_neon(y, d->pre_stride, z, b->src_stride, &sse);
+    down += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (down < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = down;
+    }
+
+
+    // now check 1 more diagonal
+    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+    //for(whichdir =0;whichdir<4;whichdir++)
+    //{
+    this_mv = startmv;
+
+    switch (whichdir)
+    {
+    case 0:
+        this_mv.col = (this_mv.col - 8) | 4;
+        this_mv.row = (this_mv.row - 8) | 4;
+        diag = vp8_sub_pixel_variance16x16s_4_4_neon(y - 1 - d->pre_stride, d->pre_stride, z, b->src_stride, &sse);
+        break;
+    case 1:
+        this_mv.col += 4;
+        this_mv.row = (this_mv.row - 8) | 4;
+        diag = vp8_sub_pixel_variance16x16s_4_4_neon(y - d->pre_stride, d->pre_stride, z, b->src_stride, &sse);
+        break;
+    case 2:
+        this_mv.col = (this_mv.col - 8) | 4;
+        this_mv.row += 4;
+        diag = vp8_sub_pixel_variance16x16s_4_4_neon(y - 1, d->pre_stride, z, b->src_stride, &sse);
+        break;
+    case 3:
+        this_mv.col += 4;
+        this_mv.row += 4;
+        diag = vp8_sub_pixel_variance16x16s_4_4_neon(y, d->pre_stride, z, b->src_stride, &sse);
+        break;
+    }
+
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+//  }
+
+
+    // time to check quarter pels.
+    if (bestmv->row < startmv.row)
+        y -= d->pre_stride;
+
+    if (bestmv->col < startmv.col)
+        y--;
+
+    startmv = *bestmv;
+
+
+
+    // go left then right and check error
+    this_mv.row = startmv.row;
+
+    if (startmv.col & 7)
+    {
+        this_mv.col = startmv.col - 2;
+        left = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+    }
+    else
+    {
+        this_mv.col = (startmv.col - 8) | 6;
+        left = svf(y - 1, d->pre_stride, 6, this_mv.row & 7, z, b->src_stride, &sse);
+    }
+
+    left += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (left < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = left;
+    }
+
+    this_mv.col += 4;
+    right = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+    right += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (right < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = right;
+    }
+
+    // go up then down and check error
+    this_mv.col = startmv.col;
+
+    if (startmv.row & 7)
+    {
+        this_mv.row = startmv.row - 2;
+        up = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+    }
+    else
+    {
+        this_mv.row = (startmv.row - 8) | 6;
+        up = svf(y - d->pre_stride, d->pre_stride, this_mv.col & 7, 6, z, b->src_stride, &sse);
+    }
+
+    up += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (up < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = up;
+    }
+
+    this_mv.row += 4;
+    down = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+    down += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (down < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = down;
+    }
+
+
+    // now check 1 more diagonal
+    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+
+//  for(whichdir=0;whichdir<4;whichdir++)
+//  {
+    this_mv = startmv;
+
+    switch (whichdir)
+    {
+    case 0:
+
+        if (startmv.row & 7)
+        {
+            this_mv.row -= 2;
+
+            if (startmv.col & 7)
+            {
+                this_mv.col -= 2;
+                diag = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+            }
+            else
+            {
+                this_mv.col = (startmv.col - 8) | 6;
+                diag = svf(y - 1, d->pre_stride, 6, this_mv.row & 7, z, b->src_stride, &sse);;
+            }
+        }
+        else
+        {
+            this_mv.row = (startmv.row - 8) | 6;
+
+            if (startmv.col & 7)
+            {
+                this_mv.col -= 2;
+                diag = svf(y - d->pre_stride, d->pre_stride, this_mv.col & 7, 6, z, b->src_stride, &sse);
+            }
+            else
+            {
+                this_mv.col = (startmv.col - 8) | 6;
+                diag = svf(y - d->pre_stride - 1, d->pre_stride, 6, 6, z, b->src_stride, &sse);
+            }
+        }
+
+        break;
+    case 1:
+        this_mv.col += 2;
+
+        if (startmv.row & 7)
+        {
+            this_mv.row -= 2;
+            diag = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+        }
+        else
+        {
+            this_mv.row = (startmv.row - 8) | 6;
+            diag = svf(y - d->pre_stride, d->pre_stride, this_mv.col & 7, 6, z, b->src_stride, &sse);
+        }
+
+        break;
+    case 2:
+        this_mv.row += 2;
+
+        if (startmv.col & 7)
+        {
+            this_mv.col -= 2;
+            diag = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+        }
+        else
+        {
+            this_mv.col = (startmv.col - 8) | 6;
+            diag = svf(y - 1, d->pre_stride, 6, this_mv.row & 7, z, b->src_stride, &sse);;
+        }
+
+        break;
+    case 3:
+        this_mv.col += 2;
+        this_mv.row += 2;
+        diag = svf(y, d->pre_stride,  this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+        break;
+    }
+
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+//  }
+
+    return bestmse;
+}
+
+int vp8_find_best_half_pixel_step(MACROBLOCK *mb, BLOCK *b, BLOCKD *d, MV *bestmv, MV *ref_mv, int error_per_bit, vp8_subpixvariance_fn_t svf, vp8_variance_fn_t vf, int *mvcost[2])
+{
+    int bestmse = INT_MAX;
+    MV startmv;
+    //MV this_mv;
+    MV this_mv;
+    unsigned char *y = *(d->base_pre) + d->pre + (bestmv->row) * d->pre_stride + bestmv->col;
+    unsigned char *z = (*(b->base_src) + b->src);
+    int left, right, up, down, diag;
+    unsigned int sse;
+
+    // Trap uncodable vectors
+    if ((abs((bestmv->col << 3) - ref_mv->col) > MAX_FULL_PEL_VAL) || (abs((bestmv->row << 3) - ref_mv->row) > MAX_FULL_PEL_VAL))
+    {
+        bestmv->row <<= 3;
+        bestmv->col <<= 3;
+        return INT_MAX;
+    }
+
+    // central mv
+    bestmv->row <<= 3;
+    bestmv->col <<= 3;
+    startmv = *bestmv;
+
+    // calculate central point error
+    bestmse = vf(y, d->pre_stride, z, b->src_stride, &sse);
+    bestmse += vp8_mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
+
+    // go left then right and check error
+    this_mv.row = startmv.row;
+    this_mv.col = ((startmv.col - 8) | 4);
+    left = vp8_sub_pixel_variance16x16s_4_0_neon(y - 1, d->pre_stride, z, b->src_stride, &sse);
+    left += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (left < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = left;
+    }
+
+    this_mv.col += 8;
+    right = vp8_sub_pixel_variance16x16s_4_0_neon(y, d->pre_stride, z, b->src_stride, &sse);
+    right += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (right < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = right;
+    }
+
+    // go up then down and check error
+    this_mv.col = startmv.col;
+    this_mv.row = ((startmv.row - 8) | 4);
+    up = vp8_sub_pixel_variance16x16s_0_4_neon(y - d->pre_stride, d->pre_stride, z, b->src_stride, &sse);
+    up += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (up < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = up;
+    }
+
+    this_mv.row += 8;
+    down = vp8_sub_pixel_variance16x16s_0_4_neon(y, d->pre_stride, z, b->src_stride, &sse);
+    down += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (down < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = down;
+    }
+
+    // somewhat strangely not doing all the diagonals for half pel is slower than doing them.
+#if 0
+    // now check 1 more diagonal -
+    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+    this_mv = startmv;
+
+    switch (whichdir)
+    {
+    case 0:
+        this_mv.col = (this_mv.col - 8) | 4;
+        this_mv.row = (this_mv.row - 8) | 4;
+        diag = svf(y - 1 - d->pre_stride, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+        break;
+    case 1:
+        this_mv.col += 4;
+        this_mv.row = (this_mv.row - 8) | 4;
+        diag = svf(y - d->pre_stride, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+        break;
+    case 2:
+        this_mv.col = (this_mv.col - 8) | 4;
+        this_mv.row += 4;
+        diag = svf(y - 1, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+        break;
+    case 3:
+        this_mv.col += 4;
+        this_mv.row += 4;
+        diag = svf(y, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+        break;
+    }
+
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+#else
+    this_mv.col = (this_mv.col - 8) | 4;
+    this_mv.row = (this_mv.row - 8) | 4;
+    diag = vp8_sub_pixel_variance16x16s_4_4_neon(y - 1 - d->pre_stride, d->pre_stride, z, b->src_stride, &sse);
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+    this_mv.col += 8;
+    diag = vp8_sub_pixel_variance16x16s_4_4_neon(y - d->pre_stride, d->pre_stride, z, b->src_stride, &sse);
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+    this_mv.col = (this_mv.col - 8) | 4;
+    this_mv.row = startmv.row + 4;
+    diag = vp8_sub_pixel_variance16x16s_4_4_neon(y - 1, d->pre_stride, z, b->src_stride, &sse);
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+    this_mv.col += 8;
+    diag = vp8_sub_pixel_variance16x16s_4_4_neon(y, d->pre_stride, z, b->src_stride, &sse);
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+#endif
+    return bestmse;
+}
+
+#if 1
+
+#define MVC(r,c) (((mvsadcost[0][((r)<<2)-rr] + mvsadcost[1][((c)<<2) - rc]) * error_per_bit + 128 )>>8 ) // estimated cost of a motion vector (r,c)
+#define PRE(r,c) (*(d->base_pre) + d->pre + (r) * d->pre_stride + (c)) // pointer to predictor base of a motionvector
+#define DIST(r,c,v) sf( src,src_stride,PRE(r,c),d->pre_stride, v) // returns sad error score.
+#define ERR(r,c,v) (MVC(r,c)+DIST(r,c,v)) // returns distortion + motion vector cost
+#define CHECK_BETTER(v,r,c) if ((v = ERR(r,c,besterr)) < besterr) { besterr = v; br=r; bc=c; } // checks if (r,c) has better score than previous best
+const MV next_chkpts[6][3] =
+{
+    {{ -2, 0}, { -1, -2}, {1, -2}},
+    {{ -1, -2}, {1, -2}, {2, 0}},
+    {{1, -2}, {2, 0}, {1, 2}},
+    {{2, 0}, {1, 2}, { -1, 2}},
+    {{1, 2}, { -1, 2}, { -2, 0}},
+    {{ -1, 2}, { -2, 0}, { -1, -2}}
+};
+int vp8_hex_search
+(
+    MACROBLOCK *x,
+    BLOCK *b,
+    BLOCKD *d,
+    MV *ref_mv,
+    MV *best_mv,
+    int search_param,
+    int error_per_bit,
+    int *num00,
+    vp8_variance_fn_t vf,
+    vp8_sad_fn_t      sf,
+    int *mvsadcost[2],
+    int *mvcost[2]
+)
+{
+    MV hex[6] = { { -1, -2}, {1, -2}, {2, 0}, {1, 2}, { -1, 2}, { -2, 0} } ;
+    MV neighbors[8] = { { -1, -1}, { -1, 0}, { -1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1} } ;
+    int i, j;
+    unsigned char *src = (*(b->base_src) + b->src);
+    int src_stride = b->src_stride;
+    int rr = ref_mv->row, rc = ref_mv->col, br = rr >> 3, bc = rc >> 3, tr, tc;
+    unsigned int besterr, thiserr = 0x7fffffff;
+    int k = -1, tk;
+
+    if (bc < x->mv_col_min) bc = x->mv_col_min;
+
+    if (bc > x->mv_col_max) bc = x->mv_col_max;
+
+    if (br < x->mv_row_min) br = x->mv_row_min;
+
+    if (br > x->mv_row_max) br = x->mv_row_max;
+
+    rr >>= 1;
+    rc >>= 1;
+
+    besterr = ERR(br, bc, thiserr);
+
+    // hex search
+    //j=0
+    tr = br;
+    tc = bc;
+
+    for (i = 0; i < 6; i++)
+    {
+        int nr = tr + hex[i].row, nc = tc + hex[i].col;
+
+        if (nc < x->mv_col_min) continue;
+
+        if (nc > x->mv_col_max) continue;
+
+        if (nr < x->mv_row_min) continue;
+
+        if (nr > x->mv_row_max) continue;
+
+        //CHECK_BETTER(thiserr,nr,nc);
+        if ((thiserr = ERR(nr, nc, besterr)) < besterr)
+        {
+            besterr = thiserr;
+            br = nr;
+            bc = nc;
+            k = i;
+        }
+    }
+
+    if (tr == br && tc == bc)
+        goto cal_neighbors;
+
+    for (j = 1; j < 127; j++)
+    {
+        tr = br;
+        tc = bc;
+        tk = k;
+
+        for (i = 0; i < 3; i++)
+        {
+            int nr = tr + next_chkpts[tk][i].row, nc = tc + next_chkpts[tk][i].col;
+
+            if (nc < x->mv_col_min) continue;
+
+            if (nc > x->mv_col_max) continue;
+
+            if (nr < x->mv_row_min) continue;
+
+            if (nr > x->mv_row_max) continue;
+
+            //CHECK_BETTER(thiserr,nr,nc);
+            if ((thiserr = ERR(nr, nc, besterr)) < besterr)
+            {
+                besterr = thiserr;
+                br = nr;
+                bc = nc; //k=(tk+5+i)%6;}
+                k = tk + 5 + i;
+
+                if (k >= 12) k -= 12;
+                else if (k >= 6) k -= 6;
+            }
+        }
+
+        if (tr == br && tc == bc)
+            break;
+    }
+
+    // check 8 1 away neighbors
+cal_neighbors:
+    tr = br;
+    tc = bc;
+
+    for (i = 0; i < 8; i++)
+    {
+        int nr = tr + neighbors[i].row, nc = tc + neighbors[i].col;
+
+        if (nc < x->mv_col_min) continue;
+
+        if (nc > x->mv_col_max) continue;
+
+        if (nr < x->mv_row_min) continue;
+
+        if (nr > x->mv_row_max) continue;
+
+        CHECK_BETTER(thiserr, nr, nc);
+    }
+
+    best_mv->row = br;
+    best_mv->col = bc;
+
+    return vf(src, src_stride, PRE(br, bc), d->pre_stride, &thiserr) + MVC(br, bc) ;
+}
+#undef MVC
+#undef PRE
+#undef SP
+#undef DIST
+#undef ERR
+#undef CHECK_BETTER
+
+#else
+
+#define MVC(r,c) (((mvsadcost[0][((r)<<2)-rr] + mvsadcost[1][((c)<<2) - rc]) * error_per_bit + 128 )>>8 ) // estimated cost of a motion vector (r,c)
+#define PRE(r,c) (*(d->base_pre) + d->pre + (r) * d->pre_stride + (c)) // pointer to predictor base of a motionvector
+#define DIST(r,c,v) sf( src,src_stride,PRE(r,c),d->pre_stride, v) // returns sad error score.
+#define ERR(r,c,v) (MVC(r,c)+DIST(r,c,v)) // returns distortion + motion vector cost
+#define CHECK_BETTER(v,r,c) if ((v = ERR(r,c,besterr)) < besterr) { besterr = v; br=r; bc=c; } // checks if (r,c) has better score than previous best
+
+int vp8_hex_search
+(
+    MACROBLOCK *x,
+    BLOCK *b,
+    BLOCKD *d,
+    MV *ref_mv,
+    MV *best_mv,
+    int search_param,
+    int error_per_bit,
+    int *num00,
+    vp8_variance_fn_t vf,
+    vp8_sad_fn_t      sf,
+    int *mvsadcost[2],
+    int *mvcost[2]
+)
+{
+    MV hex[6] = { { -2, 0}, { -1, -2}, { -1, 2}, {2, 0}, {1, 2}, {1, -2} } ;
+    MV neighbors[8] = { { -1, -1}, { -1, 0}, { -1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1} } ;
+    int i, j;
+    unsigned char *src = (*(b->base_src) + b->src);
+    int src_stride = b->src_stride;
+    //int rr= ref_mv->row,rc= ref_mv->col,br=rr,bc=rc,tr,tc;
+    int rr = ref_mv->row, rc = ref_mv->col, br = rr >> 3, bc = rc >> 3, tr, tc;
+    unsigned int besterr, thiserr = 0x7fffffff;
+
+    /*
+        if ( rc < x->mv_col_min) bc = x->mv_col_min;
+        if ( rc > x->mv_col_max) bc = x->mv_col_max;
+        if ( rr < x->mv_row_min) br = x->mv_row_min;
+        if ( rr > x->mv_row_max) br = x->mv_row_max;
+        rr>>=1;
+        rc>>=1;
+        br>>=3;
+        bc>>=3;
+    */
+    if (bc < x->mv_col_min) bc = x->mv_col_min;
+
+    if (bc > x->mv_col_max) bc = x->mv_col_max;
+
+    if (br < x->mv_row_min) br = x->mv_row_min;
+
+    if (br > x->mv_row_max) br = x->mv_row_max;
+
+    rr >>= 1;
+    rc >>= 1;
+
+    besterr = ERR(br, bc, thiserr);
+
+    // hex search  jbb changed to 127 to avoid max 256 problem steping by 2.
+    for (j = 0; j < 127; j++)
+    {
+        tr = br;
+        tc = bc;
+
+        for (i = 0; i < 6; i++)
+        {
+            int nr = tr + hex[i].row, nc = tc + hex[i].col;
+
+            if (nc < x->mv_col_min) continue;
+
+            if (nc > x->mv_col_max) continue;
+
+            if (nr < x->mv_row_min) continue;
+
+            if (nr > x->mv_row_max) continue;
+
+            CHECK_BETTER(thiserr, nr, nc);
+        }
+
+        if (tr == br && tc == bc)
+            break;
+    }
+
+    // check 8 1 away neighbors
+    tr = br;
+    tc = bc;
+
+    for (i = 0; i < 8; i++)
+    {
+        int nr = tr + neighbors[i].row, nc = tc + neighbors[i].col;
+
+        if (nc < x->mv_col_min) continue;
+
+        if (nc > x->mv_col_max) continue;
+
+        if (nr < x->mv_row_min) continue;
+
+        if (nr > x->mv_row_max) continue;
+
+        CHECK_BETTER(thiserr, nr, nc);
+    }
+
+    best_mv->row = br;
+    best_mv->col = bc;
+
+    return vf(src, src_stride, PRE(br, bc), d->pre_stride, &thiserr) + MVC(br, bc) ;
+}
+#undef MVC
+#undef PRE
+#undef SP
+#undef DIST
+#undef ERR
+#undef CHECK_BETTER
+
+#endif
+
+int vp8_diamond_search_sad
+(
+    MACROBLOCK *x,
+    BLOCK *b,
+    BLOCKD *d,
+    MV *ref_mv,
+    MV *best_mv,
+    int search_param,
+    int error_per_bit,
+    int *num00,
+    vp8_variance_fn_ptr_t *fn_ptr,
+    int *mvsadcost[2],
+    int *mvcost[2]
+)
+{
+    int i, j, step;
+
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what;
+    int in_what_stride = d->pre_stride;
+    unsigned char *best_address;
+
+    int tot_steps;
+    MV this_mv;
+
+    int bestsad = INT_MAX;
+    int best_site = 0;
+    int last_site = 0;
+
+    int ref_row = ref_mv->row >> 3;
+    int ref_col = ref_mv->col >> 3;
+    int this_row_offset;
+    int this_col_offset;
+    search_site *ss;
+
+    unsigned char *check_here;
+    int thissad;
+
+    // Work out the start point for the search
+    in_what = (unsigned char *)(*(d->base_pre) + d->pre + (ref_row * (d->pre_stride)) + ref_col);
+    best_address = in_what;
+
+    // We need to check that the starting point for the search (as indicated by ref_mv) is within the buffer limits
+    if ((ref_col > x->mv_col_min) && (ref_col < x->mv_col_max) &&
+    (ref_row > x->mv_row_min) && (ref_row < x->mv_row_max))
+    {
+        // Check the starting position
+        bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride, 0x7fffffff) + vp8_mv_err_cost(ref_mv, ref_mv, mvsadcost, error_per_bit);
+    }
+
+    // search_param determines the length of the initial step and hence the number of iterations
+    // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 = (MAX_FIRST_STEP/4) pel... etc.
+    ss = &x->ss[search_param * x->searches_per_step];
+    tot_steps = (x->ss_count / x->searches_per_step) - search_param;
+
+    i = 1;
+    best_mv->row = ref_row;
+    best_mv->col = ref_col;
+
+    *num00 = 0;
+
+    for (step = 0; step < tot_steps ; step++)
+    {
+        for (j = 0 ; j < x->searches_per_step ; j++)
+        {
+            // Trap illegal vectors
+            this_row_offset = best_mv->row + ss[i].mv.row;
+            this_col_offset = best_mv->col + ss[i].mv.col;
+
+            if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) &&
+            (this_row_offset > x->mv_row_min) && (this_row_offset < x->mv_row_max))
+
+            {
+                check_here = ss[i].offset + best_address;
+                thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+                if (thissad < bestsad)
+                {
+                    this_mv.row = this_row_offset << 3;
+                    this_mv.col = this_col_offset << 3;
+                    thissad += vp8_mv_err_cost(&this_mv, ref_mv, mvsadcost, error_per_bit);
+
+                    if (thissad < bestsad)
+                    {
+                        bestsad = thissad;
+                        best_site = i;
+                    }
+                }
+            }
+
+            i++;
+        }
+
+        if (best_site != last_site)
+        {
+            best_mv->row += ss[best_site].mv.row;
+            best_mv->col += ss[best_site].mv.col;
+            best_address += ss[best_site].offset;
+            last_site = best_site;
+        }
+        else if (best_address == in_what)
+            (*num00)++;
+    }
+
+    this_mv.row = best_mv->row << 3;
+    this_mv.col = best_mv->col << 3;
+
+    if (bestsad == INT_MAX)
+        return INT_MAX;
+
+    return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
+    + vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+}
+
+int vp8_diamond_search_sadx4
+(
+    MACROBLOCK *x,
+    BLOCK *b,
+    BLOCKD *d,
+    MV *ref_mv,
+    MV *best_mv,
+    int search_param,
+    int error_per_bit,
+    int *num00,
+    vp8_variance_fn_ptr_t *fn_ptr,
+    int *mvsadcost[2],
+    int *mvcost[2]
+)
+{
+    int i, j, step;
+
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what;
+    int in_what_stride = d->pre_stride;
+    unsigned char *best_address;
+
+    int tot_steps;
+    MV this_mv;
+
+    int bestsad = INT_MAX;
+    int best_site = 0;
+    int last_site = 0;
+
+    int ref_row = ref_mv->row >> 3;
+    int ref_col = ref_mv->col >> 3;
+    int this_row_offset;
+    int this_col_offset;
+    search_site *ss;
+
+    unsigned char *check_here;
+    int thissad;
+
+    // Work out the start point for the search
+    in_what = (unsigned char *)(*(d->base_pre) + d->pre + (ref_row * (d->pre_stride)) + ref_col);
+    best_address = in_what;
+
+    // We need to check that the starting point for the search (as indicated by ref_mv) is within the buffer limits
+    if ((ref_col > x->mv_col_min) && (ref_col < x->mv_col_max) &&
+    (ref_row > x->mv_row_min) && (ref_row < x->mv_row_max))
+    {
+        // Check the starting position
+        bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride, 0x7fffffff) + vp8_mv_err_cost(ref_mv, ref_mv, mvsadcost, error_per_bit);
+    }
+
+    // search_param determines the length of the initial step and hence the number of iterations
+    // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 = (MAX_FIRST_STEP/4) pel... etc.
+    ss = &x->ss[search_param * x->searches_per_step];
+    tot_steps = (x->ss_count / x->searches_per_step) - search_param;
+
+    i = 1;
+    best_mv->row = ref_row;
+    best_mv->col = ref_col;
+
+    *num00 = 0;
+
+    for (step = 0; step < tot_steps ; step++)
+    {
+        int check_row_min, check_col_min, check_row_max, check_col_max;
+
+        check_row_min = x->mv_row_min - best_mv->row;
+        check_row_max = x->mv_row_max - best_mv->row;
+        check_col_min = x->mv_col_min - best_mv->col;
+        check_col_max = x->mv_col_max - best_mv->col;
+
+        for (j = 0 ; j < x->searches_per_step ; j += 4)
+        {
+            char *block_offset[4];
+            unsigned int valid_block[4];
+            int all_in = 1, t;
+
+            for (t = 0; t < 4; t++)
+            {
+                valid_block [t]  = (ss[t+i].mv.col > check_col_min);
+                valid_block [t] &= (ss[t+i].mv.col < check_col_max);
+                valid_block [t] &= (ss[t+i].mv.row > check_row_min);
+                valid_block [t] &= (ss[t+i].mv.row < check_row_max);
+
+                all_in &= valid_block[t];
+                block_offset[t] = ss[i+t].offset + best_address;
+            }
+
+            if (all_in)
+            {
+                int sad_array[4];
+
+                fn_ptr->sdx4df(what, what_stride, block_offset, in_what_stride, sad_array);
+
+                for (t = 0; t < 4; t++, i++)
+                {
+                    thissad = sad_array[t];
+
+                    if (thissad < bestsad)
+                    {
+                        this_mv.row = (best_mv->row + ss[i].mv.row) << 3;
+                        this_mv.col = (best_mv->col + ss[i].mv.col) << 3;
+                        thissad += vp8_mv_err_cost(&this_mv, ref_mv, mvsadcost, error_per_bit);
+
+                        if (thissad < bestsad)
+                        {
+                            bestsad = thissad;
+                            best_site = i;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                int t;
+
+                for (t = 0; t < 4; i++, t++)
+                {
+                    // Trap illegal vectors
+                    if (valid_block[t])
+
+                    {
+                        check_here = block_offset[t];
+                        thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+                        if (thissad < bestsad)
+                        {
+                            this_row_offset = best_mv->row + ss[i].mv.row;
+                            this_col_offset = best_mv->col + ss[i].mv.col;
+
+                            this_mv.row = this_row_offset << 3;
+                            this_mv.col = this_col_offset << 3;
+                            thissad += vp8_mv_err_cost(&this_mv, ref_mv, mvsadcost, error_per_bit);
+
+                            if (thissad < bestsad)
+                            {
+                                bestsad = thissad;
+                                best_site = i;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        if (best_site != last_site)
+        {
+            best_mv->row += ss[best_site].mv.row;
+            best_mv->col += ss[best_site].mv.col;
+            best_address += ss[best_site].offset;
+            last_site = best_site;
+        }
+        else if (best_address == in_what)
+            (*num00)++;
+    }
+
+    this_mv.row = best_mv->row << 3;
+    this_mv.col = best_mv->col << 3;
+
+    if (bestsad == INT_MAX)
+        return INT_MAX;
+
+    return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
+    + vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+}
+
+
+#if !(CONFIG_REALTIME_ONLY)
+int vp8_full_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, MV *ref_mv, int error_per_bit, int distance, vp8_variance_fn_ptr_t *fn_ptr, int *mvcost[2], int *mvsadcost[2])
+{
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what;
+    int in_what_stride = d->pre_stride;
+    int mv_stride = d->pre_stride;
+    unsigned char *bestaddress;
+    MV *best_mv = &d->bmi.mv.as_mv;
+    MV this_mv;
+    int bestsad = INT_MAX;
+    int r, c;
+
+    unsigned char *check_here;
+    int thissad;
+
+    int ref_row = ref_mv->row >> 3;
+    int ref_col = ref_mv->col >> 3;
+
+    int row_min = ref_row - distance;
+    int row_max = ref_row + distance;
+    int col_min = ref_col - distance;
+    int col_max = ref_col + distance;
+
+    // Work out the mid point for the search
+    in_what = *(d->base_pre) + d->pre;
+    bestaddress = in_what + (ref_row * d->pre_stride) + ref_col;
+
+    best_mv->row = ref_row;
+    best_mv->col = ref_col;
+
+    // We need to check that the starting point for the search (as indicated by ref_mv) is within the buffer limits
+    if ((ref_col > x->mv_col_min) && (ref_col < x->mv_col_max) &&
+    (ref_row > x->mv_row_min) && (ref_row < x->mv_row_max))
+    {
+        // Baseline value at the centre
+
+        //bestsad = fn_ptr->sf( what,what_stride,bestaddress,in_what_stride) + (int)sqrt(vp8_mv_err_cost(ref_mv,ref_mv, mvcost,error_per_bit*14));
+        bestsad = fn_ptr->sdf(what, what_stride, bestaddress, in_what_stride, 0x7fffffff) + vp8_mv_err_cost(ref_mv, ref_mv, mvsadcost, error_per_bit);
+    }
+
+    // Apply further limits to prevent us looking using vectors that stretch beyiond the UMV border
+    if (col_min < x->mv_col_min)
+        col_min = x->mv_col_min;
+
+    if (col_max > x->mv_col_max)
+        col_max = x->mv_col_max;
+
+    if (row_min < x->mv_row_min)
+        row_min = x->mv_row_min;
+
+    if (row_max > x->mv_row_max)
+        row_max = x->mv_row_max;
+
+    for (r = row_min; r < row_max ; r++)
+    {
+        this_mv.row = r << 3;
+        check_here = r * mv_stride + in_what + col_min;
+
+        for (c = col_min; c < col_max; c++)
+        {
+            thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+            this_mv.col = c << 3;
+            //thissad += (int)sqrt(vp8_mv_err_cost(&this_mv,ref_mv, mvcost,error_per_bit*14));
+            //thissad  += error_per_bit * mv_bits_sadcost[mv_bits(&this_mv, ref_mv, mvcost)];
+            thissad  += vp8_mv_err_cost(&this_mv, ref_mv, mvsadcost, error_per_bit); //mv_bits(error_per_bit, &this_mv, ref_mv, mvsadcost);
+
+            if (thissad < bestsad)
+            {
+                bestsad = thissad;
+                best_mv->row = r;
+                best_mv->col = c;
+                bestaddress = check_here;
+            }
+
+            check_here++;
+        }
+    }
+
+    this_mv.row = best_mv->row << 3;
+    this_mv.col = best_mv->col << 3;
+
+    if (bestsad < INT_MAX)
+        return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad))
+        + vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+    else
+        return INT_MAX;
+}
+
+int vp8_full_search_sadx3(MACROBLOCK *x, BLOCK *b, BLOCKD *d, MV *ref_mv, int error_per_bit, int distance, vp8_variance_fn_ptr_t *fn_ptr, int *mvcost[2], int *mvsadcost[2])
+{
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what;
+    int in_what_stride = d->pre_stride;
+    int mv_stride = d->pre_stride;
+    unsigned char *bestaddress;
+    MV *best_mv = &d->bmi.mv.as_mv;
+    MV this_mv;
+    int bestsad = INT_MAX;
+    int r, c;
+
+    unsigned char *check_here;
+    int thissad;
+
+    int ref_row = ref_mv->row >> 3;
+    int ref_col = ref_mv->col >> 3;
+
+    int row_min = ref_row - distance;
+    int row_max = ref_row + distance;
+    int col_min = ref_col - distance;
+    int col_max = ref_col + distance;
+
+    int sad_array[3];
+
+    // Work out the mid point for the search
+    in_what = *(d->base_pre) + d->pre;
+    bestaddress = in_what + (ref_row * d->pre_stride) + ref_col;
+
+    best_mv->row = ref_row;
+    best_mv->col = ref_col;
+
+    // We need to check that the starting point for the search (as indicated by ref_mv) is within the buffer limits
+    if ((ref_col > x->mv_col_min) && (ref_col < x->mv_col_max) &&
+    (ref_row > x->mv_row_min) && (ref_row < x->mv_row_max))
+    {
+        // Baseline value at the centre
+        bestsad = fn_ptr->sdf(what, what_stride, bestaddress, in_what_stride, 0x7fffffff) + vp8_mv_err_cost(ref_mv, ref_mv, mvsadcost, error_per_bit);
+    }
+
+    // Apply further limits to prevent us looking using vectors that stretch beyiond the UMV border
+    if (col_min < x->mv_col_min)
+        col_min = x->mv_col_min;
+
+    if (col_max > x->mv_col_max)
+        col_max = x->mv_col_max;
+
+    if (row_min < x->mv_row_min)
+        row_min = x->mv_row_min;
+
+    if (row_max > x->mv_row_max)
+        row_max = x->mv_row_max;
+
+    for (r = row_min; r < row_max ; r++)
+    {
+        this_mv.row = r << 3;
+        check_here = r * mv_stride + in_what + col_min;
+        c = col_min;
+
+        while ((c + 3) < col_max)
+        {
+            int i;
+
+            fn_ptr->sdx3f(what, what_stride, check_here , in_what_stride, sad_array);
+
+            for (i = 0; i < 3; i++)
+            {
+                thissad = sad_array[i];
+
+                if (thissad < bestsad)
+                {
+                    this_mv.col = c << 3;
+                    thissad  += vp8_mv_err_cost(&this_mv, ref_mv, mvsadcost, error_per_bit);
+
+                    if (thissad < bestsad)
+                    {
+                        bestsad = thissad;
+                        best_mv->row = r;
+                        best_mv->col = c;
+                        bestaddress = check_here;
+                    }
+                }
+
+                check_here++;
+                c++;
+            }
+        }
+
+        while (c < col_max)
+        {
+            thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+            if (thissad < bestsad)
+            {
+                this_mv.col = c << 3;
+                thissad  += vp8_mv_err_cost(&this_mv, ref_mv, mvsadcost, error_per_bit);
+
+                if (thissad < bestsad)
+                {
+                    bestsad = thissad;
+                    best_mv->row = r;
+                    best_mv->col = c;
+                    bestaddress = check_here;
+                }
+            }
+
+            check_here ++;
+            c ++;
+        }
+
+    }
+
+    this_mv.row = best_mv->row << 3;
+    this_mv.col = best_mv->col << 3;
+
+    if (bestsad < INT_MAX)
+        return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad))
+        + vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+    else
+        return INT_MAX;
+}
+#endif
+
+#ifdef ENTROPY_STATS
+void print_mode_context(void)
+{
+    FILE *f = fopen("modecont.c", "w");
+    int i, j;
+
+    fprintf(f, "#include \"entropy.h\"\n");
+    fprintf(f, "const int vp8_mode_contexts[6][4] =\n");
+    fprintf(f, "{\n");
+
+    for (j = 0; j < 6; j++)
+    {
+        fprintf(f, "  { // %d \n", j);
+        fprintf(f, "    ");
+
+        for (i = 0; i < 4; i++)
+        {
+            int overal_prob;
+            int this_prob;
+            int count; // = mv_ref_ct[j][i][0]+mv_ref_ct[j][i][1];
+
+            // Overall probs
+            count = mv_mode_cts[i][0] + mv_mode_cts[i][1];
+
+            if (count)
+                overal_prob = 256 * mv_mode_cts[i][0] / count;
+            else
+                overal_prob = 128;
+
+            if (overal_prob == 0)
+                overal_prob = 1;
+
+            // context probs
+            count = mv_ref_ct[j][i][0] + mv_ref_ct[j][i][1];
+
+            if (count)
+                this_prob = 256 * mv_ref_ct[j][i][0] / count;
+            else
+                this_prob = 128;
+
+            if (this_prob == 0)
+                this_prob = 1;
+
+            fprintf(f, "%5d, ", this_prob);
+            //fprintf(f,"%5d, %5d, %8d,", this_prob, overal_prob, (this_prob << 10)/overal_prob);
+            //fprintf(f,"%8d, ", (this_prob << 10)/overal_prob);
+        }
+
+        fprintf(f, "  },\n");
+    }
+
+    fprintf(f, "};\n");
+    fclose(f);
+}
+
+/* MV ref count ENTROPY_STATS stats code */
+#ifdef ENTROPY_STATS
+void init_mv_ref_counts()
+{
+    vpx_memset(mv_ref_ct, 0, sizeof(mv_ref_ct));
+    vpx_memset(mv_mode_cts, 0, sizeof(mv_mode_cts));
+}
+
+void accum_mv_refs(MB_PREDICTION_MODE m, const int ct[4])
+{
+    if (m == ZEROMV)
+    {
+        ++mv_ref_ct [ct[0]] [0] [0];
+        ++mv_mode_cts[0][0];
+    }
+    else
+    {
+        ++mv_ref_ct [ct[0]] [0] [1];
+        ++mv_mode_cts[0][1];
+
+        if (m == NEARESTMV)
+        {
+            ++mv_ref_ct [ct[1]] [1] [0];
+            ++mv_mode_cts[1][0];
+        }
+        else
+        {
+            ++mv_ref_ct [ct[1]] [1] [1];
+            ++mv_mode_cts[1][1];
+
+            if (m == NEARMV)
+            {
+                ++mv_ref_ct [ct[2]] [2] [0];
+                ++mv_mode_cts[2][0];
+            }
+            else
+            {
+                ++mv_ref_ct [ct[2]] [2] [1];
+                ++mv_mode_cts[2][1];
+
+                if (m == NEWMV)
+                {
+                    ++mv_ref_ct [ct[3]] [3] [0];
+                    ++mv_mode_cts[3][0];
+                }
+                else
+                {
+                    ++mv_ref_ct [ct[3]] [3] [1];
+                    ++mv_mode_cts[3][1];
+                }
+            }
+        }
+    }
+}
+
+#endif/* END MV ref count ENTROPY_STATS stats code */
+
+#endif
diff --git a/vp8/encoder/arm/neon/boolhuff_armv7.asm b/vp8/encoder/arm/neon/boolhuff_armv7.asm
new file mode 100644
index 0000000..9a5f366
--- /dev/null
+++ b/vp8/encoder/arm/neon/boolhuff_armv7.asm
@@ -0,0 +1,292 @@
+;
+;  Copyright (c) 2010 The VP8 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 |vp8_start_encode|
+    EXPORT |vp8_encode_bool|
+    EXPORT |vp8_stop_encode|
+    EXPORT |vp8_encode_value|
+
+    INCLUDE vpx_vp8_enc_asm_offsets.asm
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY
+
+; r0 BOOL_CODER *br
+; r1 unsigned char *source
+
+|vp8_start_encode| PROC
+    mov     r12, #0
+    mov     r3,  #255
+    mvn     r2,  #23
+    str     r12, [r0, #vp8_writer_lowvalue]
+    str     r3,  [r0, #vp8_writer_range]
+    str     r12, [r0, #vp8_writer_value]
+    str     r2,  [r0, #vp8_writer_count]
+    str     r12, [r0, #vp8_writer_pos]
+    str     r1,  [r0, #vp8_writer_buffer]
+    bx      lr
+    ENDP
+
+; r0 BOOL_CODER *br
+; r1 int bit
+; r2 int probability
+|vp8_encode_bool| PROC
+    push    {r4-r9, lr}
+
+    mov     r4, r2
+
+    ldr     r2, [r0, #vp8_writer_lowvalue]
+    ldr     r5, [r0, #vp8_writer_range]
+    ldr     r3, [r0, #vp8_writer_count]
+
+    sub     r7, r5, #1                  ; range-1
+
+    cmp     r1, #0
+    mul     r4, r4, r7                  ; ((range-1) * probability)
+
+    mov     r7, #1
+    add     r4, r7, r4, lsr #8          ; 1 + (((range-1) * probability) >> 8)
+
+    addne   r2, r2, r4                  ; if  (bit) lowvalue += split
+    subne   r4, r5, r4                  ; if  (bit) range = range-split
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start
+token_zero_while_loop
+    mov     r9, #0
+    strb    r9, [r7, r4]                ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r1, [r7, r4]
+    cmpge   r1, #0xff
+    beq     token_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r9, [r7, r4]                ; w->buffer[x]
+    add     r9, r9, #1
+    strb    r9, [r7, r4]                ; w->buffer[x] + 1
+token_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r9, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r1, r4, #1                  ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r1, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+    strb    r7, [r9, r4]                ; w->buffer[w->pos++]
+
+token_count_lt_zero
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    str     r2, [r0, #vp8_writer_lowvalue]
+    str     r5, [r0, #vp8_writer_range]
+    str     r3, [r0, #vp8_writer_count]
+    pop     {r4-r9, pc}
+    ENDP
+
+; r0 BOOL_CODER *br
+|vp8_stop_encode| PROC
+    push    {r4-r10, lr}
+
+    ldr     r2, [r0, #vp8_writer_lowvalue]
+    ldr     r5, [r0, #vp8_writer_range]
+    ldr     r3, [r0, #vp8_writer_count]
+
+    mov     r10, #32
+
+stop_encode_loop
+    sub     r7, r5, #1                  ; range-1
+
+    mov     r4, r7, lsl #7              ; ((range-1) * 128)
+
+    mov     r7, #1
+    add     r4, r7, r4, lsr #8          ; 1 + (((range-1) * 128) >> 8)
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero_se      ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set_se
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start_se
+token_zero_while_loop_se
+    mov     r9, #0
+    strb    r9, [r7, r4]                ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start_se
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r1, [r7, r4]
+    cmpge   r1, #0xff
+    beq     token_zero_while_loop_se
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r9, [r7, r4]                ; w->buffer[x]
+    add     r9, r9, #1
+    strb    r9, [r7, r4]                ; w->buffer[x] + 1
+token_high_bit_not_set_se
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r9, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r1, r4, #1                  ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r1, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+    strb    r7, [r9, r4]                ; w->buffer[w->pos++]
+
+token_count_lt_zero_se
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    subs    r10, r10, #1
+    bne     stop_encode_loop
+
+    str     r2, [r0, #vp8_writer_lowvalue]
+    str     r5, [r0, #vp8_writer_range]
+    str     r3, [r0, #vp8_writer_count]
+    pop     {r4-r10, pc}
+
+    ENDP
+
+; r0 BOOL_CODER *br
+; r1 int data
+; r2 int bits
+|vp8_encode_value| PROC
+    push    {r4-r11, lr}
+
+    mov     r10, r2
+
+    ldr     r2, [r0, #vp8_writer_lowvalue]
+    ldr     r5, [r0, #vp8_writer_range]
+    ldr     r3, [r0, #vp8_writer_count]
+
+    ; reverse the stream of bits to be packed.  Normally
+    ; the most significant bit is peeled off and compared
+    ; in the form of (v >> --n) & 1.  ARM architecture has
+    ; the ability to set a flag based on the value of the
+    ; bit shifted off the bottom of the register.  To make
+    ; that happen the bitstream is reversed.
+    rbit    r11, r1
+    rsb     r4, r10, #32                 ; 32-n
+
+    ; v is kept in r1 during the token pack loop
+    lsr     r1, r11, r4                 ; v >>= 32 - n
+
+encode_value_loop
+    sub     r7, r5, #1                  ; range-1
+
+    ; Decisions are made based on the bit value shifted
+    ; off of v, so set a flag here based on this.
+    ; This value is refered to as "bb"
+    lsrs    r1, r1, #1                  ; bit = v >> n
+    mov     r4, r7, lsl #7              ; ((range-1) * 128)
+
+    mov     r7, #1
+    add     r4, r7, r4, lsr #8          ; 1 + (((range-1) * 128) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bit) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bit) range = range-split
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero_ev      ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set_ev
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start_ev
+token_zero_while_loop_ev
+    mov     r9, #0
+    strb    r9, [r7, r4]                ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start_ev
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     token_zero_while_loop_ev
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r9, [r7, r4]                ; w->buffer[x]
+    add     r9, r9, #1
+    strb    r9, [r7, r4]                ; w->buffer[x] + 1
+token_high_bit_not_set_ev
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r9, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+    strb    r7, [r9, r4]                ; w->buffer[w->pos++]
+
+token_count_lt_zero_ev
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    subs    r10, r10, #1
+    bne     encode_value_loop
+
+    str     r2, [r0, #vp8_writer_lowvalue]
+    str     r5, [r0, #vp8_writer_range]
+    str     r3, [r0, #vp8_writer_count]
+    pop     {r4-r11, pc}
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/fastfdct4x4_neon.asm b/vp8/encoder/arm/neon/fastfdct4x4_neon.asm
new file mode 100644
index 0000000..d5dec44
--- /dev/null
+++ b/vp8/encoder/arm/neon/fastfdct4x4_neon.asm
@@ -0,0 +1,126 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_fast_fdct4x4_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;void vp8_fast_fdct4x4_c(short *input, short *output, int pitch);
+;NOTE:
+;The input *src_diff. src_diff is calculated as:
+;diff_ptr[c] = src_ptr[c] - pred_ptr[c]; (in Subtract* function)
+;In which *src_ptr and *pred_ptr both are unsigned char.
+;Therefore, *src_diff should be in the range of [-255, 255].
+;CAUTION:
+;The input values of 25th block are set in vp8_build_dcblock function, which are out of [-255, 255].
+;But, VP8 encoder only uses vp8_short_fdct4x4_c for 25th block, not vp8_fast_fdct4x4_c. That makes
+;it ok for assuming *input in [-255, 255] in vp8_fast_fdct4x4_c, but not ok in vp8_short_fdct4x4_c.
+
+|vp8_fast_fdct4x4_neon| PROC
+    vld1.16         {d2}, [r0], r2              ;load input
+    ldr             r12, _ffdct_coeff_
+    vld1.16         {d3}, [r0], r2
+    vld1.16         {d4}, [r0], r2
+    vld1.16         {d0}, [r12]
+    vld1.16         {d5}, [r0], r2
+
+    ;First for-loop
+    ;transpose d2, d3, d4, d5. Then, d2=ip[0], d3=ip[1], d4=ip[2], d5=ip[3]
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+    vadd.s16        d6, d2, d5              ;ip[0]+ip[3]
+    vadd.s16        d7, d3, d4              ;ip[1]+ip[2]
+    vsub.s16        d8, d3, d4              ;ip[1]-ip[2]
+    vsub.s16        d9, d2, d5              ;ip[0]-ip[3]
+    vshl.i16        q3, q3, #1              ; a1, b1
+    vshl.i16        q4, q4, #1              ; c1, d1
+
+    vadd.s16        d10, d6, d7             ;temp1 = a1 + b1
+    vsub.s16        d11, d6, d7             ;temp2 = a1 - b1
+
+    vqdmulh.s16     q6, q5, d0[1]
+    vqdmulh.s16     q8, q4, d0[0]
+    vqdmulh.s16     q7, q4, d0[2]
+
+    vshr.s16        q6, q6, #1
+    vshr.s16        q8, q8, #1
+    vshr.s16        q7, q7, #1              ;d14:temp1 = ( c1 * x_c3)>>16;  d15:temp1 =  (d1 * x_c3)>>16
+    vadd.s16        q8, q4, q8              ;d16:temp2 = ((c1 * x_c1)>>16) + c1;  d17:temp2 = ((d1 * x_c1)>>16) + d1
+
+    vadd.s16        d2, d10, d12            ;op[0] = ((temp1 * x_c2 )>>16) + temp1
+    vadd.s16        d4, d11, d13            ;op[2] = ((temp2 * x_c2 )>>16) + temp2
+    vadd.s16        d3, d14, d17            ;op[1] = temp1 + temp2  -- q is not necessary, just for protection
+    vsub.s16        d5, d15, d16            ;op[3] = temp1 - temp2
+
+    ;Second for-loop
+    ;transpose d2, d3, d4, d5. Then, d2=ip[0], d3=ip[4], d4=ip[8], d5=ip[12]
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+    vadd.s16        d6, d2, d5              ;a1 = ip[0]+ip[12]
+    vadd.s16        d7, d3, d4              ;b1 = ip[4]+ip[8]
+    vsub.s16        d8, d3, d4              ;c1 = ip[4]-ip[8]
+    vsub.s16        d9, d2, d5              ;d1 = ip[0]-ip[12]
+
+    vadd.s16        d10, d6, d7             ;temp1 = a1 + b1
+    vsub.s16        d11, d6, d7             ;temp2 = a1 - b1
+
+
+    vqdmulh.s16     q6, q5, d0[1]
+    vqdmulh.s16     q8, q4, d0[0]
+    vqdmulh.s16     q7, q4, d0[2]
+
+    vshr.s16        q6, q6, #1
+    vshr.s16        q8, q8, #1
+    vshr.s16        q7, q7, #1              ;d14:temp1 = ( c1 * x_c3)>>16;  d15:temp1 =  (d1 * x_c3)>>16
+    vadd.s16        q8, q4, q8              ;d16:temp2 = ((c1 * x_c1)>>16) + c1;  d17:temp2 = ((d1 * x_c1)>>16) + d1
+
+    vadd.s16        d2, d10, d12            ;a2 = ((temp1 * x_c2 )>>16) + temp1
+    vadd.s16        d4, d11, d13            ;c2 = ((temp2 * x_c2 )>>16) + temp2
+    vadd.s16        d3, d14, d17            ;b2 = temp1 + temp2  -- q is not necessary, just for protection
+    vsub.s16        d5, d15, d16            ;d2 = temp1 - temp2
+
+    vclt.s16        q3, q1, #0
+    vclt.s16        q4, q2, #0
+
+    vsub.s16        q1, q1, q3
+    vsub.s16        q2, q2, q4
+
+    vshr.s16        q1, q1, #1
+    vshr.s16        q2, q2, #1
+
+    vst1.16         {q1, q2}, [r1]
+
+    bx              lr
+
+    ENDP
+
+;-----------------
+    AREA    fastfdct_dat, DATA, READONLY
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_ffdct_coeff_
+    DCD     ffdct_coeff
+ffdct_coeff
+; 60547 =  0xEC83
+; 46341 =  0xB505
+; 25080 =  0x61F8
+    DCD     0xB505EC83, 0x000061F8
+
+    END
diff --git a/vp8/encoder/arm/neon/fastfdct8x4_neon.asm b/vp8/encoder/arm/neon/fastfdct8x4_neon.asm
new file mode 100644
index 0000000..de1c254
--- /dev/null
+++ b/vp8/encoder/arm/neon/fastfdct8x4_neon.asm
@@ -0,0 +1,179 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_fast_fdct8x4_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;void vp8_fast_fdct4x4_c(short *input, short *output, int pitch);
+;NOTE:
+;The input *src_diff. src_diff is calculated as:
+;diff_ptr[c] = src_ptr[c] - pred_ptr[c]; (in Subtract* function)
+;In which *src_ptr and *pred_ptr both are unsigned char.
+;Therefore, *src_diff should be in the range of [-255, 255].
+;CAUTION:
+;The input values of 25th block are set in vp8_build_dcblock function, which are out of [-255, 255].
+;But, VP8 encoder only uses vp8_short_fdct4x4_c for 25th block, not vp8_fast_fdct4x4_c. That makes
+;it ok for assuming *input in [-255, 255] in vp8_fast_fdct4x4_c, but not ok in vp8_short_fdct4x4_c.
+
+|vp8_fast_fdct8x4_neon| PROC
+    vld1.16         {q1}, [r0], r2              ;load input
+    ldr             r12, _ffdct8_coeff_
+    vld1.16         {q2}, [r0], r2
+    vld1.16         {q3}, [r0], r2
+    vld1.16         {d0}, [r12]
+    vld1.16         {q4}, [r0], r2
+
+    ;First for-loop
+    ;transpose d2, d4, d6, d8. Then, d2=ip[0], d4=ip[1], d6=ip[2], d8=ip[3]
+    ;transpose d3, d5, d7, d9. Then, d3=ip[0], d5=ip[1], d7=ip[2], d9=ip[3]
+    vtrn.32         d2, d6
+    vtrn.32         d3, d7
+    vtrn.32         d4, d8
+    vtrn.32         d5, d9
+    vtrn.16         d2, d4
+    vtrn.16         d3, d5
+    vtrn.16         d6, d8
+    vtrn.16         d7, d9
+
+    vadd.s16        d10, d2, d8             ;ip[0]+ip[3]
+    vadd.s16        d11, d4, d6             ;ip[1]+ip[2]
+    vsub.s16        d12, d4, d6             ;ip[1]-ip[2]
+    vsub.s16        d13, d2, d8             ;ip[0]-ip[3]
+    vadd.s16        d22, d3, d9
+    vadd.s16        d23, d5, d7
+    vsub.s16        d24, d5, d7
+    vsub.s16        d25, d3, d9
+
+    vshl.i16        q5, q5, #1              ; a1, b1
+    vshl.i16        q6, q6, #1              ; c1, d1
+    vshl.i16        q1, q11, #1
+    vshl.i16        q2, q12, #1
+
+    vadd.s16        d14, d10, d11           ;temp1 = a1 + b1
+    vsub.s16        d15, d10, d11           ;temp2 = a1 - b1
+    vadd.s16        d24, d2, d3
+    vsub.s16        d25, d2, d3
+
+    vqdmulh.s16     q8, q7, d0[1]
+    vqdmulh.s16     q13, q12, d0[1]
+    vqdmulh.s16     q10, q6, d0[0]
+    vqdmulh.s16     q15, q2, d0[0]
+    vqdmulh.s16     q9, q6, d0[2]
+    vqdmulh.s16     q14, q2, d0[2]
+
+    vshr.s16        q8, q8, #1
+    vshr.s16        q13, q13, #1
+    vshr.s16        q10, q10, #1
+    vshr.s16        q15, q15, #1
+    vshr.s16        q9, q9, #1              ;d18:temp1 = ( c1 * x_c3)>>16;  d19:temp1 =  (d1 * x_c3)>>16
+    vshr.s16        q14, q14, #1            ;d28:temp1 = ( c1 * x_c3)>>16;  d29:temp1 =  (d1 * x_c3)>>16
+    vadd.s16        q10, q6, q10            ;d20:temp2 = ((c1 * x_c1)>>16) + c1;  d21:temp2 = ((d1 * x_c1)>>16) + d1
+    vadd.s16        q15, q2, q15            ;d30:temp2 = ((c1 * x_c1)>>16) + c1;  d31:temp2 = ((d1 * x_c1)>>16) + d1
+
+    vadd.s16        d2, d14, d16            ;op[0] = ((temp1 * x_c2 )>>16) + temp1
+    vadd.s16        d3, d24, d26            ;op[0] = ((temp1 * x_c2 )>>16) + temp1
+    vadd.s16        d6, d15, d17            ;op[2] = ((temp2 * x_c2 )>>16) + temp2
+    vadd.s16        d7, d25, d27            ;op[2] = ((temp2 * x_c2 )>>16) + temp2
+    vadd.s16        d4, d18, d21            ;op[1] = temp1 + temp2  -- q is not necessary, just for protection
+    vadd.s16        d5, d28, d31            ;op[1] = temp1 + temp2  -- q is not necessary, just for protection
+    vsub.s16        d8, d19, d20            ;op[3] = temp1 - temp2
+    vsub.s16        d9, d29, d30            ;op[3] = temp1 - temp2
+
+    ;Second for-loop
+    ;transpose d2, d4, d6, d8. Then, d2=ip[0], d4=ip[4], d6=ip[8], d8=ip[12]
+    ;transpose d3, d5, d7, d9. Then, d3=ip[0], d5=ip[4], d7=ip[8], d9=ip[12]
+    vtrn.32         d2, d6
+    vtrn.32         d3, d7
+    vtrn.32         d4, d8
+    vtrn.32         d5, d9
+    vtrn.16         d2, d4
+    vtrn.16         d3, d5
+    vtrn.16         d6, d8
+    vtrn.16         d7, d9
+
+    vadd.s16        d10, d2, d8             ;a1 = ip[0]+ip[12]
+    vadd.s16        d11, d4, d6             ;b1 = ip[4]+ip[8]
+    vsub.s16        d12, d4, d6             ;c1 = ip[4]-ip[8]
+    vsub.s16        d13, d2, d8             ;d1 = ip[0]-ip[12]
+    vadd.s16        d2, d3, d9
+    vadd.s16        d4, d5, d7
+    vsub.s16        d24, d5, d7
+    vsub.s16        d25, d3, d9
+
+    vadd.s16        d14, d10, d11           ;temp1 = a1 + b1
+    vsub.s16        d15, d10, d11           ;temp2 = a1 - b1
+    vadd.s16        d22, d2, d4
+    vsub.s16        d23, d2, d4
+
+    vqdmulh.s16     q8, q7, d0[1]
+    vqdmulh.s16     q13, q11, d0[1]
+    vqdmulh.s16     q10, q6, d0[0]
+    vqdmulh.s16     q15, q12, d0[0]
+    vqdmulh.s16     q9, q6, d0[2]
+    vqdmulh.s16     q14, q12, d0[2]
+
+    vshr.s16        q8, q8, #1
+    vshr.s16        q13, q13, #1
+    vshr.s16        q10, q10, #1
+    vshr.s16        q15, q15, #1
+    vshr.s16        q9, q9, #1              ;d18:temp1 = ( c1 * x_c3)>>16;  d19:temp1 =  (d1 * x_c3)>>16
+    vshr.s16        q14, q14, #1            ;d28:temp1 = ( c1 * x_c3)>>16;  d29:temp1 =  (d1 * x_c3)>>16
+    vadd.s16        q10, q6, q10            ;d20:temp2 = ((c1 * x_c1)>>16) + c1;  d21:temp2 = ((d1 * x_c1)>>16) + d1
+    vadd.s16        q15, q12, q15           ;d30:temp2 = ((c1 * x_c1)>>16) + c1;  d31:temp2 = ((d1 * x_c1)>>16) + d1
+
+    vadd.s16        d2, d14, d16            ;a2 = ((temp1 * x_c2 )>>16) + temp1
+    vadd.s16        d6, d22, d26            ;a2 = ((temp1 * x_c2 )>>16) + temp1
+    vadd.s16        d4, d15, d17            ;c2 = ((temp2 * x_c2 )>>16) + temp2
+    vadd.s16        d8, d23, d27            ;c2 = ((temp2 * x_c2 )>>16) + temp2
+    vadd.s16        d3, d18, d21            ;b2 = temp1 + temp2  -- q is not necessary, just for protection
+    vadd.s16        d7, d28, d31            ;b2 = temp1 + temp2  -- q is not necessary, just for protection
+    vsub.s16        d5, d19, d20            ;d2 = temp1 - temp2
+    vsub.s16        d9, d29, d30            ;d2 = temp1 - temp2
+
+    vclt.s16        q5, q1, #0
+    vclt.s16        q6, q2, #0
+    vclt.s16        q7, q3, #0
+    vclt.s16        q8, q4, #0
+
+    vsub.s16        q1, q1, q5
+    vsub.s16        q2, q2, q6
+    vsub.s16        q3, q3, q7
+    vsub.s16        q4, q4, q8
+
+    vshr.s16        q1, q1, #1
+    vshr.s16        q2, q2, #1
+    vshr.s16        q3, q3, #1
+    vshr.s16        q4, q4, #1
+
+    vst1.16         {q1, q2}, [r1]!
+    vst1.16         {q3, q4}, [r1]
+
+    bx              lr
+
+    ENDP
+
+;-----------------
+    AREA    fastfdct8x4_dat, DATA, READONLY
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_ffdct8_coeff_
+    DCD     ffdct8_coeff
+ffdct8_coeff
+; 60547 =  0xEC83
+; 46341 =  0xB505
+; 25080 =  0x61F8
+    DCD     0xB505EC83, 0x000061F8
+
+    END
diff --git a/vp8/encoder/arm/neon/fastquantizeb_neon.asm b/vp8/encoder/arm/neon/fastquantizeb_neon.asm
new file mode 100644
index 0000000..1107037
--- /dev/null
+++ b/vp8/encoder/arm/neon/fastquantizeb_neon.asm
@@ -0,0 +1,117 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_fast_quantize_b_neon_func|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0        short *coeff_ptr
+; r1        short *zbin_ptr
+; r2        short *qcoeff_ptr
+; r3        short *dqcoeff_ptr
+; stack     short *dequant_ptr
+; stack     short *scan_mask
+; stack     short *round_ptr
+; stack     short *quant_ptr
+
+; return    int * eob
+|vp8_fast_quantize_b_neon_func| PROC
+    vld1.16         {q0, q1}, [r0]              ;load z
+    vld1.16         {q10, q11}, [r1]            ;load zbin
+
+    vabs.s16        q4, q0                      ;calculate x = abs(z)
+    vabs.s16        q5, q1
+
+    vcge.s16        q10, q4, q10                ;x>=zbin
+    vcge.s16        q11, q5, q11
+
+    ;if x<zbin (q10 & q11 are all 0), go to zero_output
+    vorr.s16        q6, q10, q11
+    vorr.s16        d12, d12, d13
+    vmov            r0, r1, d12
+    orr             r0, r0, r1
+    cmp             r0, #0
+    beq             zero_output
+
+    ldr             r0, [sp, #8]                ;load round_ptr
+    ldr             r12, [sp, #12]              ;load quant_ptr
+
+    ;right shift 15 to get sign, all 0 if it is positive, all 1 if it is negative
+    vshr.s16        q2, q0, #15                 ; sz
+    vshr.s16        q3, q1, #15
+
+    vld1.s16        {q6, q7}, [r0]              ;load round_ptr [0-15]
+    vld1.s16        {q8, q9}, [r12]             ;load quant_ptr [0-15]
+
+    vadd.s16        q4, q6                      ;x + Round
+    vadd.s16        q5, q7
+
+    ldr             r0, [sp, #4]                ;load rvsplus1_scan_order ptr
+
+    vqdmulh.s16     q4, q8                      ;y = ((Round + abs(z)) * Quant) >> 16
+    vqdmulh.s16     q5, q9
+
+    vld1.16         {q0, q1}, [r0]              ;load rvsplus1_scan_order
+    vceq.s16        q8, q8                      ;set q8 to all 1
+
+    vshr.s16        q4, #1                      ;right shift 1 after vqdmulh
+    vshr.s16        q5, #1
+
+    ;modify data to have its original sign
+    veor.s16        q4, q2                      ; y^sz
+    veor.s16        q5, q3
+
+    ldr             r12, [sp]                   ;load dequant_ptr
+
+    vsub.s16        q4, q2                      ; x1 = (y^sz) - sz = (y^sz) - (-1) (two's complement)
+    vsub.s16        q5, q3
+
+    vand.s16        q4, q10                     ;mask off x1 elements
+    vand.s16        q5, q11
+
+    vld1.s16        {q6, q7}, [r12]             ;load dequant_ptr[i]
+
+    vtst.16         q14, q4, q8                 ;now find eob
+    vtst.16         q15, q5, q8                 ;non-zero element is set to all 1 in q4, q5
+
+    vst1.s16        {q4, q5}, [r2]              ;store: qcoeff = x1
+
+    vand            q0, q0, q14                 ;get all valid number from rvsplus1_scan_order array
+    vand            q1, q1, q15
+
+    vmax.u16        q0, q0, q1                  ;find maximum value in q0, q1
+    vmax.u16        d0, d0, d1
+    vmovl.u16       q0, d0
+
+    vmul.s16        q6, q4                      ;x * Dequant
+    vmul.s16        q7, q5
+
+    vmax.u32        d0, d0, d1
+    vpmax.u32       d0, d0, d0
+
+    vst1.s16        {q6, q7}, [r3]              ;store dqcoeff = x * Dequant
+
+    vmov.32         r0, d0[0]
+    bx              lr
+
+zero_output
+    vst1.s16        {q10, q11}, [r2]        ; qcoeff = 0
+    vst1.s16        {q10, q11}, [r3]        ; dqcoeff = 0
+    mov             r0, #0
+
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/sad16_neon.asm b/vp8/encoder/arm/neon/sad16_neon.asm
new file mode 100644
index 0000000..6169f10
--- /dev/null
+++ b/vp8/encoder/arm/neon/sad16_neon.asm
@@ -0,0 +1,206 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_sad16x16_neon|
+    EXPORT  |vp8_sad16x8_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *src_ptr
+; r1    int  src_stride
+; r2    unsigned char *ref_ptr
+; r3    int  ref_stride
+|vp8_sad16x16_neon| PROC
+;;
+    vld1.8          {q0}, [r0], r1
+    vld1.8          {q4}, [r2], r3
+
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+
+    vabdl.u8        q12, d0, d8
+    vabdl.u8        q13, d1, d9
+
+    vld1.8          {q2}, [r0], r1
+    vld1.8          {q6}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+    vabal.u8        q13, d3, d11
+
+    vld1.8          {q3}, [r0], r1
+    vld1.8          {q7}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q13, d5, d13
+
+;;
+    vld1.8          {q0}, [r0], r1
+    vld1.8          {q4}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+    vabal.u8        q13, d7, d15
+
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+    vabal.u8        q13, d1, d9
+
+    vld1.8          {q2}, [r0], r1
+    vld1.8          {q6}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+    vabal.u8        q13, d3, d11
+
+    vld1.8          {q3}, [r0], r1
+    vld1.8          {q7}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q13, d5, d13
+
+;;
+    vld1.8          {q0}, [r0], r1
+    vld1.8          {q4}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+    vabal.u8        q13, d7, d15
+
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+    vabal.u8        q13, d1, d9
+
+    vld1.8          {q2}, [r0], r1
+    vld1.8          {q6}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+    vabal.u8        q13, d3, d11
+
+    vld1.8          {q3}, [r0], r1
+    vld1.8          {q7}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q13, d5, d13
+
+;;
+    vld1.8          {q0}, [r0], r1
+    vld1.8          {q4}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+    vabal.u8        q13, d7, d15
+
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+    vabal.u8        q13, d1, d9
+
+    vld1.8          {q2}, [r0], r1
+    vld1.8          {q6}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+    vabal.u8        q13, d3, d11
+
+    vld1.8          {q3}, [r0]
+    vld1.8          {q7}, [r2]
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q13, d5, d13
+
+    vabal.u8        q12, d6, d14
+    vabal.u8        q13, d7, d15
+
+    vadd.u16        q0, q12, q13
+
+    vpaddl.u16      q1, q0
+    vpaddl.u32      q0, q1
+
+    vadd.u32        d0, d0, d1
+
+    vmov.32         r0, d0[0]
+
+    bx              lr
+
+    ENDP
+
+;==============================
+;unsigned int vp8_sad16x8_c(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+|vp8_sad16x8_neon| PROC
+    vld1.8          {q0}, [r0], r1
+    vld1.8          {q4}, [r2], r3
+
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+
+    vabdl.u8        q12, d0, d8
+    vabdl.u8        q13, d1, d9
+
+    vld1.8          {q2}, [r0], r1
+    vld1.8          {q6}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+    vabal.u8        q13, d3, d11
+
+    vld1.8          {q3}, [r0], r1
+    vld1.8          {q7}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q13, d5, d13
+
+    vld1.8          {q0}, [r0], r1
+    vld1.8          {q4}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+    vabal.u8        q13, d7, d15
+
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+    vabal.u8        q13, d1, d9
+
+    vld1.8          {q2}, [r0], r1
+    vld1.8          {q6}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+    vabal.u8        q13, d3, d11
+
+    vld1.8          {q3}, [r0], r1
+    vld1.8          {q7}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q13, d5, d13
+
+    vabal.u8        q12, d6, d14
+    vabal.u8        q13, d7, d15
+
+    vadd.u16        q0, q12, q13
+
+    vpaddl.u16      q1, q0
+    vpaddl.u32      q0, q1
+
+    vadd.u32        d0, d0, d1
+
+    vmov.32         r0, d0[0]
+
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/sad8_neon.asm b/vp8/encoder/arm/neon/sad8_neon.asm
new file mode 100644
index 0000000..28604dd
--- /dev/null
+++ b/vp8/encoder/arm/neon/sad8_neon.asm
@@ -0,0 +1,208 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_sad8x8_neon|
+    EXPORT  |vp8_sad8x16_neon|
+    EXPORT  |vp8_sad4x4_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; unsigned int vp8_sad8x8_c(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+
+|vp8_sad8x8_neon| PROC
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabdl.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q12, d6, d14
+
+    vpaddl.u16      q1, q12
+    vpaddl.u32      q0, q1
+    vadd.u32        d0, d0, d1
+
+    vmov.32         r0, d0[0]
+
+    bx              lr
+
+    ENDP
+
+;============================
+;unsigned int vp8_sad8x16_c(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+
+|vp8_sad8x16_neon| PROC
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabdl.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vabal.u8        q12, d6, d14
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabal.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q12, d6, d14
+
+    vpaddl.u16      q1, q12
+    vpaddl.u32      q0, q1
+    vadd.u32        d0, d0, d1
+
+    vmov.32         r0, d0[0]
+
+    bx              lr
+
+    ENDP
+
+;===========================
+;unsigned int vp8_sad4x4_c(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+
+|vp8_sad4x4_neon| PROC
+    vld1.8          {d0}, [r0], r1
+    vld1.8          {d8}, [r2], r3
+
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d10}, [r2], r3
+
+    vabdl.u8        q12, d0, d8
+
+    vld1.8          {d4}, [r0], r1
+    vld1.8          {d12}, [r2], r3
+
+    vabal.u8        q12, d2, d10
+
+    vld1.8          {d6}, [r0], r1
+    vld1.8          {d14}, [r2], r3
+
+    vabal.u8        q12, d4, d12
+    vabal.u8        q12, d6, d14
+
+    vpaddl.u16      d1, d24
+    vpaddl.u32      d0, d1
+    vmov.32         r0, d0[0]
+
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/shortfdct_neon.asm b/vp8/encoder/arm/neon/shortfdct_neon.asm
new file mode 100644
index 0000000..26bc0d0
--- /dev/null
+++ b/vp8/encoder/arm/neon/shortfdct_neon.asm
@@ -0,0 +1,146 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_short_fdct4x4_neon|
+    EXPORT  |vp8_short_fdct8x4_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    short *input
+; r1    short *output
+; r2    int pitch
+; Input has a pitch, output is contiguous
+|vp8_short_fdct4x4_neon| PROC
+    ldr             r12, _dct_matrix_
+    vld1.16         d0, [r0], r2
+    vld1.16         d1, [r0], r2
+    vld1.16         d2, [r0], r2
+    vld1.16         d3, [r0]
+    vld1.16         {q2, q3}, [r12]
+
+;first stage
+    vmull.s16       q11, d4, d0[0]              ;i=0
+    vmull.s16       q12, d4, d1[0]              ;i=1
+    vmull.s16       q13, d4, d2[0]              ;i=2
+    vmull.s16       q14, d4, d3[0]              ;i=3
+
+    vmlal.s16       q11, d5, d0[1]
+    vmlal.s16       q12, d5, d1[1]
+    vmlal.s16       q13, d5, d2[1]
+    vmlal.s16       q14, d5, d3[1]
+
+    vmlal.s16       q11, d6, d0[2]
+    vmlal.s16       q12, d6, d1[2]
+    vmlal.s16       q13, d6, d2[2]
+    vmlal.s16       q14, d6, d3[2]
+
+    vmlal.s16       q11, d7, d0[3]              ;sumtemp for i=0
+    vmlal.s16       q12, d7, d1[3]              ;sumtemp for i=1
+    vmlal.s16       q13, d7, d2[3]              ;sumtemp for i=2
+    vmlal.s16       q14, d7, d3[3]              ;sumtemp for i=3
+
+    ; rounding
+    vrshrn.i32      d22, q11, #14
+    vrshrn.i32      d24, q12, #14
+    vrshrn.i32      d26, q13, #14
+    vrshrn.i32      d28, q14, #14
+
+;second stage
+    vmull.s16       q4, d22, d4[0]              ;i=0
+    vmull.s16       q5, d22, d4[1]              ;i=1
+    vmull.s16       q6, d22, d4[2]              ;i=2
+    vmull.s16       q7, d22, d4[3]              ;i=3
+
+    vmlal.s16       q4, d24, d5[0]
+    vmlal.s16       q5, d24, d5[1]
+    vmlal.s16       q6, d24, d5[2]
+    vmlal.s16       q7, d24, d5[3]
+
+    vmlal.s16       q4, d26, d6[0]
+    vmlal.s16       q5, d26, d6[1]
+    vmlal.s16       q6, d26, d6[2]
+    vmlal.s16       q7, d26, d6[3]
+
+    vmlal.s16       q4, d28, d7[0]              ;sumtemp for i=0
+    vmlal.s16       q5, d28, d7[1]              ;sumtemp for i=1
+    vmlal.s16       q6, d28, d7[2]              ;sumtemp for i=2
+    vmlal.s16       q7, d28, d7[3]              ;sumtemp for i=3
+
+    vrshr.s32       q0, q4, #16
+    vrshr.s32       q1, q5, #16
+    vrshr.s32       q2, q6, #16
+    vrshr.s32       q3, q7, #16
+
+    vmovn.i32       d0, q0
+    vmovn.i32       d1, q1
+    vmovn.i32       d2, q2
+    vmovn.i32       d3, q3
+
+    vst1.16         {q0, q1}, [r1]
+
+    bx              lr
+
+    ENDP
+
+; r0    short *input
+; r1    short *output
+; r2    int pitch
+|vp8_short_fdct8x4_neon| PROC
+    ; Store link register and input before calling
+    ;  first 4x4 fdct.  Do not need to worry about
+    ;  output or pitch because those pointers are not
+    ;  touched in the 4x4 fdct function
+    stmdb           sp!, {r0, lr}
+
+    bl              vp8_short_fdct4x4_neon
+
+    ldmia           sp!, {r0, lr}
+
+    ; Move to the next block of data.
+    add             r0, r0, #8
+    add             r1, r1, #32
+
+    ; Second time through do not store off the
+    ;  link register, just return from the 4x4 fdtc
+    b               vp8_short_fdct4x4_neon
+
+    ; Should never get to this.
+    bx              lr
+
+    ENDP
+
+;-----------------
+    AREA    dct4x4_dat, DATA, READONLY
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_dct_matrix_
+    DCD     dct_matrix
+dct_matrix
+;   DCW     23170,  30274,  23170, 12540
+;   DCW     23170,  12540, -23170,-30274
+;   DCW     23170, -12540, -23170, 30274
+;   DCW     23170, -30274,  23170,-12540
+; 23170 =  0x5a82
+; -23170 =  0xa57e
+; 30274 =  0x7642
+; -30274 =  0x89be
+; 12540 =  0x30fc
+; -12540 = 0xcf04
+    DCD     0x76425a82, 0x30fc5a82
+    DCD     0x30fc5a82, 0x89bea57e
+    DCD     0xcf045a82, 0x7642a57e
+    DCD     0x89be5a82, 0xcf045a82
+
+    END
diff --git a/vp8/encoder/arm/neon/subtract_neon.asm b/vp8/encoder/arm/neon/subtract_neon.asm
new file mode 100644
index 0000000..8781ca0
--- /dev/null
+++ b/vp8/encoder/arm/neon/subtract_neon.asm
@@ -0,0 +1,171 @@
+;
+;  Copyright (c) 2010 The VP8 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 |vp8_subtract_b_neon_func|
+    EXPORT |vp8_subtract_mby_neon|
+    EXPORT |vp8_subtract_mbuv_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;=========================================
+;void vp8_subtract_b_neon_func(short *diff, unsigned char *src, unsigned char *pred, int stride, int pitch);
+|vp8_subtract_b_neon_func| PROC
+    ldr             r12, [sp]               ;load pitch
+
+    vld1.8          {d0}, [r1], r3          ;load src
+    vld1.8          {d1}, [r2], r12         ;load pred
+    vld1.8          {d2}, [r1], r3
+    vld1.8          {d3}, [r2], r12
+    vld1.8          {d4}, [r1], r3
+    vld1.8          {d5}, [r2], r12
+    vld1.8          {d6}, [r1], r3
+    vld1.8          {d7}, [r2], r12
+
+    vsubl.u8        q10, d0, d1
+    vsubl.u8        q11, d2, d3
+    vsubl.u8        q12, d4, d5
+    vsubl.u8        q13, d6, d7
+
+    mov             r12, r12, lsl #1
+
+    vst1.16         {d20}, [r0], r12        ;store diff
+    vst1.16         {d22}, [r0], r12
+    vst1.16         {d24}, [r0], r12
+    vst1.16         {d26}, [r0], r12
+
+    bx              lr
+    ENDP
+
+;==========================================
+;void vp8_subtract_mby_neon(short *diff, unsigned char *src, unsigned char *pred, int stride)
+|vp8_subtract_mby_neon| PROC
+    mov             r12, #4
+
+subtract_mby_loop
+    vld1.8          {q0}, [r1], r3          ;load src
+    vld1.8          {q1}, [r2]!             ;load pred
+    vld1.8          {q2}, [r1], r3
+    vld1.8          {q3}, [r2]!
+    vld1.8          {q4}, [r1], r3
+    vld1.8          {q5}, [r2]!
+    vld1.8          {q6}, [r1], r3
+    vld1.8          {q7}, [r2]!
+
+    vsubl.u8        q8, d0, d2
+    vsubl.u8        q9, d1, d3
+    vsubl.u8        q10, d4, d6
+    vsubl.u8        q11, d5, d7
+    vsubl.u8        q12, d8, d10
+    vsubl.u8        q13, d9, d11
+    vsubl.u8        q14, d12, d14
+    vsubl.u8        q15, d13, d15
+
+    vst1.16         {q8}, [r0]!             ;store diff
+    vst1.16         {q9}, [r0]!
+    vst1.16         {q10}, [r0]!
+    vst1.16         {q11}, [r0]!
+    vst1.16         {q12}, [r0]!
+    vst1.16         {q13}, [r0]!
+    vst1.16         {q14}, [r0]!
+    vst1.16         {q15}, [r0]!
+
+    subs            r12, r12, #1
+    bne             subtract_mby_loop
+
+    bx              lr
+    ENDP
+
+;=================================
+;void vp8_subtract_mbuv_neon(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride)
+|vp8_subtract_mbuv_neon| PROC
+    ldr             r12, [sp]
+
+;u
+    add             r0, r0, #512        ;   short *udiff = diff + 256;
+    add             r3, r3, #256        ;   unsigned char *upred = pred + 256;
+
+    vld1.8          {d0}, [r1], r12         ;load src
+    vld1.8          {d1}, [r3]!             ;load pred
+    vld1.8          {d2}, [r1], r12
+    vld1.8          {d3}, [r3]!
+    vld1.8          {d4}, [r1], r12
+    vld1.8          {d5}, [r3]!
+    vld1.8          {d6}, [r1], r12
+    vld1.8          {d7}, [r3]!
+    vld1.8          {d8}, [r1], r12
+    vld1.8          {d9}, [r3]!
+    vld1.8          {d10}, [r1], r12
+    vld1.8          {d11}, [r3]!
+    vld1.8          {d12}, [r1], r12
+    vld1.8          {d13}, [r3]!
+    vld1.8          {d14}, [r1], r12
+    vld1.8          {d15}, [r3]!
+
+    vsubl.u8        q8, d0, d1
+    vsubl.u8        q9, d2, d3
+    vsubl.u8        q10, d4, d5
+    vsubl.u8        q11, d6, d7
+    vsubl.u8        q12, d8, d9
+    vsubl.u8        q13, d10, d11
+    vsubl.u8        q14, d12, d13
+    vsubl.u8        q15, d14, d15
+
+    vst1.16         {q8}, [r0]!             ;store diff
+    vst1.16         {q9}, [r0]!
+    vst1.16         {q10}, [r0]!
+    vst1.16         {q11}, [r0]!
+    vst1.16         {q12}, [r0]!
+    vst1.16         {q13}, [r0]!
+    vst1.16         {q14}, [r0]!
+    vst1.16         {q15}, [r0]!
+
+;v
+    vld1.8          {d0}, [r2], r12         ;load src
+    vld1.8          {d1}, [r3]!             ;load pred
+    vld1.8          {d2}, [r2], r12
+    vld1.8          {d3}, [r3]!
+    vld1.8          {d4}, [r2], r12
+    vld1.8          {d5}, [r3]!
+    vld1.8          {d6}, [r2], r12
+    vld1.8          {d7}, [r3]!
+    vld1.8          {d8}, [r2], r12
+    vld1.8          {d9}, [r3]!
+    vld1.8          {d10}, [r2], r12
+    vld1.8          {d11}, [r3]!
+    vld1.8          {d12}, [r2], r12
+    vld1.8          {d13}, [r3]!
+    vld1.8          {d14}, [r2], r12
+    vld1.8          {d15}, [r3]!
+
+    vsubl.u8        q8, d0, d1
+    vsubl.u8        q9, d2, d3
+    vsubl.u8        q10, d4, d5
+    vsubl.u8        q11, d6, d7
+    vsubl.u8        q12, d8, d9
+    vsubl.u8        q13, d10, d11
+    vsubl.u8        q14, d12, d13
+    vsubl.u8        q15, d14, d15
+
+    vst1.16         {q8}, [r0]!             ;store diff
+    vst1.16         {q9}, [r0]!
+    vst1.16         {q10}, [r0]!
+    vst1.16         {q11}, [r0]!
+    vst1.16         {q12}, [r0]!
+    vst1.16         {q13}, [r0]!
+    vst1.16         {q14}, [r0]!
+    vst1.16         {q15}, [r0]!
+
+    bx              lr
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/variance_neon.asm b/vp8/encoder/arm/neon/variance_neon.asm
new file mode 100644
index 0000000..64b83ca
--- /dev/null
+++ b/vp8/encoder/arm/neon/variance_neon.asm
@@ -0,0 +1,275 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_variance16x16_neon|
+    EXPORT  |vp8_variance16x8_neon|
+    EXPORT  |vp8_variance8x16_neon|
+    EXPORT  |vp8_variance8x8_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+; r0    unsigned char *src_ptr
+; r1    int source_stride
+; r2    unsigned char *ref_ptr
+; r3    int  recon_stride
+; stack unsigned int *sse
+|vp8_variance16x16_neon| PROC
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    mov             r12, #8
+
+variance16x16_neon_loop
+    vld1.8          {q0}, [r0], r1              ;Load up source and reference
+    vld1.8          {q2}, [r2], r3
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q3}, [r2], r3
+
+    vsubl.u8        q11, d0, d4                 ;calculate diff
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    ;VPADAL adds adjacent pairs of elements of a vector, and accumulates
+    ;the results into the elements of the destination vector. The explanation
+    ;in ARM guide is wrong.
+    vpadal.s16      q8, q11                     ;calculate sum
+    vmlal.s16       q9, d22, d22                ;calculate sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    bne             variance16x16_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    ldr             r12, [sp]                   ;load *sse from stack
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    ;vmov.32        r0, d0[0]                   ;this instruction costs a lot
+    ;vmov.32        r1, d1[0]
+    ;mul            r0, r0, r0
+    ;str            r1, [r12]
+    ;sub            r0, r1, r0, asr #8
+
+    ;sum is in [-255x256, 255x256]. sumxsum is 32-bit. Shift to right should
+    ;have sign-bit exension, which is vshr.s. Have to use s32 to make it right.
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [r12]              ;store sse
+    vshr.s32        d10, d10, #8
+    vsub.s32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    bx              lr
+
+    ENDP
+
+;================================
+;unsigned int vp8_variance16x8_c(
+;    unsigned char *src_ptr,
+;    int  source_stride,
+;    unsigned char *ref_ptr,
+;    int  recon_stride,
+;   unsigned int *sse)
+|vp8_variance16x8_neon| PROC
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    mov             r12, #4
+
+variance16x8_neon_loop
+    vld1.8          {q0}, [r0], r1              ;Load up source and reference
+    vld1.8          {q2}, [r2], r3
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q3}, [r2], r3
+
+    vsubl.u8        q11, d0, d4                 ;calculate diff
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    vpadal.s16      q8, q11                     ;calculate sum
+    vmlal.s16       q9, d22, d22                ;calculate sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    bne             variance16x8_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    ldr             r12, [sp]                   ;load *sse from stack
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [r12]              ;store sse
+    vshr.s32        d10, d10, #7
+    vsub.s32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    bx              lr
+
+    ENDP
+
+;=================================
+;unsigned int vp8_variance8x16_c(
+;    unsigned char *src_ptr,
+;    int  source_stride,
+;    unsigned char *ref_ptr,
+;    int  recon_stride,
+;   unsigned int *sse)
+
+|vp8_variance8x16_neon| PROC
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    mov             r12, #8
+
+variance8x16_neon_loop
+    vld1.8          {d0}, [r0], r1              ;Load up source and reference
+    vld1.8          {d4}, [r2], r3
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d6}, [r2], r3
+
+    vsubl.u8        q11, d0, d4                 ;calculate diff
+    vsubl.u8        q12, d2, d6
+
+    vpadal.s16      q8, q11                     ;calculate sum
+    vmlal.s16       q9, d22, d22                ;calculate sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+
+    bne             variance8x16_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    ldr             r12, [sp]                   ;load *sse from stack
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [r12]              ;store sse
+    vshr.s32        d10, d10, #7
+    vsub.s32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    bx              lr
+
+    ENDP
+
+;==================================
+; r0    unsigned char *src_ptr
+; r1    int source_stride
+; r2    unsigned char *ref_ptr
+; r3    int  recon_stride
+; stack unsigned int *sse
+|vp8_variance8x8_neon| PROC
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    mov             r12, #2
+
+variance8x8_neon_loop
+    vld1.8          {d0}, [r0], r1              ;Load up source and reference
+    vld1.8          {d4}, [r2], r3
+    vld1.8          {d1}, [r0], r1
+    vld1.8          {d5}, [r2], r3
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d6}, [r2], r3
+    vld1.8          {d3}, [r0], r1
+    vld1.8          {d7}, [r2], r3
+
+    vsubl.u8        q11, d0, d4                 ;calculate diff
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    vpadal.s16      q8, q11                     ;calculate sum
+    vmlal.s16       q9, d22, d22                ;calculate sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    bne             variance8x8_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    ldr             r12, [sp]                   ;load *sse from stack
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [r12]              ;store sse
+    vshr.s32        d10, d10, #6
+    vsub.s32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/vp8_memcpy_neon.asm b/vp8/encoder/arm/neon/vp8_memcpy_neon.asm
new file mode 100644
index 0000000..f26b4d7
--- /dev/null
+++ b/vp8/encoder/arm/neon/vp8_memcpy_neon.asm
@@ -0,0 +1,67 @@
+;
+;  Copyright (c) 2010 The VP8 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 |vp8_memcpy_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;=========================================
+;void vp8_memcpy_neon(unsigned char *dst_ptr, unsigned char *src_ptr, int sz);
+|vp8_memcpy_neon| PROC
+    ;pld                [r1]                        ;preload pred data
+    ;pld                [r1, #128]
+    ;pld                [r1, #256]
+    ;pld                [r1, #384]
+
+    mov             r12, r2, lsr #8                 ;copy 256 bytes data at one time
+
+memcpy_neon_loop
+    vld1.8          {q0, q1}, [r1]!                 ;load src data
+    subs            r12, r12, #1
+    vld1.8          {q2, q3}, [r1]!
+    vst1.8          {q0, q1}, [r0]!                 ;copy to dst_ptr
+    vld1.8          {q4, q5}, [r1]!
+    vst1.8          {q2, q3}, [r0]!
+    vld1.8          {q6, q7}, [r1]!
+    vst1.8          {q4, q5}, [r0]!
+    vld1.8          {q8, q9}, [r1]!
+    vst1.8          {q6, q7}, [r0]!
+    vld1.8          {q10, q11}, [r1]!
+    vst1.8          {q8, q9}, [r0]!
+    vld1.8          {q12, q13}, [r1]!
+    vst1.8          {q10, q11}, [r0]!
+    vld1.8          {q14, q15}, [r1]!
+    vst1.8          {q12, q13}, [r0]!
+    vst1.8          {q14, q15}, [r0]!
+
+    ;pld                [r1]                        ;preload pred data -- need to adjust for real device
+    ;pld                [r1, #128]
+    ;pld                [r1, #256]
+    ;pld                [r1, #384]
+
+    bne             memcpy_neon_loop
+
+    ands            r3, r2, #0xff                   ;extra copy
+    beq             done_copy_neon_loop
+
+extra_copy_neon_loop
+    vld1.8          {q0}, [r1]!                 ;load src data
+    subs            r3, r3, #16
+    vst1.8          {q0}, [r0]!
+    bne             extra_copy_neon_loop
+
+done_copy_neon_loop
+    bx              lr
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/vp8_mse16x16_neon.asm b/vp8/encoder/arm/neon/vp8_mse16x16_neon.asm
new file mode 100644
index 0000000..f535967
--- /dev/null
+++ b/vp8/encoder/arm/neon/vp8_mse16x16_neon.asm
@@ -0,0 +1,172 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_mse16x16_neon|
+    EXPORT  |vp8_get16x16pred_error_neon|
+    EXPORT  |vp8_get4x4sse_cs_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;============================
+; r0    unsigned char *src_ptr
+; r1    int source_stride
+; r2    unsigned char *ref_ptr
+; r3    int  recon_stride
+; stack unsigned int *sse
+;note: in this function, sum is never used. So, we can remove this part of calculation
+;from vp8_variance().
+
+|vp8_mse16x16_neon| PROC
+    vmov.i8         q7, #0                      ;q7, q8, q9, q10 - sse
+    vmov.i8         q8, #0
+    vmov.i8         q9, #0
+    vmov.i8         q10, #0
+
+    mov             r12, #8
+
+mse16x16_neon_loop
+    vld1.8          {q0}, [r0], r1              ;Load up source and reference
+    vld1.8          {q2}, [r2], r3
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q3}, [r2], r3
+
+    vsubl.u8        q11, d0, d4
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    vmlal.s16       q7, d22, d22
+    vmlal.s16       q8, d23, d23
+
+    subs            r12, r12, #1
+
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vmlal.s16       q7, d26, d26
+    vmlal.s16       q8, d27, d27
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    bne             mse16x16_neon_loop
+
+    vadd.u32        q7, q7, q8
+    vadd.u32        q9, q9, q10
+
+    ldr             r12, [sp]               ;load *sse from stack
+
+    vadd.u32        q10, q7, q9
+    vpaddl.u32      q1, q10
+    vadd.u64        d0, d2, d3
+
+    vst1.32         {d0[0]}, [r12]
+    vmov.32         r0, d0[0]
+
+    bx              lr
+
+    ENDP
+
+;============================
+; r0    unsigned char *src_ptr
+; r1    int src_stride
+; r2    unsigned char *ref_ptr
+; r3    int ref_stride
+|vp8_get16x16pred_error_neon| PROC
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - pred_error
+    vmov.i8         q10, #0
+
+    mov             r12, #8
+
+get16x16pred_error_neon_loop
+    vld1.8          {q0}, [r0], r1              ;Load up source and reference
+    vld1.8          {q2}, [r2], r3
+    vld1.8          {q1}, [r0], r1
+    vld1.8          {q3}, [r2], r3
+
+    vsubl.u8        q11, d0, d4
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    vpadal.s16      q8, q11
+    vmlal.s16       q9, d22, d22
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    bne             get16x16pred_error_neon_loop
+
+    vadd.u32        q10, q9, q10
+    vpaddl.s32      q0, q8
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vshr.s32        d10, d10, #8
+    vsub.s32        d0, d1, d10
+
+    vmov.32         r0, d0[0]
+    bx              lr
+
+    ENDP
+
+;=============================
+; r0    unsigned char *src_ptr,
+; r1    int  source_stride,
+; r2    unsigned char *ref_ptr,
+; r3    int  recon_stride
+|vp8_get4x4sse_cs_neon| PROC
+    vld1.8          {d0}, [r0], r1              ;Load up source and reference
+    vld1.8          {d4}, [r2], r3
+    vld1.8          {d1}, [r0], r1
+    vld1.8          {d5}, [r2], r3
+    vld1.8          {d2}, [r0], r1
+    vld1.8          {d6}, [r2], r3
+    vld1.8          {d3}, [r0], r1
+    vld1.8          {d7}, [r2], r3
+
+    vsubl.u8        q11, d0, d4
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    vmull.s16       q7, d22, d22
+    vmull.s16       q8, d24, d24
+    vmull.s16       q9, d26, d26
+    vmull.s16       q10, d28, d28
+
+    vadd.u32        q7, q7, q8
+    vadd.u32        q9, q9, q10
+    vadd.u32        q9, q7, q9
+
+    vpaddl.u32      q1, q9
+    vadd.u64        d0, d2, d3
+
+    vmov.32         r0, d0[0]
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/vp8_packtokens_armv7.asm b/vp8/encoder/arm/neon/vp8_packtokens_armv7.asm
new file mode 100644
index 0000000..9c52c52
--- /dev/null
+++ b/vp8/encoder/arm/neon/vp8_packtokens_armv7.asm
@@ -0,0 +1,300 @@
+;
+;  Copyright (c) 2010 The VP8 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 |vp8cx_pack_tokens_armv7|
+
+    INCLUDE vpx_vp8_enc_asm_offsets.asm
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY
+
+; r0 vp8_writer *w
+; r1 const TOKENEXTRA *p
+; r2 int xcount
+; r3 vp8_coef_encodings
+; s0 vp8_extra_bits
+; s1 vp8_coef_tree
+|vp8cx_pack_tokens_armv7| PROC
+    push    {r4-r11, lr}
+
+    ; Add size of xcount * sizeof (TOKENEXTRA) to get stop
+    ;  sizeof (TOKENEXTRA) is 20
+    add     r2, r2, r2, lsl #2          ; xcount
+    sub     sp, sp, #12
+    add     r2, r1, r2, lsl #2          ; stop = p + xcount
+    str     r2, [sp, #0]
+    str     r3, [sp, #8]                ; save vp8_coef_encodings
+    ldr     r2, [r0, #vp8_writer_lowvalue]
+    ldr     r5, [r0, #vp8_writer_range]
+    ldr     r3, [r0, #vp8_writer_count]
+    b       check_p_lt_stop
+
+while_p_lt_stop
+    ldr     r6, [r1, #tokenextra_token] ; t
+    ldr     r4, [sp, #8]                ; vp8_coef_encodings
+    mov     lr, #0
+    add     r4, r4, r6, lsl #3          ; a = vp8_coef_encodings + t
+    ldr     r9, [r1, #tokenextra_context_tree]   ; pp
+
+    ldr     r7, [r1, #tokenextra_skip_eob_node]
+
+    ldr     r6, [r4, #vp8_token_value]  ; v
+    ldr     r8, [r4, #vp8_token_len]    ; n
+
+    ; vp8 specific skip_eob_node
+    cmp     r7, #0
+    movne   lr, #2                      ; i = 2
+    subne   r8, r8, #1                  ; --n
+
+    ; reverse the stream of bits to be packed.  Normally
+    ; the most significant bit is peeled off and compared
+    ; in the form of (v >> --n) & 1.  ARM architecture has
+    ; the ability to set a flag based on the value of the
+    ; bit shifted off the bottom of the register.  To make
+    ; that happen the bitstream is reversed.
+    rbit    r12, r6
+    rsb     r4, r8, #32                 ; 32-n
+    ldr     r10, [sp, #52]              ; vp8_coef_tree
+
+    ; v is kept in r12 during the token pack loop
+    lsr     r12, r12, r4                ; v >>= 32 - n
+
+; loop start
+token_loop
+    ldrb    r4, [r9, lr, asr #1]        ; pp [i>>1]
+    sub     r7, r5, #1                  ; range-1
+
+    ; Decisions are made based on the bit value shifted
+    ; off of v, so set a flag here based on this.
+    ; This value is refered to as "bb"
+    lsrs    r12, r12, #1                ; bb = v >> n
+    mul     r4, r4, r7                  ; ((range-1) * pp[i>>1]))
+
+    ; bb can only be 0 or 1.  So only execute this statement
+    ; if bb == 1, otherwise it will act like i + 0
+    addcs   lr, lr, #1                  ; i + bb
+
+    mov     r7, #1
+    ldrsb   lr, [r10, lr]               ; i = vp8_coef_tree[i+bb]
+    add     r4, r7, r4, lsr #8          ; 1 + (((range-1) * pp[i>>1]) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bb) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bb) range = range-split
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start
+token_zero_while_loop
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     token_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]               ; w->buffer[x]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]               ; w->buffer[x] + 1
+token_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]
+
+    ; r10 is used earlier in the loop, but r10 is used as
+    ; temp variable here.  So after r10 is used, reload
+    ; vp8_coef_tree_dcd into r10
+    ldr     r10, [sp, #52]              ; vp8_coef_tree
+
+token_count_lt_zero
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    subs    r8, r8, #1                  ; --n
+    bne     token_loop
+
+    ldr     r6, [r1, #tokenextra_token] ; t
+    ldr     r7, [sp, #48]               ; vp8_extra_bits
+    ; Add t * sizeof (vp8_extra_bit_struct) to get the desired
+    ;  element.  Here vp8_extra_bit_struct == 20
+    add     r6, r6, r6, lsl #2          ; b = vp8_extra_bits + t
+    add     r12, r7, r6, lsl #2         ; b = vp8_extra_bits + t
+
+    ldr     r4, [r12, #vp8_extra_bit_struct_base_val]
+    cmp     r4, #0
+    beq     skip_extra_bits
+
+;   if( b->base_val)
+    ldr     r8, [r12, #vp8_extra_bit_struct_len] ; L
+    ldr     lr, [r1, #tokenextra_extra] ; e = p->Extra
+    cmp     r8, #0                      ; if( L)
+    beq     no_extra_bits
+
+    ldr     r9, [r12, #vp8_extra_bit_struct_prob]
+    asr     r7, lr, #1                  ; v=e>>1
+
+    ldr     r10, [r12, #vp8_extra_bit_struct_tree]
+    str     r10, [sp, #4]               ; b->tree
+
+    rbit    r12, r7                     ; reverse v
+    rsb     r4, r8, #32
+    lsr     r12, r12, r4
+
+    mov     lr, #0                      ; i = 0
+
+extra_bits_loop
+    ldrb    r4, [r9, lr, asr #1]            ; pp[i>>1]
+    sub     r7, r5, #1                  ; range-1
+    lsrs    r12, r12, #1                ; v >> n
+    mul     r4, r4, r7                  ; (range-1) * pp[i>>1]
+    addcs   lr, lr, #1                  ; i + bb
+
+    mov     r7, #1
+    ldrsb   lr, [r10, lr]               ; i = b->tree[i+bb]
+    add     r4, r7, r4, lsr #8          ; split = 1 +  (((range-1) * pp[i>>1]) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bb) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bb) range = range-split
+
+    clz     r6, r4
+    sub     r6, r6, #24
+
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     extra_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset= shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     extra_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos - 1
+    b       extra_zero_while_start
+extra_zero_while_loop
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+extra_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     extra_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]
+extra_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]=(lowvalue >> (24-offset))
+    ldr     r10, [sp, #4]               ; b->tree
+extra_count_lt_zero
+    lsl     r2, r2, r6
+
+    subs    r8, r8, #1                  ; --n
+    bne     extra_bits_loop             ; while (n)
+
+no_extra_bits
+    ldr     lr, [r1, #4]                ; e = p->Extra
+    add     r4, r5, #1                  ; range + 1
+    tst     lr, #1
+    lsr     r4, r4, #1                  ; split = (range + 1) >> 1
+    addne   r2, r2, r4                  ; lowvalue += split
+    subne   r4, r5, r4                  ; range = range-split
+    tst     r2, #0x80000000             ; lowvalue & 0x80000000
+    lsl     r5, r4, #1                  ; range <<= 1
+    beq     end_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]
+    mov     r7, #0
+    sub     r4, r4, #1
+    b       end_zero_while_start
+end_zero_while_loop
+    strb    r7, [r6, r4]
+    sub     r4, r4, #1                  ; x--
+end_zero_while_start
+    cmp     r4, #0
+    ldrge   r6, [r0, #vp8_writer_buffer]
+    ldrb    r12, [r6, r4]
+    cmpge   r12, #0xff
+    beq     end_zero_while_loop
+
+    ldr     r6, [r0, #vp8_writer_buffer]
+    ldrb    r7, [r6, r4]
+    add     r7, r7, #1
+    strb    r7, [r6, r4]
+end_high_bit_not_set
+    adds    r3, r3, #1                  ; ++count
+    lsl     r2, r2, #1                  ; lowvalue  <<= 1
+    bne     end_count_zero
+
+    ldr     r4, [r0, #vp8_writer_pos]
+    mvn     r3, #7
+    ldr     r7, [r0, #vp8_writer_buffer]
+    lsr     r6, r2, #24                 ; lowvalue >> 24
+    add     r12, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r12, [r0, #0x10]
+    strb    r6, [r7, r4]
+end_count_zero
+skip_extra_bits
+    add     r1, r1, #TOKENEXTRA_SZ      ; ++p
+check_p_lt_stop
+    ldr     r4, [sp, #0]                ; stop
+    cmp     r1, r4                      ; while( p < stop)
+    bcc     while_p_lt_stop
+
+    str     r2, [r0, #vp8_writer_lowvalue]
+    str     r5, [r0, #vp8_writer_range]
+    str     r3, [r0, #vp8_writer_count]
+    add     sp, sp, #12
+    pop     {r4-r11, pc}
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/vp8_packtokens_mbrow_armv7.asm b/vp8/encoder/arm/neon/vp8_packtokens_mbrow_armv7.asm
new file mode 100644
index 0000000..92b0989
--- /dev/null
+++ b/vp8/encoder/arm/neon/vp8_packtokens_mbrow_armv7.asm
@@ -0,0 +1,335 @@
+;
+;  Copyright (c) 2010 The VP8 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 |vp8cx_pack_mb_row_tokens_armv7|
+
+    INCLUDE vpx_vp8_enc_asm_offsets.asm
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY
+
+; r0 VP8_COMP *cpi
+; r1 vp8_writer *w
+; r2 vp8_coef_encodings
+; r3 vp8_extra_bits
+; s0 vp8_coef_tree
+
+|vp8cx_pack_mb_row_tokens_armv7| PROC
+    push    {r4-r11, lr}
+    sub     sp, sp, #24
+
+    ; Compute address of cpi->common.mb_rows
+    ldr     r4, _VP8_COMP_common_
+    ldr     r6, _VP8_COMMON_MBrows_
+    add     r4, r0, r4
+
+    ldr     r5, [r4, r6]                ; load up mb_rows
+
+    str     r2, [sp, #20]               ; save vp8_coef_encodings
+    str     r5, [sp, #12]               ; save mb_rows
+    str     r3, [sp, #8]                ; save vp8_extra_bits
+
+    ldr     r4, _VP8_COMP_tplist_
+    add     r4, r0, r4
+    ldr     r7, [r4, #0]                ; dereference cpi->tp_list
+
+    mov     r0, r1                      ; keep same as other loops
+
+    ldr     r2, [r0, #vp8_writer_lowvalue]
+    ldr     r5, [r0, #vp8_writer_range]
+    ldr     r3, [r0, #vp8_writer_count]
+
+mb_row_loop
+
+    ldr     r1, [r7, #tokenlist_start]
+    ldr     r9, [r7, #tokenlist_stop]
+    str     r9, [sp, #0]                ; save stop for later comparison
+    str     r7, [sp, #16]               ; tokenlist address for next time
+
+    b       check_p_lt_stop
+
+    ; actuall work gets done here!
+
+while_p_lt_stop
+    ldr     r6, [r1, #tokenextra_token] ; t
+    ldr     r4, [sp, #20]               ; vp8_coef_encodings
+    mov     lr, #0
+    add     r4, r4, r6, lsl #3          ; a = vp8_coef_encodings + t
+    ldr     r9, [r1, #tokenextra_context_tree]   ; pp
+
+    ldr     r7, [r1, #tokenextra_skip_eob_node]
+
+    ldr     r6, [r4, #vp8_token_value]  ; v
+    ldr     r8, [r4, #vp8_token_len]    ; n
+
+    ; vp8 specific skip_eob_node
+    cmp     r7, #0
+    movne   lr, #2                      ; i = 2
+    subne   r8, r8, #1                  ; --n
+
+    ; reverse the stream of bits to be packed.  Normally
+    ; the most significant bit is peeled off and compared
+    ; in the form of (v >> --n) & 1.  ARM architecture has
+    ; the ability to set a flag based on the value of the
+    ; bit shifted off the bottom of the register.  To make
+    ; that happen the bitstream is reversed.
+    rbit    r12, r6
+    rsb     r4, r8, #32                 ; 32-n
+    ldr     r10, [sp, #60]              ; vp8_coef_tree
+
+    ; v is kept in r12 during the token pack loop
+    lsr     r12, r12, r4                ; v >>= 32 - n
+
+; loop start
+token_loop
+    ldrb    r4, [r9, lr, asr #1]        ; pp [i>>1]
+    sub     r7, r5, #1                  ; range-1
+
+    ; Decisions are made based on the bit value shifted
+    ; off of v, so set a flag here based on this.
+    ; This value is refered to as "bb"
+    lsrs    r12, r12, #1                ; bb = v >> n
+    mul     r4, r4, r7                  ; ((range-1) * pp[i>>1]))
+
+    ; bb can only be 0 or 1.  So only execute this statement
+    ; if bb == 1, otherwise it will act like i + 0
+    addcs   lr, lr, #1                  ; i + bb
+
+    mov     r7, #1
+    ldrsb   lr, [r10, lr]               ; i = vp8_coef_tree[i+bb]
+    add     r4, r7, r4, lsr #8          ; 1 + (((range-1) * pp[i>>1]) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bb) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bb) range = range-split
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start
+token_zero_while_loop
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     token_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]               ; w->buffer[x]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]               ; w->buffer[x] + 1
+token_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]
+
+    ; r10 is used earlier in the loop, but r10 is used as
+    ; temp variable here.  So after r10 is used, reload
+    ; vp8_coef_tree_dcd into r10
+    ldr     r10, [sp, #60]              ; vp8_coef_tree
+
+token_count_lt_zero
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    subs    r8, r8, #1                  ; --n
+    bne     token_loop
+
+    ldr     r6, [r1, #tokenextra_token] ; t
+    ldr     r7, [sp, #8]                ; vp8_extra_bits
+    ; Add t * sizeof (vp8_extra_bit_struct) to get the desired
+    ;  element.  Here vp8_extra_bit_struct == 20
+    add     r6, r6, r6, lsl #2          ; b = vp8_extra_bits + t
+    add     r12, r7, r6, lsl #2         ; b = vp8_extra_bits + t
+
+    ldr     r4, [r12, #vp8_extra_bit_struct_base_val]
+    cmp     r4, #0
+    beq     skip_extra_bits
+
+;   if( b->base_val)
+    ldr     r8, [r12, #vp8_extra_bit_struct_len] ; L
+    ldr     lr, [r1, #tokenextra_extra] ; e = p->Extra
+    cmp     r8, #0                      ; if( L)
+    beq     no_extra_bits
+
+    ldr     r9, [r12, #vp8_extra_bit_struct_prob]
+    asr     r7, lr, #1                  ; v=e>>1
+
+    ldr     r10, [r12, #vp8_extra_bit_struct_tree]
+    str     r10, [sp, #4]               ; b->tree
+
+    rbit    r12, r7                     ; reverse v
+    rsb     r4, r8, #32
+    lsr     r12, r12, r4
+
+    mov     lr, #0                      ; i = 0
+
+extra_bits_loop
+    ldrb    r4, [r9, lr, asr #1]            ; pp[i>>1]
+    sub     r7, r5, #1                  ; range-1
+    lsrs    r12, r12, #1                ; v >> n
+    mul     r4, r4, r7                  ; (range-1) * pp[i>>1]
+    addcs   lr, lr, #1                  ; i + bb
+
+    mov     r7, #1
+    ldrsb   lr, [r10, lr]               ; i = b->tree[i+bb]
+    add     r4, r7, r4, lsr #8          ; split = 1 +  (((range-1) * pp[i>>1]) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bb) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bb) range = range-split
+
+    clz     r6, r4
+    sub     r6, r6, #24
+
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     extra_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset= shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     extra_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos - 1
+    b       extra_zero_while_start
+extra_zero_while_loop
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+extra_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     extra_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]
+extra_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]=(lowvalue >> (24-offset))
+    ldr     r10, [sp, #4]               ; b->tree
+extra_count_lt_zero
+    lsl     r2, r2, r6
+
+    subs    r8, r8, #1                  ; --n
+    bne     extra_bits_loop             ; while (n)
+
+no_extra_bits
+    ldr     lr, [r1, #4]                ; e = p->Extra
+    add     r4, r5, #1                  ; range + 1
+    tst     lr, #1
+    lsr     r4, r4, #1                  ; split = (range + 1) >> 1
+    addne   r2, r2, r4                  ; lowvalue += split
+    subne   r4, r5, r4                  ; range = range-split
+    tst     r2, #0x80000000             ; lowvalue & 0x80000000
+    lsl     r5, r4, #1                  ; range <<= 1
+    beq     end_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]
+    mov     r7, #0
+    sub     r4, r4, #1
+    b       end_zero_while_start
+end_zero_while_loop
+    strb    r7, [r6, r4]
+    sub     r4, r4, #1                  ; x--
+end_zero_while_start
+    cmp     r4, #0
+    ldrge   r6, [r0, #vp8_writer_buffer]
+    ldrb    r12, [r6, r4]
+    cmpge   r12, #0xff
+    beq     end_zero_while_loop
+
+    ldr     r6, [r0, #vp8_writer_buffer]
+    ldrb    r7, [r6, r4]
+    add     r7, r7, #1
+    strb    r7, [r6, r4]
+end_high_bit_not_set
+    adds    r3, r3, #1                  ; ++count
+    lsl     r2, r2, #1                  ; lowvalue  <<= 1
+    bne     end_count_zero
+
+    ldr     r4, [r0, #vp8_writer_pos]
+    mvn     r3, #7
+    ldr     r7, [r0, #vp8_writer_buffer]
+    lsr     r6, r2, #24                 ; lowvalue >> 24
+    add     r12, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r12, [r0, #0x10]
+    strb    r6, [r7, r4]
+end_count_zero
+skip_extra_bits
+    add     r1, r1, #TOKENEXTRA_SZ      ; ++p
+check_p_lt_stop
+    ldr     r4, [sp, #0]                ; stop
+    cmp     r1, r4                      ; while( p < stop)
+    bcc     while_p_lt_stop
+
+    ldr     r6, [sp, #12]               ; mb_rows
+    ldr     r7, [sp, #16]               ; tokenlist address
+    subs    r6, r6, #1
+    add     r7, r7, #TOKENLIST_SZ       ; next element in the array
+    str     r6, [sp, #12]
+    bne     mb_row_loop
+
+    str     r2, [r0, #vp8_writer_lowvalue]
+    str     r5, [r0, #vp8_writer_range]
+    str     r3, [r0, #vp8_writer_count]
+    add     sp, sp, #24
+    pop     {r4-r11, pc}
+    ENDP
+
+_VP8_COMP_common_
+    DCD     vp8_comp_common
+_VP8_COMMON_MBrows_
+    DCD     vp8_common_mb_rows
+_VP8_COMP_tplist_
+    DCD     vp8_comp_tplist
+
+    END
diff --git a/vp8/encoder/arm/neon/vp8_packtokens_partitions_armv7.asm b/vp8/encoder/arm/neon/vp8_packtokens_partitions_armv7.asm
new file mode 100644
index 0000000..6d5f882
--- /dev/null
+++ b/vp8/encoder/arm/neon/vp8_packtokens_partitions_armv7.asm
@@ -0,0 +1,471 @@
+;
+;  Copyright (c) 2010 The VP8 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 |vp8cx_pack_tokens_into_partitions_armv7|
+
+    INCLUDE vpx_vp8_enc_asm_offsets.asm
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA    |.text|, CODE, READONLY
+
+; r0 VP8_COMP *cpi
+; r1 unsigned char *cx_data
+; r2 int num_part
+; r3 *size
+; s0 vp8_coef_encodings
+; s1 vp8_extra_bits,
+; s2 const vp8_tree_index *,
+
+|vp8cx_pack_tokens_into_partitions_armv7| PROC
+    push    {r4-r11, lr}
+    sub     sp, sp, #44
+
+    ; Compute address of cpi->common.mb_rows
+    ldr     r4, _VP8_COMP_common_
+    ldr     r6, _VP8_COMMON_MBrows_
+    add     r4, r0, r4
+
+    ldr     r5, [r4, r6]                ; load up mb_rows
+
+    str     r5, [sp, #36]               ; save mb_rows
+    str     r1, [sp, #24]               ; save cx_data
+    str     r2, [sp, #20]               ; save num_part
+    str     r3, [sp, #8]                ; save *size
+
+    ; *size = 3*(num_part -1 );
+    sub     r2, r2, #1                  ; num_part - 1
+    add     r2, r2, r2, lsl #1          ; 3*(num_part - 1)
+    str     r2, [r3]
+
+    add     r2, r2, r1                  ; cx_data + *size
+    str     r2, [sp, #40]               ; ptr
+
+    ldr     r4, _VP8_COMP_tplist_
+    add     r4, r0, r4
+    ldr     r7, [r4, #0]                ; dereference cpi->tp_list
+    str     r7, [sp, #32]               ; store start of cpi->tp_list
+
+    ldr     r11, _VP8_COMP_bc2_         ; load up vp8_writer out of cpi
+    add     r0, r0, r11
+
+    mov     r11, #0
+    str     r11, [sp, #28]              ; i
+
+numparts_loop
+    ldr     r10, [sp, #40]              ; ptr
+    ldr     r5,  [sp, #36]              ; move mb_rows to the counting section
+    str     r5,  [sp, #12]
+
+    ; Reset all of the VP8 Writer data for each partition that
+    ; is processed.
+    ; start_encode
+    mov     r2, #0                      ; vp8_writer_lowvalue
+    mov     r5, #255                    ; vp8_writer_range
+    mvn     r3, #23                     ; vp8_writer_count
+
+    str     r2,  [r0, #vp8_writer_value]
+    str     r2,  [r0, #vp8_writer_pos]
+    str     r10, [r0, #vp8_writer_buffer]
+
+mb_row_loop
+
+    ldr     r1, [r7, #tokenlist_start]
+    ldr     r9, [r7, #tokenlist_stop]
+    str     r9, [sp, #0]                ; save stop for later comparison
+    str     r7, [sp, #16]               ; tokenlist address for next time
+
+    b       check_p_lt_stop
+
+    ; actual work gets done here!
+
+while_p_lt_stop
+    ldr     r6, [r1, #tokenextra_token] ; t
+    ldr     r4, [sp, #80]               ; vp8_coef_encodings
+    mov     lr, #0
+    add     r4, r4, r6, lsl #3          ; a = vp8_coef_encodings + t
+    ldr     r9, [r1, #tokenextra_context_tree]   ; pp
+
+    ldr     r7, [r1, #tokenextra_skip_eob_node]
+
+    ldr     r6, [r4, #vp8_token_value]  ; v
+    ldr     r8, [r4, #vp8_token_len]    ; n
+
+    ; vp8 specific skip_eob_node
+    cmp     r7, #0
+    movne   lr, #2                      ; i = 2
+    subne   r8, r8, #1                  ; --n
+
+    ; reverse the stream of bits to be packed.  Normally
+    ; the most significant bit is peeled off and compared
+    ; in the form of (v >> --n) & 1.  ARM architecture has
+    ; the ability to set a flag based on the value of the
+    ; bit shifted off the bottom of the register.  To make
+    ; that happen the bitstream is reversed.
+    rbit    r12, r6
+    rsb     r4, r8, #32                 ; 32-n
+    ldr     r10, [sp, #88]              ; vp8_coef_tree
+
+    ; v is kept in r12 during the token pack loop
+    lsr     r12, r12, r4                ; v >>= 32 - n
+
+; loop start
+token_loop
+    ldrb    r4, [r9, lr, asr #1]        ; pp [i>>1]
+    sub     r7, r5, #1                  ; range-1
+
+    ; Decisions are made based on the bit value shifted
+    ; off of v, so set a flag here based on this.
+    ; This value is refered to as "bb"
+    lsrs    r12, r12, #1                ; bb = v >> n
+    mul     r4, r4, r7                  ; ((range-1) * pp[i>>1]))
+
+    ; bb can only be 0 or 1.  So only execute this statement
+    ; if bb == 1, otherwise it will act like i + 0
+    addcs   lr, lr, #1                  ; i + bb
+
+    mov     r7, #1
+    ldrsb   lr, [r10, lr]               ; i = vp8_coef_tree[i+bb]
+    add     r4, r7, r4, lsr #8          ; 1 + (((range-1) * pp[i>>1]) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bb) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bb) range = range-split
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start
+token_zero_while_loop
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     token_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]               ; w->buffer[x]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]               ; w->buffer[x] + 1
+token_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]
+
+    ; r10 is used earlier in the loop, but r10 is used as
+    ; temp variable here.  So after r10 is used, reload
+    ; vp8_coef_tree_dcd into r10
+    ldr     r10, [sp, #88]              ; vp8_coef_tree
+
+token_count_lt_zero
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    subs    r8, r8, #1                  ; --n
+    bne     token_loop
+
+    ldr     r6, [r1, #tokenextra_token] ; t
+    ldr     r7, [sp, #84]                ; vp8_extra_bits
+    ; Add t * sizeof (vp8_extra_bit_struct) to get the desired
+    ;  element.  Here vp8_extra_bit_struct == 20
+    add     r6, r6, r6, lsl #2          ; b = vp8_extra_bits + t
+    add     r12, r7, r6, lsl #2         ; b = vp8_extra_bits + t
+
+    ldr     r4, [r12, #vp8_extra_bit_struct_base_val]
+    cmp     r4, #0
+    beq     skip_extra_bits
+
+;   if( b->base_val)
+    ldr     r8, [r12, #vp8_extra_bit_struct_len] ; L
+    ldr     lr, [r1, #tokenextra_extra] ; e = p->Extra
+    cmp     r8, #0                      ; if( L)
+    beq     no_extra_bits
+
+    ldr     r9, [r12, #vp8_extra_bit_struct_prob]
+    asr     r7, lr, #1                  ; v=e>>1
+
+    ldr     r10, [r12, #vp8_extra_bit_struct_tree]
+    str     r10, [sp, #4]               ; b->tree
+
+    rbit    r12, r7                     ; reverse v
+    rsb     r4, r8, #32
+    lsr     r12, r12, r4
+
+    mov     lr, #0                      ; i = 0
+
+extra_bits_loop
+    ldrb    r4, [r9, lr, asr #1]        ; pp[i>>1]
+    sub     r7, r5, #1                  ; range-1
+    lsrs    r12, r12, #1                ; v >> n
+    mul     r4, r4, r7                  ; (range-1) * pp[i>>1]
+    addcs   lr, lr, #1                  ; i + bb
+
+    mov     r7, #1
+    ldrsb   lr, [r10, lr]               ; i = b->tree[i+bb]
+    add     r4, r7, r4, lsr #8          ; split = 1 +  (((range-1) * pp[i>>1]) >> 8)
+
+    addcs   r2, r2, r4                  ; if  (bb) lowvalue += split
+    subcs   r4, r5, r4                  ; if  (bb) range = range-split
+
+    clz     r6, r4
+    sub     r6, r6, #24
+
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     extra_count_lt_zero         ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset= shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     extra_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos - 1
+    b       extra_zero_while_start
+extra_zero_while_loop
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+extra_zero_while_start
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     extra_zero_while_loop
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]
+extra_high_bit_not_set
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]=(lowvalue >> (24-offset))
+    ldr     r10, [sp, #4]               ; b->tree
+extra_count_lt_zero
+    lsl     r2, r2, r6
+
+    subs    r8, r8, #1                  ; --n
+    bne     extra_bits_loop             ; while (n)
+
+no_extra_bits
+    ldr     lr, [r1, #4]                ; e = p->Extra
+    add     r4, r5, #1                  ; range + 1
+    tst     lr, #1
+    lsr     r4, r4, #1                  ; split = (range + 1) >> 1
+    addne   r2, r2, r4                  ; lowvalue += split
+    subne   r4, r5, r4                  ; range = range-split
+    tst     r2, #0x80000000             ; lowvalue & 0x80000000
+    lsl     r5, r4, #1                  ; range <<= 1
+    beq     end_high_bit_not_set
+
+    ldr     r4, [r0, #vp8_writer_pos]
+    mov     r7, #0
+    sub     r4, r4, #1
+    b       end_zero_while_start
+end_zero_while_loop
+    strb    r7, [r6, r4]
+    sub     r4, r4, #1                  ; x--
+end_zero_while_start
+    cmp     r4, #0
+    ldrge   r6, [r0, #vp8_writer_buffer]
+    ldrb    r12, [r6, r4]
+    cmpge   r12, #0xff
+    beq     end_zero_while_loop
+
+    ldr     r6, [r0, #vp8_writer_buffer]
+    ldrb    r7, [r6, r4]
+    add     r7, r7, #1
+    strb    r7, [r6, r4]
+end_high_bit_not_set
+    adds    r3, r3, #1                  ; ++count
+    lsl     r2, r2, #1                  ; lowvalue  <<= 1
+    bne     end_count_zero
+
+    ldr     r4, [r0, #vp8_writer_pos]
+    mvn     r3, #7
+    ldr     r7, [r0, #vp8_writer_buffer]
+    lsr     r6, r2, #24                 ; lowvalue >> 24
+    add     r12, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r12, [r0, #0x10]
+    strb    r6, [r7, r4]
+end_count_zero
+skip_extra_bits
+    add     r1, r1, #TOKENEXTRA_SZ      ; ++p
+check_p_lt_stop
+    ldr     r4, [sp, #0]                ; stop
+    cmp     r1, r4                      ; while( p < stop)
+    bcc     while_p_lt_stop
+
+    ldr     r10, [sp, #20]              ; num_parts
+    mov     r1, #TOKENLIST_SZ
+    mul     r1, r10, r1
+
+    ldr     r6, [sp, #12]               ; mb_rows
+    ldr     r7, [sp, #16]               ; tokenlist address
+    subs    r6, r6, r10
+    add     r7, r7, r1                  ; next element in the array
+    str     r6, [sp, #12]
+    bgt     mb_row_loop
+
+    mov     r12, #32
+
+stop_encode_loop
+    sub     r7, r5, #1                  ; range-1
+
+    mov     r4, r7, lsl #7              ; ((range-1) * 128)
+
+    mov     r7, #1
+    add     r4, r7, r4, lsr #8          ; 1 + (((range-1) * 128) >> 8)
+
+    ; Counting the leading zeros is used to normalize range.
+    clz     r6, r4
+    sub     r6, r6, #24                 ; shift
+
+    ; Flag is set on the sum of count.  This flag is used later
+    ; to determine if count >= 0
+    adds    r3, r3, r6                  ; count += shift
+    lsl     r5, r4, r6                  ; range <<= shift
+    bmi     token_count_lt_zero_se      ; if(count >= 0)
+
+    sub     r6, r6, r3                  ; offset = shift - count
+    sub     r4, r6, #1                  ; offset-1
+    lsls    r4, r2, r4                  ; if((lowvalue<<(offset-1)) & 0x80000000 )
+    bpl     token_high_bit_not_set_se
+
+    ldr     r4, [r0, #vp8_writer_pos]   ; x
+    sub     r4, r4, #1                  ; x = w->pos-1
+    b       token_zero_while_start_se
+token_zero_while_loop_se
+    mov     r10, #0
+    strb    r10, [r7, r4]               ; w->buffer[x] =(unsigned char)0
+    sub     r4, r4, #1                  ; x--
+token_zero_while_start_se
+    cmp     r4, #0
+    ldrge   r7, [r0, #vp8_writer_buffer]
+    ldrb    r11, [r7, r4]
+    cmpge   r11, #0xff
+    beq     token_zero_while_loop_se
+
+    ldr     r7, [r0, #vp8_writer_buffer]
+    ldrb    r10, [r7, r4]               ; w->buffer[x]
+    add     r10, r10, #1
+    strb    r10, [r7, r4]               ; w->buffer[x] + 1
+token_high_bit_not_set_se
+    rsb     r4, r6, #24                 ; 24-offset
+    ldr     r10, [r0, #vp8_writer_buffer]
+    lsr     r7, r2, r4                  ; lowvalue >> (24-offset)
+    ldr     r4, [r0, #vp8_writer_pos]   ; w->pos
+    lsl     r2, r2, r6                  ; lowvalue <<= offset
+    mov     r6, r3                      ; shift = count
+    add     r11, r4, #1                 ; w->pos++
+    bic     r2, r2, #0xff000000         ; lowvalue &= 0xffffff
+    str     r11, [r0, #vp8_writer_pos]
+    sub     r3, r3, #8                  ; count -= 8
+    strb    r7, [r10, r4]               ; w->buffer[w->pos++]
+
+token_count_lt_zero_se
+    lsl     r2, r2, r6                  ; lowvalue <<= shift
+
+    subs    r12, r12, #1
+    bne     stop_encode_loop
+
+    ldr     r10, [sp, #8]               ; *size
+    ldr     r11, [r10]
+    ldr     r4,  [r0, #vp8_writer_pos]  ; w->pos
+    add     r11, r11, r4                ; *size += w->pos
+    str     r11, [r10]
+
+    ldr     r9, [sp, #20]               ; num_parts
+    sub     r9, r9, #1
+    ldr     r10, [sp, #28]              ; i
+    cmp     r10, r9                     ; if(i<(num_part - 1))
+    bge     skip_write_partition
+
+    ldr     r12, [sp, #40]              ; ptr
+    add     r12, r12, r4                ; ptr += w->pos
+    str     r12, [sp, #40]
+
+    ldr     r9, [sp, #24]               ; cx_data
+    mov     r8, r4, asr #8
+    strb    r4, [r9, #0]
+    strb    r8, [r9, #1]
+    mov     r4, r4, asr #16
+    strb    r4, [r9, #2]
+
+    add     r9, r9, #3                  ; cx_data += 3
+    str     r9, [sp, #24]
+
+skip_write_partition
+
+    ldr     r11, [sp, #28]              ; i
+    ldr     r10, [sp, #20]              ; num_parts
+
+    add     r11, r11, #1                ; i++
+    str     r11, [sp, #28]
+
+    ldr     r7, [sp, #32]               ; cpi->tp_list[i]
+    mov     r1, #TOKENLIST_SZ
+    add     r7, r7, r1                  ; next element in cpi->tp_list
+    str     r7, [sp, #32]               ; cpi->tp_list[i+1]
+
+    cmp     r10, r11
+    bgt     numparts_loop
+
+
+    add     sp, sp, #44
+    pop     {r4-r11, pc}
+    ENDP
+
+_VP8_COMP_common_
+    DCD     vp8_comp_common
+_VP8_COMMON_MBrows_
+    DCD     vp8_common_mb_rows
+_VP8_COMP_tplist_
+    DCD     vp8_comp_tplist
+_VP8_COMP_bc2_
+    DCD     vp8_comp_bc2
+
+    END
diff --git a/vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm b/vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm
new file mode 100644
index 0000000..5269c0a
--- /dev/null
+++ b/vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm
@@ -0,0 +1,75 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_short_walsh4x4_neon|
+
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+;void vp8_short_walsh4x4_c(short *input, short *output, int pitch)
+
+|vp8_short_walsh4x4_neon| PROC
+    vld1.16         {d2}, [r0], r2              ;load input
+    vld1.16         {d3}, [r0], r2
+    vld1.16         {d4}, [r0], r2
+    vld1.16         {d5}, [r0], r2
+
+    ;First for-loop
+    ;transpose d2, d3, d4, d5. Then, d2=ip[0], d3=ip[1], d4=ip[2], d5=ip[3]
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+    vadd.s16        d6, d2, d5              ;a1 = ip[0]+ip[3]
+    vadd.s16        d7, d3, d4              ;b1 = ip[1]+ip[2]
+    vsub.s16        d8, d3, d4              ;c1 = ip[1]-ip[2]
+    vsub.s16        d9, d2, d5              ;d1 = ip[0]-ip[3]
+
+    vadd.s16        d2, d6, d7             ;op[0] = a1 + b1
+    vsub.s16        d4, d6, d7             ;op[2] = a1 - b1
+    vadd.s16        d3, d8, d9             ;op[1] = c1 + d1
+    vsub.s16        d5, d9, d8             ;op[3] = d1 - c1
+
+    ;Second for-loop
+    ;transpose d2, d3, d4, d5. Then, d2=ip[0], d3=ip[4], d4=ip[8], d5=ip[12]
+    vtrn.32         d2, d4
+    vtrn.32         d3, d5
+    vtrn.16         d2, d3
+    vtrn.16         d4, d5
+
+    vadd.s16        d6, d2, d5              ;a1 = ip[0]+ip[12]
+    vadd.s16        d7, d3, d4              ;b1 = ip[4]+ip[8]
+    vsub.s16        d8, d3, d4              ;c1 = ip[4]-ip[8]
+    vsub.s16        d9, d2, d5              ;d1 = ip[0]-ip[12]
+
+    vadd.s16        d2, d6, d7              ;a2 = a1 + b1;
+    vsub.s16        d4, d6, d7              ;c2 = a1 - b1;
+    vadd.s16        d3, d8, d9              ;b2 = c1 + d1;
+    vsub.s16        d5, d9, d8              ;d2 = d1 - c1;
+
+    vcgt.s16        q3, q1, #0
+    vcgt.s16        q4, q2, #0
+
+    vsub.s16        q1, q1, q3
+    vsub.s16        q2, q2, q4
+
+    vshr.s16        q1, q1, #1
+    vshr.s16        q2, q2, #1
+
+    vst1.16         {q1, q2}, [r1]
+
+    bx              lr
+
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/vp8_subpixelvariance16x16_neon.asm b/vp8/encoder/arm/neon/vp8_subpixelvariance16x16_neon.asm
new file mode 100644
index 0000000..aec716e
--- /dev/null
+++ b/vp8/encoder/arm/neon/vp8_subpixelvariance16x16_neon.asm
@@ -0,0 +1,427 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_sub_pixel_variance16x16_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; stack(r4) unsigned char *dst_ptr,
+; stack(r5) int dst_pixels_per_line,
+; stack(r6) unsigned int *sse
+;note: most of the code is copied from bilinear_predict16x16_neon and vp8_variance16x16_neon.
+
+|vp8_sub_pixel_variance16x16_neon| PROC
+    push            {r4-r6, lr}
+
+    ldr             r12, _BilinearTaps_coeff_
+    ldr             r4, [sp, #16]           ;load *dst_ptr from stack
+    ldr             r5, [sp, #20]           ;load dst_pixels_per_line from stack
+    ldr             r6, [sp, #24]           ;load *sse from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_bfilter16x16_only
+
+    add             r2, r12, r2, lsl #3     ;calculate filter location
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+
+    vld1.s32        {d31}, [r2]             ;load first_pass filter
+
+    beq             firstpass_bfilter16x16_only
+
+    sub             sp, sp, #272            ;reserve space on stack for temporary storage
+    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
+    mov             lr, sp
+    vld1.u8         {d5, d6, d7}, [r0], r1
+
+    mov             r2, #3                  ;loop counter
+    vld1.u8         {d8, d9, d10}, [r0], r1
+
+    vdup.8          d0, d31[0]              ;first_pass filter (d0 d1)
+    vld1.u8         {d11, d12, d13}, [r0], r1
+
+    vdup.8          d1, d31[4]
+
+;First Pass: output_height lines x output_width columns (17x16)
+vp8e_filt_blk2d_fp16x16_loop_neon
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d2, d0              ;(src_ptr[0] * Filter[0])
+    vmull.u8        q8, d3, d0
+    vmull.u8        q9, d5, d0
+    vmull.u8        q10, d6, d0
+    vmull.u8        q11, d8, d0
+    vmull.u8        q12, d9, d0
+    vmull.u8        q13, d11, d0
+    vmull.u8        q14, d12, d0
+
+    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
+    vext.8          d5, d5, d6, #1
+    vext.8          d8, d8, d9, #1
+    vext.8          d11, d11, d12, #1
+
+    vmlal.u8        q7, d2, d1              ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q9, d5, d1
+    vmlal.u8        q11, d8, d1
+    vmlal.u8        q13, d11, d1
+
+    vext.8          d3, d3, d4, #1
+    vext.8          d6, d6, d7, #1
+    vext.8          d9, d9, d10, #1
+    vext.8          d12, d12, d13, #1
+
+    vmlal.u8        q8, d3, d1              ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q10, d6, d1
+    vmlal.u8        q12, d9, d1
+    vmlal.u8        q14, d12, d1
+
+    subs            r2, r2, #1
+
+    vqrshrn.u16    d14, q7, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d15, q8, #7
+    vqrshrn.u16    d16, q9, #7
+    vqrshrn.u16    d17, q10, #7
+    vqrshrn.u16    d18, q11, #7
+    vqrshrn.u16    d19, q12, #7
+    vqrshrn.u16    d20, q13, #7
+
+    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
+    vqrshrn.u16    d21, q14, #7
+    vld1.u8         {d5, d6, d7}, [r0], r1
+
+    vst1.u8         {d14, d15, d16, d17}, [lr]!     ;store result
+    vld1.u8         {d8, d9, d10}, [r0], r1
+    vst1.u8         {d18, d19, d20, d21}, [lr]!
+    vld1.u8         {d11, d12, d13}, [r0], r1
+
+    bne             vp8e_filt_blk2d_fp16x16_loop_neon
+
+;First-pass filtering for rest 5 lines
+    vld1.u8         {d14, d15, d16}, [r0], r1
+
+    vmull.u8        q9, d2, d0              ;(src_ptr[0] * Filter[0])
+    vmull.u8        q10, d3, d0
+    vmull.u8        q11, d5, d0
+    vmull.u8        q12, d6, d0
+    vmull.u8        q13, d8, d0
+    vmull.u8        q14, d9, d0
+
+    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
+    vext.8          d5, d5, d6, #1
+    vext.8          d8, d8, d9, #1
+
+    vmlal.u8        q9, d2, d1              ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q11, d5, d1
+    vmlal.u8        q13, d8, d1
+
+    vext.8          d3, d3, d4, #1
+    vext.8          d6, d6, d7, #1
+    vext.8          d9, d9, d10, #1
+
+    vmlal.u8        q10, d3, d1             ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q12, d6, d1
+    vmlal.u8        q14, d9, d1
+
+    vmull.u8        q1, d11, d0
+    vmull.u8        q2, d12, d0
+    vmull.u8        q3, d14, d0
+    vmull.u8        q4, d15, d0
+
+    vext.8          d11, d11, d12, #1       ;construct src_ptr[1]
+    vext.8          d14, d14, d15, #1
+
+    vmlal.u8        q1, d11, d1             ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q3, d14, d1
+
+    vext.8          d12, d12, d13, #1
+    vext.8          d15, d15, d16, #1
+
+    vmlal.u8        q2, d12, d1             ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q4, d15, d1
+
+    vqrshrn.u16    d10, q9, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d11, q10, #7
+    vqrshrn.u16    d12, q11, #7
+    vqrshrn.u16    d13, q12, #7
+    vqrshrn.u16    d14, q13, #7
+    vqrshrn.u16    d15, q14, #7
+    vqrshrn.u16    d16, q1, #7
+    vqrshrn.u16    d17, q2, #7
+    vqrshrn.u16    d18, q3, #7
+    vqrshrn.u16    d19, q4, #7
+
+    vst1.u8         {d10, d11, d12, d13}, [lr]!         ;store result
+    vst1.u8         {d14, d15, d16, d17}, [lr]!
+    vst1.u8         {d18, d19}, [lr]!
+
+;Second pass: 16x16
+;secondpass_filter
+    add             r3, r12, r3, lsl #3
+    sub             lr, lr, #272
+
+    vld1.u32        {d31}, [r3]             ;load second_pass filter
+
+    sub             sp, sp, #256
+    mov             r3, sp
+
+    vld1.u8         {d22, d23}, [lr]!       ;load src data
+
+    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+    mov             r12, #4                 ;loop counter
+
+vp8e_filt_blk2d_sp16x16_loop_neon
+    vld1.u8         {d24, d25}, [lr]!
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * Filter[0])
+    vld1.u8         {d26, d27}, [lr]!
+    vmull.u8        q2, d23, d0
+    vld1.u8         {d28, d29}, [lr]!
+    vmull.u8        q3, d24, d0
+    vld1.u8         {d30, d31}, [lr]!
+
+    vmull.u8        q4, d25, d0
+    vmull.u8        q5, d26, d0
+    vmull.u8        q6, d27, d0
+    vmull.u8        q7, d28, d0
+    vmull.u8        q8, d29, d0
+
+    vmlal.u8        q1, d24, d1             ;(src_ptr[pixel_step] * Filter[1])
+    vmlal.u8        q2, d25, d1
+    vmlal.u8        q3, d26, d1
+    vmlal.u8        q4, d27, d1
+    vmlal.u8        q5, d28, d1
+    vmlal.u8        q6, d29, d1
+    vmlal.u8        q7, d30, d1
+    vmlal.u8        q8, d31, d1
+
+    subs            r12, r12, #1
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+    vqrshrn.u16    d4, q3, #7
+    vqrshrn.u16    d5, q4, #7
+    vqrshrn.u16    d6, q5, #7
+    vqrshrn.u16    d7, q6, #7
+    vqrshrn.u16    d8, q7, #7
+    vqrshrn.u16    d9, q8, #7
+
+    vst1.u8         {d2, d3}, [r3]!         ;store result
+    vst1.u8         {d4, d5}, [r3]!
+    vst1.u8         {d6, d7}, [r3]!
+    vmov            q11, q15
+    vst1.u8         {d8, d9}, [r3]!
+
+    bne             vp8e_filt_blk2d_sp16x16_loop_neon
+
+    b               sub_pixel_variance16x16_neon
+
+;--------------------
+firstpass_bfilter16x16_only
+    mov             r2, #4                      ;loop counter
+    sub             sp, sp, #528            ;reserve space on stack for temporary storage
+    vdup.8          d0, d31[0]                  ;first_pass filter (d0 d1)
+    vdup.8          d1, d31[4]
+    mov             r3, sp
+
+;First Pass: output_height lines x output_width columns (16x16)
+vp8e_filt_blk2d_fpo16x16_loop_neon
+    vld1.u8         {d2, d3, d4}, [r0], r1      ;load src data
+    vld1.u8         {d5, d6, d7}, [r0], r1
+    vld1.u8         {d8, d9, d10}, [r0], r1
+    vld1.u8         {d11, d12, d13}, [r0], r1
+
+    pld             [r0]
+    pld             [r0, r1]
+    pld             [r0, r1, lsl #1]
+
+    vmull.u8        q7, d2, d0              ;(src_ptr[0] * Filter[0])
+    vmull.u8        q8, d3, d0
+    vmull.u8        q9, d5, d0
+    vmull.u8        q10, d6, d0
+    vmull.u8        q11, d8, d0
+    vmull.u8        q12, d9, d0
+    vmull.u8        q13, d11, d0
+    vmull.u8        q14, d12, d0
+
+    vext.8          d2, d2, d3, #1          ;construct src_ptr[1]
+    vext.8          d5, d5, d6, #1
+    vext.8          d8, d8, d9, #1
+    vext.8          d11, d11, d12, #1
+
+    vmlal.u8        q7, d2, d1              ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q9, d5, d1
+    vmlal.u8        q11, d8, d1
+    vmlal.u8        q13, d11, d1
+
+    vext.8          d3, d3, d4, #1
+    vext.8          d6, d6, d7, #1
+    vext.8          d9, d9, d10, #1
+    vext.8          d12, d12, d13, #1
+
+    vmlal.u8        q8, d3, d1              ;(src_ptr[0] * Filter[1])
+    vmlal.u8        q10, d6, d1
+    vmlal.u8        q12, d9, d1
+    vmlal.u8        q14, d12, d1
+
+    subs            r2, r2, #1
+
+    vqrshrn.u16    d14, q7, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d15, q8, #7
+    vqrshrn.u16    d16, q9, #7
+    vqrshrn.u16    d17, q10, #7
+    vqrshrn.u16    d18, q11, #7
+    vqrshrn.u16    d19, q12, #7
+    vqrshrn.u16    d20, q13, #7
+    vst1.u8         {d14, d15}, [r3]!       ;store result
+    vqrshrn.u16    d21, q14, #7
+
+    vst1.u8         {d16, d17}, [r3]!
+    vst1.u8         {d18, d19}, [r3]!
+    vst1.u8         {d20, d21}, [r3]!
+
+    bne             vp8e_filt_blk2d_fpo16x16_loop_neon
+
+    b               sub_pixel_variance16x16_neon
+
+;---------------------
+secondpass_bfilter16x16_only
+;Second pass: 16x16
+;secondpass_filter
+    sub             sp, sp, #528            ;reserve space on stack for temporary storage
+    add             r3, r12, r3, lsl #3
+    mov             r12, #4                     ;loop counter
+    vld1.u32        {d31}, [r3]                 ;load second_pass filter
+    vld1.u8         {d22, d23}, [r0], r1        ;load src data
+    mov             r3, sp
+
+    vdup.8          d0, d31[0]                  ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+
+vp8e_filt_blk2d_spo16x16_loop_neon
+    vld1.u8         {d24, d25}, [r0], r1
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * Filter[0])
+    vld1.u8         {d26, d27}, [r0], r1
+    vmull.u8        q2, d23, d0
+    vld1.u8         {d28, d29}, [r0], r1
+    vmull.u8        q3, d24, d0
+    vld1.u8         {d30, d31}, [r0], r1
+
+    vmull.u8        q4, d25, d0
+    vmull.u8        q5, d26, d0
+    vmull.u8        q6, d27, d0
+    vmull.u8        q7, d28, d0
+    vmull.u8        q8, d29, d0
+
+    vmlal.u8        q1, d24, d1             ;(src_ptr[pixel_step] * Filter[1])
+    vmlal.u8        q2, d25, d1
+    vmlal.u8        q3, d26, d1
+    vmlal.u8        q4, d27, d1
+    vmlal.u8        q5, d28, d1
+    vmlal.u8        q6, d29, d1
+    vmlal.u8        q7, d30, d1
+    vmlal.u8        q8, d31, d1
+
+    vqrshrn.u16    d2, q1, #7               ;shift/round/saturate to u8
+    vqrshrn.u16    d3, q2, #7
+    vqrshrn.u16    d4, q3, #7
+    vqrshrn.u16    d5, q4, #7
+    vqrshrn.u16    d6, q5, #7
+    vqrshrn.u16    d7, q6, #7
+    vqrshrn.u16    d8, q7, #7
+    vqrshrn.u16    d9, q8, #7
+
+    vst1.u8         {d2, d3}, [r3]!         ;store result
+    subs            r12, r12, #1
+    vst1.u8         {d4, d5}, [r3]!
+    vmov            q11, q15
+    vst1.u8         {d6, d7}, [r3]!
+    vst1.u8         {d8, d9}, [r3]!
+
+    bne             vp8e_filt_blk2d_spo16x16_loop_neon
+
+    b               sub_pixel_variance16x16_neon
+
+;----------------------------
+;variance16x16
+sub_pixel_variance16x16_neon
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    sub             r3, r3, #256
+    mov             r12, #8
+
+sub_pixel_variance16x16_neon_loop
+    vld1.8          {q0}, [r3]!                 ;Load up source and reference
+    vld1.8          {q2}, [r4], r5
+    vld1.8          {q1}, [r3]!
+    vld1.8          {q3}, [r4], r5
+
+    vsubl.u8        q11, d0, d4                 ;diff
+    vsubl.u8        q12, d1, d5
+    vsubl.u8        q13, d2, d6
+    vsubl.u8        q14, d3, d7
+
+    vpadal.s16      q8, q11                     ;sum
+    vmlal.s16       q9, d22, d22                ;sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    bne             sub_pixel_variance16x16_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [r6]               ;store sse
+    vshr.s32        d10, d10, #8
+    vsub.s32        d0, d1, d10
+
+    add             sp, sp, #528
+    vmov.32         r0, d0[0]                   ;return
+
+    pop             {r4-r6,pc}
+
+    ENDP
+
+;-----------------
+    AREA    vp8e_bilinear_taps_dat, DATA, READWRITE          ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_BilinearTaps_coeff_
+    DCD     bilinear_taps_coeff
+bilinear_taps_coeff
+    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
+
+    END
diff --git a/vp8/encoder/arm/neon/vp8_subpixelvariance16x16s_neon.asm b/vp8/encoder/arm/neon/vp8_subpixelvariance16x16s_neon.asm
new file mode 100644
index 0000000..3d02d7c
--- /dev/null
+++ b/vp8/encoder/arm/neon/vp8_subpixelvariance16x16s_neon.asm
@@ -0,0 +1,571 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_sub_pixel_variance16x16s_4_0_neon|
+    EXPORT  |vp8_sub_pixel_variance16x16s_0_4_neon|
+    EXPORT  |vp8_sub_pixel_variance16x16s_4_4_neon|
+    EXPORT  |vp8_sub_pixel_variance16x16s_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+;================================================
+;unsigned int vp8_sub_pixel_variance16x16s_4_0_neon
+;(
+;    unsigned char  *src_ptr, r0
+;    int  src_pixels_per_line,  r1
+;    unsigned char *dst_ptr,  r2
+;    int dst_pixels_per_line,   r3
+;    unsigned int *sse
+;);
+;================================================
+|vp8_sub_pixel_variance16x16s_4_0_neon| PROC
+    push            {lr}
+
+    mov             r12, #4                  ;loop counter
+    ldr             lr, [sp, #4]           ;load *sse from stack
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+;First Pass: output_height lines x output_width columns (16x16)
+vp8_filt_fpo16x16s_4_0_loop_neon
+    vld1.u8         {d0, d1, d2, d3}, [r0], r1      ;load src data
+    vld1.8          {q11}, [r2], r3
+    vld1.u8         {d4, d5, d6, d7}, [r0], r1
+    vld1.8          {q12}, [r2], r3
+    vld1.u8         {d8, d9, d10, d11}, [r0], r1
+    vld1.8          {q13}, [r2], r3
+    vld1.u8         {d12, d13, d14, d15}, [r0], r1
+
+    ;pld                [r0]
+    ;pld                [r0, r1]
+    ;pld                [r0, r1, lsl #1]
+
+    vext.8          q1, q0, q1, #1          ;construct src_ptr[1]
+    vext.8          q3, q2, q3, #1
+    vext.8          q5, q4, q5, #1
+    vext.8          q7, q6, q7, #1
+
+    vrhadd.u8       q0, q0, q1              ;(src_ptr[0]+src_ptr[1])/round/shift right 1
+    vld1.8          {q14}, [r2], r3
+    vrhadd.u8       q1, q2, q3
+    vrhadd.u8       q2, q4, q5
+    vrhadd.u8       q3, q6, q7
+
+    vsubl.u8        q4, d0, d22                 ;diff
+    vsubl.u8        q5, d1, d23
+    vsubl.u8        q6, d2, d24
+    vsubl.u8        q7, d3, d25
+    vsubl.u8        q0, d4, d26
+    vsubl.u8        q1, d5, d27
+    vsubl.u8        q2, d6, d28
+    vsubl.u8        q3, d7, d29
+
+    vpadal.s16      q8, q4                     ;sum
+    vmlal.s16       q9, d8, d8                ;sse
+    vmlal.s16       q10, d9, d9
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q5
+    vmlal.s16       q9, d10, d10
+    vmlal.s16       q10, d11, d11
+    vpadal.s16      q8, q6
+    vmlal.s16       q9, d12, d12
+    vmlal.s16       q10, d13, d13
+    vpadal.s16      q8, q7
+    vmlal.s16       q9, d14, d14
+    vmlal.s16       q10, d15, d15
+
+    vpadal.s16      q8, q0                     ;sum
+    vmlal.s16       q9, d0, d0                ;sse
+    vmlal.s16       q10, d1, d1
+    vpadal.s16      q8, q1
+    vmlal.s16       q9, d2, d2
+    vmlal.s16       q10, d3, d3
+    vpadal.s16      q8, q2
+    vmlal.s16       q9, d4, d4
+    vmlal.s16       q10, d5, d5
+    vpadal.s16      q8, q3
+    vmlal.s16       q9, d6, d6
+    vmlal.s16       q10, d7, d7
+
+    bne             vp8_filt_fpo16x16s_4_0_loop_neon
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [lr]               ;store sse
+    vshr.s32        d10, d10, #8
+    vsub.s32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    pop             {pc}
+    ENDP
+
+;================================================
+;unsigned int vp8_sub_pixel_variance16x16s_0_4_neon
+;(
+;    unsigned char  *src_ptr, r0
+;    int  src_pixels_per_line,  r1
+;    unsigned char *dst_ptr,  r2
+;    int dst_pixels_per_line,   r3
+;    unsigned int *sse
+;);
+;================================================
+|vp8_sub_pixel_variance16x16s_0_4_neon| PROC
+    push            {lr}
+
+    mov             r12, #4                     ;loop counter
+
+    vld1.u8         {q0}, [r0], r1              ;load src data
+    ldr             lr, [sp, #4]                ;load *sse from stack
+
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+vp8_filt_spo16x16s_0_4_loop_neon
+    vld1.u8         {q2}, [r0], r1
+    vld1.8          {q1}, [r2], r3
+    vld1.u8         {q4}, [r0], r1
+    vld1.8          {q3}, [r2], r3
+    vld1.u8         {q6}, [r0], r1
+    vld1.8          {q5}, [r2], r3
+    vld1.u8         {q15}, [r0], r1
+
+    vrhadd.u8       q0, q0, q2
+    vld1.8          {q7}, [r2], r3
+    vrhadd.u8       q2, q2, q4
+    vrhadd.u8       q4, q4, q6
+    vrhadd.u8       q6, q6, q15
+
+    vsubl.u8        q11, d0, d2                 ;diff
+    vsubl.u8        q12, d1, d3
+    vsubl.u8        q13, d4, d6
+    vsubl.u8        q14, d5, d7
+    vsubl.u8        q0, d8, d10
+    vsubl.u8        q1, d9, d11
+    vsubl.u8        q2, d12, d14
+    vsubl.u8        q3, d13, d15
+
+    vpadal.s16      q8, q11                     ;sum
+    vmlal.s16       q9, d22, d22                ;sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    vpadal.s16      q8, q0                     ;sum
+    vmlal.s16       q9, d0, d0                 ;sse
+    vmlal.s16       q10, d1, d1
+    vpadal.s16      q8, q1
+    vmlal.s16       q9, d2, d2
+    vmlal.s16       q10, d3, d3
+    vpadal.s16      q8, q2
+    vmlal.s16       q9, d4, d4
+    vmlal.s16       q10, d5, d5
+
+    vmov            q0, q15
+
+    vpadal.s16      q8, q3
+    vmlal.s16       q9, d6, d6
+    vmlal.s16       q10, d7, d7
+
+    bne             vp8_filt_spo16x16s_0_4_loop_neon
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [lr]               ;store sse
+    vshr.s32        d10, d10, #8
+    vsub.s32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    pop             {pc}
+    ENDP
+
+;================================================
+;unsigned int vp8_sub_pixel_variance16x16s_4_4_neon
+;(
+;    unsigned char  *src_ptr, r0
+;    int  src_pixels_per_line,  r1
+;    unsigned char *dst_ptr,  r2
+;    int dst_pixels_per_line,   r3
+;    unsigned int *sse
+;);
+;================================================
+|vp8_sub_pixel_variance16x16s_4_4_neon| PROC
+    push            {lr}
+
+    vld1.u8         {d0, d1, d2, d3}, [r0], r1      ;load src data
+
+    ldr             lr, [sp, #4]           ;load *sse from stack
+    vmov.i8         q13, #0                      ;q8 - sum
+    vext.8          q1, q0, q1, #1          ;construct src_ptr[1]
+
+    vmov.i8         q14, #0                      ;q9, q10 - sse
+    vmov.i8         q15, #0
+
+    mov             r12, #4                  ;loop counter
+    vrhadd.u8       q0, q0, q1              ;(src_ptr[0]+src_ptr[1])/round/shift right 1
+
+;First Pass: output_height lines x output_width columns (17x16)
+vp8_filt16x16s_4_4_loop_neon
+    vld1.u8         {d4, d5, d6, d7}, [r0], r1
+    vld1.u8         {d8, d9, d10, d11}, [r0], r1
+    vld1.u8         {d12, d13, d14, d15}, [r0], r1
+    vld1.u8         {d16, d17, d18, d19}, [r0], r1
+
+    ;pld                [r0]
+    ;pld                [r0, r1]
+    ;pld                [r0, r1, lsl #1]
+
+    vext.8          q3, q2, q3, #1          ;construct src_ptr[1]
+    vext.8          q5, q4, q5, #1
+    vext.8          q7, q6, q7, #1
+    vext.8          q9, q8, q9, #1
+
+    vrhadd.u8       q1, q2, q3              ;(src_ptr[0]+src_ptr[1])/round/shift right 1
+    vrhadd.u8       q2, q4, q5
+    vrhadd.u8       q3, q6, q7
+    vrhadd.u8       q4, q8, q9
+
+    vld1.8          {q5}, [r2], r3
+    vrhadd.u8       q0, q0, q1
+    vld1.8          {q6}, [r2], r3
+    vrhadd.u8       q1, q1, q2
+    vld1.8          {q7}, [r2], r3
+    vrhadd.u8       q2, q2, q3
+    vld1.8          {q8}, [r2], r3
+    vrhadd.u8       q3, q3, q4
+
+    vsubl.u8        q9, d0, d10                 ;diff
+    vsubl.u8        q10, d1, d11
+    vsubl.u8        q11, d2, d12
+    vsubl.u8        q12, d3, d13
+
+    vsubl.u8        q0, d4, d14                 ;diff
+    vsubl.u8        q1, d5, d15
+    vsubl.u8        q5, d6, d16
+    vsubl.u8        q6, d7, d17
+
+    vpadal.s16      q13, q9                     ;sum
+    vmlal.s16       q14, d18, d18                ;sse
+    vmlal.s16       q15, d19, d19
+
+    vpadal.s16      q13, q10                     ;sum
+    vmlal.s16       q14, d20, d20                ;sse
+    vmlal.s16       q15, d21, d21
+
+    vpadal.s16      q13, q11                     ;sum
+    vmlal.s16       q14, d22, d22                ;sse
+    vmlal.s16       q15, d23, d23
+
+    vpadal.s16      q13, q12                     ;sum
+    vmlal.s16       q14, d24, d24                ;sse
+    vmlal.s16       q15, d25, d25
+
+    subs            r12, r12, #1
+
+    vpadal.s16      q13, q0                     ;sum
+    vmlal.s16       q14, d0, d0                ;sse
+    vmlal.s16       q15, d1, d1
+
+    vpadal.s16      q13, q1                     ;sum
+    vmlal.s16       q14, d2, d2                ;sse
+    vmlal.s16       q15, d3, d3
+
+    vpadal.s16      q13, q5                     ;sum
+    vmlal.s16       q14, d10, d10                ;sse
+    vmlal.s16       q15, d11, d11
+
+    vmov            q0, q4
+
+    vpadal.s16      q13, q6                     ;sum
+    vmlal.s16       q14, d12, d12                ;sse
+    vmlal.s16       q15, d13, d13
+
+    bne             vp8_filt16x16s_4_4_loop_neon
+
+    vadd.u32        q15, q14, q15                ;accumulate sse
+    vpaddl.s32      q0, q13                      ;accumulate sum
+
+    vpaddl.u32      q1, q15
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [lr]               ;store sse
+    vshr.s32        d10, d10, #8
+    vsub.s32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    pop             {pc}
+    ENDP
+
+;==============================
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; stack unsigned char *dst_ptr,
+; stack int dst_pixels_per_line,
+; stack unsigned int *sse
+;note: in vp8_find_best_half_pixel_step()(called when 8<Speed<15), and first call of vp8_find_best_sub_pixel_step()
+;(called when speed<=8). xoffset/yoffset can only be 4 or 0, which means either by pass the filter,
+;or filter coeff is {64, 64}. This simplified program only works in this situation.
+;note: It happens that both xoffset and yoffset are zero. This can be handled in c code later.
+
+|vp8_sub_pixel_variance16x16s_neon| PROC
+    push            {r4, lr}
+
+    ldr             r4, [sp, #8]            ;load *dst_ptr from stack
+    ldr             r12, [sp, #12]          ;load dst_pixels_per_line from stack
+    ldr             lr, [sp, #16]           ;load *sse from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             secondpass_bfilter16x16s_only
+
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+    beq             firstpass_bfilter16x16s_only
+
+    vld1.u8         {d0, d1, d2, d3}, [r0], r1      ;load src data
+    sub             sp, sp, #256            ;reserve space on stack for temporary storage
+    vext.8          q1, q0, q1, #1          ;construct src_ptr[1]
+    mov             r3, sp
+    mov             r2, #4                  ;loop counter
+    vrhadd.u8       q0, q0, q1              ;(src_ptr[0]+src_ptr[1])/round/shift right 1
+
+;First Pass: output_height lines x output_width columns (17x16)
+vp8e_filt_blk2d_fp16x16s_loop_neon
+    vld1.u8         {d4, d5, d6, d7}, [r0], r1
+    vld1.u8         {d8, d9, d10, d11}, [r0], r1
+    vld1.u8         {d12, d13, d14, d15}, [r0], r1
+    vld1.u8         {d16, d17, d18, d19}, [r0], r1
+
+    ;pld                [r0]
+    ;pld                [r0, r1]
+    ;pld                [r0, r1, lsl #1]
+
+    vext.8          q3, q2, q3, #1          ;construct src_ptr[1]
+    vext.8          q5, q4, q5, #1
+    vext.8          q7, q6, q7, #1
+    vext.8          q9, q8, q9, #1
+
+    vrhadd.u8       q1, q2, q3              ;(src_ptr[0]+src_ptr[1])/round/shift right 1
+    vrhadd.u8       q2, q4, q5
+    vrhadd.u8       q3, q6, q7
+    vrhadd.u8       q4, q8, q9
+
+    vrhadd.u8       q0, q0, q1
+    vrhadd.u8       q1, q1, q2
+    vrhadd.u8       q2, q2, q3
+    vrhadd.u8       q3, q3, q4
+
+    subs            r2, r2, #1
+    vst1.u8         {d0, d1 ,d2, d3}, [r3]!         ;store result
+    vmov            q0, q4
+    vst1.u8         {d4, d5, d6, d7}, [r3]!
+
+    bne             vp8e_filt_blk2d_fp16x16s_loop_neon
+
+    b               sub_pixel_variance16x16s_neon
+
+;--------------------
+firstpass_bfilter16x16s_only
+    mov             r2, #2                  ;loop counter
+    sub             sp, sp, #256            ;reserve space on stack for temporary storage
+    mov             r3, sp
+
+;First Pass: output_height lines x output_width columns (16x16)
+vp8e_filt_blk2d_fpo16x16s_loop_neon
+    vld1.u8         {d0, d1, d2, d3}, [r0], r1      ;load src data
+    vld1.u8         {d4, d5, d6, d7}, [r0], r1
+    vld1.u8         {d8, d9, d10, d11}, [r0], r1
+    vld1.u8         {d12, d13, d14, d15}, [r0], r1
+
+    ;pld                [r0]
+    ;pld                [r0, r1]
+    ;pld                [r0, r1, lsl #1]
+
+    vext.8          q1, q0, q1, #1          ;construct src_ptr[1]
+    vld1.u8         {d16, d17, d18, d19}, [r0], r1
+    vext.8          q3, q2, q3, #1
+    vld1.u8         {d20, d21, d22, d23}, [r0], r1
+    vext.8          q5, q4, q5, #1
+    vld1.u8         {d24, d25, d26, d27}, [r0], r1
+    vext.8          q7, q6, q7, #1
+    vld1.u8         {d28, d29, d30, d31}, [r0], r1
+    vext.8          q9, q8, q9, #1
+    vext.8          q11, q10, q11, #1
+    vext.8          q13, q12, q13, #1
+    vext.8          q15, q14, q15, #1
+
+    vrhadd.u8       q0, q0, q1              ;(src_ptr[0]+src_ptr[1])/round/shift right 1
+    vrhadd.u8       q1, q2, q3
+    vrhadd.u8       q2, q4, q5
+    vrhadd.u8       q3, q6, q7
+    vrhadd.u8       q4, q8, q9
+    vrhadd.u8       q5, q10, q11
+    vrhadd.u8       q6, q12, q13
+    vrhadd.u8       q7, q14, q15
+
+    subs            r2, r2, #1
+
+    vst1.u8         {d0, d1, d2, d3}, [r3]!         ;store result
+    vst1.u8         {d4, d5, d6, d7}, [r3]!
+    vst1.u8         {d8, d9, d10, d11}, [r3]!
+    vst1.u8         {d12, d13, d14, d15}, [r3]!
+
+    bne             vp8e_filt_blk2d_fpo16x16s_loop_neon
+
+    b               sub_pixel_variance16x16s_neon
+
+;---------------------
+secondpass_bfilter16x16s_only
+    sub             sp, sp, #256            ;reserve space on stack for temporary storage
+
+    mov             r2, #2                  ;loop counter
+    vld1.u8         {d0, d1}, [r0], r1      ;load src data
+    mov             r3, sp
+
+vp8e_filt_blk2d_spo16x16s_loop_neon
+    vld1.u8         {d2, d3}, [r0], r1
+    vld1.u8         {d4, d5}, [r0], r1
+    vld1.u8         {d6, d7}, [r0], r1
+    vld1.u8         {d8, d9}, [r0], r1
+
+    vrhadd.u8       q0, q0, q1
+    vld1.u8         {d10, d11}, [r0], r1
+    vrhadd.u8       q1, q1, q2
+    vld1.u8         {d12, d13}, [r0], r1
+    vrhadd.u8       q2, q2, q3
+    vld1.u8         {d14, d15}, [r0], r1
+    vrhadd.u8       q3, q3, q4
+    vld1.u8         {d16, d17}, [r0], r1
+    vrhadd.u8       q4, q4, q5
+    vrhadd.u8       q5, q5, q6
+    vrhadd.u8       q6, q6, q7
+    vrhadd.u8       q7, q7, q8
+
+    subs            r2, r2, #1
+
+    vst1.u8         {d0, d1, d2, d3}, [r3]!         ;store result
+    vmov            q0, q8
+    vst1.u8         {d4, d5, d6, d7}, [r3]!
+    vst1.u8         {d8, d9, d10, d11}, [r3]!           ;store result
+    vst1.u8         {d12, d13, d14, d15}, [r3]!
+
+    bne             vp8e_filt_blk2d_spo16x16s_loop_neon
+
+    b               sub_pixel_variance16x16s_neon
+
+;----------------------------
+;variance16x16
+sub_pixel_variance16x16s_neon
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    sub             r3, r3, #256
+    mov             r2, #4
+
+sub_pixel_variance16x16s_neon_loop
+    vld1.8          {q0}, [r3]!                 ;Load up source and reference
+    vld1.8          {q1}, [r4], r12
+    vld1.8          {q2}, [r3]!
+    vld1.8          {q3}, [r4], r12
+    vld1.8          {q4}, [r3]!
+    vld1.8          {q5}, [r4], r12
+    vld1.8          {q6}, [r3]!
+    vld1.8          {q7}, [r4], r12
+
+    vsubl.u8        q11, d0, d2                 ;diff
+    vsubl.u8        q12, d1, d3
+    vsubl.u8        q13, d4, d6
+    vsubl.u8        q14, d5, d7
+    vsubl.u8        q0, d8, d10
+    vsubl.u8        q1, d9, d11
+    vsubl.u8        q2, d12, d14
+    vsubl.u8        q3, d13, d15
+
+    vpadal.s16      q8, q11                     ;sum
+    vmlal.s16       q9, d22, d22                ;sse
+    vmlal.s16       q10, d23, d23
+
+    subs            r2, r2, #1
+
+    vpadal.s16      q8, q12
+    vmlal.s16       q9, d24, d24
+    vmlal.s16       q10, d25, d25
+    vpadal.s16      q8, q13
+    vmlal.s16       q9, d26, d26
+    vmlal.s16       q10, d27, d27
+    vpadal.s16      q8, q14
+    vmlal.s16       q9, d28, d28
+    vmlal.s16       q10, d29, d29
+
+    vpadal.s16      q8, q0                     ;sum
+    vmlal.s16       q9, d0, d0                ;sse
+    vmlal.s16       q10, d1, d1
+    vpadal.s16      q8, q1
+    vmlal.s16       q9, d2, d2
+    vmlal.s16       q10, d3, d3
+    vpadal.s16      q8, q2
+    vmlal.s16       q9, d4, d4
+    vmlal.s16       q10, d5, d5
+    vpadal.s16      q8, q3
+    vmlal.s16       q9, d6, d6
+    vmlal.s16       q10, d7, d7
+
+    bne             sub_pixel_variance16x16s_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [lr]               ;store sse
+    vshr.s32        d10, d10, #8
+    vsub.s32        d0, d1, d10
+
+    add             sp, sp, #256
+    vmov.32         r0, d0[0]                   ;return
+
+    pop             {r4, pc}
+    ENDP
+
+    END
diff --git a/vp8/encoder/arm/neon/vp8_subpixelvariance8x8_neon.asm b/vp8/encoder/arm/neon/vp8_subpixelvariance8x8_neon.asm
new file mode 100644
index 0000000..bd56761
--- /dev/null
+++ b/vp8/encoder/arm/neon/vp8_subpixelvariance8x8_neon.asm
@@ -0,0 +1,226 @@
+;
+;  Copyright (c) 2010 The VP8 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  |vp8_sub_pixel_variance8x8_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+; r0    unsigned char  *src_ptr,
+; r1    int  src_pixels_per_line,
+; r2    int  xoffset,
+; r3    int  yoffset,
+; stack(r4) unsigned char *dst_ptr,
+; stack(r5) int dst_pixels_per_line,
+; stack(r6) unsigned int *sse
+;note: most of the code is copied from bilinear_predict8x8_neon and vp8_variance8x8_neon.
+
+|vp8_sub_pixel_variance8x8_neon| PROC
+    push            {r4-r5, lr}
+
+    ldr             r12, _BilinearTaps_coeff_
+    ldr             r4, [sp, #12]           ;load *dst_ptr from stack
+    ldr             r5, [sp, #16]           ;load dst_pixels_per_line from stack
+    ldr             lr, [sp, #20]           ;load *sse from stack
+
+    cmp             r2, #0                  ;skip first_pass filter if xoffset=0
+    beq             skip_firstpass_filter
+
+;First pass: output_height lines x output_width columns (9x8)
+    add             r2, r12, r2, lsl #3     ;calculate filter location
+
+    vld1.u8         {q1}, [r0], r1          ;load src data
+    vld1.u32        {d31}, [r2]             ;load first_pass filter
+    vld1.u8         {q2}, [r0], r1
+    vdup.8          d0, d31[0]              ;first_pass filter (d0 d1)
+    vld1.u8         {q3}, [r0], r1
+    vdup.8          d1, d31[4]
+    vld1.u8         {q4}, [r0], r1
+
+    vmull.u8        q6, d2, d0              ;(src_ptr[0] * Filter[0])
+    vmull.u8        q7, d4, d0
+    vmull.u8        q8, d6, d0
+    vmull.u8        q9, d8, d0
+
+    vext.8          d3, d2, d3, #1          ;construct src_ptr[-1]
+    vext.8          d5, d4, d5, #1
+    vext.8          d7, d6, d7, #1
+    vext.8          d9, d8, d9, #1
+
+    vmlal.u8        q6, d3, d1              ;(src_ptr[1] * Filter[1])
+    vmlal.u8        q7, d5, d1
+    vmlal.u8        q8, d7, d1
+    vmlal.u8        q9, d9, d1
+
+    vld1.u8         {q1}, [r0], r1          ;load src data
+    vqrshrn.u16    d22, q6, #7              ;shift/round/saturate to u8
+    vld1.u8         {q2}, [r0], r1
+    vqrshrn.u16    d23, q7, #7
+    vld1.u8         {q3}, [r0], r1
+    vqrshrn.u16    d24, q8, #7
+    vld1.u8         {q4}, [r0], r1
+    vqrshrn.u16    d25, q9, #7
+
+    ;first_pass filtering on the rest 5-line data
+    vld1.u8         {q5}, [r0], r1
+
+    vmull.u8        q6, d2, d0              ;(src_ptr[0] * Filter[0])
+    vmull.u8        q7, d4, d0
+    vmull.u8        q8, d6, d0
+    vmull.u8        q9, d8, d0
+    vmull.u8        q10, d10, d0
+
+    vext.8          d3, d2, d3, #1          ;construct src_ptr[-1]
+    vext.8          d5, d4, d5, #1
+    vext.8          d7, d6, d7, #1
+    vext.8          d9, d8, d9, #1
+    vext.8          d11, d10, d11, #1
+
+    vmlal.u8        q6, d3, d1              ;(src_ptr[1] * Filter[1])
+    vmlal.u8        q7, d5, d1
+    vmlal.u8        q8, d7, d1
+    vmlal.u8        q9, d9, d1
+    vmlal.u8        q10, d11, d1
+
+    vqrshrn.u16    d26, q6, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d27, q7, #7
+    vqrshrn.u16    d28, q8, #7
+    vqrshrn.u16    d29, q9, #7
+    vqrshrn.u16    d30, q10, #7
+
+;Second pass: 8x8
+secondpass_filter
+    cmp             r3, #0                  ;skip second_pass filter if yoffset=0
+    ;skip_secondpass_filter
+    beq             sub_pixel_variance8x8_neon
+
+    add             r3, r12, r3, lsl #3
+
+    vld1.u32        {d31}, [r3]             ;load second_pass filter
+
+    vdup.8          d0, d31[0]              ;second_pass filter parameters (d0 d1)
+    vdup.8          d1, d31[4]
+
+    vmull.u8        q1, d22, d0             ;(src_ptr[0] * Filter[0])
+    vmull.u8        q2, d23, d0
+    vmull.u8        q3, d24, d0
+    vmull.u8        q4, d25, d0
+    vmull.u8        q5, d26, d0
+    vmull.u8        q6, d27, d0
+    vmull.u8        q7, d28, d0
+    vmull.u8        q8, d29, d0
+
+    vmlal.u8        q1, d23, d1             ;(src_ptr[pixel_step] * Filter[1])
+    vmlal.u8        q2, d24, d1
+    vmlal.u8        q3, d25, d1
+    vmlal.u8        q4, d26, d1
+    vmlal.u8        q5, d27, d1
+    vmlal.u8        q6, d28, d1
+    vmlal.u8        q7, d29, d1
+    vmlal.u8        q8, d30, d1
+
+    vqrshrn.u16    d22, q1, #7              ;shift/round/saturate to u8
+    vqrshrn.u16    d23, q2, #7
+    vqrshrn.u16    d24, q3, #7
+    vqrshrn.u16    d25, q4, #7
+    vqrshrn.u16    d26, q5, #7
+    vqrshrn.u16    d27, q6, #7
+    vqrshrn.u16    d28, q7, #7
+    vqrshrn.u16    d29, q8, #7
+
+    b               sub_pixel_variance8x8_neon
+
+;--------------------
+skip_firstpass_filter
+    vld1.u8         {d22}, [r0], r1         ;load src data
+    vld1.u8         {d23}, [r0], r1
+    vld1.u8         {d24}, [r0], r1
+    vld1.u8         {d25}, [r0], r1
+    vld1.u8         {d26}, [r0], r1
+    vld1.u8         {d27}, [r0], r1
+    vld1.u8         {d28}, [r0], r1
+    vld1.u8         {d29}, [r0], r1
+    vld1.u8         {d30}, [r0], r1
+
+    b               secondpass_filter
+
+;----------------------
+;vp8_variance8x8_neon
+sub_pixel_variance8x8_neon
+    vmov.i8         q8, #0                      ;q8 - sum
+    vmov.i8         q9, #0                      ;q9, q10 - sse
+    vmov.i8         q10, #0
+
+    mov             r12, #2
+
+sub_pixel_variance8x8_neon_loop
+    vld1.8          {d0}, [r4], r5              ;load dst data
+    subs            r12, r12, #1
+    vld1.8          {d1}, [r4], r5
+    vld1.8          {d2}, [r4], r5
+    vsubl.u8        q4, d22, d0                 ;calculate diff
+    vld1.8          {d3}, [r4], r5
+
+    vsubl.u8        q5, d23, d1
+    vsubl.u8        q6, d24, d2
+
+    vpadal.s16      q8, q4                      ;sum
+    vmlal.s16       q9, d8, d8                  ;sse
+    vmlal.s16       q10, d9, d9
+
+    vsubl.u8        q7, d25, d3
+
+    vpadal.s16      q8, q5
+    vmlal.s16       q9, d10, d10
+    vmlal.s16       q10, d11, d11
+
+    vmov            q11, q13
+
+    vpadal.s16      q8, q6
+    vmlal.s16       q9, d12, d12
+    vmlal.s16       q10, d13, d13
+
+    vmov            q12, q14
+
+    vpadal.s16      q8, q7
+    vmlal.s16       q9, d14, d14
+    vmlal.s16       q10, d15, d15
+
+    bne             sub_pixel_variance8x8_neon_loop
+
+    vadd.u32        q10, q9, q10                ;accumulate sse
+    vpaddl.s32      q0, q8                      ;accumulate sum
+
+    vpaddl.u32      q1, q10
+    vadd.s64        d0, d0, d1
+    vadd.u64        d1, d2, d3
+
+    vmull.s32       q5, d0, d0
+    vst1.32         {d1[0]}, [lr]               ;store sse
+    vshr.s32        d10, d10, #6
+    vsub.s32        d0, d1, d10
+
+    vmov.32         r0, d0[0]                   ;return
+    pop             {r4-r5, pc}
+
+    ENDP
+
+;-----------------
+    AREA    bilinear_taps_dat, DATA, READWRITE           ;read/write by default
+;Data section with name data_area is specified. DCD reserves space in memory for 48 data.
+;One word each is reserved. Label filter_coeff can be used to access the data.
+;Data address: filter_coeff, filter_coeff+4, filter_coeff+8 ...
+_BilinearTaps_coeff_
+    DCD     bilinear_taps_coeff
+bilinear_taps_coeff
+    DCD     128, 0, 112, 16, 96, 32, 80, 48, 64, 64, 48, 80, 32, 96, 16, 112
+
+    END
diff --git a/vp8/encoder/arm/picklpf_arm.c b/vp8/encoder/arm/picklpf_arm.c
new file mode 100644
index 0000000..0586e55
--- /dev/null
+++ b/vp8/encoder/arm/picklpf_arm.c
@@ -0,0 +1,49 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "onyxc_int.h"
+#include "onyx_int.h"
+#include "quantize.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_scale/yv12extend.h"
+#include "vpx_scale/vpxscale.h"
+#include "alloccommon.h"
+
+extern void vp8_memcpy_neon(unsigned char *dst_ptr, unsigned char *src_ptr, int sz);
+
+
+void
+vpxyv12_copy_partial_frame_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc, int Fraction)
+{
+    unsigned char *src_y, *dst_y;
+    int yheight;
+    int ystride;
+    int border;
+    int yoffset;
+    int linestocopy;
+
+    border   = src_ybc->border;
+    yheight  = src_ybc->y_height;
+    ystride  = src_ybc->y_stride;
+
+    linestocopy = (yheight >> (Fraction + 4));
+
+    if (linestocopy < 1)
+        linestocopy = 1;
+
+    linestocopy <<= 4;
+
+    yoffset  = ystride * ((yheight >> 5) * 16 - 8);
+    src_y = src_ybc->y_buffer + yoffset;
+    dst_y = dst_ybc->y_buffer + yoffset;
+
+    //vpx_memcpy (dst_y, src_y, ystride * (linestocopy +16));
+    vp8_memcpy_neon((unsigned char *)dst_y, (unsigned char *)src_y, (int)(ystride *(linestocopy + 16)));
+}
diff --git a/vp8/encoder/arm/quantize_arm.c b/vp8/encoder/arm/quantize_arm.c
new file mode 100644
index 0000000..46906d3
--- /dev/null
+++ b/vp8/encoder/arm/quantize_arm.c
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <math.h>
+#include "vpx_mem/vpx_mem.h"
+
+#include "quantize.h"
+#include "entropy.h"
+#include "predictdc.h"
+
+DECLARE_ALIGNED(16, const short, vp8_rvsplus1_default_zig_zag1d[16]) =
+{
+    1,  2,  6,  7,
+    3,  5,  8,  13,
+    4,  9,  12, 14,
+    10, 11, 15, 16,
+};
+
+
+extern int vp8_fast_quantize_b_neon_func(short *coeff_ptr, short *zbin_ptr, short *qcoeff_ptr, short *dqcoeff_ptr, short *dequant_ptr, const short *scan_mask, short *round_ptr, short *quant_ptr);
+
+void vp8_fast_quantize_b_neon(BLOCK *b, BLOCKD *d)
+{
+    d->eob = vp8_fast_quantize_b_neon_func(b->coeff, &b->zbin[0][0], d->qcoeff, d->dqcoeff, d->dequant[0], vp8_rvsplus1_default_zig_zag1d, &b->round[0][0], &b->quant[0][0]);
+}
+
+/*
+//neon code is written according to the following rewritten c code
+void vp8_fast_quantize_b_neon(BLOCK *b,BLOCKD *d)
+{
+    int i, rc, eob;
+    int zbin;
+    int x, x1, y, z, sz;
+    short *coeff_ptr  = &b->Coeff[0];
+    short *zbin_ptr   = &b->Zbin[0][0];
+    short *round_ptr  = &b->Round[0][0];
+    short *quant_ptr  = &b->Quant[0][0];
+    short *qcoeff_ptr = d->qcoeff;
+    short *dqcoeff_ptr= d->dqcoeff;
+    short *dequant_ptr= &d->Dequant[0][0];
+
+    eob = 0;
+
+    for(i=0;i<16;i++)
+    {
+        z    = coeff_ptr[i];
+        zbin = zbin_ptr[i] ;
+        x  = abs(z);                                    // x = abs(z)
+
+        if(x>=zbin)
+        {
+            sz = (z>>31);                               // sign of z
+            y  = ((x+round_ptr[i])*quant_ptr[i])>>16;     // quantize (x)
+            x1  = (y^sz) - sz;                          // get the sign back
+
+            qcoeff_ptr[i] = x1;                          // write to destination
+            dqcoeff_ptr[i] = x1 * dequant_ptr[i];         // dequantized value
+
+            if(y)
+            {
+                if(eob<vp8_rvsplus1_default_zig_zag1d[i])
+                    eob=(int)vp8_rvsplus1_default_zig_zag1d[i];         // last nonzero coeffs
+            }
+        }else
+        {
+            qcoeff_ptr[i] = 0;                          // write to destination
+            dqcoeff_ptr[i] = 0;         // dequantized value
+        }
+    }
+        d->eob = eob;
+}
+*/
diff --git a/vp8/encoder/arm/quantize_arm.h b/vp8/encoder/arm/quantize_arm.h
new file mode 100644
index 0000000..e93f0fe
--- /dev/null
+++ b/vp8/encoder/arm/quantize_arm.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef QUANTIZE_ARM_H
+#define QUANTIZE_ARM_H
+
+#if HAVE_ARMV7
+extern prototype_quantize_block(vp8_fast_quantize_b_neon);
+
+#undef  vp8_quantize_fastquantb
+#define vp8_quantize_fastquantb vp8_fast_quantize_b_neon
+
+#endif
+
+#endif
diff --git a/vp8/encoder/arm/variance_arm.h b/vp8/encoder/arm/variance_arm.h
new file mode 100644
index 0000000..d9fc9b3
--- /dev/null
+++ b/vp8/encoder/arm/variance_arm.h
@@ -0,0 +1,105 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef VARIANCE_ARM_H
+#define VARIANCE_ARM_H
+
+#if HAVE_ARMV7
+extern prototype_sad(vp8_sad4x4_neon);
+extern prototype_sad(vp8_sad8x8_neon);
+extern prototype_sad(vp8_sad8x16_neon);
+extern prototype_sad(vp8_sad16x8_neon);
+extern prototype_sad(vp8_sad16x16_neon);
+
+//extern prototype_variance(vp8_variance4x4_c);
+extern prototype_variance(vp8_variance8x8_neon);
+extern prototype_variance(vp8_variance8x16_neon);
+extern prototype_variance(vp8_variance16x8_neon);
+extern prototype_variance(vp8_variance16x16_neon);
+
+//extern prototype_subpixvariance(vp8_sub_pixel_variance4x4_c);
+extern prototype_subpixvariance(vp8_sub_pixel_variance8x8_neon);
+//extern prototype_subpixvariance(vp8_sub_pixel_variance8x16_c);
+//extern prototype_subpixvariance(vp8_sub_pixel_variance16x8_c);
+extern prototype_subpixvariance(vp8_sub_pixel_variance16x16_neon);
+
+//extern prototype_getmbss(vp8_get_mb_ss_c);
+extern prototype_variance(vp8_mse16x16_neon);
+extern prototype_sad(vp8_get16x16pred_error_neon);
+//extern prototype_variance2(vp8_get8x8var_c);
+//extern prototype_variance2(vp8_get16x16var_c);
+extern prototype_sad(vp8_get4x4sse_cs_neon);
+
+#undef  vp8_variance_sad4x4
+#define vp8_variance_sad4x4 vp8_sad4x4_neon
+
+#undef  vp8_variance_sad8x8
+#define vp8_variance_sad8x8 vp8_sad8x8_neon
+
+#undef  vp8_variance_sad8x16
+#define vp8_variance_sad8x16 vp8_sad8x16_neon
+
+#undef  vp8_variance_sad16x8
+#define vp8_variance_sad16x8 vp8_sad16x8_neon
+
+#undef  vp8_variance_sad16x16
+#define vp8_variance_sad16x16 vp8_sad16x16_neon
+
+//#undef  vp8_variance_var4x4
+//#define vp8_variance_var4x4 vp8_variance4x4_c
+
+#undef  vp8_variance_var8x8
+#define vp8_variance_var8x8 vp8_variance8x8_neon
+
+#undef  vp8_variance_var8x16
+#define vp8_variance_var8x16 vp8_variance8x16_neon
+
+#undef  vp8_variance_var16x8
+#define vp8_variance_var16x8 vp8_variance16x8_neon
+
+#undef  vp8_variance_var16x16
+#define vp8_variance_var16x16 vp8_variance16x16_neon
+
+//#undef  vp8_variance_subpixvar4x4
+//#define vp8_variance_subpixvar4x4 vp8_sub_pixel_variance4x4_c
+
+#undef  vp8_variance_subpixvar8x8
+#define vp8_variance_subpixvar8x8 vp8_sub_pixel_variance8x8_neon
+
+//#undef  vp8_variance_subpixvar8x16
+//#define vp8_variance_subpixvar8x16 vp8_sub_pixel_variance8x16_c
+
+//#undef  vp8_variance_subpixvar16x8
+//#define vp8_variance_subpixvar16x8 vp8_sub_pixel_variance16x8_c
+
+#undef  vp8_variance_subpixvar16x16
+#define vp8_variance_subpixvar16x16 vp8_sub_pixel_variance16x16_neon
+
+//#undef  vp8_variance_getmbss
+//#define vp8_variance_getmbss vp8_get_mb_ss_c
+
+#undef  vp8_variance_mse16x16
+#define vp8_variance_mse16x16 vp8_mse16x16_neon
+
+#undef  vp8_variance_get16x16prederror
+#define vp8_variance_get16x16prederror vp8_get16x16pred_error_neon
+
+//#undef  vp8_variance_get8x8var
+//#define vp8_variance_get8x8var vp8_get8x8var_c
+
+//#undef  vp8_variance_get16x16var
+//#define vp8_variance_get16x16var vp8_get16x16var_c
+
+#undef  vp8_variance_get4x4sse_cs
+#define vp8_variance_get4x4sse_cs vp8_get4x4sse_cs_neon
+
+#endif
+
+#endif
diff --git a/vp8/encoder/arm/vpx_vp8_enc_asm_offsets.c b/vp8/encoder/arm/vpx_vp8_enc_asm_offsets.c
new file mode 100644
index 0000000..8cdf079
--- /dev/null
+++ b/vp8/encoder/arm/vpx_vp8_enc_asm_offsets.c
@@ -0,0 +1,77 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include <stddef.h>
+
+#include "../treewriter.h"
+#include "../tokenize.h"
+#include "../onyx_int.h"
+
+#define ct_assert(name,cond) \
+    static void assert_##name(void) UNUSED;\
+    static void assert_##name(void) {switch(0){case 0:case !!(cond):;}}
+
+#define DEFINE(sym, val) int sym = val;
+
+/*
+#define BLANK() asm volatile("\n->" : : )
+*/
+
+/*
+ * int main(void)
+ * {
+ */
+
+DEFINE(vp8_writer_lowvalue,                     offsetof(vp8_writer, lowvalue));
+DEFINE(vp8_writer_range,                        offsetof(vp8_writer, range));
+DEFINE(vp8_writer_value,                        offsetof(vp8_writer, value));
+DEFINE(vp8_writer_count,                        offsetof(vp8_writer, count));
+DEFINE(vp8_writer_pos,                          offsetof(vp8_writer, pos));
+DEFINE(vp8_writer_buffer,                       offsetof(vp8_writer, buffer));
+
+DEFINE(tokenextra_token,                        offsetof(TOKENEXTRA, Token));
+DEFINE(tokenextra_extra,                        offsetof(TOKENEXTRA, Extra));
+DEFINE(tokenextra_context_tree,                  offsetof(TOKENEXTRA, context_tree));
+DEFINE(tokenextra_skip_eob_node,                offsetof(TOKENEXTRA, skip_eob_node));
+DEFINE(TOKENEXTRA_SZ,                           sizeof(TOKENEXTRA));
+
+DEFINE(vp8_extra_bit_struct_sz,                   sizeof(vp8_extra_bit_struct));
+
+DEFINE(vp8_token_value,                         offsetof(vp8_token, value));
+DEFINE(vp8_token_len,                           offsetof(vp8_token, Len));
+
+DEFINE(vp8_extra_bit_struct_tree,                 offsetof(vp8_extra_bit_struct, tree));
+DEFINE(vp8_extra_bit_struct_prob,                 offsetof(vp8_extra_bit_struct, prob));
+DEFINE(vp8_extra_bit_struct_prob_bc,               offsetof(vp8_extra_bit_struct, prob_bc));
+DEFINE(vp8_extra_bit_struct_len,                  offsetof(vp8_extra_bit_struct, Len));
+DEFINE(vp8_extra_bit_struct_base_val,              offsetof(vp8_extra_bit_struct, base_val));
+
+DEFINE(vp8_comp_tplist,                         offsetof(VP8_COMP, tplist));
+DEFINE(vp8_comp_common,                         offsetof(VP8_COMP, common));
+DEFINE(vp8_comp_bc2,                            offsetof(VP8_COMP, bc2));
+
+DEFINE(tokenlist_start,                         offsetof(TOKENLIST, start));
+DEFINE(tokenlist_stop,                          offsetof(TOKENLIST, stop));
+DEFINE(TOKENLIST_SZ,                            sizeof(TOKENLIST));
+
+DEFINE(vp8_common_mb_rows,                       offsetof(VP8_COMMON, mb_rows));
+
+// These two sizes are used in vp7cx_pack_tokens.  They are hard coded
+//  so if the size changes this will have to be adjusted.
+ct_assert(TOKENEXTRA_SZ, sizeof(TOKENEXTRA) == 20)
+ct_assert(vp8_extra_bit_struct_sz, sizeof(vp8_extra_bit_struct) == 20)
+
+//add asserts for any offset that is not supported by assembly code
+//add asserts for any size that is not supported by assembly code
+/*
+ * return 0;
+ * }
+ */
diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c
new file mode 100644
index 0000000..31ad56a
--- /dev/null
+++ b/vp8/encoder/bitstream.c
@@ -0,0 +1,1719 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "header.h"
+#include "encodemv.h"
+#include "entropymode.h"
+#include "findnearmv.h"
+#include "mcomp.h"
+#include "systemdependent.h"
+#include <assert.h>
+#include <stdio.h>
+#include "pragmas.h"
+#include "vpx_mem/vpx_mem.h"
+#include "bitstream.h"
+
+const int vp8cx_base_skip_false_prob[128] =
+{
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255,
+    251, 248, 244, 240, 236, 232, 229, 225,
+    221, 217, 213, 208, 204, 199, 194, 190,
+    187, 183, 179, 175, 172, 168, 164, 160,
+    157, 153, 149, 145, 142, 138, 134, 130,
+    127, 124, 120, 117, 114, 110, 107, 104,
+    101, 98,  95,  92,  89,  86,  83, 80,
+    77,  74,  71,  68,  65,  62,  59, 56,
+    53,  50,  47,  44,  41,  38,  35, 32,
+    30,  28,  26,  24,  22,  20,  18, 16,
+};
+#ifdef VP8REF
+#define __int64 long long
+#endif
+
+#if defined(SECTIONBITS_OUTPUT)
+unsigned __int64 Sectionbits[500];
+#endif
+
+#ifdef ENTROPY_STATS
+int intra_mode_stats[10][10][10];
+static unsigned int tree_update_hist [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1] [2];
+extern unsigned int active_section;
+#endif
+
+#ifdef MODE_STATS
+int count_mb_seg[4] = { 0, 0, 0, 0 };
+#endif
+
+#if CONFIG_BIG_ENDIAN
+# define make_endian_16(a)  \
+    (((unsigned int)(a & 0xff)) << 8) | (((unsigned int)(a & 0xff00)) >> 8)
+# define make_endian_32(a)                              \
+    (((unsigned int)(a & 0xff)) << 24)    | (((unsigned int)(a & 0xff00)) << 8) |   \
+    (((unsigned int)(a & 0xff0000)) >> 8) | (((unsigned int)(a & 0xff000000)) >> 24)
+#else
+# define make_endian_16(a)  a
+# define make_endian_32(a)  a
+#endif
+
+static void update_mode(
+    vp8_writer *const w,
+    int n,
+    vp8_token tok               [/* n */],
+    vp8_tree tree,
+    vp8_prob Pnew               [/* n-1 */],
+    vp8_prob Pcur               [/* n-1 */],
+    unsigned int bct            [/* n-1 */] [2],
+    const unsigned int num_events[/* n */]
+)
+{
+    unsigned int new_b = 0, old_b = 0;
+    int i = 0;
+
+    vp8_tree_probs_from_distribution(
+        n--, tok, tree,
+        Pnew, bct, num_events,
+        256, 1
+    );
+
+    do
+    {
+        new_b += vp8_cost_branch(bct[i], Pnew[i]);
+        old_b += vp8_cost_branch(bct[i], Pcur[i]);
+    }
+    while (++i < n);
+
+    if (new_b + (n << 8) < old_b)
+    {
+        int i = 0;
+
+        vp8_write_bit(w, 1);
+
+        do
+        {
+            const vp8_prob p = Pnew[i];
+
+            vp8_write_literal(w, Pcur[i] = p ? p : 1, 8);
+        }
+        while (++i < n);
+    }
+    else
+        vp8_write_bit(w, 0);
+}
+
+static void update_mbintra_mode_probs(VP8_COMP *cpi)
+{
+    VP8_COMMON *const x = & cpi->common;
+
+    vp8_writer *const w = & cpi->bc;
+
+    {
+        vp8_prob Pnew   [VP8_YMODES-1];
+        unsigned int bct [VP8_YMODES-1] [2];
+
+        update_mode(
+            w, VP8_YMODES, vp8_ymode_encodings, vp8_ymode_tree,
+            Pnew, x->fc.ymode_prob, bct, (unsigned int *)cpi->ymode_count
+        );
+    }
+    {
+        vp8_prob Pnew   [VP8_UV_MODES-1];
+        unsigned int bct [VP8_UV_MODES-1] [2];
+
+        update_mode(
+            w, VP8_UV_MODES, vp8_uv_mode_encodings, vp8_uv_mode_tree,
+            Pnew, x->fc.uv_mode_prob, bct, (unsigned int *)cpi->uv_mode_count
+        );
+    }
+}
+
+static void write_ymode(vp8_writer *bc, int m, const vp8_prob *p)
+{
+    vp8_write_token(bc, vp8_ymode_tree, p, vp8_ymode_encodings + m);
+}
+
+static void kfwrite_ymode(vp8_writer *bc, int m, const vp8_prob *p)
+{
+    vp8_write_token(bc, vp8_kf_ymode_tree, p, vp8_kf_ymode_encodings + m);
+}
+
+static void write_uv_mode(vp8_writer *bc, int m, const vp8_prob *p)
+{
+    vp8_write_token(bc, vp8_uv_mode_tree, p, vp8_uv_mode_encodings + m);
+}
+
+
+static void write_bmode(vp8_writer *bc, int m, const vp8_prob *p)
+{
+    vp8_write_token(bc, vp8_bmode_tree, p, vp8_bmode_encodings + m);
+}
+
+static void write_split(vp8_writer *bc, int x)
+{
+    vp8_write_token(
+        bc, vp8_mbsplit_tree, vp8_mbsplit_probs, vp8_mbsplit_encodings + x
+    );
+}
+
+static const unsigned int norm[256] =
+{
+    0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static void pack_tokens_c(vp8_writer *w, const TOKENEXTRA *p, int xcount)
+{
+    const TOKENEXTRA *const stop = p + xcount;
+    unsigned int split;
+    unsigned int shift;
+    int count = w->count;
+    unsigned int range = w->range;
+    unsigned int lowvalue = w->lowvalue;
+
+    while (p < stop)
+    {
+        const int t = p->Token;
+        vp8_token *const a = vp8_coef_encodings + t;
+        const vp8_extra_bit_struct *const b = vp8_extra_bits + t;
+        int i = 0;
+        const unsigned char *pp = p->context_tree;
+        int v = a->value;
+        int n = a->Len;
+
+        if (p->skip_eob_node)
+        {
+            n--;
+            i = 2;
+        }
+
+        do
+        {
+            const int bb = (v >> --n) & 1;
+            split = 1 + (((range - 1) * pp[i>>1]) >> 8);
+            i = vp8_coef_tree[i+bb];
+
+            if (bb)
+            {
+                lowvalue += split;
+                range = range - split;
+            }
+            else
+            {
+                range = split;
+            }
+
+            shift = norm[range];
+            range <<= shift;
+            count += shift;
+
+            if (count >= 0)
+            {
+                int offset = shift - count;
+
+                if ((lowvalue << (offset - 1)) & 0x80000000)
+                {
+                    int x = w->pos - 1;
+
+                    while (x >= 0 && w->buffer[x] == 0xff)
+                    {
+                        w->buffer[x] = (unsigned char)0;
+                        x--;
+                    }
+
+                    w->buffer[x] += 1;
+                }
+
+                w->buffer[w->pos++] = (lowvalue >> (24 - offset));
+                lowvalue <<= offset;
+                shift = count;
+                lowvalue &= 0xffffff;
+                count -= 8 ;
+            }
+
+            lowvalue <<= shift;
+        }
+        while (n);
+
+
+        if (b->base_val)
+        {
+            const int e = p->Extra, L = b->Len;
+
+            if (L)
+            {
+                const unsigned char *pp = b->prob;
+                int v = e >> 1;
+                int n = L;              /* number of bits in v, assumed nonzero */
+                int i = 0;
+
+                do
+                {
+                    const int bb = (v >> --n) & 1;
+                    split = 1 + (((range - 1) * pp[i>>1]) >> 8);
+                    i = b->tree[i+bb];
+
+                    if (bb)
+                    {
+                        lowvalue += split;
+                        range = range - split;
+                    }
+                    else
+                    {
+                        range = split;
+                    }
+
+                    shift = norm[range];
+                    range <<= shift;
+                    count += shift;
+
+                    if (count >= 0)
+                    {
+                        int offset = shift - count;
+
+                        if ((lowvalue << (offset - 1)) & 0x80000000)
+                        {
+                            int x = w->pos - 1;
+
+                            while (x >= 0 && w->buffer[x] == 0xff)
+                            {
+                                w->buffer[x] = (unsigned char)0;
+                                x--;
+                            }
+
+                            w->buffer[x] += 1;
+                        }
+
+                        w->buffer[w->pos++] = (lowvalue >> (24 - offset));
+                        lowvalue <<= offset;
+                        shift = count;
+                        lowvalue &= 0xffffff;
+                        count -= 8 ;
+                    }
+
+                    lowvalue <<= shift;
+                }
+                while (n);
+            }
+
+
+            {
+
+                split = (range + 1) >> 1;
+
+                if (e & 1)
+                {
+                    lowvalue += split;
+                    range = range - split;
+                }
+                else
+                {
+                    range = split;
+                }
+
+                range <<= 1;
+
+                if ((lowvalue & 0x80000000))
+                {
+                    int x = w->pos - 1;
+
+                    while (x >= 0 && w->buffer[x] == 0xff)
+                    {
+                        w->buffer[x] = (unsigned char)0;
+                        x--;
+                    }
+
+                    w->buffer[x] += 1;
+
+                }
+
+                lowvalue  <<= 1;
+
+                if (!++count)
+                {
+                    count = -8;
+                    w->buffer[w->pos++] = (lowvalue >> 24);
+                    lowvalue &= 0xffffff;
+                }
+            }
+
+        }
+
+        ++p;
+    }
+
+    w->count = count;
+    w->lowvalue = lowvalue;
+    w->range = range;
+
+}
+
+static void write_partition_size(unsigned char *cx_data, int size)
+{
+    signed char csize;
+
+    csize = size & 0xff;
+    *cx_data = csize;
+    csize = (size >> 8) & 0xff;
+    *(cx_data + 1) = csize;
+    csize = (size >> 16) & 0xff;
+    *(cx_data + 2) = csize;
+
+}
+
+static void pack_tokens_into_partitions_c(VP8_COMP *cpi, unsigned char *cx_data, int num_part, int *size)
+{
+
+    int i;
+    unsigned char *ptr = cx_data;
+    unsigned int shift;
+    vp8_writer *w = &cpi->bc2;
+    *size = 3 * (num_part - 1);
+    ptr = cx_data + (*size);
+
+    for (i = 0; i < num_part; i++)
+    {
+        vp8_start_encode(w, ptr);
+        {
+            unsigned int split;
+            int count = w->count;
+            unsigned int range = w->range;
+            unsigned int lowvalue = w->lowvalue;
+            int mb_row;
+
+            for (mb_row = i; mb_row < cpi->common.mb_rows; mb_row += num_part)
+            {
+                TOKENEXTRA *p    = cpi->tplist[mb_row].start;
+                TOKENEXTRA *stop = cpi->tplist[mb_row].stop;
+
+                while (p < stop)
+                {
+                    const int t = p->Token;
+                    vp8_token *const a = vp8_coef_encodings + t;
+                    const vp8_extra_bit_struct *const b = vp8_extra_bits + t;
+                    int i = 0;
+                    const unsigned char *pp = p->context_tree;
+                    int v = a->value;
+                    int n = a->Len;
+
+                    if (p->skip_eob_node)
+                    {
+                        n--;
+                        i = 2;
+                    }
+
+                    do
+                    {
+                        const int bb = (v >> --n) & 1;
+                        split = 1 + (((range - 1) * pp[i>>1]) >> 8);
+                        i = vp8_coef_tree[i+bb];
+
+                        if (bb)
+                        {
+                            lowvalue += split;
+                            range = range - split;
+                        }
+                        else
+                        {
+                            range = split;
+                        }
+
+                        shift = norm[range];
+                        range <<= shift;
+                        count += shift;
+
+                        if (count >= 0)
+                        {
+                            int offset = shift - count;
+
+                            if ((lowvalue << (offset - 1)) & 0x80000000)
+                            {
+                                int x = w->pos - 1;
+
+                                while (x >= 0 && w->buffer[x] == 0xff)
+                                {
+                                    w->buffer[x] = (unsigned char)0;
+                                    x--;
+                                }
+
+                                w->buffer[x] += 1;
+                            }
+
+                            w->buffer[w->pos++] = (lowvalue >> (24 - offset));
+                            lowvalue <<= offset;
+                            shift = count;
+                            lowvalue &= 0xffffff;
+                            count -= 8 ;
+                        }
+
+                        lowvalue <<= shift;
+                    }
+                    while (n);
+
+
+                    if (b->base_val)
+                    {
+                        const int e = p->Extra, L = b->Len;
+
+                        if (L)
+                        {
+                            const unsigned char *pp = b->prob;
+                            int v = e >> 1;
+                            int n = L;              /* number of bits in v, assumed nonzero */
+                            int i = 0;
+
+                            do
+                            {
+                                const int bb = (v >> --n) & 1;
+                                split = 1 + (((range - 1) * pp[i>>1]) >> 8);
+                                i = b->tree[i+bb];
+
+                                if (bb)
+                                {
+                                    lowvalue += split;
+                                    range = range - split;
+                                }
+                                else
+                                {
+                                    range = split;
+                                }
+
+                                shift = norm[range];
+                                range <<= shift;
+                                count += shift;
+
+                                if (count >= 0)
+                                {
+                                    int offset = shift - count;
+
+                                    if ((lowvalue << (offset - 1)) & 0x80000000)
+                                    {
+                                        int x = w->pos - 1;
+
+                                        while (x >= 0 && w->buffer[x] == 0xff)
+                                        {
+                                            w->buffer[x] = (unsigned char)0;
+                                            x--;
+                                        }
+
+                                        w->buffer[x] += 1;
+                                    }
+
+                                    w->buffer[w->pos++] = (lowvalue >> (24 - offset));
+                                    lowvalue <<= offset;
+                                    shift = count;
+                                    lowvalue &= 0xffffff;
+                                    count -= 8 ;
+                                }
+
+                                lowvalue <<= shift;
+                            }
+                            while (n);
+                        }
+
+                        {
+                            split = (range + 1) >> 1;
+
+                            if (e & 1)
+                            {
+                                lowvalue += split;
+                                range = range - split;
+                            }
+                            else
+                            {
+                                range = split;
+                            }
+
+                            range <<= 1;
+
+                            if ((lowvalue & 0x80000000))
+                            {
+                                int x = w->pos - 1;
+
+                                while (x >= 0 && w->buffer[x] == 0xff)
+                                {
+                                    w->buffer[x] = (unsigned char)0;
+                                    x--;
+                                }
+
+                                w->buffer[x] += 1;
+
+                            }
+
+                            lowvalue  <<= 1;
+
+                            if (!++count)
+                            {
+                                count = -8;
+                                w->buffer[w->pos++] = (lowvalue >> 24);
+                                lowvalue &= 0xffffff;
+                            }
+                        }
+
+                    }
+
+                    ++p;
+                }
+            }
+
+            w->count    = count;
+            w->lowvalue = lowvalue;
+            w->range    = range;
+
+        }
+
+        vp8_stop_encode(w);
+        *size +=   w->pos;
+
+        if (i < (num_part - 1))
+        {
+            write_partition_size(cx_data, w->pos);
+            cx_data += 3;
+            ptr += w->pos;
+        }
+    }
+}
+
+
+static void pack_mb_row_tokens_c(VP8_COMP *cpi, vp8_writer *w)
+{
+
+    unsigned int split;
+    int count = w->count;
+    unsigned int range = w->range;
+    unsigned int lowvalue = w->lowvalue;
+    unsigned int shift;
+    int mb_row;
+
+    for (mb_row = 0; mb_row < cpi->common.mb_rows; mb_row++)
+    {
+        TOKENEXTRA *p    = cpi->tplist[mb_row].start;
+        TOKENEXTRA *stop = cpi->tplist[mb_row].stop;
+
+        while (p < stop)
+        {
+            const int t = p->Token;
+            vp8_token *const a = vp8_coef_encodings + t;
+            const vp8_extra_bit_struct *const b = vp8_extra_bits + t;
+            int i = 0;
+            const unsigned char *pp = p->context_tree;
+            int v = a->value;
+            int n = a->Len;
+
+            if (p->skip_eob_node)
+            {
+                n--;
+                i = 2;
+            }
+
+            do
+            {
+                const int bb = (v >> --n) & 1;
+                split = 1 + (((range - 1) * pp[i>>1]) >> 8);
+                i = vp8_coef_tree[i+bb];
+
+                if (bb)
+                {
+                    lowvalue += split;
+                    range = range - split;
+                }
+                else
+                {
+                    range = split;
+                }
+
+                shift = norm[range];
+                range <<= shift;
+                count += shift;
+
+                if (count >= 0)
+                {
+                    int offset = shift - count;
+
+                    if ((lowvalue << (offset - 1)) & 0x80000000)
+                    {
+                        int x = w->pos - 1;
+
+                        while (x >= 0 && w->buffer[x] == 0xff)
+                        {
+                            w->buffer[x] = (unsigned char)0;
+                            x--;
+                        }
+
+                        w->buffer[x] += 1;
+                    }
+
+                    w->buffer[w->pos++] = (lowvalue >> (24 - offset));
+                    lowvalue <<= offset;
+                    shift = count;
+                    lowvalue &= 0xffffff;
+                    count -= 8 ;
+                }
+
+                lowvalue <<= shift;
+            }
+            while (n);
+
+
+            if (b->base_val)
+            {
+                const int e = p->Extra, L = b->Len;
+
+                if (L)
+                {
+                    const unsigned char *pp = b->prob;
+                    int v = e >> 1;
+                    int n = L;              /* number of bits in v, assumed nonzero */
+                    int i = 0;
+
+                    do
+                    {
+                        const int bb = (v >> --n) & 1;
+                        split = 1 + (((range - 1) * pp[i>>1]) >> 8);
+                        i = b->tree[i+bb];
+
+                        if (bb)
+                        {
+                            lowvalue += split;
+                            range = range - split;
+                        }
+                        else
+                        {
+                            range = split;
+                        }
+
+                        shift = norm[range];
+                        range <<= shift;
+                        count += shift;
+
+                        if (count >= 0)
+                        {
+                            int offset = shift - count;
+
+                            if ((lowvalue << (offset - 1)) & 0x80000000)
+                            {
+                                int x = w->pos - 1;
+
+                                while (x >= 0 && w->buffer[x] == 0xff)
+                                {
+                                    w->buffer[x] = (unsigned char)0;
+                                    x--;
+                                }
+
+                                w->buffer[x] += 1;
+                            }
+
+                            w->buffer[w->pos++] = (lowvalue >> (24 - offset));
+                            lowvalue <<= offset;
+                            shift = count;
+                            lowvalue &= 0xffffff;
+                            count -= 8 ;
+                        }
+
+                        lowvalue <<= shift;
+                    }
+                    while (n);
+                }
+
+                {
+                    split = (range + 1) >> 1;
+
+                    if (e & 1)
+                    {
+                        lowvalue += split;
+                        range = range - split;
+                    }
+                    else
+                    {
+                        range = split;
+                    }
+
+                    range <<= 1;
+
+                    if ((lowvalue & 0x80000000))
+                    {
+                        int x = w->pos - 1;
+
+                        while (x >= 0 && w->buffer[x] == 0xff)
+                        {
+                            w->buffer[x] = (unsigned char)0;
+                            x--;
+                        }
+
+                        w->buffer[x] += 1;
+
+                    }
+
+                    lowvalue  <<= 1;
+
+                    if (!++count)
+                    {
+                        count = -8;
+                        w->buffer[w->pos++] = (lowvalue >> 24);
+                        lowvalue &= 0xffffff;
+                    }
+                }
+
+            }
+
+            ++p;
+        }
+    }
+
+    w->count = count;
+    w->lowvalue = lowvalue;
+    w->range = range;
+
+}
+
+static void write_mv_ref
+(
+    vp8_writer *w, MB_PREDICTION_MODE m, const vp8_prob *p
+)
+{
+
+    assert(NEARESTMV <= m  &&  m <= SPLITMV);
+
+    vp8_write_token(w, vp8_mv_ref_tree, p, VP8_MVREFENCODINGS + m);
+}
+
+static void write_sub_mv_ref
+(
+    vp8_writer *w, B_PREDICTION_MODE m, const vp8_prob *p
+)
+{
+    assert(LEFT4X4 <= m  &&  m <= NEW4X4);
+
+    vp8_write_token(w, vp8_sub_mv_ref_tree, p, VP8_SUBMVREFENCODINGS + m);
+}
+
+static void write_mv
+(
+    vp8_writer *w, const MV *mv, const MV *ref, const MV_CONTEXT *mvc
+)
+{
+    MV e;
+    e.row = mv->row - ref->row;
+    e.col = mv->col - ref->col;
+
+    vp8_encode_motion_vector(w, &e, mvc);
+}
+
+static void write_mb_features(vp8_writer *w, const MB_MODE_INFO *mi, const MACROBLOCKD *x)
+{
+    // Encode the MB segment id.
+    if (x->segmentation_enabled && x->update_mb_segmentation_map)
+    {
+        switch (mi->segment_id)
+        {
+        case 0:
+            vp8_write(w, 0, x->mb_segment_tree_probs[0]);
+            vp8_write(w, 0, x->mb_segment_tree_probs[1]);
+            break;
+        case 1:
+            vp8_write(w, 0, x->mb_segment_tree_probs[0]);
+            vp8_write(w, 1, x->mb_segment_tree_probs[1]);
+            break;
+        case 2:
+            vp8_write(w, 1, x->mb_segment_tree_probs[0]);
+            vp8_write(w, 0, x->mb_segment_tree_probs[2]);
+            break;
+        case 3:
+            vp8_write(w, 1, x->mb_segment_tree_probs[0]);
+            vp8_write(w, 1, x->mb_segment_tree_probs[2]);
+            break;
+
+            // TRAP.. This should not happen
+        default:
+            vp8_write(w, 0, x->mb_segment_tree_probs[0]);
+            vp8_write(w, 0, x->mb_segment_tree_probs[1]);
+            break;
+        }
+    }
+}
+
+
+static void pack_inter_mode_mvs(VP8_COMP *const cpi)
+{
+    VP8_COMMON *const pc = & cpi->common;
+    vp8_writer *const w = & cpi->bc;
+    const MV_CONTEXT *mvc = pc->fc.mvc;
+
+    const int *const rfct = cpi->count_mb_ref_frame_usage;
+    const int rf_intra = rfct[INTRA_FRAME];
+    const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
+
+    MODE_INFO *m = pc->mi, *ms;
+    const int mis = pc->mode_info_stride;
+    int mb_row = -1;
+
+    int prob_last_coded;
+    int prob_gf_coded;
+    int prob_skip_false = 0;
+    ms = pc->mi - 1;
+
+    // Calculate the probabilities to be used to code the reference frame based on actual useage this frame
+    if (!(cpi->prob_intra_coded = rf_intra * 255 / (rf_intra + rf_inter)))
+        cpi->prob_intra_coded = 1;
+
+    prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
+
+    if (!prob_last_coded)
+        prob_last_coded = 1;
+
+    prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
+                    ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
+
+    if (!prob_gf_coded)
+        prob_gf_coded = 1;
+
+
+#ifdef ENTROPY_STATS
+    active_section = 1;
+#endif
+
+    if (pc->mb_no_coeff_skip)
+    {
+        prob_skip_false = cpi->skip_false_count * 256 / (cpi->skip_false_count + cpi->skip_true_count);
+
+        if (prob_skip_false <= 1)
+            prob_skip_false = 1;
+
+        if (prob_skip_false > 255)
+            prob_skip_false = 255;
+
+        cpi->prob_skip_false = prob_skip_false;
+        vp8_write_literal(w, prob_skip_false, 8);
+    }
+
+    vp8_write_literal(w, cpi->prob_intra_coded, 8);
+    vp8_write_literal(w, prob_last_coded, 8);
+    vp8_write_literal(w, prob_gf_coded, 8);
+
+    update_mbintra_mode_probs(cpi);
+
+    vp8_write_mvprobs(cpi);
+
+    while (++mb_row < pc->mb_rows)
+    {
+        int mb_col = -1;
+
+        while (++mb_col < pc->mb_cols)
+        {
+            const MB_MODE_INFO *const mi = & m->mbmi;
+            const MV_REFERENCE_FRAME rf = mi->ref_frame;
+            const MB_PREDICTION_MODE mode = mi->mode;
+
+            MACROBLOCKD *xd = &cpi->mb.e_mbd;
+
+            // Distance of Mb to the various image edges.
+            // These specified to 8th pel as they are always compared to MV values that are in 1/8th pel units
+            xd->mb_to_left_edge = -((mb_col * 16) << 3);
+            xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
+            xd->mb_to_top_edge = -((mb_row * 16)) << 3;
+            xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
+
+#ifdef ENTROPY_STATS
+            active_section = 9;
+#endif
+
+            if (cpi->mb.e_mbd.update_mb_segmentation_map)
+                write_mb_features(w, mi, &cpi->mb.e_mbd);
+
+            if (pc->mb_no_coeff_skip)
+                vp8_encode_bool(w, m->mbmi.mb_skip_coeff, prob_skip_false);
+
+            if (rf == INTRA_FRAME)
+            {
+                vp8_write(w, 0, cpi->prob_intra_coded);
+#ifdef ENTROPY_STATS
+                active_section = 6;
+#endif
+                write_ymode(w, mode, pc->fc.ymode_prob);
+
+                if (mode == B_PRED)
+                {
+                    int j = 0;
+
+                    do
+                        write_bmode(w, m->bmi[j].mode, pc->fc.bmode_prob);
+
+                    while (++j < 16);
+                }
+
+                write_uv_mode(w, mi->uv_mode, pc->fc.uv_mode_prob);
+            }
+            else    /* inter coded */
+            {
+                MV best_mv;
+                vp8_prob mv_ref_p [VP8_MVREFS-1];
+
+                vp8_write(w, 1, cpi->prob_intra_coded);
+
+                if (rf == LAST_FRAME)
+                    vp8_write(w, 0, prob_last_coded);
+                else
+                {
+                    vp8_write(w, 1, prob_last_coded);
+                    vp8_write(w, (rf == GOLDEN_FRAME) ? 0 : 1, prob_gf_coded);
+                }
+
+                {
+                    MV n1, n2;
+                    int ct[4];
+
+                    vp8_find_near_mvs(xd, m, &n1, &n2, &best_mv, ct, rf, cpi->common.ref_frame_sign_bias);
+                    vp8_mv_ref_probs(mv_ref_p, ct);
+
+#ifdef ENTROPY_STATS
+                    accum_mv_refs(mode, ct);
+#endif
+
+                }
+
+#ifdef ENTROPY_STATS
+                active_section = 3;
+#endif
+
+                write_mv_ref(w, mode, mv_ref_p);
+
+                switch (mode)   /* new, split require MVs */
+                {
+                case NEWMV:
+
+#ifdef ENTROPY_STATS
+                    active_section = 5;
+#endif
+
+                    write_mv(w, &mi->mv.as_mv, &best_mv, mvc);
+                    break;
+
+                case SPLITMV:
+                {
+                    int j = 0;
+
+#ifdef MODE_STATS
+                    ++count_mb_seg [mi->partitioning];
+#endif
+
+                    write_split(w, mi->partitioning);
+
+                    do
+                    {
+                        const B_MODE_INFO *const b = mi->partition_bmi + j;
+                        const int *const  L = vp8_mbsplits [mi->partitioning];
+                        int k = -1;  /* first block in subset j */
+                        int mv_contz;
+
+                        while (j != L[++k])
+                            if (k >= 16)
+                                assert(0);
+
+                        mv_contz = vp8_mv_cont
+                                   (&(vp8_left_bmi(m, k)->mv.as_mv),
+                                    &(vp8_above_bmi(m, k, mis)->mv.as_mv));
+                        write_sub_mv_ref(w, b->mode, vp8_sub_mv_ref_prob2 [mv_contz]); //pc->fc.sub_mv_ref_prob);
+
+                        if (b->mode == NEW4X4)
+                        {
+#ifdef ENTROPY_STATS
+                            active_section = 11;
+#endif
+                            write_mv(w, &b->mv.as_mv, &best_mv, (const MV_CONTEXT *) mvc);
+                        }
+                    }
+                    while (++j < mi->partition_count);
+                }
+                break;
+                default:
+                    break;
+                }
+            }
+
+            ++m;
+        }
+
+        ++m;  /* skip L prediction border */
+    }
+}
+
+
+static void write_kfmodes(VP8_COMP *cpi)
+{
+    vp8_writer *const bc = & cpi->bc;
+    const VP8_COMMON *const c = & cpi->common;
+    /* const */
+    MODE_INFO *m = c->mi;
+
+    int mb_row = -1;
+    int prob_skip_false = 0;
+
+    if (c->mb_no_coeff_skip)
+    {
+        prob_skip_false = cpi->skip_false_count * 256 / (cpi->skip_false_count + cpi->skip_true_count);
+
+        if (prob_skip_false <= 1)
+            prob_skip_false = 1;
+
+        if (prob_skip_false >= 255)
+            prob_skip_false = 255;
+
+        cpi->prob_skip_false = prob_skip_false;
+        vp8_write_literal(bc, prob_skip_false, 8);
+    }
+
+    while (++mb_row < c->mb_rows)
+    {
+        int mb_col = -1;
+
+        while (++mb_col < c->mb_cols)
+        {
+            const int ym = m->mbmi.mode;
+
+            if (cpi->mb.e_mbd.update_mb_segmentation_map)
+                write_mb_features(bc, &m->mbmi, &cpi->mb.e_mbd);
+
+            if (c->mb_no_coeff_skip)
+                vp8_encode_bool(bc, m->mbmi.mb_skip_coeff, prob_skip_false);
+
+            kfwrite_ymode(bc, ym, c->kf_ymode_prob);
+
+            if (ym == B_PRED)
+            {
+                const int mis = c->mode_info_stride;
+                int i = 0;
+
+                do
+                {
+                    const B_PREDICTION_MODE A = vp8_above_bmi(m, i, mis)->mode;
+                    const B_PREDICTION_MODE L = vp8_left_bmi(m, i)->mode;
+                    const int bm = m->bmi[i].mode;
+
+#ifdef ENTROPY_STATS
+                    ++intra_mode_stats [A] [L] [bm];
+#endif
+
+                    write_bmode(bc, bm, c->kf_bmode_prob [A] [L]);
+                }
+                while (++i < 16);
+            }
+
+            write_uv_mode(bc, (m++)->mbmi.uv_mode, c->kf_uv_mode_prob);
+        }
+
+        m++;    // skip L prediction border
+    }
+}
+int vp8_estimate_entropy_savings(VP8_COMP *cpi)
+{
+    int i = 0;
+    int savings = 0;
+
+    const int *const rfct = cpi->count_mb_ref_frame_usage;
+    const int rf_intra = rfct[INTRA_FRAME];
+    const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
+    int new_intra, new_last, gf_last, oldtotal, newtotal;
+    int ref_frame_cost[MAX_REF_FRAMES];
+
+    vp8_clear_system_state(); //__asm emms;
+
+    if (cpi->common.frame_type != KEY_FRAME)
+    {
+        if (!(new_intra = rf_intra * 255 / (rf_intra + rf_inter)))
+            new_intra = 1;
+
+        new_last = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
+
+        gf_last = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
+                  ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
+
+        // new costs
+        ref_frame_cost[INTRA_FRAME]   = vp8_cost_zero(new_intra);
+        ref_frame_cost[LAST_FRAME]    = vp8_cost_one(new_intra)
+                                        + vp8_cost_zero(new_last);
+        ref_frame_cost[GOLDEN_FRAME]  = vp8_cost_one(new_intra)
+                                        + vp8_cost_one(new_last)
+                                        + vp8_cost_zero(gf_last);
+        ref_frame_cost[ALTREF_FRAME]  = vp8_cost_one(new_intra)
+                                        + vp8_cost_one(new_last)
+                                        + vp8_cost_one(gf_last);
+
+        newtotal =
+            rfct[INTRA_FRAME] * ref_frame_cost[INTRA_FRAME] +
+            rfct[LAST_FRAME] * ref_frame_cost[LAST_FRAME] +
+            rfct[GOLDEN_FRAME] * ref_frame_cost[GOLDEN_FRAME] +
+            rfct[ALTREF_FRAME] * ref_frame_cost[ALTREF_FRAME];
+
+
+        // old costs
+        ref_frame_cost[INTRA_FRAME]   = vp8_cost_zero(cpi->prob_intra_coded);
+        ref_frame_cost[LAST_FRAME]    = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_zero(cpi->prob_last_coded);
+        ref_frame_cost[GOLDEN_FRAME]  = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_one(cpi->prob_last_coded)
+                                        + vp8_cost_zero(cpi->prob_gf_coded);
+        ref_frame_cost[ALTREF_FRAME]  = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_one(cpi->prob_last_coded)
+                                        + vp8_cost_one(cpi->prob_gf_coded);
+
+        oldtotal =
+            rfct[INTRA_FRAME] * ref_frame_cost[INTRA_FRAME] +
+            rfct[LAST_FRAME] * ref_frame_cost[LAST_FRAME] +
+            rfct[GOLDEN_FRAME] * ref_frame_cost[GOLDEN_FRAME] +
+            rfct[ALTREF_FRAME] * ref_frame_cost[ALTREF_FRAME];
+
+        savings += (oldtotal - newtotal) / 256;
+    }
+
+
+    do
+    {
+        int j = 0;
+
+        do
+        {
+            int k = 0;
+
+            do
+            {
+                /* at every context */
+
+                /* calc probs and branch cts for this frame only */
+                //vp8_prob new_p           [vp8_coef_tokens-1];
+                //unsigned int branch_ct   [vp8_coef_tokens-1] [2];
+
+                int t = 0;      /* token/prob index */
+
+                vp8_tree_probs_from_distribution(
+                    vp8_coef_tokens, vp8_coef_encodings, vp8_coef_tree,
+                    cpi->frame_coef_probs [i][j][k], cpi->frame_branch_ct [i][j][k], cpi->coef_counts [i][j][k],
+                    256, 1
+                );
+
+                do
+                {
+                    const unsigned int *ct  = cpi->frame_branch_ct [i][j][k][t];
+                    const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
+
+                    const vp8_prob old = cpi->common.fc.coef_probs [i][j][k][t];
+                    const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
+
+                    const int old_b = vp8_cost_branch(ct, old);
+                    const int new_b = vp8_cost_branch(ct, newp);
+
+                    const int update_b = 8 +
+                                         ((vp8_cost_one(upd) - vp8_cost_zero(upd)) >> 8);
+
+                    const int s = old_b - new_b - update_b;
+
+                    if (s > 0)
+                        savings += s;
+
+
+                }
+                while (++t < vp8_coef_tokens - 1);
+
+
+            }
+            while (++k < PREV_COEF_CONTEXTS);
+        }
+        while (++j < COEF_BANDS);
+    }
+    while (++i < BLOCK_TYPES);
+
+    return savings;
+}
+
+static void update_coef_probs(VP8_COMP *cpi)
+{
+    int i = 0;
+    vp8_writer *const w = & cpi->bc;
+    int savings = 0;
+
+    vp8_clear_system_state(); //__asm emms;
+
+
+    do
+    {
+        int j = 0;
+
+        do
+        {
+            int k = 0;
+
+            do
+            {
+                //note: use result from vp8_estimate_entropy_savings, so no need to call vp8_tree_probs_from_distribution here.
+                /* at every context */
+
+                /* calc probs and branch cts for this frame only */
+                //vp8_prob new_p           [vp8_coef_tokens-1];
+                //unsigned int branch_ct   [vp8_coef_tokens-1] [2];
+
+                int t = 0;      /* token/prob index */
+
+                //vp8_tree_probs_from_distribution(
+                //    vp8_coef_tokens, vp8_coef_encodings, vp8_coef_tree,
+                //    new_p, branch_ct, (unsigned int *)cpi->coef_counts [i][j][k],
+                //    256, 1
+                //    );
+
+                do
+                {
+                    const unsigned int *ct  = cpi->frame_branch_ct [i][j][k][t];
+                    const vp8_prob newp = cpi->frame_coef_probs [i][j][k][t];
+
+                    vp8_prob *Pold = cpi->common.fc.coef_probs [i][j][k] + t;
+                    const vp8_prob old = *Pold;
+                    const vp8_prob upd = vp8_coef_update_probs [i][j][k][t];
+
+                    const int old_b = vp8_cost_branch(ct, old);
+                    const int new_b = vp8_cost_branch(ct, newp);
+
+                    const int update_b = 8 +
+                                         ((vp8_cost_one(upd) - vp8_cost_zero(upd)) >> 8);
+
+                    const int s = old_b - new_b - update_b;
+                    const int u = s > 0 ? 1 : 0;
+
+                    vp8_write(w, u, upd);
+
+
+#ifdef ENTROPY_STATS
+                    ++ tree_update_hist [i][j][k][t] [u];
+#endif
+
+                    if (u)
+                    {
+                        /* send/use new probability */
+
+                        *Pold = newp;
+                        vp8_write_literal(w, newp, 8);
+
+                        savings += s;
+
+                    }
+
+                }
+                while (++t < vp8_coef_tokens - 1);
+
+                /* Accum token counts for generation of default statistics */
+#ifdef ENTROPY_STATS
+                t = 0;
+
+                do
+                {
+                    context_counters [i][j][k][t] += cpi->coef_counts [i][j][k][t];
+                }
+                while (++t < vp8_coef_tokens);
+
+#endif
+
+            }
+            while (++k < PREV_COEF_CONTEXTS);
+        }
+        while (++j < COEF_BANDS);
+    }
+    while (++i < BLOCK_TYPES);
+
+}
+#ifdef PACKET_TESTING
+FILE *vpxlogc = 0;
+#endif
+
+static void put_delta_q(vp8_writer *bc, int delta_q)
+{
+    if (delta_q != 0)
+    {
+        vp8_write_bit(bc, 1);
+        vp8_write_literal(bc, abs(delta_q), 4);
+
+        if (delta_q < 0)
+            vp8_write_bit(bc, 1);
+        else
+            vp8_write_bit(bc, 0);
+    }
+    else
+        vp8_write_bit(bc, 0);
+}
+
+void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
+{
+    int i, j;
+    VP8_HEADER oh;
+    VP8_COMMON *const pc = & cpi->common;
+    vp8_writer *const bc = & cpi->bc;
+    MACROBLOCKD *const xd = & cpi->mb.e_mbd;
+    int extra_bytes_packed = 0;
+
+    unsigned char *cx_data = dest;
+    const int *mb_feature_data_bits;
+
+    oh.show_frame = (int) pc->show_frame;
+    oh.type = (int)pc->frame_type;
+    oh.version = pc->version;
+
+    mb_feature_data_bits = vp8_mb_feature_data_bits;
+    cx_data += 3;
+
+#if defined(SECTIONBITS_OUTPUT)
+    Sectionbits[active_section = 1] += sizeof(VP8_HEADER) * 8 * 256;
+#endif
+
+    //vp8_kf_default_bmode_probs() is called in vp8_setup_key_frame() once for each
+    //K frame before encode frame. pc->kf_bmode_prob doesn't get changed anywhere
+    //else. No need to call it again here. --yw
+    //vp8_kf_default_bmode_probs( pc->kf_bmode_prob);
+
+    // every keyframe send startcode, width, height, scale factor, clamp and color type
+    if (oh.type == KEY_FRAME)
+    {
+        int w, h, hs, vs;
+
+        // Start / synch code
+        cx_data[0] = 0x9D;
+        cx_data[1] = 0x01;
+        cx_data[2] = 0x2a;
+
+        *((unsigned short *)(cx_data + 3)) = make_endian_16((pc->horiz_scale << 14) | pc->Width);
+        *((unsigned short *)(cx_data + 5)) = make_endian_16((pc->vert_scale << 14) | pc->Height);
+
+        extra_bytes_packed = 7;
+        cx_data += extra_bytes_packed ;
+
+        vp8_start_encode(bc, cx_data);
+
+        // signal clr type
+        vp8_write_bit(bc, pc->clr_type);
+        vp8_write_bit(bc, pc->clamp_type);
+
+    }
+    else
+        vp8_start_encode(bc, cx_data);
+
+
+    // Signal whether or not Segmentation is enabled
+    vp8_write_bit(bc, (xd->segmentation_enabled) ? 1 : 0);
+
+    // Indicate which features are enabled
+    if (xd->segmentation_enabled)
+    {
+        // Signal whether or not the segmentation map is being updated.
+        vp8_write_bit(bc, (xd->update_mb_segmentation_map) ? 1 : 0);
+        vp8_write_bit(bc, (xd->update_mb_segmentation_data) ? 1 : 0);
+
+        if (xd->update_mb_segmentation_data)
+        {
+            signed char Data;
+
+            vp8_write_bit(bc, (xd->mb_segement_abs_delta) ? 1 : 0);
+
+            // For each segmentation feature (Quant and loop filter level)
+            for (i = 0; i < MB_LVL_MAX; i++)
+            {
+                // For each of the segments
+                for (j = 0; j < MAX_MB_SEGMENTS; j++)
+                {
+                    Data = xd->segment_feature_data[i][j];
+
+                    // Frame level data
+                    if (Data)
+                    {
+                        vp8_write_bit(bc, 1);
+
+                        if (Data < 0)
+                        {
+                            Data = - Data;
+                            vp8_write_literal(bc, Data, mb_feature_data_bits[i]);
+                            vp8_write_bit(bc, 1);
+                        }
+                        else
+                        {
+                            vp8_write_literal(bc, Data, mb_feature_data_bits[i]);
+                            vp8_write_bit(bc, 0);
+                        }
+                    }
+                    else
+                        vp8_write_bit(bc, 0);
+                }
+            }
+        }
+
+        if (xd->update_mb_segmentation_map)
+        {
+            // Write the probs used to decode the segment id for each macro block.
+            for (i = 0; i < MB_FEATURE_TREE_PROBS; i++)
+            {
+                int Data = xd->mb_segment_tree_probs[i];
+
+                if (Data != 255)
+                {
+                    vp8_write_bit(bc, 1);
+                    vp8_write_literal(bc, Data, 8);
+                }
+                else
+                    vp8_write_bit(bc, 0);
+            }
+        }
+    }
+
+    // Code to determine whether or not to update the scan order.
+    vp8_write_bit(bc, pc->filter_type);
+    vp8_write_literal(bc, pc->filter_level, 6);
+    vp8_write_literal(bc, pc->sharpness_level, 3);
+
+    // Write out loop filter deltas applied at the MB level based on mode or ref frame (if they are enabled).
+    vp8_write_bit(bc, (xd->mode_ref_lf_delta_enabled) ? 1 : 0);
+
+    if (xd->mode_ref_lf_delta_enabled)
+    {
+        // Do the deltas need to be updated
+        vp8_write_bit(bc, (xd->mode_ref_lf_delta_update) ? 1 : 0);
+
+        if (xd->mode_ref_lf_delta_update)
+        {
+            int Data;
+
+            // Send update
+            for (i = 0; i < MAX_REF_LF_DELTAS; i++)
+            {
+                Data = xd->ref_lf_deltas[i];
+
+                // Frame level data
+                if (Data)
+                {
+                    vp8_write_bit(bc, 1);
+
+                    if (Data > 0)
+                    {
+                        vp8_write_literal(bc, (Data & 0x3F), 6);
+                        vp8_write_bit(bc, 0);    // sign
+                    }
+                    else
+                    {
+                        Data = -Data;
+                        vp8_write_literal(bc, (Data & 0x3F), 6);
+                        vp8_write_bit(bc, 1);    // sign
+                    }
+                }
+                else
+                    vp8_write_bit(bc, 0);
+            }
+
+            // Send update
+            for (i = 0; i < MAX_MODE_LF_DELTAS; i++)
+            {
+                Data = xd->mode_lf_deltas[i];
+
+                if (Data)
+                {
+                    vp8_write_bit(bc, 1);
+
+                    if (Data > 0)
+                    {
+                        vp8_write_literal(bc, (Data & 0x3F), 6);
+                        vp8_write_bit(bc, 0);    // sign
+                    }
+                    else
+                    {
+                        Data = -Data;
+                        vp8_write_literal(bc, (Data & 0x3F), 6);
+                        vp8_write_bit(bc, 1);    // sign
+                    }
+                }
+                else
+                    vp8_write_bit(bc, 0);
+            }
+        }
+    }
+
+    //signal here is multi token partition is enabled
+    vp8_write_literal(bc, pc->multi_token_partition, 2);
+
+    // Frame Qbaseline quantizer index
+    vp8_write_literal(bc, pc->base_qindex, 7);
+
+    // Transmit Dc, Second order and Uv quantizer delta information
+    put_delta_q(bc, pc->y1dc_delta_q);
+    put_delta_q(bc, pc->y2dc_delta_q);
+    put_delta_q(bc, pc->y2ac_delta_q);
+    put_delta_q(bc, pc->uvdc_delta_q);
+    put_delta_q(bc, pc->uvac_delta_q);
+
+    // When there is a key frame all reference buffers are updated using the new key frame
+    if (pc->frame_type != KEY_FRAME)
+    {
+        // Should the GF or ARF be updated using the transmitted frame or buffer
+        vp8_write_bit(bc, pc->refresh_golden_frame);
+        vp8_write_bit(bc, pc->refresh_alt_ref_frame);
+
+        // If not being updated from current frame should either GF or ARF be updated from another buffer
+        if (!pc->refresh_golden_frame)
+            vp8_write_literal(bc, pc->copy_buffer_to_gf, 2);
+
+        if (!pc->refresh_alt_ref_frame)
+            vp8_write_literal(bc, pc->copy_buffer_to_arf, 2);
+
+        // Indicate reference frame sign bias for Golden and ARF frames (always 0 for last frame buffer)
+        vp8_write_bit(bc, pc->ref_frame_sign_bias[GOLDEN_FRAME]);
+        vp8_write_bit(bc, pc->ref_frame_sign_bias[ALTREF_FRAME]);
+    }
+
+    vp8_write_bit(bc, pc->refresh_entropy_probs);
+
+    if (pc->frame_type != KEY_FRAME)
+        vp8_write_bit(bc, pc->refresh_last_frame);
+
+#ifdef ENTROPY_STATS
+
+    if (pc->frame_type == INTER_FRAME)
+        active_section = 0;
+    else
+        active_section = 7;
+
+#endif
+
+    vp8_clear_system_state();  //__asm emms;
+
+    //************************************************
+    // save a copy for later refresh
+    {
+        vpx_memcpy(&cpi->common.lfc, &cpi->common.fc, sizeof(cpi->common.fc));
+    }
+
+    update_coef_probs(cpi);
+
+#ifdef ENTROPY_STATS
+    active_section = 2;
+#endif
+
+    // Write out the mb_no_coeff_skip flag
+    vp8_write_bit(bc, pc->mb_no_coeff_skip);
+
+    if (pc->frame_type == KEY_FRAME)
+    {
+        write_kfmodes(cpi);
+
+#ifdef ENTROPY_STATS
+        active_section = 8;
+#endif
+    }
+    else
+    {
+        pack_inter_mode_mvs(cpi);
+
+#ifdef ENTROPY_STATS
+        active_section = 1;
+#endif
+    }
+
+    vp8_stop_encode(bc);
+
+
+    if (pc->multi_token_partition != ONE_PARTITION)
+    {
+        int num_part;
+        int asize;
+        num_part = 1 << pc->multi_token_partition;
+
+        pack_tokens_into_partitions(cpi, cx_data + bc->pos, num_part, &asize);
+
+        oh.first_partition_length_in_bytes = cpi->bc.pos;
+
+        *size = cpi->bc.pos + VP8_HEADER_SIZE + asize + extra_bytes_packed;
+    }
+    else
+    {
+        vp8_start_encode(&cpi->bc2, cx_data + bc->pos);
+
+        if (!cpi->b_multi_threaded)
+            pack_tokens(&cpi->bc2, cpi->tok, cpi->tok_count);
+        else
+            pack_mb_row_tokens(cpi, &cpi->bc2);
+
+        vp8_stop_encode(&cpi->bc2);
+        oh.first_partition_length_in_bytes = cpi->bc.pos ;
+        *size = cpi->bc2.pos + cpi->bc.pos + VP8_HEADER_SIZE + extra_bytes_packed;
+    }
+
+#if CONFIG_BIG_ENDIAN
+    {
+        int v = (oh.first_partition_length_in_bytes << 5) |
+                (oh.show_frame << 4) |
+                (oh.version << 1) |
+                oh.type;
+
+        v = make_endian_32(v);
+        vpx_memcpy(dest, &v, 3);
+    }
+#else
+    vpx_memcpy(dest, &oh, 3);
+#endif
+}
+
+#ifdef ENTROPY_STATS
+void print_tree_update_probs()
+{
+    int i, j, k, l;
+    FILE *f = fopen("context.c", "a");
+    int Sum;
+    fprintf(f, "\n/* Update probabilities for token entropy tree. */\n\n");
+    fprintf(f, "const vp8_prob tree_update_probs[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1] = {\n");
+
+    for (i = 0; i < BLOCK_TYPES; i++)
+    {
+        fprintf(f, "  { \n");
+
+        for (j = 0; j < COEF_BANDS; j++)
+        {
+            fprintf(f, "    {\n");
+
+            for (k = 0; k < PREV_COEF_CONTEXTS; k++)
+            {
+                fprintf(f, "      {");
+
+                for (l = 0; l < MAX_ENTROPY_TOKENS - 1; l++)
+                {
+                    Sum = tree_update_hist[i][j][k][l][0] + tree_update_hist[i][j][k][l][1];
+
+                    if (Sum > 0)
+                    {
+                        if (((tree_update_hist[i][j][k][l][0] * 255) / Sum) > 0)
+                            fprintf(f, "%3ld, ", (tree_update_hist[i][j][k][l][0] * 255) / Sum);
+                        else
+                            fprintf(f, "%3ld, ", 1);
+                    }
+                    else
+                        fprintf(f, "%3ld, ", 128);
+                }
+
+                fprintf(f, "},\n");
+            }
+
+            fprintf(f, "    },\n");
+        }
+
+        fprintf(f, "  },\n");
+    }
+
+    fprintf(f, "};\n");
+    fclose(f);
+}
+#endif
diff --git a/vp8/encoder/bitstream.h b/vp8/encoder/bitstream.h
new file mode 100644
index 0000000..ee69f66
--- /dev/null
+++ b/vp8/encoder/bitstream.h
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_BITSTREAM_H
+#define __INC_BITSTREAM_H
+
+#if HAVE_ARMV7
+void vp8cx_pack_tokens_armv7(vp8_writer *w, const TOKENEXTRA *p, int xcount,
+                             vp8_token *,
+                             vp8_extra_bit_struct *,
+                             const vp8_tree_index *);
+void vp8cx_pack_tokens_into_partitions_armv7(VP8_COMP *, unsigned char *, int , int *,
+        vp8_token *,
+        vp8_extra_bit_struct *,
+        const vp8_tree_index *);
+void vp8cx_pack_mb_row_tokens_armv7(VP8_COMP *cpi, vp8_writer *w,
+                                    vp8_token *,
+                                    vp8_extra_bit_struct *,
+                                    const vp8_tree_index *);
+# define pack_tokens(a,b,c)                  \
+    vp8cx_pack_tokens_armv7(a,b,c,vp8_coef_encodings,vp8_extra_bits,vp8_coef_tree)
+# define pack_tokens_into_partitions(a,b,c,d)  \
+    vp8cx_pack_tokens_into_partitions_armv7(a,b,c,d,vp8_coef_encodings,vp8_extra_bits,vp8_coef_tree)
+# define pack_mb_row_tokens(a,b)               \
+    vp8cx_pack_mb_row_tokens_armv7(a,b,vp8_coef_encodings,vp8_extra_bits,vp8_coef_tree)
+#else
+# define pack_tokens(a,b,c)                  pack_tokens_c(a,b,c)
+# define pack_tokens_into_partitions(a,b,c,d)  pack_tokens_into_partitions_c(a,b,c,d)
+# define pack_mb_row_tokens(a,b)               pack_mb_row_tokens_c(a,b)
+#endif
+#endif
diff --git a/vp8/encoder/block.h b/vp8/encoder/block.h
new file mode 100644
index 0000000..cc4cbe0
--- /dev/null
+++ b/vp8/encoder/block.h
@@ -0,0 +1,115 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_BLOCK_H
+#define __INC_BLOCK_H
+
+#include "onyx.h"
+#include "blockd.h"
+#include "entropymv.h"
+#include "entropy.h"
+#include "vpx_ports/mem.h"
+
+// motion search site
+typedef struct
+{
+    MV mv;
+    int offset;
+} search_site;
+
+typedef struct
+{
+    // 16 Y blocks, 4 U blocks, 4 V blocks each with 16 entries
+    short *src_diff;
+    short *coeff;
+
+    // 16 Y blocks, 4 U blocks, 4 V blocks each with 16 entries
+    short(*quant)[4];
+    short(*zbin)[4];
+    short(*zrun_zbin_boost);
+    short(*round)[4];
+
+    // Zbin Over Quant value
+    short zbin_extra;
+
+    unsigned char **base_src;
+    int src;
+    int src_stride;
+
+//  MV  enc_mv;
+    int force_empty;
+
+} BLOCK;
+
+typedef struct
+{
+    DECLARE_ALIGNED(16, short, src_diff[400]);       // 16x16 Y 8x8 U 8x8 V 4x4 2nd Y
+    DECLARE_ALIGNED(16, short, coeff[400]);     // 16x16 Y 8x8 U 8x8 V 4x4 2nd Y
+
+    // 16 Y blocks, 4 U blocks, 4 V blocks, 1 DC 2nd order block each with 16 entries
+    BLOCK block[25];
+
+    YV12_BUFFER_CONFIG src;
+
+    MACROBLOCKD e_mbd;
+
+    search_site *ss;
+    int ss_count;
+    int searches_per_step;
+
+    int errorperbit;
+    int sadperbit16;
+    int sadperbit4;
+    int errthresh;
+    int rddiv;
+    int rdmult;
+
+    int mvcosts[2][MVvals+1];
+    int *mvcost[2];
+    int mvsadcosts[2][MVvals+1];
+    int *mvsadcost[2];
+    int mbmode_cost[2][MB_MODE_COUNT];
+    int intra_uv_mode_cost[2][MB_MODE_COUNT];
+    unsigned int bmode_costs[10][10][10];
+    unsigned int inter_bmode_costs[B_MODE_COUNT];
+
+    // These define limits to motion vector components to prevent them from extending outside the UMV borders
+    int mv_col_min;
+    int mv_col_max;
+    int mv_row_min;
+    int mv_row_max;
+
+    int vector_range;    // Used to monitor limiting range of recent vectors to guide search.
+    int skip;
+
+    int encode_breakout;
+
+    unsigned char *active_ptr;
+    MV_CONTEXT *mvc;
+
+    unsigned int token_costs[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens];
+    int optimize;
+
+    void (*vp8_short_fdct4x4)(short *input, short *output, int pitch);
+    void (*vp8_short_fdct8x4)(short *input, short *output, int pitch);
+    void (*short_fdct4x4rd)(short *input, short *output, int pitch);
+    void (*short_fdct8x4rd)(short *input, short *output, int pitch);
+    void (*vp8_short_fdct4x4_ptr)(short *input, short *output, int pitch);
+    void (*short_walsh4x4)(short *input, short *output, int pitch);
+
+    void (*quantize_b)(BLOCK *b, BLOCKD *d);
+    void (*quantize_brd)(BLOCK *b, BLOCKD *d);
+
+
+
+} MACROBLOCK;
+
+
+#endif
diff --git a/vp8/encoder/boolhuff.c b/vp8/encoder/boolhuff.c
new file mode 100644
index 0000000..c101384
--- /dev/null
+++ b/vp8/encoder/boolhuff.c
@@ -0,0 +1,147 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "boolhuff.h"
+#include "blockd.h"
+
+
+
+#if defined(SECTIONBITS_OUTPUT)
+unsigned __int64 Sectionbits[500];
+
+#endif
+
+#ifdef ENTROPY_STATS
+unsigned int active_section = 0;
+#endif
+
+const unsigned int vp8_prob_cost[256] =
+{
+    2047, 2047, 1791, 1641, 1535, 1452, 1385, 1328, 1279, 1235, 1196, 1161, 1129, 1099, 1072, 1046,
+    1023, 1000,  979,  959,  940,  922,  905,  889,  873,  858,  843,  829,  816,  803,  790,  778,
+    767,  755,  744,  733,  723,  713,  703,  693,  684,  675,  666,  657,  649,  641,  633,  625,
+    617,  609,  602,  594,  587,  580,  573,  567,  560,  553,  547,  541,  534,  528,  522,  516,
+    511,  505,  499,  494,  488,  483,  477,  472,  467,  462,  457,  452,  447,  442,  437,  433,
+    428,  424,  419,  415,  410,  406,  401,  397,  393,  389,  385,  381,  377,  373,  369,  365,
+    361,  357,  353,  349,  346,  342,  338,  335,  331,  328,  324,  321,  317,  314,  311,  307,
+    304,  301,  297,  294,  291,  288,  285,  281,  278,  275,  272,  269,  266,  263,  260,  257,
+    255,  252,  249,  246,  243,  240,  238,  235,  232,  229,  227,  224,  221,  219,  216,  214,
+    211,  208,  206,  203,  201,  198,  196,  194,  191,  189,  186,  184,  181,  179,  177,  174,
+    172,  170,  168,  165,  163,  161,  159,  156,  154,  152,  150,  148,  145,  143,  141,  139,
+    137,  135,  133,  131,  129,  127,  125,  123,  121,  119,  117,  115,  113,  111,  109,  107,
+    105,  103,  101,   99,   97,   95,   93,   92,   90,   88,   86,   84,   82,   81,   79,   77,
+    75,   73,   72,   70,   68,   66,   65,   63,   61,   60,   58,   56,   55,   53,   51,   50,
+    48,   46,   45,   43,   41,   40,   38,   37,   35,   33,   32,   30,   29,   27,   25,   24,
+    22,   21,   19,   18,   16,   15,   13,   12,   10,    9,    7,    6,    4,    3,    1,   1
+};
+
+void vp8_start_encode(BOOL_CODER *br, unsigned char *source)
+{
+
+    br->lowvalue = 0;
+    br->range    = 255;
+    br->value    = 0;
+    br->count    = -24;
+    br->buffer   = source;
+    br->pos      = 0;
+}
+
+void vp8_stop_encode(BOOL_CODER *br)
+{
+    int i;
+
+    for (i = 0; i < 32; i++)
+        vp8_encode_bool(br, 0, 128);
+}
+
+DECLARE_ALIGNED(16, static const unsigned int, norm[256]) =
+{
+    0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+void vp8_encode_bool(BOOL_CODER *br, int bit, int probability)
+{
+    unsigned int split;
+    int count = br->count;
+    unsigned int range = br->range;
+    unsigned int lowvalue = br->lowvalue;
+    register unsigned int shift;
+
+#ifdef ENTROPY_STATS
+#if defined(SECTIONBITS_OUTPUT)
+
+    if (bit)
+        Sectionbits[active_section] += vp8_prob_cost[255-probability];
+    else
+        Sectionbits[active_section] += vp8_prob_cost[probability];
+
+#endif
+#endif
+
+    split = 1 + (((range - 1) * probability) >> 8);
+
+    range = split;
+
+    if (bit)
+    {
+        lowvalue += split;
+        range = br->range - split;
+    }
+
+    shift = norm[range];
+
+    range <<= shift;
+    count += shift;
+
+    if (count >= 0)
+    {
+        int offset = shift - count;
+
+        if ((lowvalue << (offset - 1)) & 0x80000000)
+        {
+            int x = br->pos - 1;
+
+            while (x >= 0 && br->buffer[x] == 0xff)
+            {
+                br->buffer[x] = (unsigned char)0;
+                x--;
+            }
+
+            br->buffer[x] += 1;
+        }
+
+        br->buffer[br->pos++] = (lowvalue >> (24 - offset));
+        lowvalue <<= offset;
+        shift = count;
+        lowvalue &= 0xffffff;
+        count -= 8 ;
+    }
+
+    lowvalue <<= shift;
+    br->count = count;
+    br->lowvalue = lowvalue;
+    br->range = range;
+}
+
+void vp8_encode_value(BOOL_CODER *br, int data, int bits)
+{
+    int bit;
+
+    for (bit = bits - 1; bit >= 0; bit--)
+        vp8_encode_bool(br, (1 & (data >> bit)), 0x80);
+
+}
diff --git a/vp8/encoder/boolhuff.h b/vp8/encoder/boolhuff.h
new file mode 100644
index 0000000..0d929f0
--- /dev/null
+++ b/vp8/encoder/boolhuff.h
@@ -0,0 +1,42 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/****************************************************************************
+*
+*   Module Title :     boolhuff.h
+*
+*   Description  :     Bool Coder header file.
+*
+****************************************************************************/
+#ifndef __INC_BOOLHUFF_H
+#define __INC_BOOLHUFF_H
+
+
+typedef struct
+{
+    unsigned int lowvalue;
+    unsigned int range;
+    unsigned int value;
+    int count;
+    unsigned int pos;
+    unsigned char *buffer;
+
+    // Variables used to track bit costs without outputing to the bitstream
+    unsigned int  measure_cost;
+    unsigned long bit_counter;
+} BOOL_CODER;
+
+extern void vp8_start_encode(BOOL_CODER *bc, unsigned char *buffer);
+extern void vp8_encode_bool(BOOL_CODER *bc, int x, int context);
+extern void vp8_encode_value(BOOL_CODER *br, int data, int bits);
+extern void vp8_stop_encode(BOOL_CODER *bc);
+extern const unsigned int vp8_prob_cost[256];
+
+#endif
diff --git a/vp8/encoder/dct.c b/vp8/encoder/dct.c
new file mode 100644
index 0000000..5207e39
--- /dev/null
+++ b/vp8/encoder/dct.c
@@ -0,0 +1,223 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <math.h>
+
+
+static const short dct_matrix2[4][4] =
+{
+    { 23170,  30274,  23170, 12540 },
+    { 23170,  12540, -23170, -30274 },
+    { 23170, -12540, -23170, 30274 },
+    { 23170, -30274,  23170, -12540 }
+};
+
+static const short dct_matrix1[4][4] =
+{
+    { 23170,  23170,  23170,  23170 },
+    { 30274,  12540, -12540, -30274 },
+    { 23170, -23170, -23170,  23170 },
+    { 12540, -30274,  30274, -12540 }
+};
+
+
+#define _1STSTAGESHIFT           14
+#define _1STSTAGEROUNDING        (1<<( _1STSTAGESHIFT-1))
+#define _2NDSTAGESHIFT           16
+#define _2NDSTAGEROUNDING        (1<<( _2NDSTAGESHIFT-1))
+
+// using matrix multiply
+void vp8_short_fdct4x4_c(short *input, short *output, int pitch)
+{
+    int i, j, k;
+    short temp[4][4];
+    int sumtemp;
+    pitch >>= 1;
+
+    for (i = 0; i < 4; i++)
+    {
+        for (j = 0; j < 4; j++)
+        {
+            sumtemp = 0;
+
+            for (k = 0; k < 4; k++)
+            {
+                sumtemp += input[i*pitch+k] * dct_matrix2[k][j];
+
+            }
+
+            temp[i][j] = (short)((sumtemp + _1STSTAGEROUNDING) >> _1STSTAGESHIFT);
+        }
+    }
+
+
+    for (i = 0; i < 4; i++)
+    {
+        for (j = 0; j < 4; j++)
+        {
+            sumtemp = 0;
+
+            for (k = 0; k < 4; k++)
+            {
+                sumtemp += dct_matrix1[i][ k] * temp[k][ j];
+            }
+
+            output[i*4+j] = (short)((sumtemp + _2NDSTAGEROUNDING) >> _2NDSTAGESHIFT);
+        }
+    }
+
+}
+
+
+void vp8_short_fdct8x4_c(short *input, short *output, int pitch)
+{
+    vp8_short_fdct4x4_c(input,   output,    pitch);
+    vp8_short_fdct4x4_c(input + 4, output + 16, pitch);
+}
+
+
+static const signed short x_c1 = 60547;
+static const signed short x_c2 = 46341;
+static const signed short x_c3 = 25080;
+
+void vp8_fast_fdct4x4_c(short *input, short *output, int pitch)
+{
+    int i;
+    int a1, b1, c1, d1;
+    int a2, b2, c2, d2;
+    short *ip = input;
+
+    short *op = output;
+    int temp1, temp2;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = (ip[0] + ip[3]) * 2;
+        b1 = (ip[1] + ip[2]) * 2;
+        c1 = (ip[1] - ip[2]) * 2;
+        d1 = (ip[0] - ip[3]) * 2;
+
+        temp1 = a1 + b1;
+        temp2 = a1 - b1;
+
+        op[0] = ((temp1 * x_c2) >> 16) + temp1;
+        op[2] = ((temp2 * x_c2) >> 16) + temp2;
+
+        temp1 = (c1 * x_c3) >> 16;
+        temp2 = ((d1 * x_c1) >> 16) + d1;
+
+        op[1] = temp1 + temp2;
+
+        temp1 = (d1 * x_c3) >> 16;
+        temp2 = ((c1 * x_c1) >> 16) + c1;
+
+        op[3] = temp1 - temp2;
+
+        ip += pitch / 2;
+        op += 4;
+    }
+
+    ip = output;
+    op = output;
+
+    for (i = 0; i < 4; i++)
+    {
+
+        a1 = ip[0] + ip[12];
+        b1 = ip[4] + ip[8];
+        c1 = ip[4] - ip[8];
+        d1 = ip[0] - ip[12];
+
+
+        temp1 = a1 + b1;
+        temp2 = a1 - b1;
+
+        a2 = ((temp1 * x_c2) >> 16) + temp1;
+        c2 = ((temp2 * x_c2) >> 16) + temp2;
+
+        temp1 = (c1 * x_c3) >> 16;
+        temp2 = ((d1 * x_c1) >> 16) + d1;
+
+        b2 = temp1 + temp2;
+
+        temp1 = (d1 * x_c3) >> 16;
+        temp2 = ((c1 * x_c1) >> 16) + c1;
+
+        d2 = temp1 - temp2;
+
+
+        op[0]   = (a2 + 1) >> 1;
+        op[4]   = (b2 + 1) >> 1;
+        op[8]   = (c2 + 1) >> 1;
+        op[12]  = (d2 + 1) >> 1;
+
+        ip++;
+        op++;
+    }
+}
+
+void vp8_fast_fdct8x4_c(short *input, short *output, int pitch)
+{
+    vp8_fast_fdct4x4_c(input,   output,    pitch);
+    vp8_fast_fdct4x4_c(input + 4, output + 16, pitch);
+}
+
+void vp8_short_walsh4x4_c(short *input, short *output, int pitch)
+{
+    int i;
+    int a1, b1, c1, d1;
+    int a2, b2, c2, d2;
+    short *ip = input;
+    short *op = output;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ip[0] + ip[3];
+        b1 = ip[1] + ip[2];
+        c1 = ip[1] - ip[2];
+        d1 = ip[0] - ip[3];
+
+        op[0] = a1 + b1;
+        op[1] = c1 + d1;
+        op[2] = a1 - b1;
+        op[3] = d1 - c1;
+        ip += pitch / 2;
+        op += 4;
+    }
+
+    ip = output;
+    op = output;
+
+    for (i = 0; i < 4; i++)
+    {
+        a1 = ip[0] + ip[12];
+        b1 = ip[4] + ip[8];
+        c1 = ip[4] - ip[8];
+        d1 = ip[0] - ip[12];
+
+        a2 = a1 + b1;
+        b2 = c1 + d1;
+        c2 = a1 - b1;
+        d2 = d1 - c1;
+
+        a2 += (a2 > 0);
+        b2 += (b2 > 0);
+        c2 += (c2 > 0);
+        d2 += (d2 > 0);
+
+        op[0] = (a2) >> 1;
+        op[4] = (b2) >> 1;
+        op[8] = (c2) >> 1;
+        op[12] = (d2) >> 1;
+
+        ip++;
+        op++;
+    }
+}
diff --git a/vp8/encoder/dct.h b/vp8/encoder/dct.h
new file mode 100644
index 0000000..fb307cf
--- /dev/null
+++ b/vp8/encoder/dct.h
@@ -0,0 +1,65 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_DCT_H
+#define __INC_DCT_H
+
+#define prototype_fdct(sym) void (sym)(short *input, short *output, int pitch)
+
+#if ARCH_X86 || ARCH_X86_64
+#include "x86/dct_x86.h"
+#endif
+
+#if ARCH_ARM
+#include "arm/dct_arm.h"
+#endif
+
+#ifndef vp8_fdct_short4x4
+#define vp8_fdct_short4x4  vp8_short_fdct4x4_c
+#endif
+extern prototype_fdct(vp8_fdct_short4x4);
+
+#ifndef vp8_fdct_short8x4
+#define vp8_fdct_short8x4  vp8_short_fdct8x4_c
+#endif
+extern prototype_fdct(vp8_fdct_short8x4);
+
+#ifndef vp8_fdct_fast4x4
+#define vp8_fdct_fast4x4  vp8_fast_fdct4x4_c
+#endif
+extern prototype_fdct(vp8_fdct_fast4x4);
+
+#ifndef vp8_fdct_fast8x4
+#define vp8_fdct_fast8x4  vp8_fast_fdct8x4_c
+#endif
+extern prototype_fdct(vp8_fdct_fast8x4);
+
+#ifndef vp8_fdct_walsh_short4x4
+#define vp8_fdct_walsh_short4x4  vp8_short_walsh4x4_c
+#endif
+extern prototype_fdct(vp8_fdct_walsh_short4x4);
+
+typedef prototype_fdct(*vp8_fdct_fn_t);
+typedef struct
+{
+    vp8_fdct_fn_t    short4x4;
+    vp8_fdct_fn_t    short8x4;
+    vp8_fdct_fn_t    fast4x4;
+    vp8_fdct_fn_t    fast8x4;
+    vp8_fdct_fn_t    walsh_short4x4;
+} vp8_fdct_rtcd_vtable_t;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define FDCT_INVOKE(ctx,fn) (ctx)->fn
+#else
+#define FDCT_INVOKE(ctx,fn) vp8_fdct_##fn
+#endif
+
+#endif
diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c
new file mode 100644
index 0000000..a4e3772
--- /dev/null
+++ b/vp8/encoder/encodeframe.c
@@ -0,0 +1,1223 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "encodemb.h"
+#include "encodemv.h"
+#include "common.h"
+#include "onyx_int.h"
+#include "extend.h"
+#include "entropymode.h"
+#include "quant_common.h"
+#include "segmentation_common.h"
+#include "setupintrarecon.h"
+#include "encodeintra.h"
+#include "reconinter.h"
+#include "rdopt.h"
+#include "pickinter.h"
+#include "findnearmv.h"
+#include "reconintra.h"
+#include <stdio.h>
+#include <limits.h>
+#include "subpixel.h"
+#include "vpx_ports/vpx_timer.h"
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define RTCD(x)     &cpi->common.rtcd.x
+#define IF_RTCD(x)  (x)
+#else
+#define RTCD(x)     NULL
+#define IF_RTCD(x)  NULL
+#endif
+extern void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) ;
+
+extern void vp8cx_initialize_me_consts(VP8_COMP *cpi, int QIndex);
+extern void vp8_auto_select_speed(VP8_COMP *cpi);
+extern void vp8cx_init_mbrthread_data(VP8_COMP *cpi,
+                                      MACROBLOCK *x,
+                                      MB_ROW_COMP *mbr_ei,
+                                      int mb_row,
+                                      int count);
+void vp8_build_block_offsets(MACROBLOCK *x);
+void vp8_setup_block_ptrs(MACROBLOCK *x);
+int vp8cx_encode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t, int recon_yoffset, int recon_uvoffset);
+int vp8cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t);
+
+#ifdef MODE_STATS
+unsigned int inter_y_modes[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+unsigned int inter_uv_modes[4] = {0, 0, 0, 0};
+unsigned int inter_b_modes[15]  = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+unsigned int y_modes[5]   = {0, 0, 0, 0, 0};
+unsigned int uv_modes[4]  = {0, 0, 0, 0};
+unsigned int b_modes[14]  = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+#endif
+
+// The first four entries are dummy values
+static const int qrounding_factors[129] =
+{
+    56, 56, 56, 56, 56, 56, 56, 56,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48, 48, 48, 48, 48, 48, 48, 48,
+    48,
+};
+
+static const int qzbin_factors[129] =
+{
+    64, 64, 64, 64, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80, 80, 80, 80, 80, 80, 80, 80,
+    80,
+};
+
+void vp8cx_init_quantizer(VP8_COMP *cpi)
+{
+    int r, c;
+    int i;
+    int quant_val;
+    int Q;
+
+    int zbin_boost[16] = {0, 0, 8, 10, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 44, 44};
+
+    for (Q = 0; Q < QINDEX_RANGE; Q++)
+    {
+        // dc values
+        quant_val = vp8_dc_quant(Q, cpi->common.y1dc_delta_q);
+        cpi->Y1quant[Q][0][0] = (1 << 16) / quant_val;
+        cpi->Y1zbin[Q][0][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
+        cpi->Y1round[Q][0][0] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->common.Y1dequant[Q][0][0] = quant_val;
+        cpi->zrun_zbin_boost_y1[Q][0] = (quant_val * zbin_boost[0]) >> 7;
+
+        quant_val = vp8_dc2quant(Q, cpi->common.y2dc_delta_q);
+        cpi->Y2quant[Q][0][0] = (1 << 16) / quant_val;
+        cpi->Y2zbin[Q][0][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
+        cpi->Y2round[Q][0][0] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->common.Y2dequant[Q][0][0] = quant_val;
+        cpi->zrun_zbin_boost_y2[Q][0] = (quant_val * zbin_boost[0]) >> 7;
+
+        quant_val = vp8_dc_uv_quant(Q, cpi->common.uvdc_delta_q);
+        cpi->UVquant[Q][0][0] = (1 << 16) / quant_val;
+        cpi->UVzbin[Q][0][0] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;;
+        cpi->UVround[Q][0][0] = (qrounding_factors[Q] * quant_val) >> 7;
+        cpi->common.UVdequant[Q][0][0] = quant_val;
+        cpi->zrun_zbin_boost_uv[Q][0] = (quant_val * zbin_boost[0]) >> 7;
+
+        // all the ac values = ;
+        for (i = 1; i < 16; i++)
+        {
+            int rc = vp8_default_zig_zag1d[i];
+            r = (rc >> 2);
+            c = (rc & 3);
+
+            quant_val = vp8_ac_yquant(Q);
+            cpi->Y1quant[Q][r][c] = (1 << 16) / quant_val;
+            cpi->Y1zbin[Q][r][c] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
+            cpi->Y1round[Q][r][c] = (qrounding_factors[Q] * quant_val) >> 7;
+            cpi->common.Y1dequant[Q][r][c] = quant_val;
+            cpi->zrun_zbin_boost_y1[Q][i] = (quant_val * zbin_boost[i]) >> 7;
+
+            quant_val = vp8_ac2quant(Q, cpi->common.y2ac_delta_q);
+            cpi->Y2quant[Q][r][c] = (1 << 16) / quant_val;
+            cpi->Y2zbin[Q][r][c] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
+            cpi->Y2round[Q][r][c] = (qrounding_factors[Q] * quant_val) >> 7;
+            cpi->common.Y2dequant[Q][r][c] = quant_val;
+            cpi->zrun_zbin_boost_y2[Q][i] = (quant_val * zbin_boost[i]) >> 7;
+
+            quant_val = vp8_ac_uv_quant(Q, cpi->common.uvac_delta_q);
+            cpi->UVquant[Q][r][c] = (1 << 16) / quant_val;
+            cpi->UVzbin[Q][r][c] = ((qzbin_factors[Q] * quant_val) + 64) >> 7;
+            cpi->UVround[Q][r][c] = (qrounding_factors[Q] * quant_val) >> 7;
+            cpi->common.UVdequant[Q][r][c] = quant_val;
+            cpi->zrun_zbin_boost_uv[Q][i] = (quant_val * zbin_boost[i]) >> 7;
+        }
+    }
+}
+
+void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x)
+{
+    int i;
+    int QIndex;
+    MACROBLOCKD *xd = &x->e_mbd;
+    MB_MODE_INFO *mbmi = &xd->mbmi;
+    int zbin_extra;
+
+    // Select the baseline MB Q index.
+    if (xd->segmentation_enabled)
+    {
+        // Abs Value
+        if (xd->mb_segement_abs_delta == SEGMENT_ABSDATA)
+            QIndex = xd->segment_feature_data[MB_LVL_ALT_Q][mbmi->segment_id];
+
+        // Delta Value
+        else
+        {
+            QIndex = cpi->common.base_qindex + xd->segment_feature_data[MB_LVL_ALT_Q][mbmi->segment_id];
+            QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0;    // Clamp to valid range
+        }
+    }
+    else
+        QIndex = cpi->common.base_qindex;
+
+    // Y
+    zbin_extra = (cpi->common.Y1dequant[QIndex][0][1] * (cpi->zbin_over_quant + cpi->zbin_mode_boost)) >> 7;
+
+    for (i = 0; i < 16; i++)
+    {
+        x->block[i].quant = cpi->Y1quant[QIndex];
+        x->block[i].zbin = cpi->Y1zbin[QIndex];
+        x->block[i].round = cpi->Y1round[QIndex];
+        x->e_mbd.block[i].dequant = cpi->common.Y1dequant[QIndex];
+        x->block[i].zrun_zbin_boost = cpi->zrun_zbin_boost_y1[QIndex];
+        x->block[i].zbin_extra = (short)zbin_extra;
+    }
+
+    // UV
+    zbin_extra = (cpi->common.UVdequant[QIndex][0][1] * (cpi->zbin_over_quant + cpi->zbin_mode_boost)) >> 7;
+
+    for (i = 16; i < 24; i++)
+    {
+        x->block[i].quant = cpi->UVquant[QIndex];
+        x->block[i].zbin = cpi->UVzbin[QIndex];
+        x->block[i].round = cpi->UVround[QIndex];
+        x->e_mbd.block[i].dequant = cpi->common.UVdequant[QIndex];
+        x->block[i].zrun_zbin_boost = cpi->zrun_zbin_boost_uv[QIndex];
+        x->block[i].zbin_extra = (short)zbin_extra;
+    }
+
+    // Y2
+    zbin_extra = (cpi->common.Y2dequant[QIndex][0][1] * ((cpi->zbin_over_quant / 2) + cpi->zbin_mode_boost)) >> 7;
+    x->block[24].quant = cpi->Y2quant[QIndex];
+    x->block[24].zbin = cpi->Y2zbin[QIndex];
+    x->block[24].round = cpi->Y2round[QIndex];
+    x->e_mbd.block[24].dequant = cpi->common.Y2dequant[QIndex];
+    x->block[24].zrun_zbin_boost = cpi->zrun_zbin_boost_y2[QIndex];
+    x->block[24].zbin_extra = (short)zbin_extra;
+}
+
+void vp8cx_frame_init_quantizer(VP8_COMP *cpi)
+{
+    // vp8cx_init_quantizer() is first called in vp8_create_compressor(). A check is added here so that vp8cx_init_quantizer() is only called
+    // when these values are not all zero.
+    if (cpi->common.y1dc_delta_q | cpi->common.y2dc_delta_q | cpi->common.uvdc_delta_q | cpi->common.y2ac_delta_q | cpi->common.uvac_delta_q)
+    {
+        vp8cx_init_quantizer(cpi);
+    }
+
+    // MB level quantizer setup
+    vp8cx_mb_init_quantizer(cpi, &cpi->mb);
+}
+
+
+
+static
+void encode_mb_row(VP8_COMP *cpi,
+                   VP8_COMMON *cm,
+                   int mb_row,
+                   MACROBLOCK  *x,
+                   MACROBLOCKD *xd,
+                   TOKENEXTRA **tp,
+                   int *segment_counts,
+                   int *totalrate)
+{
+    int i;
+    int recon_yoffset, recon_uvoffset;
+    int mb_col;
+    int recon_y_stride = cm->last_frame.y_stride;
+    int recon_uv_stride = cm->last_frame.uv_stride;
+    int seg_map_index = (mb_row * cpi->common.mb_cols);
+
+
+    // reset above block coeffs
+    xd->above_context[Y1CONTEXT] = cm->above_context[Y1CONTEXT];
+    xd->above_context[UCONTEXT ] = cm->above_context[UCONTEXT ];
+    xd->above_context[VCONTEXT ] = cm->above_context[VCONTEXT ];
+    xd->above_context[Y2CONTEXT] = cm->above_context[Y2CONTEXT];
+
+    xd->up_available = (mb_row != 0);
+    recon_yoffset = (mb_row * recon_y_stride * 16);
+    recon_uvoffset = (mb_row * recon_uv_stride * 8);
+
+    cpi->tplist[mb_row].start = *tp;
+    //printf("Main mb_row = %d\n", mb_row);
+
+    // for each macroblock col in image
+    for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+    {
+        // Distance of Mb to the various image edges.
+        // These specified to 8th pel as they are always compared to values that are in 1/8th pel units
+        xd->mb_to_left_edge = -((mb_col * 16) << 3);
+        xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3;
+        xd->mb_to_top_edge = -((mb_row * 16) << 3);
+        xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3;
+
+        // Set up limit values for motion vectors used to prevent them extending outside the UMV borders
+        x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16));
+        x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + (VP8BORDERINPIXELS - 16);
+        x->mv_row_min = -((mb_row * 16) + (VP8BORDERINPIXELS - 16));
+        x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + (VP8BORDERINPIXELS - 16);
+
+        xd->dst.y_buffer = cm->new_frame.y_buffer + recon_yoffset;
+        xd->dst.u_buffer = cm->new_frame.u_buffer + recon_uvoffset;
+        xd->dst.v_buffer = cm->new_frame.v_buffer + recon_uvoffset;
+        xd->left_available = (mb_col != 0);
+
+        // Is segmentation enabled
+        // MB level adjutment to quantizer
+        if (xd->segmentation_enabled)
+        {
+            // Code to set segment id in xd->mbmi.segment_id for current MB (with range checking)
+            if (cpi->segmentation_map[seg_map_index+mb_col] <= 3)
+                xd->mbmi.segment_id = cpi->segmentation_map[seg_map_index+mb_col];
+            else
+                xd->mbmi.segment_id = 0;
+
+            vp8cx_mb_init_quantizer(cpi, x);
+        }
+        else
+            xd->mbmi.segment_id = 0;         // Set to Segment 0 by default
+
+        x->active_ptr = cpi->active_map + seg_map_index + mb_col;
+
+        if (cm->frame_type == KEY_FRAME)
+        {
+            *totalrate += vp8cx_encode_intra_macro_block(cpi, x, tp);
+#ifdef MODE_STATS
+            y_modes[xd->mbmi.mode] ++;
+#endif
+        }
+        else
+        {
+            *totalrate += vp8cx_encode_inter_macroblock(cpi, x, tp, recon_yoffset, recon_uvoffset);
+
+#ifdef MODE_STATS
+            inter_y_modes[xd->mbmi.mode] ++;
+
+            if (xd->mbmi.mode == SPLITMV)
+            {
+                int b;
+
+                for (b = 0; b < xd->mbmi.partition_count; b++)
+                {
+                    inter_b_modes[xd->mbmi.partition_bmi[b].mode] ++;
+                }
+            }
+
+#endif
+
+            // Count of last ref frame 0,0 useage
+            if ((xd->mbmi.mode == ZEROMV) && (xd->mbmi.ref_frame == LAST_FRAME))
+                cpi->inter_zz_count ++;
+
+            // Special case code for cyclic refresh
+            // If cyclic update enabled then copy xd->mbmi.segment_id; (which may have been updated based on mode
+            // during vp8cx_encode_inter_macroblock()) back into the global sgmentation map
+            if (cpi->cyclic_refresh_mode_enabled && xd->segmentation_enabled)
+            {
+                cpi->segmentation_map[seg_map_index+mb_col] = xd->mbmi.segment_id;
+
+                // If the block has been refreshed mark it as clean (the magnitude of the -ve influences how long it will be before we consider another refresh):
+                // Else if it was coded (last frame 0,0) and has not already been refreshed then mark it as a candidate for cleanup next time (marked 0)
+                // else mark it as dirty (1).
+                if (xd->mbmi.segment_id)
+                    cpi->cyclic_refresh_map[seg_map_index+mb_col] = -1;
+                else if ((xd->mbmi.mode == ZEROMV) && (xd->mbmi.ref_frame == LAST_FRAME))
+                {
+                    if (cpi->cyclic_refresh_map[seg_map_index+mb_col] == 1)
+                        cpi->cyclic_refresh_map[seg_map_index+mb_col] = 0;
+                }
+                else
+                    cpi->cyclic_refresh_map[seg_map_index+mb_col] = 1;
+
+            }
+        }
+
+        cpi->tplist[mb_row].stop = *tp;
+
+        xd->gf_active_ptr++;      // Increment pointer into gf useage flags structure for next mb
+
+        // store macroblock mode info into context array
+        vpx_memcpy(&xd->mode_info_context->mbmi, &xd->mbmi, sizeof(xd->mbmi));
+
+        for (i = 0; i < 16; i++)
+            vpx_memcpy(&xd->mode_info_context->bmi[i], &xd->block[i].bmi, sizeof(xd->block[i].bmi));
+
+        // adjust to the next column of macroblocks
+        x->src.y_buffer += 16;
+        x->src.u_buffer += 8;
+        x->src.v_buffer += 8;
+
+        recon_yoffset += 16;
+        recon_uvoffset += 8;
+
+        // Keep track of segment useage
+        segment_counts[xd->mbmi.segment_id] ++;
+
+        // skip to next mb
+        xd->mode_info_context++;
+
+        xd->above_context[Y1CONTEXT] += 4;
+        xd->above_context[UCONTEXT ] += 2;
+        xd->above_context[VCONTEXT ] += 2;
+        xd->above_context[Y2CONTEXT] ++;
+        cpi->current_mb_col_main = mb_col;
+    }
+
+    //extend the recon for intra prediction
+    vp8_extend_mb_row(
+        &cm->new_frame,
+        xd->dst.y_buffer + 16,
+        xd->dst.u_buffer + 8,
+        xd->dst.v_buffer + 8);
+
+    // this is to account for the border
+    xd->mode_info_context++;
+}
+
+
+
+
+
+void vp8_encode_frame(VP8_COMP *cpi)
+{
+    int mb_row;
+    MACROBLOCK *const x = & cpi->mb;
+    VP8_COMMON *const cm = & cpi->common;
+    MACROBLOCKD *const xd = & x->e_mbd;
+
+    int i;
+    TOKENEXTRA *tp = cpi->tok;
+    int segment_counts[MAX_MB_SEGMENTS];
+    int totalrate;
+
+    if (cm->frame_type != KEY_FRAME)
+    {
+        if (cm->mcomp_filter_type == SIXTAP)
+        {
+            xd->subpixel_predict     = SUBPIX_INVOKE(&cpi->common.rtcd.subpix, sixtap4x4);
+            xd->subpixel_predict8x4      = SUBPIX_INVOKE(&cpi->common.rtcd.subpix, sixtap8x4);
+            xd->subpixel_predict8x8      = SUBPIX_INVOKE(&cpi->common.rtcd.subpix, sixtap8x8);
+            xd->subpixel_predict16x16    = SUBPIX_INVOKE(&cpi->common.rtcd.subpix, sixtap16x16);
+        }
+        else
+        {
+            xd->subpixel_predict     = SUBPIX_INVOKE(&cpi->common.rtcd.subpix, bilinear4x4);
+            xd->subpixel_predict8x4      = SUBPIX_INVOKE(&cpi->common.rtcd.subpix, bilinear8x4);
+            xd->subpixel_predict8x8      = SUBPIX_INVOKE(&cpi->common.rtcd.subpix, bilinear8x8);
+            xd->subpixel_predict16x16    = SUBPIX_INVOKE(&cpi->common.rtcd.subpix, bilinear16x16);
+        }
+    }
+
+    //else  // Key Frame
+    //{
+    // For key frames make sure the intra ref frame probability value
+    // is set to "all intra"
+    //cpi->prob_intra_coded = 255;
+    //}
+
+
+    xd->gf_active_ptr = (signed char *)cm->gf_active_flags;     // Point to base of GF active flags data structure
+
+    x->vector_range = 32;
+
+    // Count of MBs using the alternate Q if any
+    cpi->alt_qcount = 0;
+
+    // Reset frame count of inter 0,0 motion vector useage.
+    cpi->inter_zz_count = 0;
+
+    vpx_memset(segment_counts, 0, sizeof(segment_counts));
+
+    cpi->prediction_error = 0;
+    cpi->intra_error = 0;
+    cpi->skip_true_count = 0;
+    cpi->skip_false_count = 0;
+
+#if 0
+    // Experimental code
+    cpi->frame_distortion = 0;     
+    cpi->last_mb_distortion = 0;
+#endif
+
+    totalrate = 0;
+
+    xd->mode_info = cm->mi - 1;
+
+    xd->mode_info_context = cm->mi;
+    xd->mode_info_stride = cm->mode_info_stride;
+
+    xd->frame_type = cm->frame_type;
+
+    xd->frames_since_golden = cm->frames_since_golden;
+    xd->frames_till_alt_ref_frame = cm->frames_till_alt_ref_frame;
+    vp8_zero(cpi->MVcount);
+    // vp8_zero( Contexts)
+    vp8_zero(cpi->coef_counts);
+
+    // reset intra mode contexts
+    if (cm->frame_type == KEY_FRAME)
+        vp8_init_mbmode_probs(cm);
+
+
+    vp8cx_frame_init_quantizer(cpi);
+
+    if (cpi->compressor_speed == 2)
+    {
+        if (cpi->oxcf.cpu_used < 0)
+            cpi->Speed = -(cpi->oxcf.cpu_used);
+        else
+            vp8_auto_select_speed(cpi);
+    }
+
+    vp8_initialize_rd_consts(cpi, vp8_dc_quant(cm->base_qindex, cm->y1dc_delta_q));
+    //vp8_initialize_rd_consts( cpi, vp8_dc_quant(cpi->avg_frame_qindex, cm->y1dc_delta_q) );
+    vp8cx_initialize_me_consts(cpi, cm->base_qindex);
+    //vp8cx_initialize_me_consts( cpi, cpi->avg_frame_qindex);
+
+    // Copy data over into macro block data sturctures.
+
+    x->src = * cpi->Source;
+    xd->pre = cm->last_frame;
+    xd->dst = cm->new_frame;
+
+    // set up frame new frame for intra coded blocks
+
+    vp8_setup_intra_recon(&cm->new_frame);
+
+    vp8_build_block_offsets(x);
+
+    vp8_setup_block_dptrs(&x->e_mbd);
+
+    vp8_setup_block_ptrs(x);
+
+    x->rddiv = cpi->RDDIV;
+    x->rdmult = cpi->RDMULT;
+
+#if 0
+    // Experimental rd code
+    // 2 Pass - Possibly set Rdmult based on last frame distortion + this frame target bits or other metrics
+    // such as cpi->rate_correction_factor that indicate relative complexity.
+    /*if ( cpi->pass == 2 && (cpi->last_frame_distortion > 0) && (cpi->target_bits_per_mb > 0) )
+    {
+        //x->rdmult = ((cpi->last_frame_distortion * 256)/cpi->common.MBs)/ cpi->target_bits_per_mb;
+        x->rdmult = (int)(cpi->RDMULT * cpi->rate_correction_factor);
+    }
+    else
+        x->rdmult = cpi->RDMULT; */
+    //x->rdmult = (int)(cpi->RDMULT * pow( (cpi->rate_correction_factor * 2.0), 0.75 ));
+#endif
+
+    xd->mbmi.mode = DC_PRED;
+    xd->mbmi.uv_mode = DC_PRED;
+
+    xd->left_context = cm->left_context;
+
+    vp8_zero(cpi->count_mb_ref_frame_usage)
+    vp8_zero(cpi->ymode_count)
+    vp8_zero(cpi->uv_mode_count)
+
+    x->mvc = cm->fc.mvc;
+
+    // vp8_zero( entropy_stats)
+    {
+        ENTROPY_CONTEXT **p = cm->above_context;
+        const size_t L = cm->mb_cols;
+
+        vp8_zero_array(p [Y1CONTEXT], L * 4)
+        vp8_zero_array(p [ UCONTEXT], L * 2)
+        vp8_zero_array(p [ VCONTEXT], L * 2)
+        vp8_zero_array(p [Y2CONTEXT], L)
+    }
+
+
+    {
+        struct vpx_usec_timer  emr_timer;
+        vpx_usec_timer_start(&emr_timer);
+
+        if (!cpi->b_multi_threaded)
+        {
+            // for each macroblock row in image
+            for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+            {
+
+                vp8_zero(cm->left_context)
+
+                encode_mb_row(cpi, cm, mb_row, x, xd, &tp, segment_counts, &totalrate);
+
+                // adjust to the next row of mbs
+                x->src.y_buffer += 16 * x->src.y_stride - 16 * cm->mb_cols;
+                x->src.u_buffer += 8 * x->src.uv_stride - 8 * cm->mb_cols;
+                x->src.v_buffer += 8 * x->src.uv_stride - 8 * cm->mb_cols;
+            }
+
+            cpi->tok_count = tp - cpi->tok;
+
+        }
+        else
+        {
+#if CONFIG_MULTITHREAD
+            vp8cx_init_mbrthread_data(cpi, x, cpi->mb_row_ei, 1,  cpi->encoding_thread_count);
+
+            for (mb_row = 0; mb_row < cm->mb_rows; mb_row += (cpi->encoding_thread_count + 1))
+            {
+                int i;
+                cpi->current_mb_col_main = -1;
+
+                for (i = 0; i < cpi->encoding_thread_count; i++)
+                {
+                    if ((mb_row + i + 1) >= cm->mb_rows)
+                        break;
+
+                    cpi->mb_row_ei[i].mb_row = mb_row + i + 1;
+                    cpi->mb_row_ei[i].tp  = cpi->tok + (mb_row + i + 1) * (cm->mb_cols * 16 * 24);
+                    cpi->mb_row_ei[i].current_mb_col = -1;
+                    //SetEvent(cpi->h_event_mbrencoding[i]);
+                    sem_post(&cpi->h_event_mbrencoding[i]);
+                }
+
+                vp8_zero(cm->left_context)
+
+                tp = cpi->tok + mb_row * (cm->mb_cols * 16 * 24);
+
+                encode_mb_row(cpi, cm, mb_row, x, xd, &tp, segment_counts, &totalrate);
+
+                // adjust to the next row of mbs
+                x->src.y_buffer += 16 * x->src.y_stride * (cpi->encoding_thread_count + 1) - 16 * cm->mb_cols;
+                x->src.u_buffer +=  8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
+                x->src.v_buffer +=  8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
+
+                xd->mode_info_context += xd->mode_info_stride * cpi->encoding_thread_count;
+
+                if (mb_row < cm->mb_rows - 1)
+                    //WaitForSingleObject(cpi->h_event_main, INFINITE);
+                    sem_wait(&cpi->h_event_main);
+            }
+
+            /*
+            for( ;mb_row<cm->mb_rows; mb_row ++)
+            {
+            vp8_zero( cm->left_context)
+
+            tp = cpi->tok + mb_row * (cm->mb_cols * 16 * 24);
+
+            encode_mb_row(cpi, cm, mb_row, x, xd, &tp, segment_counts, &totalrate);
+            // adjust to the next row of mbs
+            x->src.y_buffer += 16 * x->src.y_stride - 16 * cm->mb_cols;
+            x->src.u_buffer +=  8 * x->src.uv_stride - 8 * cm->mb_cols;
+            x->src.v_buffer +=  8 * x->src.uv_stride - 8 * cm->mb_cols;
+
+            }
+            */
+            cpi->tok_count = 0;
+
+            for (mb_row = 0; mb_row < cm->mb_rows; mb_row ++)
+            {
+                cpi->tok_count += cpi->tplist[mb_row].stop - cpi->tplist[mb_row].start;
+            }
+
+            if (xd->segmentation_enabled)
+            {
+
+                int i, j;
+
+                if (xd->segmentation_enabled)
+                {
+
+                    for (i = 0; i < cpi->encoding_thread_count; i++)
+                    {
+                        for (j = 0; j < 4; j++)
+                            segment_counts[j] += cpi->mb_row_ei[i].segment_counts[j];
+                    }
+                }
+
+            }
+
+            for (i = 0; i < cpi->encoding_thread_count; i++)
+            {
+                totalrate += cpi->mb_row_ei[i].totalrate;
+            }
+
+#endif
+
+        }
+
+        vpx_usec_timer_mark(&emr_timer);
+        cpi->time_encode_mb_row += vpx_usec_timer_elapsed(&emr_timer);
+
+    }
+
+
+    // Work out the segment probabilites if segmentation is enabled
+    if (xd->segmentation_enabled)
+    {
+        int tot_count;
+        int i;
+
+        // Set to defaults
+        vpx_memset(xd->mb_segment_tree_probs, 255 , sizeof(xd->mb_segment_tree_probs));
+
+        tot_count = segment_counts[0] + segment_counts[1] + segment_counts[2] + segment_counts[3];
+
+        if (tot_count)
+        {
+            xd->mb_segment_tree_probs[0] = ((segment_counts[0] + segment_counts[1]) * 255) / tot_count;
+
+            tot_count = segment_counts[0] + segment_counts[1];
+
+            if (tot_count > 0)
+            {
+                xd->mb_segment_tree_probs[1] = (segment_counts[0] * 255) / tot_count;
+            }
+
+            tot_count = segment_counts[2] + segment_counts[3];
+
+            if (tot_count > 0)
+                xd->mb_segment_tree_probs[2] = (segment_counts[2] * 255) / tot_count;
+
+            // Zero probabilities not allowed
+            for (i = 0; i < MB_FEATURE_TREE_PROBS; i ++)
+            {
+                if (xd->mb_segment_tree_probs[i] == 0)
+                    xd->mb_segment_tree_probs[i] = 1;
+            }
+        }
+    }
+
+    // 256 rate units to the bit
+    cpi->projected_frame_size = totalrate >> 8;   // projected_frame_size in units of BYTES
+
+    // Make a note of the percentage MBs coded Intra.
+    if (cm->frame_type == KEY_FRAME)
+    {
+        cpi->this_frame_percent_intra = 100;
+    }
+    else
+    {
+        int tot_modes;
+
+        tot_modes = cpi->count_mb_ref_frame_usage[INTRA_FRAME]
+                    + cpi->count_mb_ref_frame_usage[LAST_FRAME]
+                    + cpi->count_mb_ref_frame_usage[GOLDEN_FRAME]
+                    + cpi->count_mb_ref_frame_usage[ALTREF_FRAME];
+
+        if (tot_modes)
+            cpi->this_frame_percent_intra = cpi->count_mb_ref_frame_usage[INTRA_FRAME] * 100 / tot_modes;
+
+    }
+
+#if 0
+    {
+        int cnt = 0;
+        int flag[2] = {0, 0};
+
+        for (cnt = 0; cnt < MVPcount; cnt++)
+        {
+            if (cm->fc.pre_mvc[0][cnt] != cm->fc.mvc[0][cnt])
+            {
+                flag[0] = 1;
+                vpx_memcpy(cm->fc.pre_mvc[0], cm->fc.mvc[0], MVPcount);
+                break;
+            }
+        }
+
+        for (cnt = 0; cnt < MVPcount; cnt++)
+        {
+            if (cm->fc.pre_mvc[1][cnt] != cm->fc.mvc[1][cnt])
+            {
+                flag[1] = 1;
+                vpx_memcpy(cm->fc.pre_mvc[1], cm->fc.mvc[1], MVPcount);
+                break;
+            }
+        }
+
+        if (flag[0] || flag[1])
+            vp8_build_component_cost_table(cpi->mb.mvcost, cpi->mb.mvsadcost, (const MV_CONTEXT *) cm->fc.mvc, flag);
+    }
+#endif
+
+    // Adjust the projected reference frame useage probability numbers to reflect
+    // what we have just seen. This may be usefull when we make multiple itterations
+    // of the recode loop rather than continuing to use values from the previous frame.
+    if ((cm->frame_type != KEY_FRAME) && !cm->refresh_alt_ref_frame && !cm->refresh_golden_frame)
+    {
+        const int *const rfct = cpi->count_mb_ref_frame_usage;
+        const int rf_intra = rfct[INTRA_FRAME];
+        const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
+
+        if ((rf_intra + rf_inter) > 0)
+        {
+            cpi->prob_intra_coded = (rf_intra * 255) / (rf_intra + rf_inter);
+
+            if (cpi->prob_intra_coded < 1)
+                cpi->prob_intra_coded = 1;
+
+            if ((cm->frames_since_golden > 0) || cpi->source_alt_ref_active)
+            {
+                cpi->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
+
+                if (cpi->prob_last_coded < 1)
+                    cpi->prob_last_coded = 1;
+
+                cpi->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
+                                     ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
+
+                if (cpi->prob_gf_coded < 1)
+                    cpi->prob_gf_coded = 1;
+            }
+        }
+    }
+
+#if 0
+    // Keep record of the total distortion this time around for future use
+    cpi->last_frame_distortion = cpi->frame_distortion;
+#endif
+
+}
+void vp8_setup_block_ptrs(MACROBLOCK *x)
+{
+    int r, c;
+    int i;
+
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 4; c++)
+        {
+            x->block[r*4+c].src_diff = x->src_diff + r * 4 * 16 + c * 4;
+        }
+    }
+
+    for (r = 0; r < 2; r++)
+    {
+        for (c = 0; c < 2; c++)
+        {
+            x->block[16 + r*2+c].src_diff = x->src_diff + 256 + r * 4 * 8 + c * 4;
+        }
+    }
+
+
+    for (r = 0; r < 2; r++)
+    {
+        for (c = 0; c < 2; c++)
+        {
+            x->block[20 + r*2+c].src_diff = x->src_diff + 320 + r * 4 * 8 + c * 4;
+        }
+    }
+
+    x->block[24].src_diff = x->src_diff + 384;
+
+
+    for (i = 0; i < 25; i++)
+    {
+        x->block[i].coeff = x->coeff + i * 16;
+    }
+}
+
+void vp8_build_block_offsets(MACROBLOCK *x)
+{
+    int block = 0;
+    int br, bc;
+
+    vp8_build_block_doffsets(&x->e_mbd);
+
+    // y blocks
+    for (br = 0; br < 4; br++)
+    {
+        for (bc = 0; bc < 4; bc++)
+        {
+            BLOCK *this_block = &x->block[block];
+            this_block->base_src = &x->src.y_buffer;
+            this_block->src_stride = x->src.y_stride;
+            this_block->src = 4 * br * this_block->src_stride + 4 * bc;
+            ++block;
+        }
+    }
+
+    // u blocks
+    for (br = 0; br < 2; br++)
+    {
+        for (bc = 0; bc < 2; bc++)
+        {
+            BLOCK *this_block = &x->block[block];
+            this_block->base_src = &x->src.u_buffer;
+            this_block->src_stride = x->src.uv_stride;
+            this_block->src = 4 * br * this_block->src_stride + 4 * bc;
+            ++block;
+        }
+    }
+
+    // v blocks
+    for (br = 0; br < 2; br++)
+    {
+        for (bc = 0; bc < 2; bc++)
+        {
+            BLOCK *this_block = &x->block[block];
+            this_block->base_src = &x->src.v_buffer;
+            this_block->src_stride = x->src.uv_stride;
+            this_block->src = 4 * br * this_block->src_stride + 4 * bc;
+            ++block;
+        }
+    }
+}
+
+static void sum_intra_stats(VP8_COMP *cpi, MACROBLOCK *x)
+{
+    const MACROBLOCKD *xd = & x->e_mbd;
+    const MB_PREDICTION_MODE m = xd->mbmi.mode;
+    const MB_PREDICTION_MODE uvm = xd->mbmi.uv_mode;
+
+#ifdef MODE_STATS
+    const int is_key = cpi->common.frame_type == KEY_FRAME;
+
+    ++ (is_key ? uv_modes : inter_uv_modes)[uvm];
+
+    if (m == B_PRED)
+    {
+        unsigned int *const bct = is_key ? b_modes : inter_b_modes;
+
+        int b = 0;
+
+        do
+        {
+            ++ bct[xd->block[b].bmi.mode];
+        }
+        while (++b < 16);
+    }
+
+#endif
+
+    ++cpi->ymode_count[m];
+    ++cpi->uv_mode_count[uvm];
+
+}
+int vp8cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t)
+{
+    int Error4x4, Error16x16, error_uv;
+    B_PREDICTION_MODE intra_bmodes[16];
+    int rate4x4, rate16x16, rateuv;
+    int dist4x4, dist16x16, distuv;
+    int rate = 0;
+    int rate4x4_tokenonly = 0;
+    int rate16x16_tokenonly = 0;
+    int rateuv_tokenonly = 0;
+    int i;
+
+    x->e_mbd.mbmi.ref_frame = INTRA_FRAME;
+
+#if !(CONFIG_REALTIME_ONLY)
+
+    if (cpi->sf.RD || cpi->compressor_speed != 2)
+    {
+        Error4x4 = vp8_rd_pick_intra4x4mby_modes(cpi, x, &rate4x4, &rate4x4_tokenonly, &dist4x4);
+
+        //save the b modes for possible later use
+        for (i = 0; i < 16; i++)
+            intra_bmodes[i] = x->e_mbd.block[i].bmi.mode;
+
+        Error16x16 = vp8_rd_pick_intra16x16mby_mode(cpi, x, &rate16x16, &rate16x16_tokenonly, &dist16x16);
+
+        error_uv = vp8_rd_pick_intra_mbuv_mode(cpi, x, &rateuv, &rateuv_tokenonly, &distuv);
+
+        x->e_mbd.mbmi.mb_skip_coeff = (cpi->common.mb_no_coeff_skip) ? 1 : 0;
+
+        vp8_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);
+        rate += rateuv;
+
+        if (Error4x4 < Error16x16)
+        {
+            rate += rate4x4;
+            x->e_mbd.mbmi.mode = B_PRED;
+
+            // get back the intra block modes
+            for (i = 0; i < 16; i++)
+                x->e_mbd.block[i].bmi.mode = intra_bmodes[i];
+
+            vp8_encode_intra4x4mby(IF_RTCD(&cpi->rtcd), x);
+            cpi->prediction_error += Error4x4 ;
+#if 0
+            // Experimental RD code
+            cpi->frame_distortion += dist4x4;
+#endif
+        }
+        else
+        {
+            vp8_encode_intra16x16mby(IF_RTCD(&cpi->rtcd), x);
+            rate += rate16x16;
+
+#if 0
+            // Experimental RD code
+            cpi->prediction_error += Error16x16;
+            cpi->frame_distortion += dist16x16;
+#endif
+        }
+
+        sum_intra_stats(cpi, x);
+
+        vp8_tokenize_mb(cpi, &x->e_mbd, t);
+    }
+    else
+#endif
+    {
+
+        int rate2, distortion2;
+        MB_PREDICTION_MODE mode, best_mode = DC_PRED;
+        int this_rd;
+        Error16x16 = INT_MAX;
+
+        for (mode = DC_PRED; mode <= TM_PRED; mode ++)
+        {
+            x->e_mbd.mbmi.mode = mode;
+            vp8_build_intra_predictors_mby_ptr(&x->e_mbd);
+            distortion2 = VARIANCE_INVOKE(&cpi->rtcd.variance, get16x16prederror)(x->src.y_buffer, x->src.y_stride, x->e_mbd.predictor, 16, 0x7fffffff);
+            rate2  = x->mbmode_cost[x->e_mbd.frame_type][mode];
+            this_rd = RD_ESTIMATE(x->rdmult, x->rddiv, rate2, distortion2);
+
+            if (Error16x16 > this_rd)
+            {
+                Error16x16 = this_rd;
+                best_mode = mode;
+            }
+        }
+
+        vp8_pick_intra4x4mby_modes(IF_RTCD(&cpi->rtcd), x, &rate2, &distortion2);
+
+        if (distortion2 == INT_MAX)
+            Error4x4 = INT_MAX;
+        else
+            Error4x4 = RD_ESTIMATE(x->rdmult, x->rddiv, rate2, distortion2);
+
+        x->e_mbd.mbmi.mb_skip_coeff = (cpi->common.mb_no_coeff_skip) ? 1 : 0;
+
+        if (Error4x4 < Error16x16)
+        {
+            x->e_mbd.mbmi.mode = B_PRED;
+            vp8_encode_intra4x4mby(IF_RTCD(&cpi->rtcd), x);
+            cpi->prediction_error += Error4x4;
+        }
+        else
+        {
+            x->e_mbd.mbmi.mode = best_mode;
+            vp8_encode_intra16x16mby(IF_RTCD(&cpi->rtcd), x);
+            cpi->prediction_error += Error16x16;
+        }
+
+        vp8_pick_intra_mbuv_mode(x);
+        vp8_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);
+        sum_intra_stats(cpi, x);
+        vp8_tokenize_mb(cpi, &x->e_mbd, t);
+    }
+
+    return rate;
+}
+#ifdef SPEEDSTATS
+extern int cnt_pm;
+#endif
+
+extern void vp8_fix_contexts(VP8_COMP *cpi, MACROBLOCKD *x);
+
+int vp8cx_encode_inter_macroblock
+(
+    VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t,
+    int recon_yoffset, int recon_uvoffset
+)
+{
+    MACROBLOCKD *const xd = &x->e_mbd;
+    int inter_error;
+    int intra_error = 0;
+    int rate;
+    int distortion;
+
+    x->skip = 0;
+
+    if (xd->segmentation_enabled)
+        x->encode_breakout = cpi->segment_encode_breakout[xd->mbmi.segment_id];
+    else
+        x->encode_breakout = cpi->oxcf.encode_breakout;
+
+#if !(CONFIG_REALTIME_ONLY)
+
+    if (cpi->sf.RD)
+    {
+        inter_error = vp8_rd_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate, &distortion, &intra_error);
+    }
+    else
+#endif
+        inter_error = vp8_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate, &distortion, &intra_error);
+
+
+    cpi->prediction_error += inter_error;
+    cpi->intra_error += intra_error;
+
+#if 0
+    // Experimental RD code
+    cpi->frame_distortion += distortion;
+    cpi->last_mb_distortion = distortion;
+#endif
+
+    // MB level adjutment to quantizer setup
+    if (xd->segmentation_enabled || cpi->zbin_mode_boost_enabled)
+    {
+        // If cyclic update enabled
+        if (cpi->cyclic_refresh_mode_enabled)
+        {
+            // Clear segment_id back to 0 if not coded (last frame 0,0)
+            if ((xd->mbmi.segment_id == 1) &&
+                ((xd->mbmi.ref_frame != LAST_FRAME) || (xd->mbmi.mode != ZEROMV)))
+            {
+                xd->mbmi.segment_id = 0;
+            }
+        }
+
+        // Experimental code. Special case for gf and arf zeromv modes. Increase zbin size to supress noise
+        if (cpi->zbin_mode_boost_enabled)
+        {
+            if ((xd->mbmi.mode == ZEROMV) && (xd->mbmi.ref_frame != LAST_FRAME))
+                cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
+            else
+                cpi->zbin_mode_boost = 0;
+        }
+
+        vp8cx_mb_init_quantizer(cpi,  x);
+    }
+
+    cpi->count_mb_ref_frame_usage[xd->mbmi.ref_frame] ++;
+
+    if (xd->mbmi.ref_frame == INTRA_FRAME)
+    {
+        x->e_mbd.mbmi.mb_skip_coeff = (cpi->common.mb_no_coeff_skip) ? 1 : 0;
+
+        vp8_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);
+
+        if (xd->mbmi.mode == B_PRED)
+        {
+            vp8_encode_intra4x4mby(IF_RTCD(&cpi->rtcd), x);
+        }
+        else
+        {
+            vp8_encode_intra16x16mby(IF_RTCD(&cpi->rtcd), x);
+        }
+
+        sum_intra_stats(cpi, x);
+    }
+    else
+    {
+        MV best_ref_mv;
+        MV nearest, nearby;
+        int mdcounts[4];
+
+        vp8_find_near_mvs(xd, xd->mode_info_context,
+                          &nearest, &nearby, &best_ref_mv, mdcounts, xd->mbmi.ref_frame, cpi->common.ref_frame_sign_bias);
+
+        vp8_build_uvmvs(xd, cpi->common.full_pixel);
+
+        // store motion vectors in our motion vector list
+        if (xd->mbmi.ref_frame == LAST_FRAME)
+        {
+            // Set up pointers for this macro block into the previous frame recon buffer
+            xd->pre.y_buffer = cpi->common.last_frame.y_buffer + recon_yoffset;
+            xd->pre.u_buffer = cpi->common.last_frame.u_buffer + recon_uvoffset;
+            xd->pre.v_buffer = cpi->common.last_frame.v_buffer + recon_uvoffset;
+        }
+        else if (xd->mbmi.ref_frame == GOLDEN_FRAME)
+        {
+            // Set up pointers for this macro block into the golden frame recon buffer
+            xd->pre.y_buffer = cpi->common.golden_frame.y_buffer + recon_yoffset;
+            xd->pre.u_buffer = cpi->common.golden_frame.u_buffer + recon_uvoffset;
+            xd->pre.v_buffer = cpi->common.golden_frame.v_buffer + recon_uvoffset;
+        }
+        else
+        {
+            // Set up pointers for this macro block into the alternate reference frame recon buffer
+            xd->pre.y_buffer = cpi->common.alt_ref_frame.y_buffer + recon_yoffset;
+            xd->pre.u_buffer = cpi->common.alt_ref_frame.u_buffer + recon_uvoffset;
+            xd->pre.v_buffer = cpi->common.alt_ref_frame.v_buffer + recon_uvoffset;
+        }
+
+        if (xd->mbmi.mode == SPLITMV)
+        {
+            int i;
+
+            for (i = 0; i < 16; i++)
+            {
+                if (xd->block[i].bmi.mode == NEW4X4)
+                {
+                    cpi->MVcount[0][mv_max+((xd->block[i].bmi.mv.as_mv.row - best_ref_mv.row) >> 1)]++;
+                    cpi->MVcount[1][mv_max+((xd->block[i].bmi.mv.as_mv.col - best_ref_mv.col) >> 1)]++;
+                }
+            }
+        }
+        else if (xd->mbmi.mode == NEWMV)
+        {
+            cpi->MVcount[0][mv_max+((xd->block[0].bmi.mv.as_mv.row - best_ref_mv.row) >> 1)]++;
+            cpi->MVcount[1][mv_max+((xd->block[0].bmi.mv.as_mv.col - best_ref_mv.col) >> 1)]++;
+        }
+
+        if (!x->skip && !x->e_mbd.mbmi.force_no_skip)
+        {
+            vp8_encode_inter16x16(IF_RTCD(&cpi->rtcd), x);
+
+            // Clear mb_skip_coeff if mb_no_coeff_skip is not set
+            if (!cpi->common.mb_no_coeff_skip)
+                xd->mbmi.mb_skip_coeff = 0;
+
+        }
+        else
+            vp8_stuff_inter16x16(x);
+    }
+
+    if (!x->skip)
+        vp8_tokenize_mb(cpi, xd, t);
+    else
+    {
+        if (cpi->common.mb_no_coeff_skip)
+        {
+            if (xd->mbmi.mode != B_PRED && xd->mbmi.mode != SPLITMV)
+                xd->mbmi.dc_diff = 0;
+            else
+                xd->mbmi.dc_diff = 1;
+
+            xd->mbmi.mb_skip_coeff = 1;
+            cpi->skip_true_count ++;
+            vp8_fix_contexts(cpi, xd);
+        }
+        else
+        {
+            vp8_stuff_mb(cpi, xd, t);
+            xd->mbmi.mb_skip_coeff = 0;
+            cpi->skip_false_count ++;
+        }
+    }
+
+    return rate;
+}
diff --git a/vp8/encoder/encodeintra.c b/vp8/encoder/encodeintra.c
new file mode 100644
index 0000000..403d020
--- /dev/null
+++ b/vp8/encoder/encodeintra.c
@@ -0,0 +1,236 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "idct.h"
+#include "quantize.h"
+#include "reconintra.h"
+#include "reconintra4x4.h"
+#include "encodemb.h"
+#include "invtrans.h"
+#include "recon.h"
+#include "dct.h"
+#include "g_common.h"
+#include "encodeintra.h"
+
+#define intra4x4ibias_rate    128
+#define intra4x4pbias_rate    256
+
+
+void vp8_update_mode_context(int *abmode, int *lbmode, int i, int best_mode)
+{
+    if (i < 12)
+    {
+        abmode[i+4] = best_mode;
+    }
+
+    if ((i & 3) != 3)
+    {
+        lbmode[i+1] = best_mode;
+    }
+
+}
+#if CONFIG_RUNTIME_CPU_DETECT
+#define IF_RTCD(x) (x)
+#else
+#define IF_RTCD(x) NULL
+#endif
+void vp8_encode_intra4x4block(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x, BLOCK *be, BLOCKD *b, int best_mode)
+{
+    vp8_predict_intra4x4(b, best_mode, b->predictor);
+
+    ENCODEMB_INVOKE(&rtcd->encodemb, subb)(be, b, 16);
+
+    x->vp8_short_fdct4x4(be->src_diff, be->coeff, 32);
+
+    x->quantize_b(be, b);
+
+    x->e_mbd.mbmi.mb_skip_coeff &= (!b->eob);
+
+    vp8_inverse_transform_b(IF_RTCD(&rtcd->common->idct), b, 32);
+
+    RECON_INVOKE(&rtcd->common->recon, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+}
+
+void vp8_encode_intra4x4block_rd(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x, BLOCK *be, BLOCKD *b, int best_mode)
+{
+    vp8_predict_intra4x4(b, best_mode, b->predictor);
+
+    ENCODEMB_INVOKE(&rtcd->encodemb, subb)(be, b, 16);
+
+    x->short_fdct4x4rd(be->src_diff, be->coeff, 32);
+
+    x->quantize_brd(be, b);
+
+    x->e_mbd.mbmi.mb_skip_coeff &= (!b->eob);
+
+    IDCT_INVOKE(&rtcd->common->idct, idct16)(b->dqcoeff, b->diff, 32);
+
+    RECON_INVOKE(&rtcd->common->recon, recon)(b->predictor, b->diff, *(b->base_dst) + b->dst, b->dst_stride);
+}
+
+void vp8_encode_intra4x4mby(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *mb)
+{
+    int i;
+
+    MACROBLOCKD *x = &mb->e_mbd;
+    vp8_intra_prediction_down_copy(x);
+
+    for (i = 0; i < 16; i++)
+    {
+        BLOCK *be = &mb->block[i];
+        BLOCKD *b = &x->block[i];
+
+        vp8_encode_intra4x4block(rtcd, mb, be, b, b->bmi.mode);
+    }
+
+    return;
+}
+
+void vp8_encode_intra16x16mby(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+{
+    int b;
+
+    vp8_build_intra_predictors_mby_ptr(&x->e_mbd);
+
+    ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, x->src.y_buffer, x->e_mbd.predictor, x->src.y_stride);
+
+    vp8_transform_intra_mby(x);
+
+    vp8_quantize_mby(x);
+
+#if !(CONFIG_REALTIME_ONLY)
+#if 1
+
+    if (x->optimize && x->rddiv > 1)
+        vp8_optimize_mby(x, rtcd);
+
+#endif
+#endif
+
+    vp8_inverse_transform_mby(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+
+    vp8_recon16x16mby(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
+
+    // make sure block modes are set the way we want them for context updates
+    for (b = 0; b < 16; b++)
+    {
+        BLOCKD *d = &x->e_mbd.block[b];
+
+        switch (x->e_mbd.mbmi.mode)
+        {
+
+        case DC_PRED:
+            d->bmi.mode = B_DC_PRED;
+            break;
+        case V_PRED:
+            d->bmi.mode = B_VE_PRED;
+            break;
+        case H_PRED:
+            d->bmi.mode = B_HE_PRED;
+            break;
+        case TM_PRED:
+            d->bmi.mode = B_TM_PRED;
+            break;
+        default:
+            d->bmi.mode = B_DC_PRED;
+            break;
+
+        }
+    }
+}
+
+void vp8_encode_intra16x16mbyrd(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+{
+    int b;
+
+    vp8_build_intra_predictors_mby_ptr(&x->e_mbd);
+
+    ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, x->src.y_buffer, x->e_mbd.predictor, x->src.y_stride);
+
+    vp8_transform_intra_mbyrd(x);
+
+    x->e_mbd.mbmi.mb_skip_coeff = 1;
+
+    vp8_quantize_mbyrd(x);
+
+
+    vp8_inverse_transform_mby(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+
+    vp8_recon16x16mby(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
+
+    // make sure block modes are set the way we want them for context updates
+    for (b = 0; b < 16; b++)
+    {
+        BLOCKD *d = &x->e_mbd.block[b];
+
+        switch (x->e_mbd.mbmi.mode)
+        {
+
+        case DC_PRED:
+            d->bmi.mode = B_DC_PRED;
+            break;
+        case V_PRED:
+            d->bmi.mode = B_VE_PRED;
+            break;
+        case H_PRED:
+            d->bmi.mode = B_HE_PRED;
+            break;
+        case TM_PRED:
+            d->bmi.mode = B_TM_PRED;
+            break;
+        default:
+            d->bmi.mode = B_DC_PRED;
+            break;
+
+        }
+    }
+}
+
+void vp8_encode_intra16x16mbuv(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+{
+    vp8_build_intra_predictors_mbuv(&x->e_mbd);
+
+    ENCODEMB_INVOKE(&rtcd->encodemb, submbuv)(x->src_diff, x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
+
+    vp8_transform_mbuv(x);
+
+    vp8_quantize_mbuv(x);
+
+#if !(CONFIG_REALTIME_ONLY)
+#if 1
+
+    if (x->optimize && x->rddiv > 1)
+        vp8_optimize_mbuv(x, rtcd);
+
+#endif
+#endif
+
+    vp8_inverse_transform_mbuv(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+
+    vp8_recon_intra_mbuv(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
+}
+
+void vp8_encode_intra16x16mbuvrd(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+{
+    vp8_build_intra_predictors_mbuv(&x->e_mbd);
+
+    ENCODEMB_INVOKE(&rtcd->encodemb, submbuv)(x->src_diff, x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
+
+    vp8_transform_mbuvrd(x);
+
+    vp8_quantize_mbuvrd(x);
+
+
+
+    vp8_inverse_transform_mbuv(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+
+    vp8_recon_intra_mbuv(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
+}
diff --git a/vp8/encoder/encodeintra.h b/vp8/encoder/encodeintra.h
new file mode 100644
index 0000000..4a43ab2
--- /dev/null
+++ b/vp8/encoder/encodeintra.h
@@ -0,0 +1,24 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef _ENCODEINTRA_H_
+#define _ENCODEINTRA_H_
+#include "onyx_int.h"
+
+void vp8_encode_intra16x16mby(const VP8_ENCODER_RTCD *, MACROBLOCK *x);
+void vp8_encode_intra16x16mbuv(const VP8_ENCODER_RTCD *, MACROBLOCK *x);
+void vp8_encode_intra4x4mby(const VP8_ENCODER_RTCD *, MACROBLOCK *mb);
+void vp8_encode_intra4x4block(const VP8_ENCODER_RTCD *, MACROBLOCK *x, BLOCK *be, BLOCKD *b, int best_mode);
+void vp8_update_mode_context(int *abmode, int *lbmode, int i, int best_mode);
+void vp8_encode_intra4x4block_rd(const VP8_ENCODER_RTCD *, MACROBLOCK *x, BLOCK *be, BLOCKD *b, int best_mode);
+void vp8_encode_intra16x16mbyrd(const VP8_ENCODER_RTCD *, MACROBLOCK *x);
+void vp8_encode_intra16x16mbuvrd(const VP8_ENCODER_RTCD *, MACROBLOCK *x);
+
+#endif
diff --git a/vp8/encoder/encodemb.c b/vp8/encoder/encodemb.c
new file mode 100644
index 0000000..d825133
--- /dev/null
+++ b/vp8/encoder/encodemb.c
@@ -0,0 +1,1129 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "encodemb.h"
+#include "reconinter.h"
+#include "quantize.h"
+#include "invtrans.h"
+#include "recon.h"
+#include "reconintra.h"
+#include "dct.h"
+#include "vpx_mem/vpx_mem.h"
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define IF_RTCD(x) (x)
+#else
+#define IF_RTCD(x) NULL
+#endif
+void vp8_subtract_b_c(BLOCK *be, BLOCKD *bd, int pitch)
+{
+    unsigned char *src_ptr = (*(be->base_src) + be->src);
+    short *diff_ptr = be->src_diff;
+    unsigned char *pred_ptr = bd->predictor;
+    int src_stride = be->src_stride;
+
+    int r, c;
+
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 4; c++)
+        {
+            diff_ptr[c] = src_ptr[c] - pred_ptr[c];
+        }
+
+        diff_ptr += pitch;
+        pred_ptr += pitch;
+        src_ptr  += src_stride;
+    }
+}
+
+void vp8_subtract_mbuv_c(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride)
+{
+    short *udiff = diff + 256;
+    short *vdiff = diff + 320;
+    unsigned char *upred = pred + 256;
+    unsigned char *vpred = pred + 320;
+
+    int r, c;
+
+    for (r = 0; r < 8; r++)
+    {
+        for (c = 0; c < 8; c++)
+        {
+            udiff[c] = usrc[c] - upred[c];
+        }
+
+        udiff += 8;
+        upred += 8;
+        usrc  += stride;
+    }
+
+    for (r = 0; r < 8; r++)
+    {
+        for (c = 0; c < 8; c++)
+        {
+            vdiff[c] = vsrc[c] - vpred[c];
+        }
+
+        vdiff += 8;
+        vpred += 8;
+        vsrc  += stride;
+    }
+}
+
+void vp8_subtract_mby_c(short *diff, unsigned char *src, unsigned char *pred, int stride)
+{
+    int r, c;
+
+    for (r = 0; r < 16; r++)
+    {
+        for (c = 0; c < 16; c++)
+        {
+            diff[c] = src[c] - pred[c];
+        }
+
+        diff += 16;
+        pred += 16;
+        src  += stride;
+    }
+}
+
+static void vp8_subtract_mb(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+{
+    ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, x->src.y_buffer, x->e_mbd.predictor, x->src.y_stride);
+    ENCODEMB_INVOKE(&rtcd->encodemb, submbuv)(x->src_diff, x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
+}
+
+void vp8_build_dcblock(MACROBLOCK *x)
+{
+    short *src_diff_ptr = &x->src_diff[384];
+    int i;
+
+    for (i = 0; i < 16; i++)
+    {
+        src_diff_ptr[i] = x->coeff[i * 16];
+    }
+}
+
+void vp8_transform_mbuv(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 16; i < 24; i += 2)
+    {
+        x->vp8_short_fdct8x4(&x->block[i].src_diff[0], &x->block[i].coeff[0], 16);
+    }
+}
+
+void vp8_transform_mbuvrd(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 16; i < 24; i += 2)
+    {
+        x->short_fdct8x4rd(&x->block[i].src_diff[0], &x->block[i].coeff[0], 16);
+    }
+}
+
+void vp8_transform_intra_mby(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 0; i < 16; i += 2)
+    {
+        x->vp8_short_fdct8x4(&x->block[i].src_diff[0], &x->block[i].coeff[0], 32);
+    }
+
+    // build dc block from 16 y dc values
+    vp8_build_dcblock(x);
+
+    // do 2nd order transform on the dc block
+    x->short_walsh4x4(&x->block[24].src_diff[0], &x->block[24].coeff[0], 8);
+
+}
+
+void vp8_transform_intra_mbyrd(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 0; i < 16; i += 2)
+    {
+        x->short_fdct8x4rd(&x->block[i].src_diff[0], &x->block[i].coeff[0], 32);
+    }
+
+    // build dc block from 16 y dc values
+    vp8_build_dcblock(x);
+
+    // do 2nd order transform on the dc block
+    x->short_walsh4x4(&x->block[24].src_diff[0], &x->block[24].coeff[0], 8);
+}
+
+void vp8_transform_mb(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 0; i < 16; i += 2)
+    {
+        x->vp8_short_fdct8x4(&x->block[i].src_diff[0], &x->block[i].coeff[0], 32);
+    }
+
+    // build dc block from 16 y dc values
+    if (x->e_mbd.mbmi.mode != SPLITMV)
+        vp8_build_dcblock(x);
+
+    for (i = 16; i < 24; i += 2)
+    {
+        x->vp8_short_fdct8x4(&x->block[i].src_diff[0], &x->block[i].coeff[0], 16);
+    }
+
+    // do 2nd order transform on the dc block
+    if (x->e_mbd.mbmi.mode != SPLITMV)
+        x->short_walsh4x4(&x->block[24].src_diff[0], &x->block[24].coeff[0], 8);
+
+}
+
+void vp8_transform_mby(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 0; i < 16; i += 2)
+    {
+        x->vp8_short_fdct8x4(&x->block[i].src_diff[0], &x->block[i].coeff[0], 32);
+    }
+
+    // build dc block from 16 y dc values
+    if (x->e_mbd.mbmi.mode != SPLITMV)
+    {
+        vp8_build_dcblock(x);
+        x->short_walsh4x4(&x->block[24].src_diff[0], &x->block[24].coeff[0], 8);
+    }
+}
+
+void vp8_transform_mbrd(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 0; i < 16; i += 2)
+    {
+        x->short_fdct8x4rd(&x->block[i].src_diff[0], &x->block[i].coeff[0], 32);
+    }
+
+    // build dc block from 16 y dc values
+    if (x->e_mbd.mbmi.mode != SPLITMV)
+        vp8_build_dcblock(x);
+
+    for (i = 16; i < 24; i += 2)
+    {
+        x->short_fdct8x4rd(&x->block[i].src_diff[0], &x->block[i].coeff[0], 16);
+    }
+
+    // do 2nd order transform on the dc block
+    if (x->e_mbd.mbmi.mode != SPLITMV)
+        x->short_walsh4x4(&x->block[24].src_diff[0], &x->block[24].coeff[0], 8);
+}
+
+void vp8_stuff_inter16x16(MACROBLOCK *x)
+{
+    vp8_build_inter_predictors_mb_s(&x->e_mbd);
+    /*
+        // recon = copy from predictors to destination
+        {
+            BLOCKD *b = &x->e_mbd.block[0];
+            unsigned char *pred_ptr = b->predictor;
+            unsigned char *dst_ptr = *(b->base_dst) + b->dst;
+            int stride = b->dst_stride;
+
+            int i;
+            for(i=0;i<16;i++)
+                vpx_memcpy(dst_ptr+i*stride,pred_ptr+16*i,16);
+
+            b = &x->e_mbd.block[16];
+            pred_ptr = b->predictor;
+            dst_ptr = *(b->base_dst) + b->dst;
+            stride = b->dst_stride;
+
+            for(i=0;i<8;i++)
+                vpx_memcpy(dst_ptr+i*stride,pred_ptr+8*i,8);
+
+            b = &x->e_mbd.block[20];
+            pred_ptr = b->predictor;
+            dst_ptr = *(b->base_dst) + b->dst;
+            stride = b->dst_stride;
+
+            for(i=0;i<8;i++)
+                vpx_memcpy(dst_ptr+i*stride,pred_ptr+8*i,8);
+        }
+    */
+}
+
+#if !(CONFIG_REALTIME_ONLY)
+extern const TOKENEXTRA vp8_dct_value_tokens[DCT_MAX_VALUE*2];
+extern const TOKENEXTRA *vp8_dct_value_tokens_ptr;
+extern int vp8_dct_value_cost[DCT_MAX_VALUE*2];
+extern int *vp8_dct_value_cost_ptr;
+
+static int cost_coeffs(MACROBLOCK *mb, BLOCKD *b, int type, ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l)
+{
+    int c = !type;              /* start at coef 0, unless Y with Y2 */
+    int eob = b->eob;
+    int pt ;    /* surrounding block/prev coef predictor */
+    int cost = 0;
+    short *qcoeff_ptr = b->qcoeff;
+
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+# define QC( I)  ( qcoeff_ptr [vp8_default_zig_zag1d[I]] )
+
+    for (; c < eob; c++)
+    {
+        int v = QC(c);
+        int t = vp8_dct_value_tokens_ptr[v].Token;
+        cost += mb->token_costs [type] [vp8_coef_bands[c]] [pt] [t];
+        cost += vp8_dct_value_cost_ptr[v];
+        pt = vp8_prev_token_class[t];
+    }
+
+# undef QC
+
+    if (c < 16)
+        cost += mb->token_costs [type] [vp8_coef_bands[c]] [pt] [DCT_EOB_TOKEN];
+
+    return cost;
+}
+
+static int mbycost_coeffs(MACROBLOCK *mb)
+{
+    int cost = 0;
+    int b;
+    TEMP_CONTEXT t;
+    int type = 0;
+
+    MACROBLOCKD *x = &mb->e_mbd;
+
+    vp8_setup_temp_context(&t, x->above_context[Y1CONTEXT], x->left_context[Y1CONTEXT], 4);
+
+    if (x->mbmi.mode == SPLITMV)
+        type = 3;
+
+    for (b = 0; b < 16; b++)
+        cost += cost_coeffs(mb, x->block + b, type,
+                            t.a + vp8_block2above[b], t.l + vp8_block2left[b]);
+
+    return cost;
+}
+
+#define RDFUNC(RM,DM,R,D,target_rd) ( ((128+(R)*(RM)) >> 8) + (DM)*(D) )
+
+void vp8_optimize_b(MACROBLOCK *x, int i, int type, ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l, const VP8_ENCODER_RTCD *rtcd)
+{
+    BLOCK *b = &x->block[i];
+    BLOCKD *bd = &x->e_mbd.block[i];
+    short *dequant_ptr = &bd->dequant[0][0];
+    int nzpos[16] = {0};
+    short saved_qcoefs[16];
+    short saved_dqcoefs[16];
+    int baserate, baseerror, baserd;
+    int rate, error, thisrd;
+    int k;
+    int nzcoefcount = 0;
+    int nc, bestnc = 0;
+    int besteob;
+
+    // count potential coefficient to be optimized
+    for (k = !type; k < 16; k++)
+    {
+        int qcoef = abs(bd->qcoeff[k]);
+        int coef = abs(b->coeff[k]);
+        int dq   = dequant_ptr[k];
+
+        if (qcoef && (qcoef * dq > coef) && (qcoef * dq < coef + dq))
+        {
+            nzpos[nzcoefcount] = k;
+            nzcoefcount++;
+        }
+    }
+
+    // if nothing here, do nothing for this block.
+    if (!nzcoefcount)
+    {
+        *a = *l = (bd->eob != !type);
+        return;
+    }
+
+    // save a copy of quantized coefficients
+    vpx_memcpy(saved_qcoefs, bd->qcoeff, 32);
+    vpx_memcpy(saved_dqcoefs, bd->dqcoeff, 32);
+
+    besteob   = bd->eob;
+    baserate  = cost_coeffs(x, bd, type, a, l);
+    baseerror = ENCODEMB_INVOKE(&rtcd->encodemb, berr)(b->coeff, bd->dqcoeff) >> 2;
+    baserd    = RDFUNC(x->rdmult, x->rddiv, baserate, baseerror, 100);
+
+    for (nc = 1; nc < (1 << nzcoefcount); nc++)
+    {
+        //reset coefficients
+        vpx_memcpy(bd->qcoeff,  saved_qcoefs,  32);
+        vpx_memcpy(bd->dqcoeff, saved_dqcoefs, 32);
+
+        for (k = 0; k < nzcoefcount; k++)
+        {
+            int pos = nzpos[k];
+
+            if ((nc & (1 << k)))
+            {
+                int cur_qcoef = bd->qcoeff[pos];
+
+                if (cur_qcoef < 0)
+                {
+                    bd->qcoeff[pos]++;
+                    bd->dqcoeff[pos] = bd->qcoeff[pos] * dequant_ptr[pos];
+                }
+                else
+                {
+                    bd->qcoeff[pos]--;
+                    bd->dqcoeff[pos] = bd->qcoeff[pos] * dequant_ptr[pos];
+                }
+            }
+        }
+
+        {
+            int eob = -1;
+            int rc;
+            int m;
+
+            for (m = 0; m < 16; m++)
+            {
+                rc   = vp8_default_zig_zag1d[m];
+
+                if (bd->qcoeff[rc])
+                    eob = m;
+            }
+
+            bd->eob = eob + 1;
+        }
+
+        rate  = cost_coeffs(x, bd, type, a, l);
+        error = ENCODEMB_INVOKE(&rtcd->encodemb, berr)(b->coeff, bd->dqcoeff) >> 2;
+        thisrd = RDFUNC(x->rdmult, x->rddiv, rate, error, 100);
+
+        if (thisrd < baserd)
+        {
+            baserd = thisrd;
+            bestnc = nc;
+            besteob = bd->eob;
+        }
+    }
+
+    //reset coefficients
+    vpx_memcpy(bd->qcoeff,  saved_qcoefs, 32);
+    vpx_memcpy(bd->dqcoeff, saved_dqcoefs, 32);
+
+    if (bestnc)
+    {
+        for (k = 0; k < nzcoefcount; k++)
+        {
+            int pos = nzpos[k];
+
+            if (bestnc & (1 << k))
+            {
+                int cur_qcoef = bd->qcoeff[pos];
+
+                if (cur_qcoef < 0)
+                {
+                    bd->qcoeff[pos]++;
+                    bd->dqcoeff[pos] = bd->qcoeff[pos] * dequant_ptr[pos];
+                }
+                else
+                {
+                    bd->qcoeff[pos]--;
+                    bd->dqcoeff[pos] = bd->qcoeff[pos] * dequant_ptr[pos];
+                }
+            }
+        }
+
+#if 0
+        {
+            int eob = -1;
+            int rc;
+            int m;
+
+            for (m = 0; m < 16; m++)
+            {
+                rc   = vp8_default_zig_zag1d[m];
+
+                if (bd->qcoeff[rc])
+                    eob = m;
+            }
+
+            bd->eob = eob + 1;
+        }
+#endif
+    }
+
+#if 1
+    bd->eob = besteob;
+#endif
+#if 0
+    {
+        int eob = -1;
+        int rc;
+        int m;
+
+        for (m = 0; m < 16; m++)
+        {
+            rc   = vp8_default_zig_zag1d[m];
+
+            if (bd->qcoeff[rc])
+                eob = m;
+        }
+
+        bd->eob = eob + 1;
+    }
+
+#endif
+    *a = *l = (bd->eob != !type);
+    return;
+}
+
+void vp8_optimize_bplus(MACROBLOCK *x, int i, int type, ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l, const VP8_ENCODER_RTCD *rtcd)
+{
+    BLOCK *b = &x->block[i];
+    BLOCKD *bd = &x->e_mbd.block[i];
+    short *dequant_ptr = &bd->dequant[0][0];
+    int nzpos[16] = {0};
+    short saved_qcoefs[16];
+    short saved_dqcoefs[16];
+    int baserate, baseerror, baserd;
+    int rate, error, thisrd;
+    int k;
+    int nzcoefcount = 0;
+    int nc, bestnc = 0;
+    int besteob;
+
+    // count potential coefficient to be optimized
+    for (k = !type; k < 16; k++)
+    {
+        int qcoef = abs(bd->qcoeff[k]);
+        int coef = abs(b->coeff[k]);
+        int dq   = dequant_ptr[k];
+
+        if (qcoef && (qcoef * dq < coef) && (coef < (qcoef * dq + dq)))
+        {
+            nzpos[nzcoefcount] = k;
+            nzcoefcount++;
+        }
+    }
+
+    // if nothing here, do nothing for this block.
+    if (!nzcoefcount)
+    {
+        //do not update context, we need do the other half.
+        //*a = *l = (bd->eob != !type);
+        return;
+    }
+
+    // save a copy of quantized coefficients
+    vpx_memcpy(saved_qcoefs, bd->qcoeff, 32);
+    vpx_memcpy(saved_dqcoefs, bd->dqcoeff, 32);
+
+    besteob   = bd->eob;
+    baserate  = cost_coeffs(x, bd, type, a, l);
+    baseerror = ENCODEMB_INVOKE(&rtcd->encodemb, berr)(b->coeff, bd->dqcoeff) >> 2;
+    baserd    = RDFUNC(x->rdmult, x->rddiv, baserate, baseerror, 100);
+
+    for (nc = 1; nc < (1 << nzcoefcount); nc++)
+    {
+        //reset coefficients
+        vpx_memcpy(bd->qcoeff, saved_qcoefs, 32);
+        vpx_memcpy(bd->dqcoeff, saved_dqcoefs, 32);
+
+        for (k = 0; k < nzcoefcount; k++)
+        {
+            int pos = nzpos[k];
+
+            if ((nc & (1 << k)))
+            {
+                int cur_qcoef = bd->qcoeff[pos];
+
+                if (cur_qcoef < 0)
+                {
+                    bd->qcoeff[pos]--;
+                    bd->dqcoeff[pos] = bd->qcoeff[pos] * dequant_ptr[pos];
+                }
+                else
+                {
+                    bd->qcoeff[pos]++;
+                    bd->dqcoeff[pos] = bd->qcoeff[pos] * dequant_ptr[pos];
+                }
+            }
+        }
+
+        {
+            int eob = -1;
+            int rc;
+            int m;
+
+            for (m = 0; m < 16; m++)
+            {
+                rc   = vp8_default_zig_zag1d[m];
+
+                if (bd->qcoeff[rc])
+                    eob = m;
+            }
+
+            bd->eob = eob + 1;
+        }
+
+        rate  = cost_coeffs(x, bd, type, a, l);
+        error = ENCODEMB_INVOKE(&rtcd->encodemb, berr)(b->coeff, bd->dqcoeff) >> 2;
+        thisrd = RDFUNC(x->rdmult, x->rddiv, rate, error, 100);
+
+        if (thisrd < baserd)
+        {
+            baserd = thisrd;
+            bestnc = nc;
+            besteob = bd->eob;
+        }
+    }
+
+    //reset coefficients
+    vpx_memcpy(bd->qcoeff,  saved_qcoefs, 32);
+    vpx_memcpy(bd->dqcoeff, saved_dqcoefs, 32);
+
+    if (bestnc)
+    {
+        for (k = 0; k < nzcoefcount; k++)
+        {
+            int pos = nzpos[k];
+
+            if (bestnc & (1 << k))
+            {
+                int cur_qcoef = bd->qcoeff[pos];
+
+                if (cur_qcoef < 0)
+                {
+                    bd->qcoeff[pos]++;
+                    bd->dqcoeff[pos] = bd->qcoeff[pos] * dequant_ptr[pos];
+                }
+                else
+                {
+                    bd->qcoeff[pos]--;
+                    bd->dqcoeff[pos] = bd->qcoeff[pos] * dequant_ptr[pos];
+                }
+            }
+        }
+    }
+
+    bd->eob = besteob;
+    //do not update context, we need do the other half.
+    //*a = *l = (bd->eob != !type);
+    return;
+}
+
+void vp8_optimize_y2b(MACROBLOCK *x, int i, int type, ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l, const VP8_ENCODER_RTCD *rtcd)
+{
+
+    BLOCK *b = &x->block[i];
+    BLOCKD *bd = &x->e_mbd.block[i];
+    short *dequant_ptr = &bd->dequant[0][0];
+
+    int baserate, baseerror, baserd;
+    int rate, error, thisrd;
+    int k;
+
+    if (bd->eob == 0)
+        return;
+
+    baserate  = cost_coeffs(x, bd, type, a, l);
+    baseerror = ENCODEMB_INVOKE(&rtcd->encodemb, berr)(b->coeff, bd->dqcoeff) >> 4;
+    baserd = RDFUNC(x->rdmult, x->rddiv, baserate, baseerror, 100);
+
+    for (k = 0; k < 16; k++)
+    {
+        int cur_qcoef = bd->qcoeff[k];
+
+        if (!cur_qcoef)
+            continue;
+
+        if (cur_qcoef < 0)
+        {
+            bd->qcoeff[k]++;
+            bd->dqcoeff[k] = bd->qcoeff[k] * dequant_ptr[k];
+        }
+        else
+        {
+            bd->qcoeff[k]--;
+            bd->dqcoeff[k] = bd->qcoeff[k] * dequant_ptr[k];
+        }
+
+        if (bd->qcoeff[k] == 0)
+        {
+            int eob = -1;
+            int rc;
+            int l;
+
+            for (l = 0; l < 16; l++)
+            {
+                rc   = vp8_default_zig_zag1d[l];
+
+                if (bd->qcoeff[rc])
+                    eob = l;
+            }
+
+            bd->eob = eob + 1;
+        }
+
+        rate  =   cost_coeffs(x, bd, type, a, l);
+        error = ENCODEMB_INVOKE(&rtcd->encodemb, berr)(b->coeff, bd->dqcoeff) >> 4;
+        thisrd = RDFUNC(x->rdmult, x->rddiv, rate, error, 100);
+
+        if (thisrd > baserd)
+        {
+            bd->qcoeff[k] = cur_qcoef;
+            bd->dqcoeff[k] = cur_qcoef * dequant_ptr[k];
+        }
+        else
+        {
+            baserd = thisrd;
+        }
+
+    }
+
+    {
+        int eob = -1;
+        int rc;
+
+        for (k = 0; k < 16; k++)
+        {
+            rc   = vp8_default_zig_zag1d[k];
+
+            if (bd->qcoeff[rc])
+                eob = k;
+        }
+
+        bd->eob = eob + 1;
+    }
+
+    return;
+}
+
+
+void vp8_optimize_mb(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+{
+    int cost = 0;
+    int b;
+    TEMP_CONTEXT t, t2;
+    int type = 0;
+
+    vp8_setup_temp_context(&t, x->e_mbd.above_context[Y1CONTEXT], x->e_mbd.left_context[Y1CONTEXT], 4);
+
+    if (x->e_mbd.mbmi.mode == SPLITMV || x->e_mbd.mbmi.mode == B_PRED)
+        type = 3;
+
+    for (b = 0; b < 16; b++)
+    {
+        //vp8_optimize_bplus(x, b, type, t.a + vp8_block2above[b], t.l + vp8_block2left[b]);
+        vp8_optimize_b(x, b, type, t.a + vp8_block2above[b], t.l + vp8_block2left[b], rtcd);
+    }
+
+    vp8_setup_temp_context(&t, x->e_mbd.above_context[UCONTEXT], x->e_mbd.left_context[UCONTEXT], 2);
+    vp8_setup_temp_context(&t2, x->e_mbd.above_context[VCONTEXT], x->e_mbd.left_context[VCONTEXT], 2);
+
+    for (b = 16; b < 20; b++)
+    {
+        //vp8_optimize_bplus(x, b, vp8_block2type[b], t.a + vp8_block2above[b], t.l + vp8_block2left[b]);
+        vp8_optimize_b(x, b, vp8_block2type[b], t.a + vp8_block2above[b], t.l + vp8_block2left[b], rtcd);
+    }
+
+    for (b = 20; b < 24; b++)
+    {
+        //vp8_optimize_bplus(x, b, vp8_block2type[b], t2.a + vp8_block2above[b], t2.l + vp8_block2left[b]);
+        vp8_optimize_b(x, b, vp8_block2type[b], t2.a + vp8_block2above[b], t2.l + vp8_block2left[b], rtcd);
+    }
+}
+
+
+
+void vp8_super_slow_yquant_optimization(MACROBLOCK *x, int type, const VP8_ENCODER_RTCD *rtcd)
+{
+    BLOCK  *b = &x->block[0];
+    BLOCKD *bd = &x->e_mbd.block[0];
+    short *dequant_ptr = &bd->dequant[0][0];
+    struct
+    {
+        int block;
+        int pos;
+    } nzpos[256];
+    short saved_qcoefs[256];
+    short saved_dqcoefs[256];
+    short *coef_ptr   = x->coeff;
+    short *qcoef_ptr  = x->e_mbd.qcoeff;
+    short *dqcoef_ptr = x->e_mbd.dqcoeff;
+
+    int baserate, baseerror, baserd;
+    int rate, error, thisrd;
+    int i, k;
+    int nzcoefcount = 0;
+    int nc, bestnc = 0;
+    int besteob;
+
+    //this code has assumption in macroblock coeff buffer layout
+    for (i = 0; i < 16; i++)
+    {
+        // count potential coefficient to be optimized
+        for (k = !type; k < 16; k++)
+        {
+            int qcoef = abs(qcoef_ptr[i*16 + k]);
+            int coef = abs(coef_ptr[i*16 + k]);
+            int dq   = dequant_ptr[k];
+
+            if (qcoef && (qcoef * dq > coef) && (qcoef * dq < coef + dq))
+            {
+                nzpos[nzcoefcount].block = i;
+                nzpos[nzcoefcount].pos   = k;
+                nzcoefcount++;
+            }
+        }
+    }
+
+    // if nothing here, do nothing for this macro_block.
+    if (!nzcoefcount || nzcoefcount > 15)
+    {
+        return;
+    }
+
+    /******************************************************************************
+    looking from each coeffient's perspective, each identifed coefficent above could
+    have 2 values:roundeddown(x) and roundedup(x). Therefore the total number of
+    different states is less than 2**nzcoefcount.
+    ******************************************************************************/
+    // save the qunatized coefficents and dequantized coefficicents
+    vpx_memcpy(saved_qcoefs, x->e_mbd.qcoeff,  256);
+    vpx_memcpy(saved_dqcoefs, x->e_mbd.dqcoeff, 256);
+
+    baserate    = mbycost_coeffs(x);
+    baseerror   = ENCODEMB_INVOKE(&rtcd->encodemb, mberr)(x, !type);
+    baserd      = RDFUNC(x->rdmult, x->rddiv, baserate, baseerror, 100);
+
+    for (nc = 1; nc < (1 << nzcoefcount); nc++)
+    {
+        //reset coefficients
+        vpx_memcpy(x->e_mbd.qcoeff,  saved_qcoefs, 256);
+        vpx_memcpy(x->e_mbd.dqcoeff, saved_dqcoefs, 256);
+
+        for (k = 0; k < nzcoefcount; k++)
+        {
+            int bk  = nzpos[k].block;
+            int pos = nzpos[k].pos;
+            int mbkpos  = bk * 16 + pos;
+
+            if ((nc & (1 << k)))
+            {
+                int cur_qcoef = x->e_mbd.qcoeff[mbkpos];
+
+                if (cur_qcoef < 0)
+                {
+                    x->e_mbd.qcoeff[mbkpos]++;
+                    x->e_mbd.dqcoeff[mbkpos] = x->e_mbd.qcoeff[mbkpos] * dequant_ptr[pos];
+                }
+                else
+                {
+                    x->e_mbd.qcoeff[mbkpos]--;
+                    x->e_mbd.dqcoeff[mbkpos] = x->e_mbd.qcoeff[mbkpos] * dequant_ptr[pos];
+                }
+            }
+        }
+
+        for (i = 0; i < 16; i++)
+        {
+            BLOCKD *bd = &x->e_mbd.block[i];
+            {
+                int eob = -1;
+                int rc;
+                int l;
+
+                for (l = 0; l < 16; l++)
+                {
+                    rc   = vp8_default_zig_zag1d[l];
+
+                    if (bd->qcoeff[rc])
+                        eob = l;
+                }
+
+                bd->eob = eob + 1;
+            }
+        }
+
+        rate  = mbycost_coeffs(x);
+        error = ENCODEMB_INVOKE(&rtcd->encodemb, mberr)(x, !type);;
+        thisrd = RDFUNC(x->rdmult, x->rddiv, rate, error, 100);
+
+        if (thisrd < baserd)
+        {
+            baserd = thisrd;
+            bestnc = nc;
+            besteob = bd->eob;
+        }
+    }
+
+    //reset coefficients
+    vpx_memcpy(x->e_mbd.qcoeff,  saved_qcoefs, 256);
+    vpx_memcpy(x->e_mbd.dqcoeff, saved_dqcoefs, 256);
+
+    if (bestnc)
+    {
+        for (k = 0; k < nzcoefcount; k++)
+        {
+            int bk  = nzpos[k].block;
+            int pos = nzpos[k].pos;
+            int mbkpos  = bk * 16 + pos;
+
+            if ((nc & (1 << k)))
+            {
+                int cur_qcoef = x->e_mbd.qcoeff[mbkpos];
+
+                if (cur_qcoef < 0)
+                {
+                    x->e_mbd.qcoeff[mbkpos]++;
+                    x->e_mbd.dqcoeff[mbkpos] = x->e_mbd.qcoeff[mbkpos] * dequant_ptr[pos];
+                }
+                else
+                {
+                    x->e_mbd.qcoeff[mbkpos]--;
+                    x->e_mbd.dqcoeff[mbkpos] = x->e_mbd.qcoeff[mbkpos] * dequant_ptr[pos];
+                }
+            }
+        }
+    }
+
+    for (i = 0; i < 16; i++)
+    {
+        BLOCKD *bd = &x->e_mbd.block[i];
+        {
+            int eob = -1;
+            int rc;
+            int l;
+
+            for (l = 0; l < 16; l++)
+            {
+                rc   = vp8_default_zig_zag1d[l];
+
+                if (bd->qcoeff[rc])
+                    eob = l;
+            }
+
+            bd->eob = eob + 1;
+        }
+    }
+
+    return;
+}
+
+static void vp8_find_mb_skip_coef(MACROBLOCK *x)
+{
+    int i;
+
+    x->e_mbd.mbmi.mb_skip_coeff = 1;
+
+    if (x->e_mbd.mbmi.mode != B_PRED && x->e_mbd.mbmi.mode != SPLITMV)
+    {
+        for (i = 0; i < 16; i++)
+        {
+            x->e_mbd.mbmi.mb_skip_coeff &= (x->e_mbd.block[i].eob < 2);
+        }
+
+        for (i = 16; i < 25; i++)
+        {
+            x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+        }
+    }
+    else
+    {
+        for (i = 0; i < 24; i++)
+        {
+            x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+        }
+    }
+}
+
+
+void vp8_optimize_mb_slow(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+{
+    int cost = 0;
+    int b;
+    TEMP_CONTEXT t, t2;
+    int type = 0;
+
+
+    vp8_setup_temp_context(&t, x->e_mbd.above_context[Y1CONTEXT], x->e_mbd.left_context[Y1CONTEXT], 4);
+
+    if (x->e_mbd.mbmi.mode == SPLITMV || x->e_mbd.mbmi.mode == B_PRED)
+        type = 3;
+
+    vp8_super_slow_yquant_optimization(x, type, rtcd);
+    /*
+    for(b=0;b<16;b++)
+    {
+        vp8_optimize_b(x, b, type, t.a + vp8_block2above[b], t.l + vp8_block2left[b]);
+    }
+    */
+
+    vp8_setup_temp_context(&t, x->e_mbd.above_context[UCONTEXT], x->e_mbd.left_context[UCONTEXT], 2);
+
+    for (b = 16; b < 20; b++)
+    {
+        vp8_optimize_b(x, b, vp8_block2type[b], t.a + vp8_block2above[b], t.l + vp8_block2left[b], rtcd);
+    }
+
+    vp8_setup_temp_context(&t2, x->e_mbd.above_context[VCONTEXT], x->e_mbd.left_context[VCONTEXT], 2);
+
+    for (b = 20; b < 24; b++)
+    {
+        vp8_optimize_b(x, b, vp8_block2type[b], t2.a + vp8_block2above[b], t2.l + vp8_block2left[b], rtcd);
+    }
+}
+
+
+void vp8_optimize_mby(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+{
+    int cost = 0;
+    int b;
+    TEMP_CONTEXT t;
+    int type = 0;
+
+    if (!x->e_mbd.above_context[Y1CONTEXT])
+        return;
+
+    if (!x->e_mbd.left_context[Y1CONTEXT])
+        return;
+
+    vp8_setup_temp_context(&t, x->e_mbd.above_context[Y1CONTEXT], x->e_mbd.left_context[Y1CONTEXT], 4);
+
+    if (x->e_mbd.mbmi.mode == SPLITMV || x->e_mbd.mbmi.mode == B_PRED)
+        type = 3;
+
+    for (b = 0; b < 16; b++)
+    {
+        vp8_optimize_b(x, b, type, t.a + vp8_block2above[b], t.l + vp8_block2left[b], rtcd);
+    }
+
+}
+
+void vp8_optimize_mbuv(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
+{
+    int cost = 0;
+    int b;
+    TEMP_CONTEXT t, t2;
+    int type = 0;
+
+    if (!x->e_mbd.above_context[UCONTEXT])
+        return;
+
+    if (!x->e_mbd.left_context[UCONTEXT])
+        return;
+
+    if (!x->e_mbd.above_context[VCONTEXT])
+        return;
+
+    if (!x->e_mbd.left_context[VCONTEXT])
+        return;
+
+
+    vp8_setup_temp_context(&t, x->e_mbd.above_context[UCONTEXT], x->e_mbd.left_context[UCONTEXT], 2);
+    vp8_setup_temp_context(&t2, x->e_mbd.above_context[VCONTEXT], x->e_mbd.left_context[VCONTEXT], 2);
+
+    for (b = 16; b < 20; b++)
+    {
+        vp8_optimize_b(x, b, vp8_block2type[b],
+                       t.a + vp8_block2above[b], t.l + vp8_block2left[b], rtcd);
+
+    }
+
+    for (b = 20; b < 24; b++)
+    {
+        vp8_optimize_b(x, b, vp8_block2type[b],
+                       t2.a + vp8_block2above[b], t2.l + vp8_block2left[b], rtcd);
+    }
+
+}
+#endif
+
+void vp8_encode_inter16x16(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+{
+    vp8_build_inter_predictors_mb(&x->e_mbd);
+
+    vp8_subtract_mb(rtcd, x);
+
+    vp8_transform_mb(x);
+
+    vp8_quantize_mb(x);
+
+#if !(CONFIG_REALTIME_ONLY)
+#if 1
+
+    if (x->optimize && x->rddiv > 1)
+    {
+        vp8_optimize_mb(x, rtcd);
+        vp8_find_mb_skip_coef(x);
+    }
+
+#endif
+#endif
+
+    vp8_inverse_transform_mb(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+
+    vp8_recon16x16mb(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
+}
+
+
+/* this funciton is used by first pass only */
+void vp8_encode_inter16x16y(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+{
+    vp8_build_inter_predictors_mby(&x->e_mbd);
+
+    ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, x->src.y_buffer, x->e_mbd.predictor, x->src.y_stride);
+
+    vp8_transform_mby(x);
+
+    vp8_quantize_mby(x);
+
+    vp8_inverse_transform_mby(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+
+    vp8_recon16x16mby(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
+}
+
+
+void vp8_encode_inter16x16uv(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+{
+    vp8_build_inter_predictors_mbuv(&x->e_mbd);
+
+    ENCODEMB_INVOKE(&rtcd->encodemb, submbuv)(x->src_diff, x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
+
+    vp8_transform_mbuv(x);
+
+    vp8_quantize_mbuv(x);
+
+    vp8_inverse_transform_mbuv(IF_RTCD(&rtcd->common->idct), &x->e_mbd);
+
+    vp8_recon_intra_mbuv(IF_RTCD(&rtcd->common->recon), &x->e_mbd);
+}
+
+
+void vp8_encode_inter16x16uvrd(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
+{
+    vp8_build_inter_predictors_mbuv(&x->e_mbd);
+    ENCODEMB_INVOKE(&rtcd->encodemb, submbuv)(x->src_diff, x->src.u_buffer, x->src.v_buffer, x->e_mbd.predictor, x->src.uv_stride);
+
+    vp8_transform_mbuvrd(x);
+
+    vp8_quantize_mbuvrd(x);
+
+}
diff --git a/vp8/encoder/encodemb.h b/vp8/encoder/encodemb.h
new file mode 100644
index 0000000..91ca8f5
--- /dev/null
+++ b/vp8/encoder/encodemb.h
@@ -0,0 +1,112 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_ENCODEMB_H
+#define __INC_ENCODEMB_H
+
+#include "vpx_ports/config.h"
+#include "block.h"
+
+#define prototype_mberr(sym) \
+    int (sym)(MACROBLOCK *mb, int dc)
+
+#define prototype_berr(sym) \
+    int (sym)(short *coeff, short *dqcoeff)
+
+#define prototype_mbuverr(sym) \
+    int (sym)(MACROBLOCK *mb)
+
+#define prototype_subb(sym) \
+    void (sym)(BLOCK *be,BLOCKD *bd, int pitch)
+
+#define prototype_submby(sym) \
+    void (sym)(short *diff, unsigned char *src, unsigned char *pred, int stride)
+
+#define prototype_submbuv(sym) \
+    void (sym)(short *diff, unsigned char *usrc, unsigned char *vsrc,\
+               unsigned char *pred, int stride)
+
+#if ARCH_X86 || ARCH_X86_64
+#include "x86/encodemb_x86.h"
+#endif
+
+#if ARCH_ARM
+#include "arm/encodemb_arm.h"
+#endif
+
+#ifndef vp8_encodemb_berr
+#define vp8_encodemb_berr vp8_block_error_c
+#endif
+extern prototype_berr(vp8_encodemb_berr);
+
+#ifndef vp8_encodemb_mberr
+#define vp8_encodemb_mberr vp8_mbblock_error_c
+#endif
+extern prototype_mberr(vp8_encodemb_mberr);
+
+#ifndef vp8_encodemb_mbuverr
+#define vp8_encodemb_mbuverr vp8_mbuverror_c
+#endif
+extern prototype_mbuverr(vp8_encodemb_mbuverr);
+
+#ifndef vp8_encodemb_subb
+#define vp8_encodemb_subb vp8_subtract_b_c
+#endif
+extern prototype_subb(vp8_encodemb_subb);
+
+#ifndef vp8_encodemb_submby
+#define vp8_encodemb_submby vp8_subtract_mby_c
+#endif
+extern prototype_submby(vp8_encodemb_submby);
+
+#ifndef vp8_encodemb_submbuv
+#define vp8_encodemb_submbuv vp8_subtract_mbuv_c
+#endif
+extern prototype_submbuv(vp8_encodemb_submbuv);
+
+
+typedef struct
+{
+    prototype_berr(*berr);
+    prototype_mberr(*mberr);
+    prototype_mbuverr(*mbuverr);
+    prototype_subb(*subb);
+    prototype_submby(*submby);
+    prototype_submbuv(*submbuv);
+} vp8_encodemb_rtcd_vtable_t;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define ENCODEMB_INVOKE(ctx,fn) (ctx)->fn
+#else
+#define ENCODEMB_INVOKE(ctx,fn) vp8_encodemb_##fn
+#endif
+
+
+
+#include "onyx_int.h"
+struct VP8_ENCODER_RTCD;
+void vp8_encode_inter16x16(const struct VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x);
+
+extern void vp8_stuff_inter16x16(MACROBLOCK *x);
+
+void vp8_build_dcblock(MACROBLOCK *b);
+void vp8_transform_mb(MACROBLOCK *mb);
+void vp8_transform_mbuv(MACROBLOCK *x);
+void vp8_transform_mbuvrd(MACROBLOCK *x);
+void vp8_transform_intra_mby(MACROBLOCK *x);
+void vp8_transform_intra_mbyrd(MACROBLOCK *x);
+void Encode16x16Y(MACROBLOCK *x);
+void Encode16x16UV(MACROBLOCK *x);
+void vp8_encode_inter16x16uv(const struct VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x);
+void vp8_encode_inter16x16uvrd(const struct VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x);
+void vp8_optimize_mby(MACROBLOCK *x, const struct VP8_ENCODER_RTCD *rtcd);
+void vp8_optimize_mbuv(MACROBLOCK *x, const struct VP8_ENCODER_RTCD *rtcd);
+void vp8_encode_inter16x16y(const struct VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x);
+#endif
diff --git a/vp8/encoder/encodemv.c b/vp8/encoder/encodemv.c
new file mode 100644
index 0000000..f287edc
--- /dev/null
+++ b/vp8/encoder/encodemv.c
@@ -0,0 +1,445 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "common.h"
+#include "encodemv.h"
+#include "entropymode.h"
+#include "systemdependent.h"
+
+#include <math.h>
+
+#ifdef ENTROPY_STATS
+extern unsigned int active_section;
+#endif
+
+static void encode_mvcomponent(
+    vp8_writer *const w,
+    const int v,
+    const struct mv_context *mvc
+)
+{
+    const vp8_prob *p = mvc->prob;
+    const int x = v < 0 ? -v : v;
+
+    if (x < mvnum_short)     // Small
+    {
+        vp8_write(w, 0, p [mvpis_short]);
+        vp8_treed_write(w, vp8_small_mvtree, p + MVPshort, x, 3);
+
+        if (!x)
+            return;         // no sign bit
+    }
+    else                    // Large
+    {
+        int i = 0;
+
+        vp8_write(w, 1, p [mvpis_short]);
+
+        do
+            vp8_write(w, (x >> i) & 1, p [MVPbits + i]);
+
+        while (++i < 3);
+
+        i = mvlong_width - 1;  /* Skip bit 3, which is sometimes implicit */
+
+        do
+            vp8_write(w, (x >> i) & 1, p [MVPbits + i]);
+
+        while (--i > 3);
+
+        if (x & 0xFFF0)
+            vp8_write(w, (x >> 3) & 1, p [MVPbits + 3]);
+    }
+
+    vp8_write(w, v < 0, p [MVPsign]);
+}
+#if 0
+static int max_mv_r = 0;
+static int max_mv_c = 0;
+#endif
+void vp8_encode_motion_vector(vp8_writer *w, const MV *mv, const MV_CONTEXT *mvc)
+{
+
+#if 0
+    {
+        if (abs(mv->row >> 1) > max_mv_r)
+        {
+            FILE *f = fopen("maxmv.stt", "a");
+            max_mv_r = abs(mv->row >> 1);
+            fprintf(f, "New Mv Row Max %6d\n", (mv->row >> 1));
+
+            if ((abs(mv->row) / 2) != max_mv_r)
+                fprintf(f, "MV Row conversion error %6d\n", abs(mv->row) / 2);
+
+            fclose(f);
+        }
+
+        if (abs(mv->col >> 1) > max_mv_c)
+        {
+            FILE *f = fopen("maxmv.stt", "a");
+            fprintf(f, "New Mv Col Max %6d\n", (mv->col >> 1));
+            max_mv_c = abs(mv->col >> 1);
+            fclose(f);
+        }
+    }
+#endif
+
+    encode_mvcomponent(w, mv->row >> 1, &mvc[0]);
+    encode_mvcomponent(w, mv->col >> 1, &mvc[1]);
+}
+
+
+static unsigned int cost_mvcomponent(const int v, const struct mv_context *mvc)
+{
+    const vp8_prob *p = mvc->prob;
+    const int x = v;   //v<0? -v:v;
+    unsigned int cost;
+
+    if (x < mvnum_short)
+    {
+        cost = vp8_cost_zero(p [mvpis_short])
+               + vp8_treed_cost(vp8_small_mvtree, p + MVPshort, x, 3);
+
+        if (!x)
+            return cost;
+    }
+    else
+    {
+        int i = 0;
+        cost = vp8_cost_one(p [mvpis_short]);
+
+        do
+            cost += vp8_cost_bit(p [MVPbits + i], (x >> i) & 1);
+
+        while (++i < 3);
+
+        i = mvlong_width - 1;  /* Skip bit 3, which is sometimes implicit */
+
+        do
+            cost += vp8_cost_bit(p [MVPbits + i], (x >> i) & 1);
+
+        while (--i > 3);
+
+        if (x & 240)
+            cost += vp8_cost_bit(p [MVPbits + 3], (x >> 3) & 1);
+    }
+
+    return cost;   // + vp8_cost_bit( p [MVPsign], v < 0);
+}
+//#define M_LOG2_E 0.693147180559945309417
+//#define log2f(x) (log (x) / (float) M_LOG2_E)
+
+void vp8_build_component_cost_table(int *mvcost[2], int *mvsadcost[2], const MV_CONTEXT *mvc, int mvc_flag[2])
+{
+    int i = 1;   //-mv_max;
+    unsigned int cost0 = 0;
+    unsigned int cost1 = 0;
+
+    vp8_clear_system_state();
+#if 0
+    mvsadcost [0] [0] = 300;
+    mvsadcost [1] [0] = 300;
+
+    do
+    {
+        double z = 256 * (2 * (log2f(2 * i) + .6));
+        mvsadcost [0][i] = (int) z;
+        mvsadcost [1][i] = (int) z;
+        mvsadcost [0][-i] = (int) z;
+        mvsadcost [1][-i] = (int) z;
+    }
+    while (++i <= mv_max);
+
+#endif
+
+    i = 1;
+
+    if (mvc_flag[0])
+    {
+        mvcost [0] [0] = cost_mvcomponent(0, &mvc[0]);
+
+        do
+        {
+            //mvcost [0] [i] = cost_mvcomponent( i, &mvc[0]);
+            cost0 = cost_mvcomponent(i, &mvc[0]);
+
+            mvcost [0] [i] = cost0 + vp8_cost_zero(mvc[0].prob[MVPsign]);
+            mvcost [0] [-i] = cost0 + vp8_cost_one(mvc[0].prob[MVPsign]);
+        }
+        while (++i <= mv_max);
+    }
+
+    i = 1;
+
+    if (mvc_flag[1])
+    {
+        mvcost [1] [0] = cost_mvcomponent(0, &mvc[1]);
+
+        do
+        {
+            //mvcost [1] [i] = cost_mvcomponent( i, mvc[1]);
+            cost1 = cost_mvcomponent(i, &mvc[1]);
+
+            mvcost [1] [i] = cost1 + vp8_cost_zero(mvc[1].prob[MVPsign]);
+            mvcost [1] [-i] = cost1 + vp8_cost_one(mvc[1].prob[MVPsign]);
+        }
+        while (++i <= mv_max);
+    }
+
+    /*
+        i=-mv_max;
+        do
+        {
+            mvcost [0] [i] = cost_mvcomponent( i, mvc[0]);
+            mvcost [1] [i] = cost_mvcomponent( i, mvc[1]);
+        }
+        while( ++i <= mv_max);
+    */
+}
+
+
+// Motion vector probability table update depends on benefit.
+// Small correction allows for the fact that an update to an MV probability
+// may have benefit in subsequent frames as well as the current one.
+
+#define MV_PROB_UPDATE_CORRECTION   -1
+
+
+__inline static void calc_prob(vp8_prob *p, const unsigned int ct[2])
+{
+    const unsigned int tot = ct[0] + ct[1];
+
+    if (tot)
+    {
+        const vp8_prob x = ((ct[0] * 255) / tot) & -2;
+        *p = x ? x : 1;
+    }
+}
+
+static void update(
+    vp8_writer *const w,
+    const unsigned int ct[2],
+    vp8_prob *const cur_p,
+    const vp8_prob new_p,
+    const vp8_prob update_p,
+    int *updated
+)
+{
+    const int cur_b = vp8_cost_branch(ct, *cur_p);
+    const int new_b = vp8_cost_branch(ct, new_p);
+    const int cost = 7 + MV_PROB_UPDATE_CORRECTION + ((vp8_cost_one(update_p) - vp8_cost_zero(update_p) + 128) >> 8);
+
+    if (cur_b - new_b > cost)
+    {
+        *cur_p = new_p;
+        vp8_write(w, 1, update_p);
+        vp8_write_literal(w, new_p >> 1, 7);
+        *updated = 1;
+
+    }
+    else
+        vp8_write(w, 0, update_p);
+}
+
+static void write_component_probs(
+    vp8_writer *const w,
+    struct mv_context *cur_mvc,
+    const struct mv_context *default_mvc_,
+    const struct mv_context *update_mvc,       
+    const unsigned int events [MVvals],
+    unsigned int rc,
+    int *updated
+)
+{
+    vp8_prob *Pcur = cur_mvc->prob;
+    const vp8_prob *default_mvc = default_mvc_->prob;
+    const vp8_prob *Pupdate = update_mvc->prob;
+    unsigned int is_short_ct[2], sign_ct[2];
+
+    unsigned int bit_ct [mvlong_width] [2];
+
+    unsigned int short_ct  [mvnum_short];
+    unsigned int short_bct [mvnum_short-1] [2];
+
+    vp8_prob Pnew [MVPcount];
+
+    (void) rc;
+    vp8_copy_array(Pnew, default_mvc, MVPcount);
+
+    vp8_zero(is_short_ct)
+    vp8_zero(sign_ct)
+    vp8_zero(bit_ct)
+    vp8_zero(short_ct)
+    vp8_zero(short_bct)
+
+
+    //j=0
+    {
+        int j = 0;
+
+        const int c = events [mv_max];
+
+        is_short_ct [0] += c;     // Short vector
+        short_ct [0] += c;       // Magnitude distribution
+    }
+
+    //j: 1 ~ mv_max (1023)
+    {
+        int j = 1;
+
+        do
+        {
+            const int c1 = events [mv_max + j];  //positive
+            const int c2 = events [mv_max - j];  //negative
+            const int c  = c1 + c2;
+            int a = j;
+
+            sign_ct [0] += c1;
+            sign_ct [1] += c2;
+
+            if (a < mvnum_short)
+            {
+                is_short_ct [0] += c;     // Short vector
+                short_ct [a] += c;       // Magnitude distribution
+            }
+            else
+            {
+                int k = mvlong_width - 1;
+                is_short_ct [1] += c;     // Long vector
+
+                /*  bit 3 not always encoded. */
+                do
+                    bit_ct [k] [(a >> k) & 1] += c;
+
+                while (--k >= 0);
+            }
+        }
+        while (++j <= mv_max);
+    }
+
+    /*
+    {
+        int j = -mv_max;
+        do
+        {
+
+            const int c = events [mv_max + j];
+            int a = j;
+
+            if( j < 0)
+            {
+                sign_ct [1] += c;
+                a = -j;
+            }
+            else if( j)
+                sign_ct [0] += c;
+
+            if( a < mvnum_short)
+            {
+                is_short_ct [0] += c;     // Short vector
+                short_ct [a] += c;       // Magnitude distribution
+            }
+            else
+            {
+                int k = mvlong_width - 1;
+                is_short_ct [1] += c;     // Long vector
+
+                //  bit 3 not always encoded.
+
+                do
+                    bit_ct [k] [(a >> k) & 1] += c;
+                while( --k >= 0);
+            }
+        } while( ++j <= mv_max);
+    }
+    */
+
+    calc_prob(Pnew + mvpis_short, is_short_ct);
+
+    calc_prob(Pnew + MVPsign, sign_ct);
+
+    {
+        vp8_prob p [mvnum_short - 1];    /* actually only need branch ct */
+        int j = 0;
+
+        vp8_tree_probs_from_distribution(
+            8, vp8_small_mvencodings, vp8_small_mvtree,
+            p, short_bct, short_ct,
+            256, 1
+        );
+
+        do
+            calc_prob(Pnew + MVPshort + j, short_bct[j]);
+
+        while (++j < mvnum_short - 1);
+    }
+
+    {
+        int j = 0;
+
+        do
+            calc_prob(Pnew + MVPbits + j, bit_ct[j]);
+
+        while (++j < mvlong_width);
+    }
+
+    update(w, is_short_ct, Pcur + mvpis_short, Pnew[mvpis_short], *Pupdate++, updated);
+
+    update(w, sign_ct, Pcur + MVPsign, Pnew[MVPsign], *Pupdate++, updated);
+
+    {
+        const vp8_prob *const new_p = Pnew + MVPshort;
+        vp8_prob *const cur_p = Pcur + MVPshort;
+
+        int j = 0;
+
+        do
+
+            update(w, short_bct[j], cur_p + j, new_p[j], *Pupdate++, updated);
+
+        while (++j < mvnum_short - 1);
+    }
+
+    {
+        const vp8_prob *const new_p = Pnew + MVPbits;
+        vp8_prob *const cur_p = Pcur + MVPbits;
+
+        int j = 0;
+
+        do
+
+            update(w, bit_ct[j], cur_p + j, new_p[j], *Pupdate++, updated);
+
+        while (++j < mvlong_width);
+    }
+}
+
+void vp8_write_mvprobs(VP8_COMP *cpi)
+{
+    vp8_writer *const w  = & cpi->bc;
+    MV_CONTEXT *mvc = cpi->common.fc.mvc;
+    int flags[2] = {0, 0};
+#ifdef ENTROPY_STATS
+    active_section = 4;
+#endif
+    write_component_probs(
+        w, &mvc[0], &vp8_default_mv_context[0], &vp8_mv_update_probs[0], cpi->MVcount[0], 0, &flags[0]
+    );
+    write_component_probs(
+        w, &mvc[1], &vp8_default_mv_context[1], &vp8_mv_update_probs[1], cpi->MVcount[1], 1, &flags[1]
+    );
+
+    if (flags[0] || flags[1])
+        vp8_build_component_cost_table(cpi->mb.mvcost, cpi->mb.mvsadcost, (const MV_CONTEXT *) cpi->common.fc.mvc, flags);
+
+#ifdef ENTROPY_STATS
+    active_section = 5;
+#endif
+}
diff --git a/vp8/encoder/encodemv.h b/vp8/encoder/encodemv.h
new file mode 100644
index 0000000..1c1f450
--- /dev/null
+++ b/vp8/encoder/encodemv.h
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_ENCODEMV_H
+#define __INC_ENCODEMV_H
+
+#include "onyx_int.h"
+
+void vp8_write_mvprobs(VP8_COMP *);
+void vp8_encode_motion_vector(vp8_writer *, const MV *, const MV_CONTEXT *);
+void vp8_build_component_cost_table(int *mvcost[2], int *mvsadcost[2], const MV_CONTEXT *mvc, int mvc_flag[2]);
+
+#endif
diff --git a/vp8/encoder/ethreading.c b/vp8/encoder/ethreading.c
new file mode 100644
index 0000000..a0b50d2
--- /dev/null
+++ b/vp8/encoder/ethreading.c
@@ -0,0 +1,510 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "onyx_int.h"
+#include "threading.h"
+#include "common.h"
+#include "extend.h"
+
+
+extern int vp8cx_encode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t, int recon_yoffset, int recon_uvoffset);
+extern int vp8cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t);
+extern void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x);
+extern void vp8_build_block_offsets(MACROBLOCK *x);
+extern void vp8_setup_block_ptrs(MACROBLOCK *x);
+
+static
+THREAD_FUNCTION thread_encoding_proc(void *p_data)
+{
+#if CONFIG_MULTITHREAD
+    int ithread = ((ENCODETHREAD_DATA *)p_data)->ithread;
+    VP8_COMP *cpi   = (VP8_COMP *)(((ENCODETHREAD_DATA *)p_data)->ptr1);
+    MB_ROW_COMP *mbri = (MB_ROW_COMP *)(((ENCODETHREAD_DATA *)p_data)->ptr2);
+    ENTROPY_CONTEXT mb_row_left_context[4][4];
+
+    //printf("Started thread %d\n", ithread);
+
+    while (1)
+    {
+        if (cpi->b_multi_threaded == 0)
+            break;
+
+        //if(WaitForSingleObject(cpi->h_event_mbrencoding[ithread], INFINITE) == WAIT_OBJECT_0)
+        if (sem_wait(&cpi->h_event_mbrencoding[ithread]) == 0)
+        {
+            if (cpi->b_multi_threaded == FALSE) // we're shutting down
+                break;
+            else
+            {
+                VP8_COMMON *cm      = &cpi->common;
+                int mb_row           = mbri->mb_row;
+                MACROBLOCK  *x      = &mbri->mb;
+                MACROBLOCKD *xd     = &x->e_mbd;
+                TOKENEXTRA **tp     = &mbri->tp;
+                int *segment_counts  = mbri->segment_counts;
+                int *totalrate      = &mbri->totalrate;
+
+                {
+                    int i;
+                    int recon_yoffset, recon_uvoffset;
+                    int mb_col;
+                    int recon_y_stride = cm->last_frame.y_stride;
+                    int recon_uv_stride = cm->last_frame.uv_stride;
+                    volatile int *last_row_current_mb_col;
+
+                    if (ithread > 0)
+                        last_row_current_mb_col = &cpi->mb_row_ei[ithread-1].current_mb_col;
+                    else
+                        last_row_current_mb_col = &cpi->current_mb_col_main;
+
+                    // reset above block coeffs
+                    xd->above_context[Y1CONTEXT] = cm->above_context[Y1CONTEXT];
+                    xd->above_context[UCONTEXT ] = cm->above_context[UCONTEXT ];
+                    xd->above_context[VCONTEXT ] = cm->above_context[VCONTEXT ];
+                    xd->above_context[Y2CONTEXT] = cm->above_context[Y2CONTEXT];
+                    xd->left_context = mb_row_left_context;
+
+                    vp8_zero(mb_row_left_context);
+
+                    xd->up_available = (mb_row != 0);
+                    recon_yoffset = (mb_row * recon_y_stride * 16);
+                    recon_uvoffset = (mb_row * recon_uv_stride * 8);
+
+
+                    cpi->tplist[mb_row].start = *tp;
+
+                    //printf("Thread mb_row = %d\n", mb_row);
+
+                    // for each macroblock col in image
+                    for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+                    {
+                        int seg_map_index = (mb_row * cm->mb_cols);
+
+                        while (mb_col > (*last_row_current_mb_col - 1) && *last_row_current_mb_col != cm->mb_cols - 1)
+                        {
+                            x86_pause_hint();
+                            thread_sleep(0);
+                        }
+
+                        // Distance of Mb to the various image edges.
+                        // These specified to 8th pel as they are always compared to values that are in 1/8th pel units
+                        xd->mb_to_left_edge = -((mb_col * 16) << 3);
+                        xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3;
+                        xd->mb_to_top_edge = -((mb_row * 16) << 3);
+                        xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3;
+
+                        // Set up limit values for motion vectors used to prevent them extending outside the UMV borders
+                        x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16));
+                        x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + (VP8BORDERINPIXELS - 16);
+                        x->mv_row_min = -((mb_row * 16) + (VP8BORDERINPIXELS - 16));
+                        x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + (VP8BORDERINPIXELS - 16);
+
+                        xd->dst.y_buffer = cm->new_frame.y_buffer + recon_yoffset;
+                        xd->dst.u_buffer = cm->new_frame.u_buffer + recon_uvoffset;
+                        xd->dst.v_buffer = cm->new_frame.v_buffer + recon_uvoffset;
+                        xd->left_available = (mb_col != 0);
+
+                        // Is segmentation enabled
+                        // MB level adjutment to quantizer
+                        if (xd->segmentation_enabled)
+                        {
+                            // Code to set segment id in xd->mbmi.segment_id for current MB (with range checking)
+                            if (cpi->segmentation_map[seg_map_index+mb_col] <= 3)
+                                xd->mbmi.segment_id = cpi->segmentation_map[seg_map_index+mb_col];
+                            else
+                                xd->mbmi.segment_id = 0;
+
+                            vp8cx_mb_init_quantizer(cpi, x);
+                        }
+                        else
+                            xd->mbmi.segment_id = 0;         // Set to Segment 0 by default
+
+
+                        if (cm->frame_type == KEY_FRAME)
+                        {
+                            *totalrate += vp8cx_encode_intra_macro_block(cpi, x, tp);
+#ifdef MODE_STATS
+                            y_modes[xd->mbmi.mode] ++;
+#endif
+                        }
+                        else
+                        {
+                            *totalrate += vp8cx_encode_inter_macroblock(cpi, x, tp, recon_yoffset, recon_uvoffset);
+
+#ifdef MODE_STATS
+                            inter_y_modes[xd->mbmi.mode] ++;
+
+                            if (xd->mbmi.mode == SPLITMV)
+                            {
+                                int b;
+
+                                for (b = 0; b < xd->mbmi.partition_count; b++)
+                                {
+                                    inter_b_modes[xd->mbmi.partition_bmi[b].mode] ++;
+                                }
+                            }
+
+#endif
+
+                            // Count of last ref frame 0,0 useage
+                            if ((xd->mbmi.mode == ZEROMV) && (xd->mbmi.ref_frame == LAST_FRAME))
+                                cpi->inter_zz_count ++;
+
+                        }
+
+                        cpi->tplist[mb_row].stop = *tp;
+
+                        xd->gf_active_ptr++;      // Increment pointer into gf useage flags structure for next mb
+
+                        // store macroblock mode info into context array
+                        vpx_memcpy(&xd->mode_info_context->mbmi, &xd->mbmi, sizeof(xd->mbmi));
+
+                        for (i = 0; i < 16; i++)
+                            vpx_memcpy(&xd->mode_info_context->bmi[i], &xd->block[i].bmi, sizeof(xd->block[i].bmi));
+
+                        // adjust to the next column of macroblocks
+                        x->src.y_buffer += 16;
+                        x->src.u_buffer += 8;
+                        x->src.v_buffer += 8;
+
+                        recon_yoffset += 16;
+                        recon_uvoffset += 8;
+
+                        // Keep track of segment useage
+                        segment_counts[xd->mbmi.segment_id] ++;
+
+                        // skip to next mb
+                        xd->mode_info_context++;
+
+                        xd->above_context[Y1CONTEXT] += 4;
+                        xd->above_context[UCONTEXT ] += 2;
+                        xd->above_context[VCONTEXT ] += 2;
+                        xd->above_context[Y2CONTEXT] ++;
+
+                        cpi->mb_row_ei[ithread].current_mb_col = mb_col;
+
+                    }
+
+                    //extend the recon for intra prediction
+                    vp8_extend_mb_row(
+                        &cm->new_frame,
+                        xd->dst.y_buffer + 16,
+                        xd->dst.u_buffer + 8,
+                        xd->dst.v_buffer + 8);
+
+                    // this is to account for the border
+                    xd->mode_info_context++;
+
+                    x->src.y_buffer += 16 * x->src.y_stride * (cpi->encoding_thread_count + 1) - 16 * cm->mb_cols;
+                    x->src.u_buffer +=  8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
+                    x->src.v_buffer +=  8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
+
+                    xd->mode_info_context += xd->mode_info_stride * cpi->encoding_thread_count;
+
+                    if (ithread == (cpi->encoding_thread_count - 1) || mb_row == cm->mb_rows - 1)
+                    {
+                        //SetEvent(cpi->h_event_main);
+                        sem_post(&cpi->h_event_main);
+                    }
+
+                }
+
+            }
+        }
+    }
+
+#else
+    (void) p_data;
+#endif
+
+    //printf("exit thread %d\n", ithread);
+    return 0;
+}
+
+static void setup_mbby_copy(MACROBLOCK *mbdst, MACROBLOCK *mbsrc)
+{
+
+    MACROBLOCK *x = mbsrc;
+    MACROBLOCK *z = mbdst;
+    int i;
+
+    z->ss               = x->ss;
+    z->ss_count          = x->ss_count;
+    z->searches_per_step  = x->searches_per_step;
+    z->errorperbit      = x->errorperbit;
+
+    z->sadperbit16      = x->sadperbit16;
+    z->sadperbit4       = x->sadperbit4;
+    z->errthresh        = x->errthresh;
+    z->rddiv            = x->rddiv;
+    z->rdmult           = x->rdmult;
+
+    /*
+    z->mv_col_min    = x->mv_col_min;
+    z->mv_col_max    = x->mv_col_max;
+    z->mv_row_min    = x->mv_row_min;
+    z->mv_row_max    = x->mv_row_max;
+    z->vector_range = x->vector_range ;
+    */
+
+    z->vp8_short_fdct4x4     = x->vp8_short_fdct4x4;
+    z->vp8_short_fdct8x4     = x->vp8_short_fdct8x4;
+    z->short_fdct4x4rd   = x->short_fdct4x4rd;
+    z->short_fdct8x4rd   = x->short_fdct8x4rd;
+    z->short_fdct8x4rd   = x->short_fdct8x4rd;
+    z->vp8_short_fdct4x4_ptr = x->vp8_short_fdct4x4_ptr;
+    z->short_walsh4x4    = x->short_walsh4x4;
+    z->quantize_b        = x->quantize_b;
+    z->quantize_brd      = x->quantize_brd;
+
+    /*
+    z->mvc              = x->mvc;
+    z->src.y_buffer      = x->src.y_buffer;
+    z->src.u_buffer      = x->src.u_buffer;
+    z->src.v_buffer      = x->src.v_buffer;
+    */
+
+
+    vpx_memcpy(z->mvcosts,          x->mvcosts,         sizeof(x->mvcosts));
+    z->mvcost[0] = &z->mvcosts[0][mv_max+1];
+    z->mvcost[1] = &z->mvcosts[1][mv_max+1];
+    z->mvsadcost[0] = &z->mvsadcosts[0][mv_max+1];
+    z->mvsadcost[1] = &z->mvsadcosts[1][mv_max+1];
+
+
+    vpx_memcpy(z->token_costs,       x->token_costs,      sizeof(x->token_costs));
+    vpx_memcpy(z->inter_bmode_costs,  x->inter_bmode_costs, sizeof(x->inter_bmode_costs));
+    //memcpy(z->mvcosts,            x->mvcosts,         sizeof(x->mvcosts));
+    //memcpy(z->mvcost,         x->mvcost,          sizeof(x->mvcost));
+    vpx_memcpy(z->mbmode_cost,       x->mbmode_cost,      sizeof(x->mbmode_cost));
+    vpx_memcpy(z->intra_uv_mode_cost,  x->intra_uv_mode_cost, sizeof(x->intra_uv_mode_cost));
+    vpx_memcpy(z->bmode_costs,       x->bmode_costs,      sizeof(x->bmode_costs));
+
+    for (i = 0; i < 25; i++)
+    {
+        z->block[i].quant           = x->block[i].quant;
+        z->block[i].zbin            = x->block[i].zbin;
+        z->block[i].zrun_zbin_boost   = x->block[i].zrun_zbin_boost;
+        z->block[i].round           = x->block[i].round;
+        /*
+        z->block[i].src             = x->block[i].src;
+        */
+        z->block[i].src_stride       = x->block[i].src_stride;
+        z->block[i].force_empty      = x->block[i].force_empty;
+
+    }
+
+    {
+        MACROBLOCKD *xd = &x->e_mbd;
+        MACROBLOCKD *zd = &z->e_mbd;
+
+        /*
+        zd->mode_info_context = xd->mode_info_context;
+        zd->mode_info        = xd->mode_info;
+
+        zd->mode_info_stride  = xd->mode_info_stride;
+        zd->frame_type       = xd->frame_type;
+        zd->up_available     = xd->up_available   ;
+        zd->left_available   = xd->left_available;
+        zd->left_context     = xd->left_context;
+        zd->last_frame_dc     = xd->last_frame_dc;
+        zd->last_frame_dccons = xd->last_frame_dccons;
+        zd->gold_frame_dc     = xd->gold_frame_dc;
+        zd->gold_frame_dccons = xd->gold_frame_dccons;
+        zd->mb_to_left_edge    = xd->mb_to_left_edge;
+        zd->mb_to_right_edge   = xd->mb_to_right_edge;
+        zd->mb_to_top_edge     = xd->mb_to_top_edge   ;
+        zd->mb_to_bottom_edge  = xd->mb_to_bottom_edge;
+        zd->gf_active_ptr     = xd->gf_active_ptr;
+        zd->frames_since_golden       = xd->frames_since_golden;
+        zd->frames_till_alt_ref_frame   = xd->frames_till_alt_ref_frame;
+        */
+        zd->subpixel_predict         = xd->subpixel_predict;
+        zd->subpixel_predict8x4      = xd->subpixel_predict8x4;
+        zd->subpixel_predict8x8      = xd->subpixel_predict8x8;
+        zd->subpixel_predict16x16    = xd->subpixel_predict16x16;
+        zd->segmentation_enabled     = xd->segmentation_enabled;
+        zd->mb_segement_abs_delta      = xd->mb_segement_abs_delta;
+        vpx_memcpy(zd->segment_feature_data, xd->segment_feature_data, sizeof(xd->segment_feature_data));
+
+        /*
+        memcpy(zd->above_context,        xd->above_context, sizeof(xd->above_context));
+        memcpy(zd->mb_segment_tree_probs,  xd->mb_segment_tree_probs, sizeof(xd->mb_segment_tree_probs));
+        memcpy(zd->segment_feature_data,  xd->segment_feature_data, sizeof(xd->segment_feature_data));
+        */
+        for (i = 0; i < 25; i++)
+        {
+            zd->block[i].dequant = xd->block[i].dequant;
+        }
+    }
+}
+
+
+void vp8cx_init_mbrthread_data(VP8_COMP *cpi,
+                               MACROBLOCK *x,
+                               MB_ROW_COMP *mbr_ei,
+                               int mb_row,
+                               int count
+                              )
+{
+
+    VP8_COMMON *const cm = & cpi->common;
+    MACROBLOCKD *const xd = & x->e_mbd;
+    int i;
+    (void) mb_row;
+
+    for (i = 0; i < count; i++)
+    {
+        MACROBLOCK *mb = & mbr_ei[i].mb;
+        MACROBLOCKD *mbd = &mb->e_mbd;
+
+        mbd->subpixel_predict        = xd->subpixel_predict;
+        mbd->subpixel_predict8x4     = xd->subpixel_predict8x4;
+        mbd->subpixel_predict8x8     = xd->subpixel_predict8x8;
+        mbd->subpixel_predict16x16   = xd->subpixel_predict16x16;
+#if CONFIG_RUNTIME_CPU_DETECT
+        mbd->rtcd                   = xd->rtcd;
+#endif
+        mbd->gf_active_ptr            = xd->gf_active_ptr;
+
+        mb->vector_range             = 32;
+
+        vpx_memset(mbr_ei[i].segment_counts, 0, sizeof(mbr_ei[i].segment_counts));
+        mbr_ei[i].totalrate = 0;
+
+        mbd->mode_info        = cm->mi - 1;
+        mbd->mode_info_context = cm->mi   + x->e_mbd.mode_info_stride * (i + 1);
+        mbd->mode_info_stride  = cm->mode_info_stride;
+
+        mbd->frame_type = cm->frame_type;
+
+        mbd->frames_since_golden = cm->frames_since_golden;
+        mbd->frames_till_alt_ref_frame = cm->frames_till_alt_ref_frame;
+
+        mb->src = * cpi->Source;
+        mbd->pre = cm->last_frame;
+        mbd->dst = cm->new_frame;
+
+        mb->src.y_buffer += 16 * x->src.y_stride * (i + 1);
+        mb->src.u_buffer +=  8 * x->src.uv_stride * (i + 1);
+        mb->src.v_buffer +=  8 * x->src.uv_stride * (i + 1);
+
+
+        vp8_build_block_offsets(mb);
+
+        vp8_setup_block_dptrs(mbd);
+
+        vp8_setup_block_ptrs(mb);
+
+        mb->rddiv = cpi->RDDIV;
+        mb->rdmult = cpi->RDMULT;
+
+        mbd->mbmi.mode = DC_PRED;
+        mbd->mbmi.uv_mode = DC_PRED;
+
+        mbd->left_context = cm->left_context;
+        mb->mvc = cm->fc.mvc;
+
+        setup_mbby_copy(&mbr_ei[i].mb, x);
+
+    }
+}
+
+
+void vp8cx_create_encoder_threads(VP8_COMP *cpi)
+{
+    cpi->b_multi_threaded = 0;
+
+    cpi->processor_core_count = 32; //vp8_get_proc_core_count();
+
+    CHECK_MEM_ERROR(cpi->tplist, vpx_malloc(sizeof(TOKENLIST) * cpi->common.mb_rows));
+
+#if CONFIG_MULTITHREAD
+
+    if (cpi->processor_core_count > 1 && cpi->oxcf.multi_threaded > 1)
+    {
+        int ithread;
+
+        if (cpi->oxcf.multi_threaded > cpi->processor_core_count)
+            cpi->encoding_thread_count = cpi->processor_core_count - 1;
+        else
+            cpi->encoding_thread_count = cpi->oxcf.multi_threaded - 1;
+
+
+        CHECK_MEM_ERROR(cpi->h_encoding_thread, vpx_malloc(sizeof(pthread_t) * cpi->encoding_thread_count));
+        CHECK_MEM_ERROR(cpi->h_event_mbrencoding, vpx_malloc(sizeof(sem_t) * cpi->encoding_thread_count));
+        CHECK_MEM_ERROR(cpi->mb_row_ei, vpx_memalign(32, sizeof(MB_ROW_COMP) * cpi->encoding_thread_count));
+        vpx_memset(cpi->mb_row_ei, 0, sizeof(MB_ROW_COMP) * cpi->encoding_thread_count);
+        CHECK_MEM_ERROR(cpi->en_thread_data, vpx_malloc(sizeof(ENCODETHREAD_DATA) * cpi->encoding_thread_count));
+        //cpi->h_event_main = CreateEvent(NULL, FALSE, FALSE, NULL);
+        sem_init(&cpi->h_event_main, 0, 0);
+
+        cpi->b_multi_threaded = 1;
+
+        //printf("[VP8:] multi_threaded encoding is enabled with %d threads\n\n", (cpi->encoding_thread_count +1));
+
+        for (ithread = 0; ithread < cpi->encoding_thread_count; ithread++)
+        {
+            //cpi->h_event_mbrencoding[ithread] = CreateEvent(NULL, FALSE, FALSE, NULL);
+            sem_init(&cpi->h_event_mbrencoding[ithread], 0, 0);
+            cpi->en_thread_data[ithread].ithread = ithread;
+            cpi->en_thread_data[ithread].ptr1 = (void *)cpi;
+            cpi->en_thread_data[ithread].ptr2 = (void *)&cpi->mb_row_ei[ithread];
+
+            //printf(" call begin thread %d \n", ithread);
+
+            //cpi->h_encoding_thread[ithread] =   (HANDLE)_beginthreadex(
+            //  NULL,           // security
+            //  0,              // stksize
+            //  thread_encoding_proc,
+            //  (&cpi->en_thread_data[ithread]),          // Thread data
+            //  0,
+            //  NULL);
+
+            pthread_create(&cpi->h_encoding_thread[ithread], 0, thread_encoding_proc, (&cpi->en_thread_data[ithread]));
+
+        }
+
+    }
+
+#endif
+}
+
+void vp8cx_remove_encoder_threads(VP8_COMP *cpi)
+{
+#if CONFIG_MULTITHREAD
+
+    if (cpi->b_multi_threaded)
+    {
+        //shutdown other threads
+        cpi->b_multi_threaded = 0;
+        {
+            int i;
+
+            for (i = 0; i < cpi->encoding_thread_count; i++)
+            {
+                //SetEvent(cpi->h_event_mbrencoding[i]);
+                sem_post(&cpi->h_event_mbrencoding[i]);
+                pthread_join(cpi->h_encoding_thread[i], 0);
+            }
+
+            for (i = 0; i < cpi->encoding_thread_count; i++)
+                sem_destroy(&cpi->h_event_mbrencoding[i]);
+        }
+        //free thread related resources
+        vpx_free(cpi->h_event_mbrencoding);
+        vpx_free(cpi->h_encoding_thread);
+        vpx_free(cpi->mb_row_ei);
+        vpx_free(cpi->en_thread_data);
+    }
+
+#endif
+    vpx_free(cpi->tplist);
+}
diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c
new file mode 100644
index 0000000..c519080
--- /dev/null
+++ b/vp8/encoder/firstpass.c
@@ -0,0 +1,2512 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "math.h"
+#include "limits.h"
+#include "block.h"
+#include "onyx_int.h"
+#include "variance.h"
+#include "encodeintra.h"
+#include "setupintrarecon.h"
+#include "mcomp.h"
+#include "vpx_scale/vpxscale.h"
+#include "encodemb.h"
+#include "extend.h"
+#include "systemdependent.h"
+#include "vpx_scale/yv12extend.h"
+#include "vpx_mem/vpx_mem.h"
+#include "swapyv12buffer.h"
+#include <stdio.h>
+#include "rdopt.h"
+#include "quant_common.h"
+#include "encodemv.h"
+
+//#define OUTPUT_FPF 1
+//#define FIRSTPASS_MM 1
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define IF_RTCD(x) (x)
+#else
+#define IF_RTCD(x) NULL
+#endif
+
+extern void vp8_build_block_offsets(MACROBLOCK *x);
+extern void vp8_setup_block_ptrs(MACROBLOCK *x);
+extern void vp8cx_frame_init_quantizer(VP8_COMP *cpi);
+extern void vp8_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, MV *mv);
+extern void vp8_alloc_compressor_data(VP8_COMP *cpi);
+
+//#define GFQ_ADJUSTMENT (40 + ((15*Q)/10))
+//#define GFQ_ADJUSTMENT (80 + ((15*Q)/10))
+#define GFQ_ADJUSTMENT vp8_gf_boost_qadjustment[Q]
+extern int vp8_kf_boost_qadjustment[QINDEX_RANGE];
+
+extern const int vp8_gf_boost_qadjustment[QINDEX_RANGE];
+
+#define IIFACTOR   1.4
+#define IIKFACTOR1 1.40
+#define IIKFACTOR2 1.5
+#define RMAX    14.0
+#define GF_RMAX 48.0        // 128.0
+
+#define DOUBLE_DIVIDE_CHECK(X) ((X)<0?(X)-.000001:(X)+.000001)
+
+#define POW1 (double)cpi->oxcf.two_pass_vbrbias/100.0
+#define POW2 (double)cpi->oxcf.two_pass_vbrbias/100.0
+
+static int vscale_lookup[7] = {0, 1, 1, 2, 2, 3, 3};
+static int hscale_lookup[7] = {0, 0, 1, 1, 2, 2, 3};
+
+
+void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame);
+int vp8_input_stats(VP8_COMP *cpi, FIRSTPASS_STATS *fps);
+
+int vp8_encode_intra(VP8_COMP *cpi, MACROBLOCK *x, int use_dc_pred)
+{
+
+    int i;
+    int intra_pred_var = 0;
+    (void) cpi;
+
+    if (use_dc_pred)
+    {
+        x->e_mbd.mbmi.mode = DC_PRED;
+        x->e_mbd.mbmi.uv_mode = DC_PRED;
+        x->e_mbd.mbmi.ref_frame = INTRA_FRAME;
+
+        vp8_encode_intra16x16mby(IF_RTCD(&cpi->rtcd), x);
+    }
+    else
+    {
+        for (i = 0; i < 16; i++)
+        {
+            BLOCKD *b = &x->e_mbd.block[i];
+            BLOCK  *be = &x->block[i];
+
+            vp8_encode_intra4x4block(IF_RTCD(&cpi->rtcd), x, be, b, B_DC_PRED);
+        }
+    }
+
+    intra_pred_var = VARIANCE_INVOKE(&cpi->rtcd.variance, getmbss)(x->src_diff);
+
+    return intra_pred_var;
+}
+
+// Resets the first pass file to the given position using a relative seek from the current position
+static void reset_fpf_position(VP8_COMP *cpi, FIRSTPASS_STATS *Position)
+{
+    cpi->stats_in = Position;
+}
+
+static int lookup_next_frame_stats(VP8_COMP *cpi, FIRSTPASS_STATS *next_frame)
+{
+    /*FIRSTPASS_STATS * start_pos;
+    int ret_val;
+
+    start_pos = cpi->stats_in;
+    ret_val = vp8_input_stats(cpi, next_frame);
+    reset_fpf_position(cpi, start_pos);
+
+    return ret_val;*/
+
+    if (cpi->stats_in >= cpi->stats_in_end)
+        return EOF;
+
+    *next_frame = *cpi->stats_in;
+    return 1;
+}
+
+// Calculate a modified Error used in distributing bits between easier and harder frames
+static double calculate_modified_err(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
+{
+    double av_err = cpi->total_stats.ssim_weighted_pred_err;
+    double this_err = this_frame->ssim_weighted_pred_err;
+    double modified_err;
+
+    //double relative_next_iiratio;
+    //double next_iiratio;
+    //double sum_iiratio;
+    //int i;
+
+    //FIRSTPASS_STATS next_frame;
+    //FIRSTPASS_STATS *start_pos;
+
+    /*start_pos = cpi->stats_in;
+    sum_iiratio = 0.0;
+    i = 0;
+    while ( (i < 1) && vp8_input_stats(cpi,&next_frame) != EOF )
+    {
+
+        next_iiratio = next_frame.intra_error / DOUBLE_DIVIDE_CHECK(next_frame.coded_error);
+        next_iiratio = ( next_iiratio < 1.0 ) ? 1.0 : (next_iiratio > 20.0) ? 20.0 : next_iiratio;
+        sum_iiratio += next_iiratio;
+        i++;
+    }
+    if ( i > 0 )
+    {
+        relative_next_iiratio = sum_iiratio / DOUBLE_DIVIDE_CHECK(cpi->avg_iiratio * (double)i);
+    }
+    else
+    {
+        relative_next_iiratio = 1.0;
+    }
+    reset_fpf_position(cpi, start_pos);*/
+
+    if (this_err > av_err)
+        modified_err = av_err * pow((this_err / DOUBLE_DIVIDE_CHECK(av_err)), POW1);
+    else
+        modified_err = av_err * pow((this_err / DOUBLE_DIVIDE_CHECK(av_err)), POW2);
+
+    /*
+    relative_next_iiratio = pow(relative_next_iiratio,0.25);
+    modified_err = modified_err * relative_next_iiratio;
+    */
+
+    return modified_err;
+}
+
+double vp8_simple_weight(YV12_BUFFER_CONFIG *source)
+{
+    int i, j;
+    int Total = 0;
+
+    unsigned char *src = source->y_buffer;
+    unsigned char value;
+    double sum_weights = 0.0;
+    double Weight;
+
+    // Loop throught the Y plane raw examining levels and creating a weight for the image
+    for (i = 0; i < source->y_height; i++)
+    {
+        for (j = 0; j < source->y_width; j++)
+        {
+            value = src[j];
+
+            if (value >= 64)
+                Weight = 1.0;
+            else if (value > 32)
+                Weight = (value - 32.0f) / 32.0f;
+            else
+                Weight = 0.02;
+
+            sum_weights += Weight;
+        }
+
+        src += source->y_stride;
+    }
+
+    sum_weights /= (source->y_height * source->y_width);
+
+    return sum_weights;
+}
+
+// This function returns the current per frame maximum bitrate target
+int frame_max_bits(VP8_COMP *cpi)
+{
+    // Max allocation for a single frame based on the max section guidelines passed in and how many bits are left
+    int max_bits;
+
+    // For CBR we need to also consider buffer fullness.
+    // If we are running below the optimal level then we need to gradually tighten up on max_bits.
+    if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+    {
+        double buffer_fullness_ratio = (double)DOUBLE_DIVIDE_CHECK(cpi->buffer_level) / (double)cpi->oxcf.optimal_buffer_level;
+
+        // For CBR base this on the target average bits per frame plus the maximum sedction rate passed in by the user
+        max_bits = (int)(cpi->av_per_frame_bandwidth * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
+
+        // If our buffer is below the optimum level
+        if (buffer_fullness_ratio < 1.0)
+        {
+            // The lower of max_bits / 4 or cpi->av_per_frame_bandwidth / 4.
+            int min_max_bits = ((cpi->av_per_frame_bandwidth >> 2) < (max_bits >> 2)) ? cpi->av_per_frame_bandwidth >> 2 : max_bits >> 2;
+
+            max_bits = (int)(max_bits * buffer_fullness_ratio);
+
+            if (max_bits < min_max_bits)
+                max_bits = min_max_bits;       // Lowest value we will set ... which should allow the buffer to refil.
+        }
+    }
+    // VBR
+    else
+    {
+        // For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user
+        max_bits = (int)(((double)cpi->bits_left / (cpi->total_stats.count - (double)cpi->common.current_video_frame)) * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
+    }
+
+    // Trap case where we are out of bits
+    if (max_bits < 0)
+        max_bits = 0;
+
+    return max_bits;
+}
+
+void vp8_output_stats(struct vpx_codec_pkt_list *pktlist,
+                      FIRSTPASS_STATS            *stats)
+{
+    struct vpx_codec_cx_pkt pkt;
+    pkt.kind = VPX_CODEC_STATS_PKT;
+    pkt.data.twopass_stats.buf = stats;
+    pkt.data.twopass_stats.sz = sizeof(*stats);
+    vpx_codec_pkt_list_add(pktlist, &pkt);
+
+// TEMP debug code
+#ifdef OUTPUT_FPF
+    {
+        FILE *fpfile;
+        fpfile = fopen("firstpass.stt", "a");
+
+        fprintf(fpfile, "%12.0f %12.0f %12.0f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.0f\n",
+                stats->frame,
+                stats->intra_error,
+                stats->coded_error,
+                stats->ssim_weighted_pred_err,
+                stats->pcnt_inter,
+                stats->pcnt_motion,
+                stats->pcnt_second_ref,
+                stats->MVr,
+                stats->mvr_abs,
+                stats->MVc,
+                stats->mvc_abs,
+                stats->MVrv,
+                stats->MVcv,
+                stats->mv_in_out_count,
+                stats->count);
+        fclose(fpfile);
+    }
+#endif
+}
+
+int vp8_input_stats(VP8_COMP *cpi, FIRSTPASS_STATS *fps)
+{
+    if (cpi->stats_in >= cpi->stats_in_end)
+        return EOF;
+
+    *fps = *cpi->stats_in++;
+    return 1;
+}
+
+void vp8_zero_stats(FIRSTPASS_STATS *section)
+{
+    section->frame      = 0.0;
+    section->intra_error = 0.0;
+    section->coded_error = 0.0;
+    section->ssim_weighted_pred_err = 0.0;
+    section->pcnt_inter  = 0.0;
+    section->pcnt_motion  = 0.0;
+    section->pcnt_second_ref = 0.0;
+    section->MVr        = 0.0;
+    section->mvr_abs     = 0.0;
+    section->MVc        = 0.0;
+    section->mvc_abs     = 0.0;
+    section->MVrv       = 0.0;
+    section->MVcv       = 0.0;
+    section->mv_in_out_count  = 0.0;
+    section->count      = 0.0;
+    section->duration   = 1.0;
+}
+void vp8_accumulate_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame)
+{
+    section->frame += frame->frame;
+    section->intra_error += frame->intra_error;
+    section->coded_error += frame->coded_error;
+    section->ssim_weighted_pred_err += frame->ssim_weighted_pred_err;
+    section->pcnt_inter  += frame->pcnt_inter;
+    section->pcnt_motion += frame->pcnt_motion;
+    section->pcnt_second_ref += frame->pcnt_second_ref;
+    section->MVr        += frame->MVr;
+    section->mvr_abs     += frame->mvr_abs;
+    section->MVc        += frame->MVc;
+    section->mvc_abs     += frame->mvc_abs;
+    section->MVrv       += frame->MVrv;
+    section->MVcv       += frame->MVcv;
+    section->mv_in_out_count  += frame->mv_in_out_count;
+    section->count      += frame->count;
+    section->duration   += frame->duration;
+}
+void vp8_avg_stats(FIRSTPASS_STATS *section)
+{
+    if (section->count < 1.0)
+        return;
+
+    section->intra_error /= section->count;
+    section->coded_error /= section->count;
+    section->ssim_weighted_pred_err /= section->count;
+    section->pcnt_inter  /= section->count;
+    section->pcnt_second_ref /= section->count;
+    section->pcnt_motion /= section->count;
+    section->MVr        /= section->count;
+    section->mvr_abs     /= section->count;
+    section->MVc        /= section->count;
+    section->mvc_abs     /= section->count;
+    section->MVrv       /= section->count;
+    section->MVcv       /= section->count;
+    section->mv_in_out_count   /= section->count;
+    section->duration   /= section->count;
+}
+
+int vp8_fpmm_get_pos(VP8_COMP *cpi)
+{
+    return ftell(cpi->fp_motion_mapfile);
+}
+void vp8_fpmm_reset_pos(VP8_COMP *cpi, int target_pos)
+{
+    int Offset;
+
+    if (cpi->fp_motion_mapfile)
+    {
+        Offset = ftell(cpi->fp_motion_mapfile) - target_pos;
+        fseek(cpi->fp_motion_mapfile, (int) - Offset, SEEK_CUR);
+    }
+}
+
+void vp8_advance_fpmm(VP8_COMP *cpi, int count)
+{
+#ifdef FIRSTPASS_MM
+    fseek(cpi->fp_motion_mapfile, (int)(count * cpi->common.MBs), SEEK_CUR);
+#endif
+}
+
+void vp8_input_fpmm(VP8_COMP *cpi, int count)
+{
+#ifdef FIRSTPASS_MM
+
+    unsigned char *tmp_motion_map;
+    int i, j;
+
+    if (!cpi->fp_motion_mapfile)
+        return;                 // Error
+
+    // Create the first pass motion map structure and set to 0
+    CHECK_MEM_ERROR(tmp_motion_map, vpx_calloc(cpi->common.MBs, 1));
+
+    // Reset the state of the global map
+    vpx_memset(cpi->fp_motion_map, 0, cpi->common.MBs);
+
+    // Read the specified number of frame maps and set the global map to the highest value seen for each mb.
+    for (i = 0; i < count; i++)
+    {
+        if (fread(tmp_motion_map, 1, cpi->common.MBs, cpi->fp_motion_mapfile) == cpi->common.MBs)
+        {
+            for (j = 0; j < cpi->common.MBs; j++)
+            {
+                if (tmp_motion_map[j] > 1)
+                    cpi->fp_motion_map[j] += 5;   // Intra is flagged
+                else
+                    cpi->fp_motion_map[j] += tmp_motion_map[j];
+            }
+        }
+        else
+            break;  // Read error
+
+    }
+
+    if (tmp_motion_map != 0)
+        vpx_free(tmp_motion_map);
+
+#endif
+
+}
+
+void vp8_init_first_pass(VP8_COMP *cpi)
+{
+    vp8_zero_stats(&cpi->total_stats);
+
+#ifdef FIRSTPASS_MM
+    cpi->fp_motion_mapfile = fopen("fpmotionmap.stt", "wb");
+#endif
+
+// TEMP debug code
+#ifdef OUTPUT_FPF
+    {
+        FILE *fpfile;
+        fpfile = fopen("firstpass.stt", "w");
+        fclose(fpfile);
+    }
+#endif
+
+}
+
+void vp8_end_first_pass(VP8_COMP *cpi)
+{
+    vp8_output_stats(cpi->output_pkt_list, &cpi->total_stats);
+
+#ifdef FIRSTPASS_MM
+
+    if (cpi->fp_motion_mapfile)
+        fclose(cpi->fp_motion_mapfile);
+
+#endif
+
+}
+void vp8_zz_motion_search( VP8_COMP *cpi, MACROBLOCK * x, YV12_BUFFER_CONFIG * recon_buffer, int * best_motion_err, int recon_yoffset )
+{
+    MACROBLOCKD * const xd = & x->e_mbd;
+    BLOCK *b = &x->block[0];
+    BLOCKD *d = &x->e_mbd.block[0];
+
+    unsigned char *src_ptr = (*(b->base_src) + b->src);
+    int src_stride = b->src_stride;
+    unsigned char *ref_ptr;
+    int ref_stride=d->pre_stride;
+
+    // Set up pointers for this macro block recon buffer
+    xd->pre.y_buffer = recon_buffer->y_buffer + recon_yoffset;
+
+    ref_ptr = (unsigned char *)(*(d->base_pre) + d->pre );
+
+    VARIANCE_INVOKE(IF_RTCD(&cpi->rtcd.variance), mse16x16) ( src_ptr, src_stride, ref_ptr, ref_stride, (unsigned int *)(best_motion_err));
+}
+
+
+void vp8_first_pass_motion_search(VP8_COMP *cpi, MACROBLOCK *x, MV *ref_mv, MV *best_mv, YV12_BUFFER_CONFIG *recon_buffer, int *best_motion_err, int recon_yoffset )
+{
+    MACROBLOCKD *const xd = & x->e_mbd;
+    BLOCK *b = &x->block[0];
+    BLOCKD *d = &x->e_mbd.block[0];
+    int num00;
+
+    MV tmp_mv = {0, 0};
+
+    int tmp_err;
+    int step_param = 3;                                       //3;          // Dont search over full range for first pass
+    int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param; //3;
+    int n;
+    vp8_variance_fn_ptr_t v_fn_ptr;
+    int new_mv_mode_penalty = 256;
+
+    v_fn_ptr.vf    = VARIANCE_INVOKE(IF_RTCD(&cpi->rtcd.variance), mse16x16);
+    v_fn_ptr.sdf   = cpi->fn_ptr.sdf;
+    v_fn_ptr.sdx4df = cpi->fn_ptr.sdx4df;
+
+    // Set up pointers for this macro block recon buffer
+    xd->pre.y_buffer = recon_buffer->y_buffer + recon_yoffset;
+
+    // Initial step/diamond search centred on best mv
+    tmp_err = cpi->diamond_search_sad(x, b, d, ref_mv, &tmp_mv, step_param, x->errorperbit, &num00, &v_fn_ptr, x->mvsadcost, x->mvcost);
+    if ( tmp_err < INT_MAX-new_mv_mode_penalty )
+        tmp_err += new_mv_mode_penalty;
+
+    if (tmp_err < *best_motion_err)
+    {
+        *best_motion_err = tmp_err;
+        best_mv->row = tmp_mv.row;
+        best_mv->col = tmp_mv.col;
+    }
+
+    // Further step/diamond searches as necessary
+    n = num00;
+    num00 = 0;
+
+    while (n < further_steps)
+    {
+        n++;
+
+        if (num00)
+            num00--;
+        else
+        {
+            tmp_err = cpi->diamond_search_sad(x, b, d, ref_mv, &tmp_mv, step_param + n, x->errorperbit, &num00, &v_fn_ptr, x->mvsadcost, x->mvcost);
+            if ( tmp_err < INT_MAX-new_mv_mode_penalty )
+                tmp_err += new_mv_mode_penalty;
+
+            if (tmp_err < *best_motion_err)
+            {
+                *best_motion_err = tmp_err;
+                best_mv->row = tmp_mv.row;
+                best_mv->col = tmp_mv.col;
+            }
+        }
+    }
+}
+
+void vp8_first_pass(VP8_COMP *cpi)
+{
+    int mb_row, mb_col;
+    MACROBLOCK *const x = & cpi->mb;
+    VP8_COMMON *const cm = & cpi->common;
+    MACROBLOCKD *const xd = & x->e_mbd;
+
+    int col_blocks = 4 * cm->mb_cols;
+    int recon_yoffset, recon_uvoffset;
+    int recon_y_stride = cm->last_frame.y_stride;
+    int recon_uv_stride = cm->last_frame.uv_stride;
+    int intra_error = 0;
+    int coded_error = 0;
+
+    int sum_mvr = 0, sum_mvc = 0;
+    int sum_mvr_abs = 0, sum_mvc_abs = 0;
+    int sum_mvrs = 0, sum_mvcs = 0;
+    int mvcount = 0;
+    int intercount = 0;
+    int second_ref_count = 0;
+    int intrapenalty = 256;
+
+    int sum_in_vectors = 0;
+
+    MV best_ref_mv = {0, 0};
+    MV zero_ref_mv = {0, 0};
+
+    unsigned char *fp_motion_map_ptr = cpi->fp_motion_map;
+
+    vp8_clear_system_state();  //__asm emms;
+
+    x->src = * cpi->Source;
+    xd->pre = cm->last_frame;
+    xd->dst = cm->new_frame;
+
+    vp8_build_block_offsets(x);
+
+    vp8_setup_block_dptrs(&x->e_mbd);
+
+    vp8_setup_block_ptrs(x);
+
+    // set up frame new frame for intra coded blocks
+    vp8_setup_intra_recon(&cm->new_frame);
+    vp8cx_frame_init_quantizer(cpi);
+
+    // Initialise the MV cost table to the defaults
+    //if( cm->current_video_frame == 0)
+    //if ( 0 )
+    {
+        int flag[2] = {1, 1};
+        vp8_initialize_rd_consts(cpi, vp8_dc_quant(cm->base_qindex, cm->y1dc_delta_q));
+        vpx_memcpy(cm->fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context));
+        vp8_build_component_cost_table(cpi->mb.mvcost, cpi->mb.mvsadcost, (const MV_CONTEXT *) cm->fc.mvc, flag);
+    }
+
+    // for each macroblock row in image
+    for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
+    {
+        MV best_ref_mv = {0, 0};
+
+        // reset above block coeffs
+        xd->up_available = (mb_row != 0);
+        recon_yoffset = (mb_row * recon_y_stride * 16);
+        recon_uvoffset = (mb_row * recon_uv_stride * 8);
+
+        // for each macroblock col in image
+        for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
+        {
+            int this_error;
+            int gf_motion_error = INT_MAX;
+            int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
+
+            xd->dst.y_buffer = cm->new_frame.y_buffer + recon_yoffset;
+            xd->dst.u_buffer = cm->new_frame.u_buffer + recon_uvoffset;
+            xd->dst.v_buffer = cm->new_frame.v_buffer + recon_uvoffset;
+            xd->left_available = (mb_col != 0);
+
+            // do intra 16x16 prediction
+            this_error = vp8_encode_intra(cpi, x, use_dc_pred);
+
+            // "intrapenalty" below deals with situations where the intra and inter error scores are very low (eg a plain black frame)
+            // We do not have special cases in first pass for 0,0 and nearest etc so all inter modes carry an overhead cost estimate fot the mv.
+            // When the error score is very low this causes us to pick all or lots of INTRA modes and throw lots of key frames.
+            // This penalty adds a cost matching that of a 0,0 mv to the intra case.
+            this_error += intrapenalty;
+
+            // Cumulative intra error total
+            intra_error += this_error;
+
+            // Indicate default assumption of intra in the motion map
+            *fp_motion_map_ptr = 2;
+
+            // Set up limit values for motion vectors to prevent them extending outside the UMV borders
+            x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16));
+            x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + (VP8BORDERINPIXELS - 16);
+            x->mv_row_min = -((mb_row * 16) + (VP8BORDERINPIXELS - 16));
+            x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + (VP8BORDERINPIXELS - 16);
+
+            // Other than for the first frame do a motion search
+            if (cm->current_video_frame > 0)
+            {
+                BLOCK *b = &x->block[0];
+                BLOCKD *d = &x->e_mbd.block[0];
+                MV tmp_mv = {0, 0};
+                int tmp_err;
+                int motion_error = INT_MAX;
+
+                // Simple 0,0 motion with no mv overhead
+                vp8_zz_motion_search( cpi, x, &cm->last_frame, &motion_error, recon_yoffset );
+                d->bmi.mv.as_mv.row = 0;
+                d->bmi.mv.as_mv.col = 0;
+
+                // Test last reference frame using the previous best mv as the starting point (best reference) for the search
+                vp8_first_pass_motion_search(cpi, x, &best_ref_mv, &d->bmi.mv.as_mv, &cm->last_frame, &motion_error, recon_yoffset);
+
+                // If the current best reference mv is not centred on 0,0 then do a 0,0 based search as well
+                if ((best_ref_mv.col != 0) || (best_ref_mv.row != 0))
+                {
+                   tmp_err = INT_MAX;
+                   vp8_first_pass_motion_search(cpi, x, &zero_ref_mv, &tmp_mv, &cm->last_frame, &motion_error, recon_yoffset);
+
+                   if ( tmp_err < motion_error )
+                   {
+                        motion_error = tmp_err;
+                        d->bmi.mv.as_mv.row = tmp_mv.row;
+                        d->bmi.mv.as_mv.col = tmp_mv.col;
+                   }
+
+                }
+
+                // Experimental search in a second reference frame ((0,0) based only)
+                if (cm->current_video_frame > 1)
+                {
+                    vp8_first_pass_motion_search(cpi, x, &zero_ref_mv, &tmp_mv, &cm->golden_frame, &gf_motion_error, recon_yoffset);
+
+                    if ((gf_motion_error < motion_error) && (gf_motion_error < this_error))
+                    {
+                        second_ref_count++;
+                        //motion_error = gf_motion_error;
+                        //d->bmi.mv.as_mv.row = tmp_mv.row;
+                        //d->bmi.mv.as_mv.col = tmp_mv.col;
+                    }
+                    /*else
+                    {
+                        xd->pre.y_buffer = cm->last_frame.y_buffer + recon_yoffset;
+                        xd->pre.u_buffer = cm->last_frame.u_buffer + recon_uvoffset;
+                        xd->pre.v_buffer = cm->last_frame.v_buffer + recon_uvoffset;
+                    }*/
+
+
+                    // Reset to last frame as reference buffer
+                    xd->pre.y_buffer = cm->last_frame.y_buffer + recon_yoffset;
+                    xd->pre.u_buffer = cm->last_frame.u_buffer + recon_uvoffset;
+                    xd->pre.v_buffer = cm->last_frame.v_buffer + recon_uvoffset;
+                }
+
+                if (motion_error <= this_error)
+                {
+                    d->bmi.mv.as_mv.row <<= 3;
+                    d->bmi.mv.as_mv.col <<= 3;
+                    this_error = motion_error;
+                    vp8_set_mbmode_and_mvs(x, NEWMV, &d->bmi.mv.as_mv);
+                    vp8_encode_inter16x16y(IF_RTCD(&cpi->rtcd), x);
+                    sum_mvr += d->bmi.mv.as_mv.row;
+                    sum_mvr_abs += abs(d->bmi.mv.as_mv.row);
+                    sum_mvc += d->bmi.mv.as_mv.col;
+                    sum_mvc_abs += abs(d->bmi.mv.as_mv.col);
+                    sum_mvrs += d->bmi.mv.as_mv.row * d->bmi.mv.as_mv.row;
+                    sum_mvcs += d->bmi.mv.as_mv.col * d->bmi.mv.as_mv.col;
+                    intercount++;
+
+                    best_ref_mv.row = d->bmi.mv.as_mv.row;
+                    best_ref_mv.col = d->bmi.mv.as_mv.col;
+                    //best_ref_mv.row = 0;
+                    //best_ref_mv.col = 0;
+
+                    // Was the vector non-zero
+                    if (d->bmi.mv.as_mv.row || d->bmi.mv.as_mv.col)
+                    {
+                        mvcount++;
+
+                        *fp_motion_map_ptr = 1;
+
+                        // Does the Row vector point inwards or outwards
+                        if (mb_row < cm->mb_rows / 2)
+                        {
+                            if (d->bmi.mv.as_mv.row > 0)
+                                sum_in_vectors--;
+                            else if (d->bmi.mv.as_mv.row < 0)
+                                sum_in_vectors++;
+                        }
+                        else if (mb_row > cm->mb_rows / 2)
+                        {
+                            if (d->bmi.mv.as_mv.row > 0)
+                                sum_in_vectors++;
+                            else if (d->bmi.mv.as_mv.row < 0)
+                                sum_in_vectors--;
+                        }
+
+                        // Does the Row vector point inwards or outwards
+                        if (mb_col < cm->mb_cols / 2)
+                        {
+                            if (d->bmi.mv.as_mv.col > 0)
+                                sum_in_vectors--;
+                            else if (d->bmi.mv.as_mv.col < 0)
+                                sum_in_vectors++;
+                        }
+                        else if (mb_col > cm->mb_cols / 2)
+                        {
+                            if (d->bmi.mv.as_mv.col > 0)
+                                sum_in_vectors++;
+                            else if (d->bmi.mv.as_mv.col < 0)
+                                sum_in_vectors--;
+                        }
+                    }
+                    else
+                        *fp_motion_map_ptr = 0;    // 0,0 mv was best
+                }
+                else
+                {
+                    best_ref_mv.row = 0;
+                    best_ref_mv.col = 0;
+                }
+            }
+
+            coded_error += this_error;
+
+            // adjust to the next column of macroblocks
+            x->src.y_buffer += 16;
+            x->src.u_buffer += 8;
+            x->src.v_buffer += 8;
+
+            recon_yoffset += 16;
+            recon_uvoffset += 8;
+
+            // Update the motion map
+            fp_motion_map_ptr++;
+        }
+
+        // adjust to the next row of mbs
+        x->src.y_buffer += 16 * x->src.y_stride - 16 * cm->mb_cols;
+        x->src.u_buffer += 8 * x->src.uv_stride - 8 * cm->mb_cols;
+        x->src.v_buffer += 8 * x->src.uv_stride - 8 * cm->mb_cols;
+
+        //extend the recon for intra prediction
+        vp8_extend_mb_row(&cm->new_frame, xd->dst.y_buffer + 16, xd->dst.u_buffer + 8, xd->dst.v_buffer + 8);
+        vp8_clear_system_state();  //__asm emms;
+    }
+
+    vp8_clear_system_state();  //__asm emms;
+    {
+        double weight = 0.0;
+        double weigth2 = 0.0;
+
+        FIRSTPASS_STATS fps;
+
+        fps.frame      = cm->current_video_frame ;
+        fps.intra_error = intra_error >> 8;
+        fps.coded_error = coded_error >> 8;
+        weight = vp8_simple_weight(cpi->Source);
+
+        if (weight < 0.1)
+            weight = 0.1;
+
+        fps.ssim_weighted_pred_err = fps.coded_error * weight;
+
+        fps.pcnt_inter  = 0.0;
+        fps.pcnt_motion = 0.0;
+        fps.MVr        = 0.0;
+        fps.mvr_abs     = 0.0;
+        fps.MVc        = 0.0;
+        fps.mvc_abs     = 0.0;
+        fps.MVrv       = 0.0;
+        fps.MVcv       = 0.0;
+        fps.mv_in_out_count  = 0.0;
+        fps.count      = 1.0;
+
+        fps.pcnt_inter   = 1.0 * (double)intercount / cm->MBs;
+        fps.pcnt_second_ref = 1.0 * (double)second_ref_count / cm->MBs;
+
+        if (mvcount > 0)
+        {
+            fps.MVr = (double)sum_mvr / (double)mvcount;
+            fps.mvr_abs = (double)sum_mvr_abs / (double)mvcount;
+            fps.MVc = (double)sum_mvc / (double)mvcount;
+            fps.mvc_abs = (double)sum_mvc_abs / (double)mvcount;
+            fps.MVrv = ((double)sum_mvrs - (fps.MVr * fps.MVr / (double)mvcount)) / (double)mvcount;
+            fps.MVcv = ((double)sum_mvcs - (fps.MVc * fps.MVc / (double)mvcount)) / (double)mvcount;
+            fps.mv_in_out_count = (double)sum_in_vectors / (double)(mvcount * 2);
+
+            fps.pcnt_motion = 1.0 * (double)mvcount / cpi->common.MBs;
+        }
+
+        // TODO:  handle the case when duration is set to 0, or something less
+        // than the full time between subsequent cpi->source_time_stamp s  .
+        fps.duration = cpi->source_end_time_stamp - cpi->source_time_stamp;
+
+        // don't want to do outputstats with a stack variable!
+        cpi->this_frame_stats = fps;
+        vp8_output_stats(cpi->output_pkt_list, &cpi->this_frame_stats);
+        vp8_accumulate_stats(&cpi->total_stats, &fps);
+
+#ifdef FIRSTPASS_MM
+        fwrite(cpi->fp_motion_map, 1, cpi->common.MBs, cpi->fp_motion_mapfile);
+#endif
+    }
+
+    // Copy the previous Last Frame into the GF buffer if specific conditions for doing so are met
+    if ((cm->current_video_frame > 0) &&
+        (cpi->this_frame_stats.pcnt_inter > 0.20) &&
+        ((cpi->this_frame_stats.intra_error / cpi->this_frame_stats.coded_error) > 2.0))
+    {
+        vp8_yv12_copy_frame_ptr(&cm->last_frame, &cm->golden_frame);
+    }
+
+    // swap frame pointers so last frame refers to the frame we just compressed
+    vp8_swap_yv12_buffer(&cm->last_frame, &cm->new_frame);
+    vp8_yv12_extend_frame_borders(&cm->last_frame);
+
+    // Special case for the first frame. Copy into the GF buffer as a second reference.
+    if (cm->current_video_frame == 0)
+    {
+        vp8_yv12_copy_frame_ptr(&cm->last_frame, &cm->golden_frame);
+    }
+
+
+    // use this to see what the first pass reconstruction looks like
+    if (0)
+    {
+        char filename[512];
+        FILE *recon_file;
+        sprintf(filename, "enc%04d.yuv", (int) cm->current_video_frame);
+
+        if (cm->current_video_frame == 0)
+            recon_file = fopen(filename, "wb");
+        else
+            recon_file = fopen(filename, "ab");
+
+        fwrite(cm->last_frame.buffer_alloc, cm->last_frame.frame_size, 1, recon_file);
+        fclose(recon_file);
+    }
+
+    cm->current_video_frame++;
+
+}
+extern const int vp8_bits_per_mb[2][QINDEX_RANGE];
+
+#define BASE_ERRPERMB   150
+static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_bandwitdh, int Height, int Width)
+{
+    int Q;
+    int num_mbs = ((Height * Width) / (16 * 16));
+    int target_norm_bits_per_mb;
+
+    double err_per_mb = section_err / num_mbs;
+    double correction_factor;
+    double corr_high;
+    double speed_correction = 1.0;
+    double rolling_ratio;
+
+    double pow_highq = 0.90;
+    double pow_lowq = 0.40;
+
+    if (section_target_bandwitdh <= 0)
+        return MAXQ;
+
+    target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) ? (512 * section_target_bandwitdh) / num_mbs : 512 * (section_target_bandwitdh / num_mbs);
+
+    // Calculate a corrective factor based on a rolling ratio of bits spent vs target bits
+    if ((cpi->rolling_target_bits > 0.0) && (cpi->active_worst_quality < cpi->worst_quality))
+    {
+        //double adjustment_rate = 0.985 + (0.00005 * cpi->active_worst_quality);
+        double adjustment_rate = 0.99;
+
+        rolling_ratio = (double)cpi->rolling_actual_bits / (double)cpi->rolling_target_bits;
+
+        //if ( cpi->est_max_qcorrection_factor > rolling_ratio )
+        if (rolling_ratio < 0.95)
+            //cpi->est_max_qcorrection_factor *= adjustment_rate;
+            cpi->est_max_qcorrection_factor -= 0.005;
+        //else if ( cpi->est_max_qcorrection_factor < rolling_ratio )
+        else if (rolling_ratio > 1.05)
+            cpi->est_max_qcorrection_factor += 0.005;
+
+        //cpi->est_max_qcorrection_factor /= adjustment_rate;
+
+        cpi->est_max_qcorrection_factor = (cpi->est_max_qcorrection_factor < 0.1) ? 0.1 : (cpi->est_max_qcorrection_factor > 10.0) ? 10.0 : cpi->est_max_qcorrection_factor;
+    }
+
+    // Corrections for higher compression speed settings (reduced compression expected)
+    if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1))
+    {
+        if (cpi->oxcf.cpu_used <= 5)
+            speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
+        else
+            speed_correction = 1.25;
+    }
+
+    // Correction factor used for Q values >= 20
+    corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq);
+    corr_high = (corr_high < 0.05) ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high;
+
+    // Try and pick a Q that should be high enough to encode the content at the given rate.
+    for (Q = 0; Q < MAXQ; Q++)
+    {
+        int bits_per_mb_at_this_q;
+
+        if (Q < 50)
+        {
+            correction_factor = pow(err_per_mb / BASE_ERRPERMB, (pow_lowq + Q * 0.01));
+            correction_factor = (correction_factor < 0.05) ? 0.05 : (correction_factor > 5.0) ? 5.0 : correction_factor;
+        }
+        else
+            correction_factor = corr_high;
+
+        bits_per_mb_at_this_q = (int)(.5 + correction_factor * speed_correction * cpi->est_max_qcorrection_factor * cpi->section_max_qfactor * (double)vp8_bits_per_mb[INTER_FRAME][Q] / 1.0);
+        //bits_per_mb_at_this_q = (int)(.5 + correction_factor * speed_correction * cpi->est_max_qcorrection_factor * (double)vp8_bits_per_mb[INTER_FRAME][Q] / 1.0);
+
+        if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
+            break;
+    }
+
+    return Q;
+}
+static int estimate_q(VP8_COMP *cpi, double section_err, int section_target_bandwitdh, int Height, int Width)
+{
+    int Q;
+    int num_mbs = ((Height * Width) / (16 * 16));
+    int target_norm_bits_per_mb;
+
+    double err_per_mb = section_err / num_mbs;
+    double correction_factor;
+    double corr_high;
+    double speed_correction = 1.0;
+    double pow_highq = 0.90;
+    double pow_lowq = 0.40;
+
+    target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) ? (512 * section_target_bandwitdh) / num_mbs : 512 * (section_target_bandwitdh / num_mbs);
+
+    // Corrections for higher compression speed settings (reduced compression expected)
+    if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1))
+    {
+        if (cpi->oxcf.cpu_used <= 5)
+            speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
+        else
+            speed_correction = 1.25;
+    }
+
+    // Correction factor used for Q values >= 20
+    corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq);
+    corr_high = (corr_high < 0.05) ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high;
+
+    // Try and pick a Q that can encode the content at the given rate.
+    for (Q = 0; Q < MAXQ; Q++)
+    {
+        int bits_per_mb_at_this_q;
+
+        if (Q < 50)
+        {
+            correction_factor = pow(err_per_mb / BASE_ERRPERMB, (pow_lowq + Q * 0.01));
+            correction_factor = (correction_factor < 0.05) ? 0.05 : (correction_factor > 5.0) ? 5.0 : correction_factor;
+        }
+        else
+            correction_factor = corr_high;
+
+        bits_per_mb_at_this_q = (int)(.5 + correction_factor * speed_correction * cpi->est_max_qcorrection_factor * (double)vp8_bits_per_mb[INTER_FRAME][Q] / 1.0);
+
+        if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
+            break;
+    }
+
+    return Q;
+}
+
+// Estimate a worst case Q for a KF group
+static int estimate_kf_group_q(VP8_COMP *cpi, double section_err, int section_target_bandwitdh, int Height, int Width, double group_iiratio)
+{
+    int Q;
+    int num_mbs = ((Height * Width) / (16 * 16));
+    int target_norm_bits_per_mb = (512 * section_target_bandwitdh) / num_mbs;
+    int bits_per_mb_at_this_q;
+
+    double err_per_mb = section_err / num_mbs;
+    double err_correction_factor;
+    double corr_high;
+    double speed_correction = 1.0;
+    double current_spend_ratio = 1.0;
+
+    double pow_highq = (POW1 < 0.6) ? POW1 + 0.3 : 0.90;
+    double pow_lowq = (POW1 < 0.7) ? POW1 + 0.1 : 0.80;
+
+    double iiratio_correction_factor = 1.0;
+
+    double combined_correction_factor;
+
+    // Trap special case where the target is <= 0
+    if (target_norm_bits_per_mb <= 0)
+        return MAXQ * 2;
+
+    // Calculate a corrective factor based on a rolling ratio of bits spent vs target bits
+    // This is clamped to the range 0.1 to 10.0
+    if (cpi->long_rolling_target_bits <= 0)
+        current_spend_ratio = 10.0;
+    else
+    {
+        current_spend_ratio = (double)cpi->long_rolling_actual_bits / (double)cpi->long_rolling_target_bits;
+        current_spend_ratio = (current_spend_ratio > 10.0) ? 10.0 : (current_spend_ratio < 0.1) ? 0.1 : current_spend_ratio;
+    }
+
+    // Calculate a correction factor based on the quality of prediction in the sequence as indicated by intra_inter error score ratio (IIRatio)
+    // The idea here is to favour subsampling in the hardest sections vs the easyest.
+    iiratio_correction_factor = 1.0 - ((group_iiratio - 6.0) * 0.1);
+
+    if (iiratio_correction_factor < 0.5)
+        iiratio_correction_factor = 0.5;
+
+    // Corrections for higher compression speed settings (reduced compression expected)
+    if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1))
+    {
+        if (cpi->oxcf.cpu_used <= 5)
+            speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
+        else
+            speed_correction = 1.25;
+    }
+
+    // Combine the various factors calculated above
+    combined_correction_factor = speed_correction * iiratio_correction_factor * current_spend_ratio;
+
+    // Correction factor used for Q values >= 20
+    corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq);
+    corr_high = (corr_high < 0.05) ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high;
+
+    // Try and pick a Q that should be high enough to encode the content at the given rate.
+    for (Q = 0; Q < MAXQ; Q++)
+    {
+        // Q values < 20 treated as a special case
+        if (Q < 20)
+        {
+            err_correction_factor = pow(err_per_mb / BASE_ERRPERMB, (pow_lowq + Q * 0.01));
+            err_correction_factor = (err_correction_factor < 0.05) ? 0.05 : (err_correction_factor > 5.0) ? 5.0 : err_correction_factor;
+        }
+        else
+            err_correction_factor = corr_high;
+
+        bits_per_mb_at_this_q = (int)(.5 + err_correction_factor * combined_correction_factor * (double)vp8_bits_per_mb[INTER_FRAME][Q]);
+
+        if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
+            break;
+    }
+
+    // If we could not hit the target even at Max Q then estimate what Q would have bee required
+    while ((bits_per_mb_at_this_q > target_norm_bits_per_mb)  && (Q < (MAXQ * 2)))
+    {
+
+        bits_per_mb_at_this_q = (int)(0.96 * bits_per_mb_at_this_q);
+        Q++;
+    }
+
+    if (0)
+    {
+        FILE *f = fopen("estkf_q.stt", "a");
+        fprintf(f, "%8d %8d %8d %8.2f %8.3f %8.2f %8.3f %8.3f %8.3f %8d\n", cpi->common.current_video_frame, bits_per_mb_at_this_q,
+                target_norm_bits_per_mb, err_per_mb, err_correction_factor,
+                current_spend_ratio, group_iiratio, iiratio_correction_factor,
+                (double)cpi->buffer_level / (double)cpi->oxcf.optimal_buffer_level, Q);
+        fclose(f);
+    }
+
+    return Q;
+}
+extern void vp8_new_frame_rate(VP8_COMP *cpi, double framerate);
+
+void vp8_init_second_pass(VP8_COMP *cpi)
+{
+    FIRSTPASS_STATS this_frame;
+    FIRSTPASS_STATS *start_pos;
+
+    double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+
+    vp8_zero_stats(&cpi->total_stats);
+
+    if (!cpi->stats_in_end)
+        return;
+
+    cpi->total_stats = *cpi->stats_in_end;
+
+    cpi->total_error_left = cpi->total_stats.ssim_weighted_pred_err;
+    cpi->total_intra_error_left = cpi->total_stats.intra_error;
+    cpi->total_coded_error_left = cpi->total_stats.coded_error;
+    cpi->start_tot_err_left = cpi->total_error_left;
+
+    //cpi->bits_left = (long long)(cpi->total_stats.count * cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate));
+    //cpi->bits_left -= (long long)(cpi->total_stats.count * two_pass_min_rate / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate));
+
+    // each frame can have a different duration, as the frame rate in the source
+    // isn't guaranteed to be constant.   The frame rate prior to the first frame
+    // encoded in the second pass is a guess.  However the sum duration is not.
+    // Its calculated based on the actual durations of all frames from the first
+    // pass.
+    vp8_new_frame_rate(cpi, 10000000.0 * cpi->total_stats.count / cpi->total_stats.duration);
+
+    cpi->output_frame_rate = cpi->oxcf.frame_rate;
+    cpi->bits_left = (long long)(cpi->total_stats.duration * cpi->oxcf.target_bandwidth / 10000000.0) ;
+    cpi->bits_left -= (long long)(cpi->total_stats.duration * two_pass_min_rate / 10000000.0);
+
+    vp8_avg_stats(&cpi->total_stats);
+
+    // Scan the first pass file and calculate an average Intra / Inter error score ratio for the sequence
+    {
+        double sum_iiratio = 0.0;
+        double IIRatio;
+
+        start_pos = cpi->stats_in;               // Note starting "file" position
+
+        while (vp8_input_stats(cpi, &this_frame) != EOF)
+        {
+            IIRatio = this_frame.intra_error / DOUBLE_DIVIDE_CHECK(this_frame.coded_error);
+            IIRatio = (IIRatio < 1.0) ? 1.0 : (IIRatio > 20.0) ? 20.0 : IIRatio;
+            sum_iiratio += IIRatio;
+        }
+
+        cpi->avg_iiratio = sum_iiratio / DOUBLE_DIVIDE_CHECK((double)cpi->total_stats.count);
+
+        // Reset file position
+        reset_fpf_position(cpi, start_pos);
+    }
+
+    // Scan the first pass file and calculate a modified total error based upon the bias/power function
+    // used to allocate bits
+    {
+        start_pos = cpi->stats_in;               // Note starting "file" position
+
+        cpi->modified_total_error_left = 0.0;
+
+        while (vp8_input_stats(cpi, &this_frame) != EOF)
+        {
+            cpi->modified_total_error_left += calculate_modified_err(cpi, &this_frame);
+        }
+
+        reset_fpf_position(cpi, start_pos);            // Reset file position
+
+    }
+
+#ifdef FIRSTPASS_MM
+    cpi->fp_motion_mapfile = 0;
+    cpi->fp_motion_mapfile = fopen("fpmotionmap.stt", "rb");
+#endif
+
+}
+
+void vp8_end_second_pass(VP8_COMP *cpi)
+{
+#ifdef FIRSTPASS_MM
+
+    if (cpi->fp_motion_mapfile)
+        fclose(cpi->fp_motion_mapfile);
+
+#endif
+}
+
+// Analyse and define a gf/arf group .
+static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
+{
+    FIRSTPASS_STATS next_frame;
+    FIRSTPASS_STATS *start_pos;
+    int i;
+    int count = 0;
+    int image_size = cpi->common.last_frame.y_width  * cpi->common.last_frame.y_height;
+    double boost_score = 0.0;
+    double old_boost_score = 0.0;
+    double gf_group_err = 0.0;
+    double gf_first_frame_err = 0.0;
+    double mod_frame_err = 0.0;
+
+    double mv_accumulator_rabs  = 0.0;
+    double mv_accumulator_cabs  = 0.0;
+    double this_mv_rabs;
+    double this_mv_cabs;
+    double mv_ratio_accumulator = 0.0;
+    double distance_factor = 0.0;
+    double decay_accumulator = 1.0;
+
+    double boost_factor = IIFACTOR;
+    double loop_decay_rate = 1.00;        // Starting decay rate
+
+    double this_frame_mv_in_out = 0.0;
+    double mv_in_out_accumulator = 0.0;
+    double abs_mv_in_out_accumulator = 0.0;
+    double mod_err_per_mb_accumulator = 0.0;
+
+    int max_bits = frame_max_bits(cpi);    // Max for a single frame
+
+#ifdef FIRSTPASS_MM
+    int fpmm_pos;
+#endif
+
+    cpi->gf_group_bits = 0;
+    cpi->gf_decay_rate = 0;
+
+    vp8_clear_system_state();  //__asm emms;
+
+#ifdef FIRSTPASS_MM
+    fpmm_pos = vp8_fpmm_get_pos(cpi);
+#endif
+
+    start_pos = cpi->stats_in;
+
+    // Preload the stats for the next frame.
+    mod_frame_err = calculate_modified_err(cpi, this_frame);
+
+    // Note the error of the frame at the start of the group (this will be the GF frame error if we code a normal gf
+    gf_first_frame_err = mod_frame_err;
+
+    // Special treatment if the current frame is a key frame (which is also a gf).
+    // If it is then its error score (and hence bit allocation) need to be subtracted out
+    // from the calculation for the GF group
+    if (cpi->common.frame_type == KEY_FRAME)
+        gf_group_err -= gf_first_frame_err;
+
+    // Scan forward to try and work out how many frames the next gf group should contain and
+    // what level of boost is appropriate for the GF or ARF that will be coded with the group
+    i = 0;
+
+    while (((i < cpi->max_gf_interval) || ((cpi->frames_to_key - i) < MIN_GF_INTERVAL)) && (i < cpi->frames_to_key))
+    {
+        double r;
+        double motion_factor;
+        double this_frame_mvr_ratio;
+        double this_frame_mvc_ratio;
+
+        i++;                                                    // Increment the loop counter
+
+        // Accumulate error score of frames in this gf group
+        mod_frame_err = calculate_modified_err(cpi, this_frame);
+
+        gf_group_err += mod_frame_err;
+
+        mod_err_per_mb_accumulator += mod_frame_err / DOUBLE_DIVIDE_CHECK((double)cpi->common.MBs);
+
+        if (EOF == vp8_input_stats(cpi, &next_frame))
+            break;
+
+        // Accumulate motion stats.
+        motion_factor = next_frame.pcnt_motion;
+        this_mv_rabs = fabs(next_frame.mvr_abs * motion_factor);
+        this_mv_cabs = fabs(next_frame.mvc_abs * motion_factor);
+
+        mv_accumulator_rabs += fabs(next_frame.mvr_abs * motion_factor);
+        mv_accumulator_cabs += fabs(next_frame.mvc_abs * motion_factor);
+
+        //Accumulate Motion In/Out of frame stats
+        this_frame_mv_in_out = next_frame.mv_in_out_count * next_frame.pcnt_motion;
+        mv_in_out_accumulator += next_frame.mv_in_out_count * next_frame.pcnt_motion;
+        abs_mv_in_out_accumulator += fabs(next_frame.mv_in_out_count * next_frame.pcnt_motion);
+
+        // If there is a significant amount of motion
+        if (motion_factor > 0.05)
+        {
+            this_frame_mvr_ratio = fabs(next_frame.mvr_abs) / DOUBLE_DIVIDE_CHECK(fabs(next_frame.MVr));
+            this_frame_mvc_ratio = fabs(next_frame.mvc_abs) / DOUBLE_DIVIDE_CHECK(fabs(next_frame.MVc));
+
+            mv_ratio_accumulator += (this_frame_mvr_ratio < next_frame.mvr_abs) ? (this_frame_mvr_ratio * motion_factor) : next_frame.mvr_abs * motion_factor;
+            mv_ratio_accumulator += (this_frame_mvc_ratio < next_frame.mvc_abs) ? (this_frame_mvc_ratio * motion_factor) : next_frame.mvc_abs * motion_factor;
+        }
+        else
+        {
+            mv_ratio_accumulator += 0.0;
+            this_frame_mvr_ratio = 1.0;
+            this_frame_mvc_ratio = 1.0;
+        }
+
+        // Underlying boost factor is based on inter intra error ratio
+        r = (boost_factor * (next_frame.intra_error / DOUBLE_DIVIDE_CHECK(next_frame.coded_error)));
+
+        // Increase boost for frames where new data coming into frame (eg zoom out)
+        // Slightly reduce boost if there is a net balance of motion out of the frame (zoom in)
+        // The range for this_frame_mv_in_out is -1.0 to +1.0
+        if (this_frame_mv_in_out > 0.0)
+            r += r * (this_frame_mv_in_out * 2.0);
+        else
+            r += r * (this_frame_mv_in_out / 2.0);  // In extreme case boost is halved
+
+        if (r > GF_RMAX)
+            r = GF_RMAX;
+
+        // Adjust loop decay rate
+        //if ( next_frame.pcnt_inter < loop_decay_rate )
+        loop_decay_rate = next_frame.pcnt_inter;
+
+        // High % motion -> somewhat higher decay rate
+        if ((1.0 - (next_frame.pcnt_motion / 10.0)) < loop_decay_rate)
+            loop_decay_rate = (1.0 - (next_frame.pcnt_motion / 10.0));
+
+        distance_factor = sqrt((this_mv_rabs * this_mv_rabs) + (this_mv_cabs * this_mv_cabs)) / 300.0;
+        distance_factor = ((distance_factor > 1.0) ? 0.0 : (1.0 - distance_factor));
+
+        if (distance_factor < loop_decay_rate)
+            loop_decay_rate = distance_factor;
+
+        // Cumulative effect of decay
+        decay_accumulator = decay_accumulator * loop_decay_rate;
+        decay_accumulator = decay_accumulator < 0.1 ? 0.1 : decay_accumulator;
+        //decay_accumulator = ( loop_decay_rate < decay_accumulator ) ? loop_decay_rate : decay_accumulator;
+
+        boost_score += (decay_accumulator * r);
+
+        // Break out conditions.
+        if (   /* i>4 || */
+            (
+                (i > MIN_GF_INTERVAL) &&                            // Dont break out with a very short interval
+                ((cpi->frames_to_key - i) >= MIN_GF_INTERVAL) &&      // Dont break out very close to a key frame
+                ((boost_score > 20.0) || (next_frame.pcnt_inter < 0.75)) &&
+                ((mv_ratio_accumulator > 100.0) ||
+                 (abs_mv_in_out_accumulator > 3.0) ||
+                 (mv_in_out_accumulator < -2.0) ||
+                 ((boost_score - old_boost_score) < 2.0)
+                )
+            )
+        )
+        {
+            boost_score = old_boost_score;
+            break;
+        }
+
+        vpx_memcpy(this_frame, &next_frame, sizeof(*this_frame));
+
+        old_boost_score = boost_score;
+    }
+
+    cpi->gf_decay_rate = (i > 0) ? (int)(100.0 * (1.0 - decay_accumulator)) / i : 0;
+
+    // When using CBR apply additional buffer related upper limits
+    if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+    {
+        double max_boost;
+
+        // For cbr apply buffer related limits
+        if (cpi->drop_frames_allowed)
+        {
+            int df_buffer_level = cpi->oxcf.drop_frames_water_mark * (cpi->oxcf.optimal_buffer_level / 100);
+
+            if (cpi->buffer_level > df_buffer_level)
+                max_boost = ((double)((cpi->buffer_level - df_buffer_level) * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
+            else
+                max_boost = 0.0;
+        }
+        else if (cpi->buffer_level > 0)
+        {
+            max_boost = ((double)(cpi->buffer_level * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
+        }
+        else
+        {
+            max_boost = 0.0;
+        }
+
+        if (boost_score > max_boost)
+            boost_score = max_boost;
+    }
+
+    cpi->gfu_boost = (int)(boost_score * 100.0) >> 4;
+
+    // Should we use the alternate refernce frame
+    if (cpi->oxcf.play_alternate &&
+        (i >= MIN_GF_INTERVAL) &&
+        (i <= (cpi->frames_to_key - MIN_GF_INTERVAL)) &&          // dont use ARF very near next kf
+        (((next_frame.pcnt_inter > 0.75) &&
+          ((mv_in_out_accumulator / (double)i > -0.2) || (mv_in_out_accumulator > -2.0)) &&
+          //(cpi->gfu_boost>150) &&
+          (cpi->gfu_boost > 100) &&
+          //(cpi->gfu_boost>AF_THRESH2) &&
+          //((cpi->gfu_boost/i)>AF_THRESH) &&
+          //(decay_accumulator > 0.5) &&
+          (cpi->gf_decay_rate <= (ARF_DECAY_THRESH + (cpi->gfu_boost / 200)))
+         )
+        )
+       )
+    {
+        int Boost;
+        int allocation_chunks;
+        int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
+        int tmp_q;
+        int arf_frame_bits = 0;
+        int group_bits;
+
+        // Estimate the bits to be allocated to the group as a whole
+        if ((cpi->kf_group_bits > 0) && (cpi->kf_group_error_left > 0))
+            group_bits = (int)((double)cpi->kf_group_bits * (gf_group_err / (double)cpi->kf_group_error_left));
+        else
+            group_bits = 0;
+
+        // Boost for arf frame
+        Boost = (cpi->gfu_boost * 3 * GFQ_ADJUSTMENT) / (2 * 100);
+        Boost += (cpi->baseline_gf_interval * 50);
+        allocation_chunks = (i * 100) + Boost;
+
+        // Normalize Altboost and allocations chunck down to prevent overflow
+        while (Boost > 1000)
+        {
+            Boost /= 2;
+            allocation_chunks /= 2;
+        }
+
+        // Calculate the number of bits to be spent on the arf based on the boost number
+        arf_frame_bits = (int)((double)Boost * (group_bits / (double)allocation_chunks));
+
+        // Estimate if there are enough bits available to make worthwhile use of an arf.
+        tmp_q = estimate_q(cpi, mod_frame_err, (int)arf_frame_bits, cpi->common.Height, cpi->common.Width);
+
+        // Only use an arf if it is likely we will be able to code it at a lower Q than the surrounding frames.
+        if (tmp_q < cpi->worst_quality)
+        {
+            cpi->source_alt_ref_pending = TRUE;
+
+            // For alt ref frames the error score for the end frame of the group (the alt ref frame) should not contribute to the group total and hence
+            // the number of bit allocated to the group. Rather it forms part of the next group (it is the GF at the start of the next group)
+            gf_group_err -= mod_frame_err;
+
+            // Set the interval till the next gf or arf. For ARFs this is the number of frames to be coded before the future frame that is coded as an ARF.
+            // The future frame itself is part of the next group
+            cpi->baseline_gf_interval = i - 1;
+
+#ifdef FIRSTPASS_MM
+            // Read through the motion map to load up the entry for the ARF
+            {
+                int j;
+
+                // Advance to the region of interest
+                // Current default 2 frames before to 2 frames after the ARF frame itsef
+                vp8_fpmm_reset_pos(cpi, cpi->fpmm_pos);
+
+                for (j = 0; j < cpi->baseline_gf_interval - 2; j++)
+                    vp8_advance_fpmm(cpi, 1);
+
+                // Read / create a motion map for the region of interest
+                vp8_input_fpmm(cpi, 5);
+            }
+#endif
+        }
+        else
+        {
+            cpi->source_alt_ref_pending = FALSE;
+            cpi->baseline_gf_interval = i;
+        }
+    }
+    else
+    {
+        cpi->source_alt_ref_pending = FALSE;
+        cpi->baseline_gf_interval = i;
+    }
+
+    // Conventional GF
+    if (!cpi->source_alt_ref_pending)
+    {
+        // Dont allow conventional gf too near the next kf
+        if ((cpi->frames_to_key - cpi->baseline_gf_interval) < MIN_GF_INTERVAL)
+        {
+            while (cpi->baseline_gf_interval < cpi->frames_to_key)
+            {
+                if (EOF == vp8_input_stats(cpi, this_frame))
+                    break;
+
+                cpi->baseline_gf_interval++;
+
+                if (cpi->baseline_gf_interval < cpi->frames_to_key)
+                    gf_group_err += calculate_modified_err(cpi, this_frame);
+            }
+        }
+    }
+
+    // Now decide how many bits should be allocated to the GF group as  a proportion of those remaining in the kf group.
+    // The final key frame group in the clip is treated as a special case where cpi->kf_group_bits is tied to cpi->bits_left.
+    // This is also important for short clips where there may only be one key frame.
+    if (cpi->frames_to_key >= (int)(cpi->total_stats.count - cpi->common.current_video_frame))
+    {
+        cpi->kf_group_bits = (cpi->bits_left > 0) ? cpi->bits_left : 0;
+    }
+
+    // Calculate the bits to be allocated to the group as a whole
+    if ((cpi->kf_group_bits > 0) && (cpi->kf_group_error_left > 0))
+        cpi->gf_group_bits = (int)((double)cpi->kf_group_bits * (gf_group_err / (double)cpi->kf_group_error_left));
+    else
+        cpi->gf_group_bits = 0;
+
+    cpi->gf_group_bits = (cpi->gf_group_bits < 0) ? 0 : (cpi->gf_group_bits > cpi->kf_group_bits) ? cpi->kf_group_bits : cpi->gf_group_bits;
+
+    // Clip cpi->gf_group_bits based on user supplied data rate variability limit (cpi->oxcf.two_pass_vbrmax_section)
+    if (cpi->gf_group_bits > max_bits * cpi->baseline_gf_interval)
+        cpi->gf_group_bits = max_bits * cpi->baseline_gf_interval;
+
+    // Reset the file position
+    reset_fpf_position(cpi, start_pos);
+
+    // Assign  bits to the arf or gf.
+    {
+        int Boost;
+        int frames_in_section;
+        int allocation_chunks;
+        int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
+
+        // For ARF frames
+        if (cpi->source_alt_ref_pending)
+        {
+            Boost = (cpi->gfu_boost * 3 * GFQ_ADJUSTMENT) / (2 * 100);
+            //Boost += (cpi->baseline_gf_interval * 25);
+            Boost += (cpi->baseline_gf_interval * 50);
+
+            // Set max and minimum boost and hence minimum allocation
+            if (Boost > ((cpi->baseline_gf_interval + 1) * 200))
+                Boost = ((cpi->baseline_gf_interval + 1) * 200);
+            else if (Boost < 125)
+                Boost = 125;
+
+            frames_in_section = cpi->baseline_gf_interval + 1;
+            allocation_chunks = (frames_in_section * 100) + Boost;
+        }
+        // Else for standard golden frames
+        else
+        {
+            // boost based on inter / intra ratio of subsequent frames
+            Boost = (cpi->gfu_boost * GFQ_ADJUSTMENT) / 100;
+
+            // Set max and minimum boost and hence minimum allocation
+            if (Boost > (cpi->baseline_gf_interval * 150))
+                Boost = (cpi->baseline_gf_interval * 150);
+            else if (Boost < 125)
+                Boost = 125;
+
+            frames_in_section = cpi->baseline_gf_interval;
+            allocation_chunks = (frames_in_section * 100) + (Boost - 100);
+        }
+
+        // Normalize Altboost and allocations chunck down to prevent overflow
+        while (Boost > 1000)
+        {
+            Boost /= 2;
+            allocation_chunks /= 2;
+        }
+
+        // Calculate the number of bits to be spent on the gf or arf based on the boost number
+        cpi->gf_bits = (int)((double)Boost * (cpi->gf_group_bits / (double)allocation_chunks));
+
+        // If the frame that is to be boosted is simpler than the average for the gf/arf group then use an alternative calculation
+        // based on the error score of the frame itself
+        if (mod_frame_err < gf_group_err / (double)cpi->baseline_gf_interval)
+        {
+            double  alt_gf_grp_bits;
+            int     alt_gf_bits;
+
+            alt_gf_grp_bits = ((double)cpi->kf_group_bits  * (mod_frame_err * (double)cpi->baseline_gf_interval) / (double)cpi->kf_group_error_left) ;
+            alt_gf_bits = (int)((double)Boost * (alt_gf_grp_bits / (double)allocation_chunks));
+
+            if (cpi->gf_bits > alt_gf_bits)
+            {
+                cpi->gf_bits = alt_gf_bits;
+            }
+        }
+        // Else if it is harder than other frames in the group make sure it at least receives an allocation in keeping with
+        // its relative error score, otherwise it may be worse off than an "un-boosted" frame
+        else
+        {
+            int alt_gf_bits = (int)((double)cpi->kf_group_bits * (mod_frame_err / (double)cpi->kf_group_error_left));
+
+            if (alt_gf_bits > cpi->gf_bits)
+            {
+                cpi->gf_bits = alt_gf_bits;
+            }
+        }
+
+        // Apply an additional limit for CBR
+        if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+        {
+            if (cpi->gf_bits > (cpi->buffer_level >> 1))
+                cpi->gf_bits = cpi->buffer_level >> 1;
+        }
+
+        // Dont allow a negative value for gf_bits
+        if (cpi->gf_bits < 0)
+            cpi->gf_bits = 0;
+
+        // Adjust KF group bits and error remainin
+        cpi->kf_group_error_left -= gf_group_err;
+        cpi->kf_group_bits -= cpi->gf_group_bits;
+
+        if (cpi->kf_group_bits < 0)
+            cpi->kf_group_bits = 0;
+
+        // Note the error score left in the remaining frames of the group.
+        // For normal GFs we want to remove the error score for the first frame of the group (except in Key frame case where this has already happened)
+        if (!cpi->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME)
+            cpi->gf_group_error_left = gf_group_err - gf_first_frame_err;
+        else
+            cpi->gf_group_error_left = gf_group_err;
+
+        cpi->gf_group_bits -= cpi->gf_bits;
+
+        if (cpi->gf_group_bits < 0)
+            cpi->gf_group_bits = 0;
+
+        // Set aside some bits for a mid gf sequence boost
+        if ((cpi->gfu_boost > 150) && (cpi->baseline_gf_interval > 5))
+        {
+            int pct_extra = (cpi->gfu_boost - 100) / 50;
+            pct_extra = (pct_extra > 10) ? 10 : pct_extra;
+
+            cpi->mid_gf_extra_bits = (cpi->gf_group_bits * pct_extra) / 100;
+            cpi->gf_group_bits -= cpi->mid_gf_extra_bits;
+        }
+        else
+            cpi->mid_gf_extra_bits = 0;
+
+        cpi->gf_bits += cpi->min_frame_bandwidth;                                              // Add in minimum for a frame
+    }
+
+    if (!cpi->source_alt_ref_pending && (cpi->common.frame_type != KEY_FRAME))                  // Normal GF and not a KF
+    {
+        cpi->per_frame_bandwidth = cpi->gf_bits;                                               // Per frame bit target for this frame
+    }
+
+    // Adjustment to estimate_max_q based on a measure of complexity of the section
+    if (cpi->common.frame_type != KEY_FRAME)
+    {
+        FIRSTPASS_STATS sectionstats;
+        double Ratio;
+
+        vp8_zero_stats(&sectionstats);
+        reset_fpf_position(cpi, start_pos);
+
+        for (i = 0 ; i < cpi->baseline_gf_interval ; i++)
+        {
+            vp8_input_stats(cpi, &next_frame);
+            vp8_accumulate_stats(&sectionstats, &next_frame);
+        }
+
+        vp8_avg_stats(&sectionstats);
+
+        if (sectionstats.pcnt_motion < .17)
+            cpi->section_is_low_motion = 1;
+        else
+            cpi->section_is_low_motion = 0;
+
+        if (sectionstats.mvc_abs + sectionstats.mvr_abs > 45)
+            cpi->section_is_fast_motion = 1;
+        else
+            cpi->section_is_fast_motion = 0;
+
+        cpi->section_intra_rating = sectionstats.intra_error / DOUBLE_DIVIDE_CHECK(sectionstats.coded_error);
+
+        Ratio = sectionstats.intra_error / DOUBLE_DIVIDE_CHECK(sectionstats.coded_error);
+        //if( (Ratio > 11) ) //&& (sectionstats.pcnt_second_ref < .20) )
+        //{
+        cpi->section_max_qfactor = 1.0 - ((Ratio - 10.0) * 0.025);
+
+        if (cpi->section_max_qfactor < 0.80)
+            cpi->section_max_qfactor = 0.80;
+
+        //}
+        //else
+        //    cpi->section_max_qfactor = 1.0;
+
+        reset_fpf_position(cpi, start_pos);
+    }
+
+#ifdef FIRSTPASS_MM
+    // Reset the First pass motion map file position
+    vp8_fpmm_reset_pos(cpi, fpmm_pos);
+#endif
+}
+
+// Allocate bits to a normal frame that is neither a gf an arf or a key frame.
+static void assign_std_frame_bits(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
+{
+    int    target_frame_size;                                                             // gf_group_error_left
+
+    double modified_err;
+    double err_fraction;                                                                 // What portion of the remaining GF group error is used by this frame
+
+    int max_bits = frame_max_bits(cpi);    // Max for a single frame
+
+    // The final few frames have special treatment
+    if (cpi->frames_till_gf_update_due >= (int)(cpi->total_stats.count - cpi->common.current_video_frame))
+    {
+        cpi->gf_group_bits = (cpi->bits_left > 0) ? cpi->bits_left : 0;;
+    }
+
+    // Calculate modified prediction error used in bit allocation
+    modified_err = calculate_modified_err(cpi, this_frame);
+
+    if (cpi->gf_group_error_left > 0)
+        err_fraction = modified_err / cpi->gf_group_error_left;                              // What portion of the remaining GF group error is used by this frame
+    else
+        err_fraction = 0.0;
+
+    target_frame_size = (int)((double)cpi->gf_group_bits * err_fraction);                    // How many of those bits available for allocation should we give it?
+
+    // Clip to target size to 0 - max_bits (or cpi->gf_group_bits) at the top end.
+    if (target_frame_size < 0)
+        target_frame_size = 0;
+    else
+    {
+        if (target_frame_size > max_bits)
+            target_frame_size = max_bits;
+
+        if (target_frame_size > cpi->gf_group_bits)
+            target_frame_size = cpi->gf_group_bits;
+    }
+
+    cpi->gf_group_error_left -= modified_err;                                               // Adjust error remaining
+    cpi->gf_group_bits -= target_frame_size;                                                // Adjust bits remaining
+
+    if (cpi->gf_group_bits < 0)
+        cpi->gf_group_bits = 0;
+
+    target_frame_size += cpi->min_frame_bandwidth;                                          // Add in the minimum number of bits that is set aside for every frame.
+
+    // Special case for the frame that lies half way between two gfs
+    if (cpi->common.frames_since_golden == cpi->baseline_gf_interval / 2)
+        target_frame_size += cpi->mid_gf_extra_bits;
+
+    cpi->per_frame_bandwidth = target_frame_size;                                           // Per frame bit target for this frame
+}
+
+void vp8_second_pass(VP8_COMP *cpi)
+{
+    int tmp_q;
+    int frames_left = (int)(cpi->total_stats.count - cpi->common.current_video_frame);
+
+    FIRSTPASS_STATS this_frame;
+    FIRSTPASS_STATS this_frame_copy;
+
+    VP8_COMMON *cm = &cpi->common;
+
+    double this_frame_error;
+    double this_frame_intra_error;
+    double this_frame_coded_error;
+
+    FIRSTPASS_STATS *start_pos;
+
+    if (!cpi->stats_in)
+    {
+        return ;
+    }
+
+    vp8_clear_system_state();
+
+    if (EOF == vp8_input_stats(cpi, &this_frame))
+        return;
+
+#ifdef FIRSTPASS_MM
+    vpx_memset(cpi->fp_motion_map, 0, cpi->common.MBs);
+    cpi->fpmm_pos = vp8_fpmm_get_pos(cpi);
+    vp8_advance_fpmm(cpi, 1);         // Read this frame's first pass motion map
+#endif
+
+    this_frame_error = this_frame.ssim_weighted_pred_err;
+    this_frame_intra_error = this_frame.intra_error;
+    this_frame_coded_error = this_frame.coded_error;
+
+    // Store information regarding level of motion etc for use mode decisions.
+    cpi->motion_speed = (int)(fabs(this_frame.MVr) + fabs(this_frame.MVc));
+    cpi->motion_var = (int)(fabs(this_frame.MVrv) + fabs(this_frame.MVcv));
+    cpi->inter_lvl = (int)(this_frame.pcnt_inter * 100);
+    cpi->intra_lvl = (int)((1.0 - this_frame.pcnt_inter) * 100);
+    cpi->motion_lvl = (int)(this_frame.pcnt_motion * 100);
+
+    start_pos = cpi->stats_in;
+
+    // keyframe and section processing !
+    if (cpi->frames_to_key == 0)
+    {
+        // Define next KF group and assign bits to it
+        vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
+        vp8_find_next_key_frame(cpi, &this_frame_copy);
+
+        // Special case: Error error_resilient_mode mode does not make much sense for two pass but with its current meaning but this code is designed to stop
+        // outlandish behaviour if someone does set it when using two pass. It effectively disables GF groups.
+        // This is temporary code till we decide what should really happen in this case.
+        if (cpi->oxcf.error_resilient_mode)
+        {
+            cpi->gf_group_bits = cpi->kf_group_bits;
+            cpi->gf_group_error_left = cpi->kf_group_error_left;
+            cpi->baseline_gf_interval = cpi->frames_to_key;
+            cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+            cpi->source_alt_ref_pending = FALSE;
+        }
+
+    }
+
+    // Is this a GF / ARF (Note that a KF is always also a GF)
+    if (cpi->frames_till_gf_update_due == 0)
+    {
+        // Define next gf group and assign bits to it
+        vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
+        define_gf_group(cpi, &this_frame_copy);
+
+        // If we are going to code an altref frame at the end of the group and the current frame is not a key frame....
+        // If the previous group used an arf this frame has already benefited from that arf boost and it should not be given extra bits
+        // If the previous group was NOT coded using arf we may want to apply some boost to this GF as well
+        if (cpi->source_alt_ref_pending && (cpi->common.frame_type != KEY_FRAME))
+        {
+            // Assign a standard frames worth of bits from those allocated to the GF group
+            vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
+            assign_std_frame_bits(cpi, &this_frame_copy);
+
+            // If appropriate (we are switching into ARF active but it was not previously active) apply a boost for the gf at the start of the group.
+            //if ( !cpi->source_alt_ref_active && (cpi->gfu_boost > 150) )
+            if (FALSE)
+            {
+                int extra_bits;
+                int pct_extra = (cpi->gfu_boost - 100) / 50;
+
+                pct_extra = (pct_extra > 20) ? 20 : pct_extra;
+
+                extra_bits = (cpi->gf_group_bits * pct_extra) / 100;
+                cpi->gf_group_bits -= extra_bits;
+                cpi->per_frame_bandwidth += extra_bits;
+            }
+        }
+    }
+
+    // Otherwise this is an ordinary frame
+    else
+    {
+        // Special case: Error error_resilient_mode mode does not make much sense for two pass but with its current meaning but this code is designed to stop
+        // outlandish behaviour if someone does set it when using two pass. It effectively disables GF groups.
+        // This is temporary code till we decide what should really happen in this case.
+        if (cpi->oxcf.error_resilient_mode)
+        {
+            cpi->frames_till_gf_update_due = cpi->frames_to_key;
+
+            if (cpi->common.frame_type != KEY_FRAME)
+            {
+                // Assign bits from those allocated to the GF group
+                vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
+                assign_std_frame_bits(cpi, &this_frame_copy);
+            }
+        }
+        else
+        {
+            // Assign bits from those allocated to the GF group
+            vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
+            assign_std_frame_bits(cpi, &this_frame_copy);
+        }
+    }
+
+    // Set nominal per second bandwidth for this frame
+    cpi->target_bandwidth = cpi->per_frame_bandwidth * cpi->output_frame_rate;
+    if (cpi->target_bandwidth < 0)
+        cpi->target_bandwidth = 0;
+
+    if (cpi->common.current_video_frame == 0)
+    {
+        // guess at 2nd pass q
+        cpi->est_max_qcorrection_factor = 1.0;
+        tmp_q = estimate_max_q(cpi, (cpi->total_coded_error_left / frames_left), (int)(cpi->bits_left / frames_left), cpi->common.Height, cpi->common.Width);
+
+        if (tmp_q < cpi->worst_quality)
+        {
+            cpi->active_worst_quality         = tmp_q;
+            cpi->ni_av_qi                     = tmp_q;
+        }
+        else
+        {
+            cpi->active_worst_quality         = cpi->worst_quality;
+            cpi->ni_av_qi                     = cpi->worst_quality;
+        }
+    }
+    else
+    {
+        if (frames_left < 1)
+            frames_left = 1;
+
+        tmp_q = estimate_max_q(cpi, (cpi->total_coded_error_left / frames_left), (int)(cpi->bits_left / frames_left), cpi->common.Height, cpi->common.Width);
+
+        // Move active_worst_quality but in a damped way
+        if (tmp_q > cpi->active_worst_quality)
+            cpi->active_worst_quality ++;
+        else if (tmp_q < cpi->active_worst_quality)
+            cpi->active_worst_quality --;
+
+        cpi->active_worst_quality = ((cpi->active_worst_quality * 3) + tmp_q + 2) / 4;
+
+        // Clamp to user set limits
+        if (cpi->active_worst_quality > cpi->worst_quality)
+            cpi->active_worst_quality = cpi->worst_quality;
+        else if (cpi->active_worst_quality < cpi->best_quality)
+            cpi->active_worst_quality = cpi->best_quality;
+
+    }
+
+    cpi->frames_to_key --;
+    cpi->total_error_left      -= this_frame_error;
+    cpi->total_intra_error_left -= this_frame_intra_error;
+    cpi->total_coded_error_left -= this_frame_coded_error;
+}
+
+
+static BOOL test_candidate_kf(VP8_COMP *cpi,  FIRSTPASS_STATS *last_frame, FIRSTPASS_STATS *this_frame, FIRSTPASS_STATS *next_frame)
+{
+    BOOL is_viable_kf = FALSE;
+
+    // Does the frame satisfy the primary criteria of a key frame
+    //      If so, then examine how well it predicts subsequent frames
+    if ((this_frame->pcnt_second_ref < 0.10) &&
+        (next_frame->pcnt_second_ref < 0.10) &&
+        ((this_frame->pcnt_inter < 0.05) ||
+         (
+             (this_frame->pcnt_inter < .25) &&
+             ((this_frame->intra_error / DOUBLE_DIVIDE_CHECK(this_frame->coded_error)) < 2.5) &&
+             ((fabs(last_frame->coded_error - this_frame->coded_error) / DOUBLE_DIVIDE_CHECK(this_frame->coded_error) > .40) ||
+              (fabs(last_frame->intra_error - this_frame->intra_error) / DOUBLE_DIVIDE_CHECK(this_frame->intra_error) > .40) ||
+              ((next_frame->intra_error / DOUBLE_DIVIDE_CHECK(next_frame->coded_error)) > 3.5)
+             )
+         )
+        )
+       )
+    {
+        int i;
+        FIRSTPASS_STATS *start_pos;
+
+        FIRSTPASS_STATS local_next_frame;
+
+        double boost_score = 0.0;
+        double old_boost_score = 0.0;
+        double decay_accumulator = 1.0;
+        double next_iiratio;
+
+        vpx_memcpy(&local_next_frame, next_frame, sizeof(*next_frame));
+
+        // Note the starting file position so we can reset to it
+        start_pos = cpi->stats_in;
+
+        // Examine how well the key frame predicts subsequent frames
+        for (i = 0 ; i < 16; i++)
+        {
+            next_iiratio = (IIKFACTOR1 * local_next_frame.intra_error / DOUBLE_DIVIDE_CHECK(local_next_frame.coded_error)) ;
+
+            if (next_iiratio > RMAX)
+                next_iiratio = RMAX;
+
+            // Cumulative effect of decay in prediction quality
+            if (local_next_frame.pcnt_inter > 0.85)
+                decay_accumulator = decay_accumulator * local_next_frame.pcnt_inter;
+            else
+                decay_accumulator = decay_accumulator * ((0.85 + local_next_frame.pcnt_inter) / 2.0);
+
+            //decay_accumulator = decay_accumulator * local_next_frame.pcnt_inter;
+
+            // Keep a running total
+            boost_score += (decay_accumulator * next_iiratio);
+
+            // Test various breakout clauses
+            if ((local_next_frame.pcnt_inter < 0.05) ||
+                (next_iiratio < 1.5) ||
+                ((local_next_frame.pcnt_inter < 0.20) && (next_iiratio < 3.0)) ||
+                ((boost_score - old_boost_score) < 0.5) ||
+                (local_next_frame.intra_error < 200)
+               )
+            {
+                break;
+            }
+
+            old_boost_score = boost_score;
+
+            // Get the next frame details
+            if (EOF == vp8_input_stats(cpi, &local_next_frame))
+                break;
+        }
+
+        // If there is tolerable prediction for at least the next 3 frames then break out else discard this pottential key frame and move on
+        if (boost_score > 5.0 && (i > 3))
+            is_viable_kf = TRUE;
+        else
+        {
+            // Reset the file position
+            reset_fpf_position(cpi, start_pos);
+
+            is_viable_kf = FALSE;
+        }
+    }
+
+    return is_viable_kf;
+}
+void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
+{
+    int i;
+    FIRSTPASS_STATS last_frame;
+    FIRSTPASS_STATS first_frame;
+    FIRSTPASS_STATS next_frame;
+    FIRSTPASS_STATS *start_position;
+
+    double decay_accumulator = 0;
+    double boost_score = 0;
+    double old_boost_score = 0.0;
+    double loop_decay_rate;
+
+    double kf_mod_err = 0.0;
+    double kf_group_err = 0.0;
+    double kf_group_intra_err = 0.0;
+    double kf_group_coded_err = 0.0;
+    double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+
+    vp8_clear_system_state();  //__asm emms;
+    start_position = cpi->stats_in;
+
+    cpi->common.frame_type = KEY_FRAME;
+
+    // Clear the alt ref active flag as this can never be active on a key frame
+    cpi->source_alt_ref_active = FALSE;
+
+    // Kf is always a gf so clear frames till next gf counter
+    cpi->frames_till_gf_update_due = 0;
+
+    cpi->frames_to_key = 1;
+
+    // Take a copy of the initial frame details
+    vpx_memcpy(&first_frame, this_frame, sizeof(*this_frame));
+
+    cpi->kf_group_bits = 0;       // Estimate of total bits avaialable to kf group
+    cpi->kf_group_error_left = 0;  // Group modified error score.
+
+    kf_mod_err = calculate_modified_err(cpi, this_frame);
+
+    // find the next keyframe
+    while (cpi->stats_in < cpi->stats_in_end)
+    {
+        // Accumulate kf group error
+        kf_group_err += calculate_modified_err(cpi, this_frame);
+
+        // These figures keep intra and coded error counts for all frames including key frames in the group.
+        // The effect of the key frame itself can be subtracted out using the first_frame data collected above
+        kf_group_intra_err += this_frame->intra_error;
+        kf_group_coded_err += this_frame->coded_error;
+
+        vpx_memcpy(&last_frame, this_frame, sizeof(*this_frame));
+
+        // Provided that we are not at the end of the file...
+        if (EOF != vp8_input_stats(cpi, this_frame))
+        {
+            if (lookup_next_frame_stats(cpi, &next_frame) != EOF)
+            {
+                if (test_candidate_kf(cpi, &last_frame, this_frame, &next_frame))
+                    break;
+            }
+        }
+
+        // Step on to the next frame
+        cpi->frames_to_key ++;
+
+        // If we don't have a real key frame within the next two
+        // forcekeyframeevery intervals then break out of the loop.
+        if (cpi->frames_to_key >= 2 *(int)cpi->key_frame_frequency)
+            break;
+
+    }
+
+    // If there is a max kf interval set by the user we must obey it.
+    // We already breakout of the loop above at 2x max.
+    // This code centers the extra kf if the actual natural
+    // interval is between 1x and 2x
+    if ( cpi->frames_to_key > (int)cpi->key_frame_frequency )
+    {
+        cpi->frames_to_key /= 2;
+
+        // Estimate corrected kf group error
+        kf_group_err /= 2.0;
+        kf_group_intra_err /= 2.0;
+        kf_group_coded_err /= 2.0;
+    }
+
+    // Special case for the last frame of the file
+    if (cpi->stats_in >= cpi->stats_in_end)
+    {
+        // Accumulate kf group error
+        kf_group_err += calculate_modified_err(cpi, this_frame);
+
+        // These figures keep intra and coded error counts for all frames including key frames in the group.
+        // The effect of the key frame itself can be subtracted out using the first_frame data collected above
+        kf_group_intra_err += this_frame->intra_error;
+        kf_group_coded_err += this_frame->coded_error;
+    }
+
+    // Calculate the number of bits that should be assigned to the kf group.
+    if ((cpi->bits_left > 0) && ((int)cpi->modified_total_error_left > 0))
+    {
+        int max_bits = frame_max_bits(cpi);    // Max for a single normal frame (not key frame)
+
+        // Default allocation based on bits left and relative complexity of the section
+        cpi->kf_group_bits = (int)(cpi->bits_left * (kf_group_err / cpi->modified_total_error_left));
+
+        // Clip based on maximum per frame rate defined by the user.
+        if (cpi->kf_group_bits > max_bits * cpi->frames_to_key)
+            cpi->kf_group_bits = max_bits * cpi->frames_to_key;
+
+        // Additional special case for CBR if buffer is getting full.
+        if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+        {
+            // If the buffer is near or above the optimal and this kf group is not being allocated much
+            // then increase the allocation a bit.
+            if (cpi->buffer_level >= cpi->oxcf.optimal_buffer_level)
+            {
+                int high_water_mark = (cpi->oxcf.optimal_buffer_level + cpi->oxcf.maximum_buffer_size) >> 1;
+                int min_group_bits;
+
+                // We are at or above the maximum.
+                if (cpi->buffer_level >= high_water_mark)
+                {
+                    min_group_bits = (cpi->av_per_frame_bandwidth * cpi->frames_to_key) + (cpi->buffer_level - high_water_mark);
+
+                    if (cpi->kf_group_bits < min_group_bits)
+                        cpi->kf_group_bits = min_group_bits;
+                }
+                // We are above optimal but below the maximum
+                else if (cpi->kf_group_bits < (cpi->av_per_frame_bandwidth * cpi->frames_to_key))
+                {
+                    int bits_below_av = (cpi->av_per_frame_bandwidth * cpi->frames_to_key) - cpi->kf_group_bits;
+                    cpi->kf_group_bits += (int)((double)bits_below_av * (double)(cpi->buffer_level - cpi->oxcf.optimal_buffer_level) /
+                                                (double)(high_water_mark - cpi->oxcf.optimal_buffer_level));
+                }
+            }
+        }
+    }
+    else
+        cpi->kf_group_bits = 0;
+
+    // Reset the first pass file position
+    reset_fpf_position(cpi, start_position);
+
+    // determine how big to make this keyframe based on how well the subsequent frames use inter blocks
+    decay_accumulator = 1.0;
+    boost_score = 0.0;
+    loop_decay_rate = 1.00;       // Starting decay rate
+
+    for (i = 0 ; i < cpi->frames_to_key ; i++)
+    {
+        double r;
+
+        if (EOF == vp8_input_stats(cpi, &next_frame))
+            break;
+
+        r = (IIKFACTOR2 * next_frame.intra_error / DOUBLE_DIVIDE_CHECK(next_frame.coded_error)) ;
+
+        if (r > RMAX)
+            r = RMAX;
+
+        // Adjust loop decay rate
+        //if ( next_frame.pcnt_inter < loop_decay_rate )
+        loop_decay_rate = next_frame.pcnt_inter;
+
+        if ((1.0 - (next_frame.pcnt_motion / 10.0)) < loop_decay_rate)
+            loop_decay_rate = (1.0 - (next_frame.pcnt_motion / 10.0));
+
+        decay_accumulator = decay_accumulator * loop_decay_rate;
+
+        boost_score += (decay_accumulator * r);
+
+        if ((i > MIN_GF_INTERVAL) &&
+            ((boost_score - old_boost_score) < 1.0))
+        {
+            break;
+        }
+
+        old_boost_score = boost_score;
+    }
+
+    if (1)
+    {
+        FIRSTPASS_STATS sectionstats;
+        double Ratio;
+
+        vp8_zero_stats(&sectionstats);
+        reset_fpf_position(cpi, start_position);
+
+        for (i = 0 ; i < cpi->frames_to_key ; i++)
+        {
+            vp8_input_stats(cpi, &next_frame);
+            vp8_accumulate_stats(&sectionstats, &next_frame);
+        }
+
+        vp8_avg_stats(&sectionstats);
+
+        if (sectionstats.pcnt_motion < .17)
+            cpi->section_is_low_motion = 1;
+        else
+            cpi->section_is_low_motion = 0;
+
+        if (sectionstats.mvc_abs + sectionstats.mvr_abs > 45)
+            cpi->section_is_fast_motion = 1;
+        else
+            cpi->section_is_fast_motion = 0;
+
+        cpi->section_intra_rating = sectionstats.intra_error / DOUBLE_DIVIDE_CHECK(sectionstats.coded_error);
+
+        Ratio = sectionstats.intra_error / DOUBLE_DIVIDE_CHECK(sectionstats.coded_error);
+        // if( (Ratio > 11) ) //&& (sectionstats.pcnt_second_ref < .20) )
+        //{
+        cpi->section_max_qfactor = 1.0 - ((Ratio - 10.0) * 0.025);
+
+        if (cpi->section_max_qfactor < 0.80)
+            cpi->section_max_qfactor = 0.80;
+
+        //}
+        //else
+        //    cpi->section_max_qfactor = 1.0;
+    }
+
+    // When using CBR apply additional buffer fullness related upper limits
+    if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+    {
+        double max_boost;
+
+        if (cpi->drop_frames_allowed)
+        {
+            int df_buffer_level = cpi->oxcf.drop_frames_water_mark * (cpi->oxcf.optimal_buffer_level / 100);
+
+            if (cpi->buffer_level > df_buffer_level)
+                max_boost = ((double)((cpi->buffer_level - df_buffer_level) * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
+            else
+                max_boost = 0.0;
+        }
+        else if (cpi->buffer_level > 0)
+        {
+            max_boost = ((double)(cpi->buffer_level * 2 / 3) * 16.0) / DOUBLE_DIVIDE_CHECK((double)cpi->av_per_frame_bandwidth);
+        }
+        else
+        {
+            max_boost = 0.0;
+        }
+
+        if (boost_score > max_boost)
+            boost_score = max_boost;
+    }
+
+    // Reset the first pass file position
+    reset_fpf_position(cpi, start_position);
+
+    // Work out how many bits to allocate for the key frame itself
+    if (1)
+    {
+        int kf_boost = boost_score;
+        int allocation_chunks;
+        int Counter = cpi->frames_to_key;
+        int alt_kf_bits;
+
+        // Min boost based on kf interval
+#if 0
+
+        while ((kf_boost < 48) && (Counter > 0))
+        {
+            Counter -= 2;
+            kf_boost ++;
+        }
+
+#endif
+
+        if (kf_boost < 48)
+        {
+            kf_boost += ((Counter + 1) >> 1);
+
+            if (kf_boost > 48) kf_boost = 48;
+        }
+
+        // bigger frame sizes need larger kf boosts, smaller frames smaller boosts...
+        if ((cpi->common.last_frame.y_width  * cpi->common.last_frame.y_height) > (320 * 240))
+            kf_boost += 2 * (cpi->common.last_frame.y_width  * cpi->common.last_frame.y_height) / (320 * 240);
+        else if ((cpi->common.last_frame.y_width  * cpi->common.last_frame.y_height) < (320 * 240))
+            kf_boost -= 4 * (320 * 240) / (cpi->common.last_frame.y_width  * cpi->common.last_frame.y_height);
+
+        kf_boost = (int)((double)kf_boost * 100.0) >> 4;                          // Scale 16 to 100
+
+        // Adjustment to boost based on recent average q
+        kf_boost = kf_boost * vp8_kf_boost_qadjustment[cpi->ni_av_qi] / 100;
+
+        if (kf_boost < 250)                                                      // Min KF boost
+            kf_boost = 250;
+
+        // We do three calculations for kf size.
+        // The first is based on the error score for the whole kf group.
+        // The second (optionaly) on the key frames own error if this is smaller than the average for the group.
+        // The final one insures that the frame receives at least the allocation it would have received based on its own error score vs the error score remaining
+
+        allocation_chunks = ((cpi->frames_to_key - 1) * 100) + kf_boost;           // cpi->frames_to_key-1 because key frame itself is taken care of by kf_boost
+
+        // Normalize Altboost and allocations chunck down to prevent overflow
+        while (kf_boost > 1000)
+        {
+            kf_boost /= 2;
+            allocation_chunks /= 2;
+        }
+
+        cpi->kf_group_bits = (cpi->kf_group_bits < 0) ? 0 : cpi->kf_group_bits;
+
+        // Calculate the number of bits to be spent on the key frame
+        cpi->kf_bits  = (int)((double)kf_boost * ((double)cpi->kf_group_bits / (double)allocation_chunks));
+
+        // Apply an additional limit for CBR
+        if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+        {
+            if (cpi->kf_bits > ((3 * cpi->buffer_level) >> 2))
+                cpi->kf_bits = (3 * cpi->buffer_level) >> 2;
+        }
+
+        // If the key frame is actually easier than the average for the kf group (which does sometimes happen... eg a blank intro frame)
+        // Then use an alternate calculation based on the kf error score which should give a smaller key frame.
+        if (kf_mod_err < kf_group_err / cpi->frames_to_key)
+        {
+            double  alt_kf_grp_bits = ((double)cpi->bits_left * (kf_mod_err * (double)cpi->frames_to_key) / cpi->modified_total_error_left) ;
+
+            alt_kf_bits = (int)((double)kf_boost * (alt_kf_grp_bits / (double)allocation_chunks));
+
+            if (cpi->kf_bits > alt_kf_bits)
+            {
+                cpi->kf_bits = alt_kf_bits;
+            }
+        }
+        // Else if it is much harder than other frames in the group make sure it at least receives an allocation in keeping with its relative error score
+        else
+        {
+            alt_kf_bits = (int)((double)cpi->bits_left * (kf_mod_err / cpi->modified_total_error_left));
+
+            if (alt_kf_bits > cpi->kf_bits)
+            {
+                cpi->kf_bits = alt_kf_bits;
+            }
+        }
+
+        cpi->kf_group_bits -= cpi->kf_bits;
+        cpi->kf_bits += cpi->min_frame_bandwidth;                                          // Add in the minimum frame allowance
+
+        cpi->per_frame_bandwidth = cpi->kf_bits;                                           // Peer frame bit target for this frame
+        cpi->target_bandwidth = cpi->kf_bits * cpi->output_frame_rate;                      // Convert to a per second bitrate
+    }
+
+    // Note the total error score of the kf group minus the key frame itself
+    cpi->kf_group_error_left = (int)(kf_group_err - kf_mod_err);
+
+    // Adjust the count of total modified error left.
+    // The count of bits left is adjusted elsewhere based on real coded frame sizes
+    cpi->modified_total_error_left -= kf_group_err;
+
+    if (cpi->oxcf.allow_spatial_resampling)
+    {
+        int resample_trigger = FALSE;
+        int last_kf_resampled = FALSE;
+        int kf_q;
+        int scale_val = 0;
+        int hr, hs, vr, vs;
+        int new_width = cpi->oxcf.Width;
+        int new_height = cpi->oxcf.Height;
+
+        int projected_buffer_level = cpi->buffer_level;
+        int tmp_q;
+
+        double projected_bits_perframe;
+        double group_iiratio = (kf_group_intra_err - first_frame.intra_error) / (kf_group_coded_err - first_frame.coded_error);
+        double err_per_frame = kf_group_err / cpi->frames_to_key;
+        double bits_per_frame;
+        double av_bits_per_frame;
+        double effective_size_ratio;
+
+        if ((cpi->common.Width != cpi->oxcf.Width) || (cpi->common.Height != cpi->oxcf.Height))
+            last_kf_resampled = TRUE;
+
+        // Set back to unscaled by defaults
+        cpi->common.horiz_scale = NORMAL;
+        cpi->common.vert_scale = NORMAL;
+
+        // Calculate Average bits per frame.
+        //av_bits_per_frame = cpi->bits_left/(double)(cpi->total_stats.count - cpi->common.current_video_frame);
+        av_bits_per_frame = cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate);
+        //if ( av_bits_per_frame < 0.0 )
+        //  av_bits_per_frame = 0.0
+
+        // CBR... Use the clip average as the target for deciding resample
+        if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+        {
+            bits_per_frame = av_bits_per_frame;
+        }
+
+        // In VBR we want to avoid downsampling in easy section unless we are under extreme pressure
+        // So use the larger of target bitrate for this sectoion or average bitrate for sequence
+        else
+        {
+            bits_per_frame = cpi->kf_group_bits / cpi->frames_to_key;     // This accounts for how hard the section is...
+
+            if (bits_per_frame < av_bits_per_frame)                      // Dont turn to resampling in easy sections just because they have been assigned a small number of bits
+                bits_per_frame = av_bits_per_frame;
+        }
+
+        // bits_per_frame should comply with our minimum
+        if (bits_per_frame < (cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100))
+            bits_per_frame = (cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+
+        // Work out if spatial resampling is necessary
+        kf_q = estimate_kf_group_q(cpi, err_per_frame, bits_per_frame, new_height, new_width, group_iiratio);
+
+        // If we project a required Q higher than the maximum allowed Q then make a guess at the actual size of frames in this section
+        projected_bits_perframe = bits_per_frame;
+        tmp_q = kf_q;
+
+        while (tmp_q > cpi->worst_quality)
+        {
+            projected_bits_perframe *= 1.04;
+            tmp_q--;
+        }
+
+        // Guess at buffer level at the end of the section
+        projected_buffer_level = cpi->buffer_level - (int)((projected_bits_perframe - av_bits_per_frame) * cpi->frames_to_key);
+
+        if (0)
+        {
+            FILE *f = fopen("Subsamle.stt", "a");
+            fprintf(f, " %8d %8d %8d %8d %12.0f %8d %8d %8d\n",  cpi->common.current_video_frame, kf_q, cpi->common.horiz_scale, cpi->common.vert_scale,  kf_group_err / cpi->frames_to_key, cpi->kf_group_bits / cpi->frames_to_key, new_height, new_width);
+            fclose(f);
+        }
+
+        // The trigger for spatial resampling depends on the various parameters such as whether we are streaming (CBR) or VBR.
+        if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+        {
+            // Trigger resample if we are projected to fall below down sample level or
+            // resampled last time and are projected to remain below the up sample level
+            if ((projected_buffer_level < (cpi->oxcf.resample_down_water_mark * cpi->oxcf.optimal_buffer_level / 100)) ||
+                (last_kf_resampled && (projected_buffer_level < (cpi->oxcf.resample_up_water_mark * cpi->oxcf.optimal_buffer_level / 100))))
+                //( ((cpi->buffer_level < (cpi->oxcf.resample_down_water_mark * cpi->oxcf.optimal_buffer_level / 100))) &&
+                //  ((projected_buffer_level < (cpi->oxcf.resample_up_water_mark * cpi->oxcf.optimal_buffer_level / 100))) ))
+                resample_trigger = TRUE;
+            else
+                resample_trigger = FALSE;
+        }
+        else
+        {
+            long long clip_bits = (long long)(cpi->total_stats.count * cpi->oxcf.target_bandwidth / DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.frame_rate));
+            long long over_spend = cpi->oxcf.starting_buffer_level - cpi->buffer_level;
+            long long over_spend2 = cpi->oxcf.starting_buffer_level - projected_buffer_level;
+
+            if ((last_kf_resampled && (kf_q > cpi->worst_quality)) ||                                               // If triggered last time the threshold for triggering again is reduced
+                ((kf_q > cpi->worst_quality) &&                                                                  // Projected Q higher than allowed and ...
+                 (over_spend > clip_bits / 20)))                                                               // ... Overspend > 5% of total bits
+                resample_trigger = TRUE;
+            else
+                resample_trigger = FALSE;
+
+        }
+
+        if (resample_trigger)
+        {
+            while ((kf_q >= cpi->worst_quality) && (scale_val < 6))
+            {
+                scale_val ++;
+
+                cpi->common.vert_scale   = vscale_lookup[scale_val];
+                cpi->common.horiz_scale  = hscale_lookup[scale_val];
+
+                Scale2Ratio(cpi->common.horiz_scale, &hr, &hs);
+                Scale2Ratio(cpi->common.vert_scale, &vr, &vs);
+
+                new_width = ((hs - 1) + (cpi->oxcf.Width * hr)) / hs;
+                new_height = ((vs - 1) + (cpi->oxcf.Height * vr)) / vs;
+
+                // Reducing the area to 1/4 does not reduce the complexity (err_per_frame) to 1/4...
+                // effective_sizeratio attempts to provide a crude correction for this
+                effective_size_ratio = (double)(new_width * new_height) / (double)(cpi->oxcf.Width * cpi->oxcf.Height);
+                effective_size_ratio = (1.0 + (3.0 * effective_size_ratio)) / 4.0;
+
+                // Now try again and see what Q we get with the smaller image size
+                kf_q = estimate_kf_group_q(cpi, err_per_frame * effective_size_ratio, bits_per_frame, new_height, new_width, group_iiratio);
+
+                if (0)
+                {
+                    FILE *f = fopen("Subsamle.stt", "a");
+                    fprintf(f, "******** %8d %8d %8d %12.0f %8d %8d %8d\n",  kf_q, cpi->common.horiz_scale, cpi->common.vert_scale,  kf_group_err / cpi->frames_to_key, cpi->kf_group_bits / cpi->frames_to_key, new_height, new_width);
+                    fclose(f);
+                }
+            }
+        }
+
+        if ((cpi->common.Width != new_width) || (cpi->common.Height != new_height))
+        {
+            cpi->common.Width = new_width;
+            cpi->common.Height = new_height;
+            vp8_alloc_compressor_data(cpi);
+        }
+    }
+}
diff --git a/vp8/encoder/firstpass.h b/vp8/encoder/firstpass.h
new file mode 100644
index 0000000..d7b52f3
--- /dev/null
+++ b/vp8/encoder/firstpass.h
@@ -0,0 +1,22 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#if !defined __INC_FIRSTPASS_H
+#define      __INC_FIRSTPASS_H
+
+extern void vp8_init_first_pass(VP8_COMP *cpi);
+extern void vp8_first_pass(VP8_COMP *cpi);
+extern void vp8_end_first_pass(VP8_COMP *cpi);
+
+extern void vp8_init_second_pass(VP8_COMP *cpi);
+extern void vp8_second_pass(VP8_COMP *cpi);
+extern void vp8_end_second_pass(VP8_COMP *cpi);
+
+#endif
diff --git a/vp8/encoder/generic/csystemdependent.c b/vp8/encoder/generic/csystemdependent.c
new file mode 100644
index 0000000..52aab66
--- /dev/null
+++ b/vp8/encoder/generic/csystemdependent.c
@@ -0,0 +1,96 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "variance.h"
+#include "onyx_int.h"
+
+
+void vp8_arch_x86_encoder_init(VP8_COMP *cpi);
+
+
+void (*vp8_fast_quantize_b)(BLOCK *b, BLOCKD *d);
+extern void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d);
+
+void (*vp8_yv12_copy_partial_frame_ptr)(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc, int Fraction);
+extern void vp8_yv12_copy_partial_frame(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc, int Fraction);
+
+void vp8_cmachine_specific_config(VP8_COMP *cpi)
+{
+#if CONFIG_RUNTIME_CPU_DETECT
+    cpi->rtcd.common                    = &cpi->common.rtcd;
+    cpi->rtcd.variance.sad16x16              = vp8_sad16x16_c;
+    cpi->rtcd.variance.sad16x8               = vp8_sad16x8_c;
+    cpi->rtcd.variance.sad8x16               = vp8_sad8x16_c;
+    cpi->rtcd.variance.sad8x8                = vp8_sad8x8_c;
+    cpi->rtcd.variance.sad4x4                = vp8_sad4x4_c;
+
+    cpi->rtcd.variance.sad16x16x3            = vp8_sad16x16x3_c;
+    cpi->rtcd.variance.sad16x8x3             = vp8_sad16x8x3_c;
+    cpi->rtcd.variance.sad8x16x3             = vp8_sad8x16x3_c;
+    cpi->rtcd.variance.sad8x8x3              = vp8_sad8x8x3_c;
+    cpi->rtcd.variance.sad4x4x3              = vp8_sad4x4x3_c;
+
+    cpi->rtcd.variance.sad16x16x4d           = vp8_sad16x16x4d_c;
+    cpi->rtcd.variance.sad16x8x4d            = vp8_sad16x8x4d_c;
+    cpi->rtcd.variance.sad8x16x4d            = vp8_sad8x16x4d_c;
+    cpi->rtcd.variance.sad8x8x4d             = vp8_sad8x8x4d_c;
+    cpi->rtcd.variance.sad4x4x4d             = vp8_sad4x4x4d_c;
+
+    cpi->rtcd.variance.var4x4                = vp8_variance4x4_c;
+    cpi->rtcd.variance.var8x8                = vp8_variance8x8_c;
+    cpi->rtcd.variance.var8x16               = vp8_variance8x16_c;
+    cpi->rtcd.variance.var16x8               = vp8_variance16x8_c;
+    cpi->rtcd.variance.var16x16              = vp8_variance16x16_c;
+
+    cpi->rtcd.variance.subpixvar4x4          = vp8_sub_pixel_variance4x4_c;
+    cpi->rtcd.variance.subpixvar8x8          = vp8_sub_pixel_variance8x8_c;
+    cpi->rtcd.variance.subpixvar8x16         = vp8_sub_pixel_variance8x16_c;
+    cpi->rtcd.variance.subpixvar16x8         = vp8_sub_pixel_variance16x8_c;
+    cpi->rtcd.variance.subpixvar16x16        = vp8_sub_pixel_variance16x16_c;
+    cpi->rtcd.variance.subpixmse16x16        = vp8_sub_pixel_mse16x16_c;
+
+    cpi->rtcd.variance.mse16x16              = vp8_mse16x16_c;
+    cpi->rtcd.variance.getmbss               = vp8_get_mb_ss_c;
+
+    cpi->rtcd.variance.get16x16prederror     = vp8_get16x16pred_error_c;
+    cpi->rtcd.variance.get8x8var             = vp8_get8x8var_c;
+    cpi->rtcd.variance.get16x16var           = vp8_get16x16var_c;;
+    cpi->rtcd.variance.get4x4sse_cs          = vp8_get4x4sse_cs_c;
+
+    cpi->rtcd.fdct.short4x4                  = vp8_short_fdct4x4_c;
+    cpi->rtcd.fdct.short8x4                  = vp8_short_fdct8x4_c;
+    cpi->rtcd.fdct.fast4x4                   = vp8_fast_fdct4x4_c;
+    cpi->rtcd.fdct.fast8x4                   = vp8_fast_fdct8x4_c;
+    cpi->rtcd.fdct.walsh_short4x4            = vp8_short_walsh4x4_c;
+
+    cpi->rtcd.encodemb.berr                  = vp8_block_error_c;
+    cpi->rtcd.encodemb.mberr                 = vp8_mbblock_error_c;
+    cpi->rtcd.encodemb.mbuverr               = vp8_mbuverror_c;
+    cpi->rtcd.encodemb.subb                  = vp8_subtract_b_c;
+    cpi->rtcd.encodemb.submby                = vp8_subtract_mby_c;
+    cpi->rtcd.encodemb.submbuv               = vp8_subtract_mbuv_c;
+
+    cpi->rtcd.quantize.quantb                = vp8_regular_quantize_b;
+    cpi->rtcd.quantize.fastquantb            = vp8_fast_quantize_b_c;
+
+    cpi->rtcd.search.full_search             = vp8_full_search_sad;
+    cpi->rtcd.search.diamond_search          = vp8_diamond_search_sad;
+#endif
+
+    // Pure C:
+    vp8_yv12_copy_partial_frame_ptr = vp8_yv12_copy_partial_frame;
+
+
+#if ARCH_X86 || ARCH_X86_64
+    vp8_arch_x86_encoder_init(cpi);
+#endif
+
+}
diff --git a/vp8/encoder/mcomp.c b/vp8/encoder/mcomp.c
new file mode 100644
index 0000000..d80059d
--- /dev/null
+++ b/vp8/encoder/mcomp.c
@@ -0,0 +1,1467 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "mcomp.h"
+#include "vpx_mem/vpx_mem.h"
+
+#include <stdio.h>
+#include <limits.h>
+#include <math.h>
+
+#ifdef ENTROPY_STATS
+static int mv_ref_ct [31] [4] [2];
+static int mv_mode_cts [4] [2];
+#endif
+
+static int mv_bits_sadcost[256];
+
+void vp8cx_init_mv_bits_sadcost()
+{
+    int i;
+
+    for (i = 0; i < 256; i++)
+    {
+        mv_bits_sadcost[i] = (int)sqrt(i * 16);
+    }
+}
+
+
+int vp8_mv_bit_cost(MV *mv, MV *ref, int *mvcost[2], int Weight)
+{
+    // MV costing is based on the distribution of vectors in the previous frame and as such will tend to
+    // over state the cost of vectors. In addition coding a new vector can have a knock on effect on the
+    // cost of subsequent vectors and the quality of prediction from NEAR and NEAREST for subsequent blocks.
+    // The "Weight" parameter allows, to a limited extent, for some account to be taken of these factors.
+    return ((mvcost[0][(mv->row - ref->row) >> 1] + mvcost[1][(mv->col - ref->col) >> 1]) * Weight) >> 7;
+}
+
+int vp8_mv_err_cost(MV *mv, MV *ref, int *mvcost[2], int error_per_bit)
+{
+    //int i;
+    //return ((mvcost[0][(mv->row - ref->row)>>1] + mvcost[1][(mv->col - ref->col)>>1] + 128) * error_per_bit) >> 8;
+    //return ( (vp8_mv_bit_cost(mv,  ref, mvcost, 100) + 128) * error_per_bit) >> 8;
+
+    //i = (vp8_mv_bit_cost(mv,  ref, mvcost, 100) * error_per_bit + 128) >> 8;
+    return ((mvcost[0][(mv->row - ref->row) >> 1] + mvcost[1][(mv->col - ref->col) >> 1]) * error_per_bit + 128) >> 8;
+    //return (vp8_mv_bit_cost(mv,  ref, mvcost, 128) * error_per_bit + 128) >> 8;
+}
+
+
+static int mv_bits(MV *mv, MV *ref, int *mvcost[2])
+{
+    // get the estimated number of bits for a motion vector, to be used for costing in SAD based
+    // motion estimation
+    return ((mvcost[0][(mv->row - ref->row) >> 1]  +  mvcost[1][(mv->col - ref->col)>> 1]) + 128) >> 8;
+}
+
+void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride)
+{
+    int Len;
+    int search_site_count = 0;
+
+
+    // Generate offsets for 4 search sites per step.
+    Len = MAX_FIRST_STEP;
+    x->ss[search_site_count].mv.col = 0;
+    x->ss[search_site_count].mv.row = 0;
+    x->ss[search_site_count].offset = 0;
+    search_site_count++;
+
+    while (Len > 0)
+    {
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = 0;
+        x->ss[search_site_count].mv.row = -Len;
+        x->ss[search_site_count].offset = -Len * stride;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = 0;
+        x->ss[search_site_count].mv.row = Len;
+        x->ss[search_site_count].offset = Len * stride;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = -Len;
+        x->ss[search_site_count].mv.row = 0;
+        x->ss[search_site_count].offset = -Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = Len;
+        x->ss[search_site_count].mv.row = 0;
+        x->ss[search_site_count].offset = Len;
+        search_site_count++;
+
+        // Contract.
+        Len /= 2;
+    }
+
+    x->ss_count = search_site_count;
+    x->searches_per_step = 4;
+}
+
+void vp8_init3smotion_compensation(MACROBLOCK *x, int stride)
+{
+    int Len;
+    int search_site_count = 0;
+
+    // Generate offsets for 8 search sites per step.
+    Len = MAX_FIRST_STEP;
+    x->ss[search_site_count].mv.col = 0;
+    x->ss[search_site_count].mv.row = 0;
+    x->ss[search_site_count].offset = 0;
+    search_site_count++;
+
+    while (Len > 0)
+    {
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = 0;
+        x->ss[search_site_count].mv.row = -Len;
+        x->ss[search_site_count].offset = -Len * stride;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = 0;
+        x->ss[search_site_count].mv.row = Len;
+        x->ss[search_site_count].offset = Len * stride;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = -Len;
+        x->ss[search_site_count].mv.row = 0;
+        x->ss[search_site_count].offset = -Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = Len;
+        x->ss[search_site_count].mv.row = 0;
+        x->ss[search_site_count].offset = Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = -Len;
+        x->ss[search_site_count].mv.row = -Len;
+        x->ss[search_site_count].offset = -Len * stride - Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = Len;
+        x->ss[search_site_count].mv.row = -Len;
+        x->ss[search_site_count].offset = -Len * stride + Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = -Len;
+        x->ss[search_site_count].mv.row = Len;
+        x->ss[search_site_count].offset = Len * stride - Len;
+        search_site_count++;
+
+        // Compute offsets for search sites.
+        x->ss[search_site_count].mv.col = Len;
+        x->ss[search_site_count].mv.row = Len;
+        x->ss[search_site_count].offset = Len * stride + Len;
+        search_site_count++;
+
+
+        // Contract.
+        Len /= 2;
+    }
+
+    x->ss_count = search_site_count;
+    x->searches_per_step = 8;
+}
+
+
+#define MVC(r,c) (((mvcost[0][(r)-rr] + mvcost[1][(c) - rc]) * error_per_bit + 128 )>>8 ) // estimated cost of a motion vector (r,c)
+#define PRE(r,c) (*(d->base_pre) + d->pre + ((r)>>2) * d->pre_stride + ((c)>>2)) // pointer to predictor base of a motionvector
+#define SP(x) (((x)&3)<<1) // convert motion vector component to offset for svf calc
+#define DIST(r,c) svf( PRE(r,c), d->pre_stride, SP(c),SP(r), z,b->src_stride,&sse) // returns subpixel variance error function.
+#define IFMVCV(r,c,s,e) if ( c >= minc && c <= maxc && r >= minr && r <= maxr) s else e;
+#define ERR(r,c) (MVC(r,c)+DIST(r,c)) // returns distortion + motion vector cost
+#define CHECK_BETTER(v,r,c) IFMVCV(r,c,{if((v = ERR(r,c)) < besterr) { besterr = v; br=r; bc=c; }}, v=INT_MAX;)// checks if (r,c) has better score than previous best
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#define MAX(x,y) (((x)>(y))?(x):(y))
+
+//#define CHECK_BETTER(v,r,c) if((v = ERR(r,c)) < besterr) { besterr = v; br=r; bc=c; }
+
+int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d, MV *bestmv, MV *ref_mv, int error_per_bit, vp8_subpixvariance_fn_t svf, vp8_variance_fn_t vf, int *mvcost[2])
+{
+    unsigned char *y = *(d->base_pre) + d->pre + (bestmv->row) * d->pre_stride + bestmv->col;
+    unsigned char *z = (*(b->base_src) + b->src);
+
+    int rr = ref_mv->row >> 1, rc = ref_mv->col >> 1;
+    int br = bestmv->row << 2, bc = bestmv->col << 2;
+    int tr = br, tc = bc;
+    unsigned int besterr = INT_MAX;
+    unsigned int left, right, up, down, diag;
+    unsigned int sse;
+    unsigned int whichdir;
+    unsigned int halfiters = 4;
+    unsigned int quarteriters = 4;
+
+    int minc = MAX(x->mv_col_min << 2, (ref_mv->col >> 1) - ((1 << mvlong_width) - 1));
+    int maxc = MIN(x->mv_col_max << 2, (ref_mv->col >> 1) + ((1 << mvlong_width) - 1));
+    int minr = MAX(x->mv_row_min << 2, (ref_mv->row >> 1) - ((1 << mvlong_width) - 1));
+    int maxr = MIN(x->mv_row_max << 2, (ref_mv->row >> 1) + ((1 << mvlong_width) - 1));
+
+    // central mv
+    bestmv->row <<= 3;
+    bestmv->col <<= 3;
+
+    // calculate central point error
+    besterr = vf(y, d->pre_stride, z, b->src_stride, &sse);
+    besterr += vp8_mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
+
+    // TODO: Each subsequent iteration checks at least one point in common with the last iteration could be 2 ( if diag selected)
+    while (--halfiters)
+    {
+        // 1/2 pel
+        CHECK_BETTER(left, tr, tc - 2);
+        CHECK_BETTER(right, tr, tc + 2);
+        CHECK_BETTER(up, tr - 2, tc);
+        CHECK_BETTER(down, tr + 2, tc);
+
+        whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+
+        switch (whichdir)
+        {
+        case 0:
+            CHECK_BETTER(diag, tr - 2, tc - 2);
+            break;
+        case 1:
+            CHECK_BETTER(diag, tr - 2, tc + 2);
+            break;
+        case 2:
+            CHECK_BETTER(diag, tr + 2, tc - 2);
+            break;
+        case 3:
+            CHECK_BETTER(diag, tr + 2, tc + 2);
+            break;
+        }
+
+        // no reason to check the same one again.
+        if (tr == br && tc == bc)
+            break;
+
+        tr = br;
+        tc = bc;
+    }
+
+    // TODO: Each subsequent iteration checks at least one point in common with the last iteration could be 2 ( if diag selected)
+    // 1/4 pel
+    while (--quarteriters)
+    {
+        CHECK_BETTER(left, tr, tc - 1);
+        CHECK_BETTER(right, tr, tc + 1);
+        CHECK_BETTER(up, tr - 1, tc);
+        CHECK_BETTER(down, tr + 1, tc);
+
+        whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+
+        switch (whichdir)
+        {
+        case 0:
+            CHECK_BETTER(diag, tr - 1, tc - 1);
+            break;
+        case 1:
+            CHECK_BETTER(diag, tr - 1, tc + 1);
+            break;
+        case 2:
+            CHECK_BETTER(diag, tr + 1, tc - 1);
+            break;
+        case 3:
+            CHECK_BETTER(diag, tr + 1, tc + 1);
+            break;
+        }
+
+        // no reason to check the same one again.
+        if (tr == br && tc == bc)
+            break;
+
+        tr = br;
+        tc = bc;
+    }
+
+    bestmv->row = br << 1;
+    bestmv->col = bc << 1;
+
+    if ((abs(bestmv->col - ref_mv->col) > MAX_FULL_PEL_VAL) || (abs(bestmv->row - ref_mv->row) > MAX_FULL_PEL_VAL))
+        return INT_MAX;
+
+    return besterr;
+}
+#undef MVC
+#undef PRE
+#undef SP
+#undef DIST
+#undef ERR
+#undef CHECK_BETTER
+#undef MIN
+#undef MAX
+int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, MV *bestmv, MV *ref_mv, int error_per_bit, vp8_subpixvariance_fn_t svf, vp8_variance_fn_t vf, int *mvcost[2])
+{
+    int bestmse = INT_MAX;
+    MV startmv;
+    //MV this_mv;
+    MV this_mv;
+    unsigned char *y = *(d->base_pre) + d->pre + (bestmv->row) * d->pre_stride + bestmv->col;
+    unsigned char *z = (*(b->base_src) + b->src);
+    int left, right, up, down, diag;
+    unsigned int sse;
+    int whichdir ;
+
+
+    // Trap uncodable vectors
+    if ((abs((bestmv->col << 3) - ref_mv->col) > MAX_FULL_PEL_VAL) || (abs((bestmv->row << 3) - ref_mv->row) > MAX_FULL_PEL_VAL))
+    {
+        bestmv->row <<= 3;
+        bestmv->col <<= 3;
+        return INT_MAX;
+    }
+
+    // central mv
+    bestmv->row <<= 3;
+    bestmv->col <<= 3;
+    startmv = *bestmv;
+
+    // calculate central point error
+    bestmse = vf(y, d->pre_stride, z, b->src_stride, &sse);
+    bestmse += vp8_mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
+
+    // go left then right and check error
+    this_mv.row = startmv.row;
+    this_mv.col = ((startmv.col - 8) | 4);
+    left = svf(y - 1, d->pre_stride, 4, 0, z, b->src_stride, &sse);
+    left += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (left < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = left;
+    }
+
+    this_mv.col += 8;
+    right = svf(y, d->pre_stride, 4, 0, z, b->src_stride, &sse);
+    right += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (right < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = right;
+    }
+
+    // go up then down and check error
+    this_mv.col = startmv.col;
+    this_mv.row = ((startmv.row - 8) | 4);
+    up = svf(y - d->pre_stride, d->pre_stride, 0, 4, z, b->src_stride, &sse);
+    up += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (up < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = up;
+    }
+
+    this_mv.row += 8;
+    down = svf(y, d->pre_stride, 0, 4, z, b->src_stride, &sse);
+    down += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (down < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = down;
+    }
+
+
+    // now check 1 more diagonal
+    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+    // whichdir must be 0-4. Therefore, one of the cases below
+    // must run through. However, because there is no default
+    // and diag is not set elsewhere, we get a compile warning
+    diag = 0;
+    //for(whichdir =0;whichdir<4;whichdir++)
+    //{
+    this_mv = startmv;
+
+    switch (whichdir)
+    {
+    case 0:
+        this_mv.col = (this_mv.col - 8) | 4;
+        this_mv.row = (this_mv.row - 8) | 4;
+        diag = svf(y - 1 - d->pre_stride, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+        break;
+    case 1:
+        this_mv.col += 4;
+        this_mv.row = (this_mv.row - 8) | 4;
+        diag = svf(y - d->pre_stride, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+        break;
+    case 2:
+        this_mv.col = (this_mv.col - 8) | 4;
+        this_mv.row += 4;
+        diag = svf(y - 1, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+        break;
+    case 3:
+        this_mv.col += 4;
+        this_mv.row += 4;
+        diag = svf(y, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+        break;
+    }
+
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+//  }
+
+
+    // time to check quarter pels.
+    if (bestmv->row < startmv.row)
+        y -= d->pre_stride;
+
+    if (bestmv->col < startmv.col)
+        y--;
+
+    startmv = *bestmv;
+
+
+
+    // go left then right and check error
+    this_mv.row = startmv.row;
+
+    if (startmv.col & 7)
+    {
+        this_mv.col = startmv.col - 2;
+        left = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+    }
+    else
+    {
+        this_mv.col = (startmv.col - 8) | 6;
+        left = svf(y - 1, d->pre_stride, 6, this_mv.row & 7, z, b->src_stride, &sse);
+    }
+
+    left += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (left < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = left;
+    }
+
+    this_mv.col += 4;
+    right = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+    right += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (right < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = right;
+    }
+
+    // go up then down and check error
+    this_mv.col = startmv.col;
+
+    if (startmv.row & 7)
+    {
+        this_mv.row = startmv.row - 2;
+        up = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+    }
+    else
+    {
+        this_mv.row = (startmv.row - 8) | 6;
+        up = svf(y - d->pre_stride, d->pre_stride, this_mv.col & 7, 6, z, b->src_stride, &sse);
+    }
+
+    up += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (up < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = up;
+    }
+
+    this_mv.row += 4;
+    down = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+    down += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (down < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = down;
+    }
+
+
+    // now check 1 more diagonal
+    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+
+//  for(whichdir=0;whichdir<4;whichdir++)
+//  {
+    this_mv = startmv;
+
+    switch (whichdir)
+    {
+    case 0:
+
+        if (startmv.row & 7)
+        {
+            this_mv.row -= 2;
+
+            if (startmv.col & 7)
+            {
+                this_mv.col -= 2;
+                diag = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+            }
+            else
+            {
+                this_mv.col = (startmv.col - 8) | 6;
+                diag = svf(y - 1, d->pre_stride, 6, this_mv.row & 7, z, b->src_stride, &sse);;
+            }
+        }
+        else
+        {
+            this_mv.row = (startmv.row - 8) | 6;
+
+            if (startmv.col & 7)
+            {
+                this_mv.col -= 2;
+                diag = svf(y - d->pre_stride, d->pre_stride, this_mv.col & 7, 6, z, b->src_stride, &sse);
+            }
+            else
+            {
+                this_mv.col = (startmv.col - 8) | 6;
+                diag = svf(y - d->pre_stride - 1, d->pre_stride, 6, 6, z, b->src_stride, &sse);
+            }
+        }
+
+        break;
+    case 1:
+        this_mv.col += 2;
+
+        if (startmv.row & 7)
+        {
+            this_mv.row -= 2;
+            diag = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+        }
+        else
+        {
+            this_mv.row = (startmv.row - 8) | 6;
+            diag = svf(y - d->pre_stride, d->pre_stride, this_mv.col & 7, 6, z, b->src_stride, &sse);
+        }
+
+        break;
+    case 2:
+        this_mv.row += 2;
+
+        if (startmv.col & 7)
+        {
+            this_mv.col -= 2;
+            diag = svf(y, d->pre_stride, this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+        }
+        else
+        {
+            this_mv.col = (startmv.col - 8) | 6;
+            diag = svf(y - 1, d->pre_stride, 6, this_mv.row & 7, z, b->src_stride, &sse);;
+        }
+
+        break;
+    case 3:
+        this_mv.col += 2;
+        this_mv.row += 2;
+        diag = svf(y, d->pre_stride,  this_mv.col & 7, this_mv.row & 7, z, b->src_stride, &sse);
+        break;
+    }
+
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+//  }
+
+    return bestmse;
+}
+
+int vp8_find_best_half_pixel_step(MACROBLOCK *mb, BLOCK *b, BLOCKD *d, MV *bestmv, MV *ref_mv, int error_per_bit, vp8_subpixvariance_fn_t svf, vp8_variance_fn_t vf, int *mvcost[2])
+{
+    int bestmse = INT_MAX;
+    MV startmv;
+    //MV this_mv;
+    MV this_mv;
+    unsigned char *y = *(d->base_pre) + d->pre + (bestmv->row) * d->pre_stride + bestmv->col;
+    unsigned char *z = (*(b->base_src) + b->src);
+    int left, right, up, down, diag;
+    unsigned int sse;
+
+    // Trap uncodable vectors
+    if ((abs((bestmv->col << 3) - ref_mv->col) > MAX_FULL_PEL_VAL) || (abs((bestmv->row << 3) - ref_mv->row) > MAX_FULL_PEL_VAL))
+    {
+        bestmv->row <<= 3;
+        bestmv->col <<= 3;
+        return INT_MAX;
+    }
+
+    // central mv
+    bestmv->row <<= 3;
+    bestmv->col <<= 3;
+    startmv = *bestmv;
+
+    // calculate central point error
+    bestmse = vf(y, d->pre_stride, z, b->src_stride, &sse);
+    bestmse += vp8_mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit);
+
+    // go left then right and check error
+    this_mv.row = startmv.row;
+    this_mv.col = ((startmv.col - 8) | 4);
+    left = svf(y - 1, d->pre_stride, 4, 0, z, b->src_stride, &sse);
+    left += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (left < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = left;
+    }
+
+    this_mv.col += 8;
+    right = svf(y, d->pre_stride, 4, 0, z, b->src_stride, &sse);
+    right += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (right < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = right;
+    }
+
+    // go up then down and check error
+    this_mv.col = startmv.col;
+    this_mv.row = ((startmv.row - 8) | 4);
+    up = svf(y - d->pre_stride, d->pre_stride, 0, 4, z, b->src_stride, &sse);
+    up += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (up < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = up;
+    }
+
+    this_mv.row += 8;
+    down = svf(y, d->pre_stride, 0, 4, z, b->src_stride, &sse);
+    down += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (down < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = down;
+    }
+
+    // somewhat strangely not doing all the diagonals for half pel is slower than doing them.
+#if 0
+    // now check 1 more diagonal -
+    whichdir = (left < right ? 0 : 1) + (up < down ? 0 : 2);
+    this_mv = startmv;
+
+    switch (whichdir)
+    {
+    case 0:
+        this_mv.col = (this_mv.col - 8) | 4;
+        this_mv.row = (this_mv.row - 8) | 4;
+        diag = svf(y - 1 - d->pre_stride, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+        break;
+    case 1:
+        this_mv.col += 4;
+        this_mv.row = (this_mv.row - 8) | 4;
+        diag = svf(y - d->pre_stride, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+        break;
+    case 2:
+        this_mv.col = (this_mv.col - 8) | 4;
+        this_mv.row += 4;
+        diag = svf(y - 1, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+        break;
+    case 3:
+        this_mv.col += 4;
+        this_mv.row += 4;
+        diag = svf(y, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+        break;
+    }
+
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+#else
+    this_mv.col = (this_mv.col - 8) | 4;
+    this_mv.row = (this_mv.row - 8) | 4;
+    diag = svf(y - 1 - d->pre_stride, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+    this_mv.col += 8;
+    diag = svf(y - d->pre_stride, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+    this_mv.col = (this_mv.col - 8) | 4;
+    this_mv.row = startmv.row + 4;
+    diag = svf(y - 1, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+    this_mv.col += 8;
+    diag = svf(y, d->pre_stride, 4, 4, z, b->src_stride, &sse);
+    diag += vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+
+    if (diag < bestmse)
+    {
+        *bestmv = this_mv;
+        bestmse = diag;
+    }
+
+#endif
+    return bestmse;
+}
+
+
+#define MVC(r,c) (((mvsadcost[0][((r)<<2)-rr] + mvsadcost[1][((c)<<2) - rc]) * error_per_bit + 128 )>>8 ) // estimated cost of a motion vector (r,c)
+#define PRE(r,c) (*(d->base_pre) + d->pre + (r) * d->pre_stride + (c)) // pointer to predictor base of a motionvector
+#define DIST(r,c,v) sf( src,src_stride,PRE(r,c),d->pre_stride, v) // returns sad error score.
+#define ERR(r,c,v) (MVC(r,c)+DIST(r,c,v)) // returns distortion + motion vector cost
+#define CHECK_BETTER(v,r,c) if ((v = ERR(r,c,besterr)) < besterr) { besterr = v; br=r; bc=c; } // checks if (r,c) has better score than previous best
+
+int vp8_hex_search
+(
+    MACROBLOCK *x,
+    BLOCK *b,
+    BLOCKD *d,
+    MV *ref_mv,
+    MV *best_mv,
+    int search_param,
+    int error_per_bit,
+    int *num00,
+    vp8_variance_fn_t vf,
+    vp8_sad_fn_t      sf,
+    int *mvsadcost[2],
+    int *mvcost[2]
+)
+{
+    MV hex[6] = { { -2, 0}, { -1, -2}, { -1, 2}, {2, 0}, {1, 2}, {1, -2} } ;
+    MV neighbors[8] = { { -1, -1}, { -1, 0}, { -1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1} } ;
+    int i, j;
+    unsigned char *src = (*(b->base_src) + b->src);
+    int src_stride = b->src_stride;
+    int rr = ref_mv->row, rc = ref_mv->col, br = rr, bc = rc, tr, tc;
+    unsigned int besterr, thiserr = 0x7fffffff;
+
+    if (rc < x->mv_col_min) bc = x->mv_col_min;
+
+    if (rc > x->mv_col_max) bc = x->mv_col_max;
+
+    if (rr < x->mv_row_min) br = x->mv_row_min;
+
+    if (rr > x->mv_row_max) br = x->mv_row_max;
+
+    rr >>= 1;
+    rc >>= 1;
+    br >>= 3;
+    bc >>= 3;
+
+    besterr = ERR(br, bc, thiserr);
+
+    // hex search  jbb changed to 127 to avoid max 256 problem steping by 2.
+    for (j = 0; j < 127; j++)
+    {
+        tr = br;
+        tc = bc;
+
+        for (i = 0; i < 6; i++)
+        {
+            int nr = tr + hex[i].row, nc = tc + hex[i].col;
+
+            if (nc < x->mv_col_min) continue;
+
+            if (nc > x->mv_col_max) continue;
+
+            if (nr < x->mv_row_min) continue;
+
+            if (nr > x->mv_row_max) continue;
+
+            CHECK_BETTER(thiserr, nr, nc);
+        }
+
+        if (tr == br && tc == bc)
+            break;
+    }
+
+    // check 8 1 away neighbors
+    tr = br;
+    tc = bc;
+
+    for (i = 0; i < 8; i++)
+    {
+        int nr = tr + neighbors[i].row, nc = tc + neighbors[i].col;
+
+        if (nc < x->mv_col_min) continue;
+
+        if (nc > x->mv_col_max) continue;
+
+        if (nr < x->mv_row_min) continue;
+
+        if (nr > x->mv_row_max) continue;
+
+        CHECK_BETTER(thiserr, nr, nc);
+    }
+
+    best_mv->row = br;
+    best_mv->col = bc;
+
+    return vf(src, src_stride, PRE(br, bc), d->pre_stride, &thiserr) + MVC(br, bc) ;
+}
+#undef MVC
+#undef PRE
+#undef SP
+#undef DIST
+#undef ERR
+#undef CHECK_BETTER
+int vp8_diamond_search_sad
+(
+    MACROBLOCK *x,
+    BLOCK *b,
+    BLOCKD *d,
+    MV *ref_mv,
+    MV *best_mv,
+    int search_param,
+    int error_per_bit,
+    int *num00,
+    vp8_variance_fn_ptr_t *fn_ptr,
+    int *mvsadcost[2],
+    int *mvcost[2]
+)
+{
+    int i, j, step;
+
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what;
+    int in_what_stride = d->pre_stride;
+    unsigned char *best_address;
+
+    int tot_steps;
+    MV this_mv;
+
+    int bestsad = INT_MAX;
+    int best_site = 0;
+    int last_site = 0;
+
+    int ref_row = ref_mv->row >> 3;
+    int ref_col = ref_mv->col >> 3;
+    int this_row_offset;
+    int this_col_offset;
+    search_site *ss;
+
+    unsigned char *check_here;
+    int thissad;
+
+    // Work out the start point for the search
+    in_what = (unsigned char *)(*(d->base_pre) + d->pre + (ref_row * (d->pre_stride)) + ref_col);
+    best_address = in_what;
+
+    // We need to check that the starting point for the search (as indicated by ref_mv) is within the buffer limits
+    if ((ref_col > x->mv_col_min) && (ref_col < x->mv_col_max) &&
+    (ref_row > x->mv_row_min) && (ref_row < x->mv_row_max))
+    {
+        // Check the starting position
+        bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride, 0x7fffffff) + vp8_mv_err_cost(ref_mv, ref_mv, mvsadcost, error_per_bit);
+    }
+
+    // search_param determines the length of the initial step and hence the number of iterations
+    // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 = (MAX_FIRST_STEP/4) pel... etc.
+    ss = &x->ss[search_param * x->searches_per_step];
+    tot_steps = (x->ss_count / x->searches_per_step) - search_param;
+
+    i = 1;
+    best_mv->row = ref_row;
+    best_mv->col = ref_col;
+
+    *num00 = 0;
+
+    for (step = 0; step < tot_steps ; step++)
+    {
+        for (j = 0 ; j < x->searches_per_step ; j++)
+        {
+            // Trap illegal vectors
+            this_row_offset = best_mv->row + ss[i].mv.row;
+            this_col_offset = best_mv->col + ss[i].mv.col;
+
+            if ((this_col_offset > x->mv_col_min) && (this_col_offset < x->mv_col_max) &&
+            (this_row_offset > x->mv_row_min) && (this_row_offset < x->mv_row_max))
+
+            {
+                check_here = ss[i].offset + best_address;
+                thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+                if (thissad < bestsad)
+                {
+                    this_mv.row = this_row_offset << 3;
+                    this_mv.col = this_col_offset << 3;
+                    thissad += vp8_mv_err_cost(&this_mv, ref_mv, mvsadcost, error_per_bit);
+
+                    if (thissad < bestsad)
+                    {
+                        bestsad = thissad;
+                        best_site = i;
+                    }
+                }
+            }
+
+            i++;
+        }
+
+        if (best_site != last_site)
+        {
+            best_mv->row += ss[best_site].mv.row;
+            best_mv->col += ss[best_site].mv.col;
+            best_address += ss[best_site].offset;
+            last_site = best_site;
+        }
+        else if (best_address == in_what)
+            (*num00)++;
+    }
+
+    this_mv.row = best_mv->row << 3;
+    this_mv.col = best_mv->col << 3;
+
+    if (bestsad == INT_MAX)
+        return INT_MAX;
+
+    return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
+    + vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+}
+
+int vp8_diamond_search_sadx4
+(
+    MACROBLOCK *x,
+    BLOCK *b,
+    BLOCKD *d,
+    MV *ref_mv,
+    MV *best_mv,
+    int search_param,
+    int error_per_bit,
+    int *num00,
+    vp8_variance_fn_ptr_t *fn_ptr,
+    int *mvsadcost[2],
+    int *mvcost[2]
+)
+{
+    int i, j, step;
+
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what;
+    int in_what_stride = d->pre_stride;
+    unsigned char *best_address;
+
+    int tot_steps;
+    MV this_mv;
+
+    unsigned int bestsad = UINT_MAX;
+    int best_site = 0;
+    int last_site = 0;
+
+    int ref_row = ref_mv->row >> 3;
+    int ref_col = ref_mv->col >> 3;
+    int this_row_offset;
+    int this_col_offset;
+    search_site *ss;
+
+    unsigned char *check_here;
+    unsigned int thissad;
+
+    // Work out the start point for the search
+    in_what = (unsigned char *)(*(d->base_pre) + d->pre + (ref_row * (d->pre_stride)) + ref_col);
+    best_address = in_what;
+
+    // We need to check that the starting point for the search (as indicated by ref_mv) is within the buffer limits
+    if ((ref_col > x->mv_col_min) && (ref_col < x->mv_col_max) &&
+    (ref_row > x->mv_row_min) && (ref_row < x->mv_row_max))
+    {
+        // Check the starting position
+        bestsad = fn_ptr->sdf(what, what_stride, in_what, in_what_stride, 0x7fffffff) + vp8_mv_err_cost(ref_mv, ref_mv, mvsadcost, error_per_bit);
+    }
+
+    // search_param determines the length of the initial step and hence the number of iterations
+    // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 = (MAX_FIRST_STEP/4) pel... etc.
+    ss = &x->ss[search_param * x->searches_per_step];
+    tot_steps = (x->ss_count / x->searches_per_step) - search_param;
+
+    i = 1;
+    best_mv->row = ref_row;
+    best_mv->col = ref_col;
+
+    *num00 = 0;
+
+    for (step = 0; step < tot_steps ; step++)
+    {
+        int check_row_min, check_col_min, check_row_max, check_col_max;
+
+        check_row_min = x->mv_row_min - best_mv->row;
+        check_row_max = x->mv_row_max - best_mv->row;
+        check_col_min = x->mv_col_min - best_mv->col;
+        check_col_max = x->mv_col_max - best_mv->col;
+
+        for (j = 0 ; j < x->searches_per_step ; j += 4)
+        {
+            unsigned char *block_offset[4];
+            unsigned int valid_block[4];
+            int all_in = 1, t;
+
+            for (t = 0; t < 4; t++)
+            {
+                valid_block [t]  = (ss[t+i].mv.col > check_col_min);
+                valid_block [t] &= (ss[t+i].mv.col < check_col_max);
+                valid_block [t] &= (ss[t+i].mv.row > check_row_min);
+                valid_block [t] &= (ss[t+i].mv.row < check_row_max);
+
+                all_in &= valid_block[t];
+                block_offset[t] = ss[i+t].offset + best_address;
+            }
+
+            if (all_in)
+            {
+                unsigned int sad_array[4];
+
+                fn_ptr->sdx4df(what, what_stride, block_offset, in_what_stride, sad_array);
+
+                for (t = 0; t < 4; t++, i++)
+                {
+                    thissad = sad_array[t];
+
+                    if (thissad < bestsad)
+                    {
+                        this_mv.row = (best_mv->row + ss[i].mv.row) << 3;
+                        this_mv.col = (best_mv->col + ss[i].mv.col) << 3;
+                        thissad += vp8_mv_err_cost(&this_mv, ref_mv, mvsadcost, error_per_bit);
+
+                        if (thissad < bestsad)
+                        {
+                            bestsad = thissad;
+                            best_site = i;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                int t;
+
+                for (t = 0; t < 4; i++, t++)
+                {
+                    // Trap illegal vectors
+                    if (valid_block[t])
+
+                    {
+                        check_here = block_offset[t];
+                        thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+                        if (thissad < bestsad)
+                        {
+                            this_row_offset = best_mv->row + ss[i].mv.row;
+                            this_col_offset = best_mv->col + ss[i].mv.col;
+
+                            this_mv.row = this_row_offset << 3;
+                            this_mv.col = this_col_offset << 3;
+                            thissad += vp8_mv_err_cost(&this_mv, ref_mv, mvsadcost, error_per_bit);
+
+                            if (thissad < bestsad)
+                            {
+                                bestsad = thissad;
+                                best_site = i;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        if (best_site != last_site)
+        {
+            best_mv->row += ss[best_site].mv.row;
+            best_mv->col += ss[best_site].mv.col;
+            best_address += ss[best_site].offset;
+            last_site = best_site;
+        }
+        else if (best_address == in_what)
+            (*num00)++;
+    }
+
+    this_mv.row = best_mv->row << 3;
+    this_mv.col = best_mv->col << 3;
+
+    if (bestsad == INT_MAX)
+        return INT_MAX;
+
+    return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad))
+    + vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+}
+
+
+#if !(CONFIG_REALTIME_ONLY)
+int vp8_full_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, MV *ref_mv, int error_per_bit, int distance, vp8_variance_fn_ptr_t *fn_ptr, int *mvcost[2], int *mvsadcost[2])
+{
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what;
+    int in_what_stride = d->pre_stride;
+    int mv_stride = d->pre_stride;
+    unsigned char *bestaddress;
+    MV *best_mv = &d->bmi.mv.as_mv;
+    MV this_mv;
+    int bestsad = INT_MAX;
+    int r, c;
+
+    unsigned char *check_here;
+    int thissad;
+
+    int ref_row = ref_mv->row >> 3;
+    int ref_col = ref_mv->col >> 3;
+
+    int row_min = ref_row - distance;
+    int row_max = ref_row + distance;
+    int col_min = ref_col - distance;
+    int col_max = ref_col + distance;
+
+    // Work out the mid point for the search
+    in_what = *(d->base_pre) + d->pre;
+    bestaddress = in_what + (ref_row * d->pre_stride) + ref_col;
+
+    best_mv->row = ref_row;
+    best_mv->col = ref_col;
+
+    // We need to check that the starting point for the search (as indicated by ref_mv) is within the buffer limits
+    if ((ref_col > x->mv_col_min) && (ref_col < x->mv_col_max) &&
+    (ref_row > x->mv_row_min) && (ref_row < x->mv_row_max))
+    {
+        // Baseline value at the centre
+
+        //bestsad = fn_ptr->sf( what,what_stride,bestaddress,in_what_stride) + (int)sqrt(vp8_mv_err_cost(ref_mv,ref_mv, mvcost,error_per_bit*14));
+        bestsad = fn_ptr->sdf(what, what_stride, bestaddress, in_what_stride, 0x7fffffff) + vp8_mv_err_cost(ref_mv, ref_mv, mvsadcost, error_per_bit);
+    }
+
+    // Apply further limits to prevent us looking using vectors that stretch beyiond the UMV border
+    if (col_min < x->mv_col_min)
+        col_min = x->mv_col_min;
+
+    if (col_max > x->mv_col_max)
+        col_max = x->mv_col_max;
+
+    if (row_min < x->mv_row_min)
+        row_min = x->mv_row_min;
+
+    if (row_max > x->mv_row_max)
+        row_max = x->mv_row_max;
+
+    for (r = row_min; r < row_max ; r++)
+    {
+        this_mv.row = r << 3;
+        check_here = r * mv_stride + in_what + col_min;
+
+        for (c = col_min; c < col_max; c++)
+        {
+            thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+            this_mv.col = c << 3;
+            //thissad += (int)sqrt(vp8_mv_err_cost(&this_mv,ref_mv, mvcost,error_per_bit*14));
+            //thissad  += error_per_bit * mv_bits_sadcost[mv_bits(&this_mv, ref_mv, mvcost)];
+            thissad  += vp8_mv_err_cost(&this_mv, ref_mv, mvsadcost, error_per_bit); //mv_bits(error_per_bit, &this_mv, ref_mv, mvsadcost);
+
+            if (thissad < bestsad)
+            {
+                bestsad = thissad;
+                best_mv->row = r;
+                best_mv->col = c;
+                bestaddress = check_here;
+            }
+
+            check_here++;
+        }
+    }
+
+    this_mv.row = best_mv->row << 3;
+    this_mv.col = best_mv->col << 3;
+
+    if (bestsad < INT_MAX)
+        return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad))
+        + vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+    else
+        return INT_MAX;
+}
+
+int vp8_full_search_sadx3(MACROBLOCK *x, BLOCK *b, BLOCKD *d, MV *ref_mv, int error_per_bit, int distance, vp8_variance_fn_ptr_t *fn_ptr, int *mvcost[2], int *mvsadcost[2])
+{
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what;
+    int in_what_stride = d->pre_stride;
+    int mv_stride = d->pre_stride;
+    unsigned char *bestaddress;
+    MV *best_mv = &d->bmi.mv.as_mv;
+    MV this_mv;
+    unsigned int bestsad = UINT_MAX;
+    int r, c;
+
+    unsigned char *check_here;
+    unsigned int thissad;
+
+    int ref_row = ref_mv->row >> 3;
+    int ref_col = ref_mv->col >> 3;
+
+    int row_min = ref_row - distance;
+    int row_max = ref_row + distance;
+    int col_min = ref_col - distance;
+    int col_max = ref_col + distance;
+
+    unsigned int sad_array[3];
+
+    // Work out the mid point for the search
+    in_what = *(d->base_pre) + d->pre;
+    bestaddress = in_what + (ref_row * d->pre_stride) + ref_col;
+
+    best_mv->row = ref_row;
+    best_mv->col = ref_col;
+
+    // We need to check that the starting point for the search (as indicated by ref_mv) is within the buffer limits
+    if ((ref_col > x->mv_col_min) && (ref_col < x->mv_col_max) &&
+    (ref_row > x->mv_row_min) && (ref_row < x->mv_row_max))
+    {
+        // Baseline value at the centre
+        bestsad = fn_ptr->sdf(what, what_stride, bestaddress, in_what_stride, 0x7fffffff) + vp8_mv_err_cost(ref_mv, ref_mv, mvsadcost, error_per_bit);
+    }
+
+    // Apply further limits to prevent us looking using vectors that stretch beyiond the UMV border
+    if (col_min < x->mv_col_min)
+        col_min = x->mv_col_min;
+
+    if (col_max > x->mv_col_max)
+        col_max = x->mv_col_max;
+
+    if (row_min < x->mv_row_min)
+        row_min = x->mv_row_min;
+
+    if (row_max > x->mv_row_max)
+        row_max = x->mv_row_max;
+
+    for (r = row_min; r < row_max ; r++)
+    {
+        this_mv.row = r << 3;
+        check_here = r * mv_stride + in_what + col_min;
+        c = col_min;
+
+        while ((c + 3) < col_max)
+        {
+            int i;
+
+            fn_ptr->sdx3f(what, what_stride, check_here , in_what_stride, sad_array);
+
+            for (i = 0; i < 3; i++)
+            {
+                thissad = sad_array[i];
+
+                if (thissad < bestsad)
+                {
+                    this_mv.col = c << 3;
+                    thissad  += vp8_mv_err_cost(&this_mv, ref_mv, mvsadcost, error_per_bit);
+
+                    if (thissad < bestsad)
+                    {
+                        bestsad = thissad;
+                        best_mv->row = r;
+                        best_mv->col = c;
+                        bestaddress = check_here;
+                    }
+                }
+
+                check_here++;
+                c++;
+            }
+        }
+
+        while (c < col_max)
+        {
+            thissad = fn_ptr->sdf(what, what_stride, check_here , in_what_stride, bestsad);
+
+            if (thissad < bestsad)
+            {
+                this_mv.col = c << 3;
+                thissad  += vp8_mv_err_cost(&this_mv, ref_mv, mvsadcost, error_per_bit);
+
+                if (thissad < bestsad)
+                {
+                    bestsad = thissad;
+                    best_mv->row = r;
+                    best_mv->col = c;
+                    bestaddress = check_here;
+                }
+            }
+
+            check_here ++;
+            c ++;
+        }
+
+    }
+
+    this_mv.row = best_mv->row << 3;
+    this_mv.col = best_mv->col << 3;
+
+    if (bestsad < INT_MAX)
+        return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad))
+        + vp8_mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit);
+    else
+        return INT_MAX;
+}
+#endif
+
+#ifdef ENTROPY_STATS
+void print_mode_context(void)
+{
+    FILE *f = fopen("modecont.c", "w");
+    int i, j;
+
+    fprintf(f, "#include \"entropy.h\"\n");
+    fprintf(f, "const int vp8_mode_contexts[6][4] =\n");
+    fprintf(f, "{\n");
+
+    for (j = 0; j < 6; j++)
+    {
+        fprintf(f, "  { // %d \n", j);
+        fprintf(f, "    ");
+
+        for (i = 0; i < 4; i++)
+        {
+            int overal_prob;
+            int this_prob;
+            int count; // = mv_ref_ct[j][i][0]+mv_ref_ct[j][i][1];
+
+            // Overall probs
+            count = mv_mode_cts[i][0] + mv_mode_cts[i][1];
+
+            if (count)
+                overal_prob = 256 * mv_mode_cts[i][0] / count;
+            else
+                overal_prob = 128;
+
+            if (overal_prob == 0)
+                overal_prob = 1;
+
+            // context probs
+            count = mv_ref_ct[j][i][0] + mv_ref_ct[j][i][1];
+
+            if (count)
+                this_prob = 256 * mv_ref_ct[j][i][0] / count;
+            else
+                this_prob = 128;
+
+            if (this_prob == 0)
+                this_prob = 1;
+
+            fprintf(f, "%5d, ", this_prob);
+            //fprintf(f,"%5d, %5d, %8d,", this_prob, overal_prob, (this_prob << 10)/overal_prob);
+            //fprintf(f,"%8d, ", (this_prob << 10)/overal_prob);
+        }
+
+        fprintf(f, "  },\n");
+    }
+
+    fprintf(f, "};\n");
+    fclose(f);
+}
+
+/* MV ref count ENTROPY_STATS stats code */
+#ifdef ENTROPY_STATS
+void init_mv_ref_counts()
+{
+    vpx_memset(mv_ref_ct, 0, sizeof(mv_ref_ct));
+    vpx_memset(mv_mode_cts, 0, sizeof(mv_mode_cts));
+}
+
+void accum_mv_refs(MB_PREDICTION_MODE m, const int ct[4])
+{
+    if (m == ZEROMV)
+    {
+        ++mv_ref_ct [ct[0]] [0] [0];
+        ++mv_mode_cts[0][0];
+    }
+    else
+    {
+        ++mv_ref_ct [ct[0]] [0] [1];
+        ++mv_mode_cts[0][1];
+
+        if (m == NEARESTMV)
+        {
+            ++mv_ref_ct [ct[1]] [1] [0];
+            ++mv_mode_cts[1][0];
+        }
+        else
+        {
+            ++mv_ref_ct [ct[1]] [1] [1];
+            ++mv_mode_cts[1][1];
+
+            if (m == NEARMV)
+            {
+                ++mv_ref_ct [ct[2]] [2] [0];
+                ++mv_mode_cts[2][0];
+            }
+            else
+            {
+                ++mv_ref_ct [ct[2]] [2] [1];
+                ++mv_mode_cts[2][1];
+
+                if (m == NEWMV)
+                {
+                    ++mv_ref_ct [ct[3]] [3] [0];
+                    ++mv_mode_cts[3][0];
+                }
+                else
+                {
+                    ++mv_ref_ct [ct[3]] [3] [1];
+                    ++mv_mode_cts[3][1];
+                }
+            }
+        }
+    }
+}
+
+#endif/* END MV ref count ENTROPY_STATS stats code */
+
+#endif
diff --git a/vp8/encoder/mcomp.h b/vp8/encoder/mcomp.h
new file mode 100644
index 0000000..921206f
--- /dev/null
+++ b/vp8/encoder/mcomp.h
@@ -0,0 +1,121 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_MCOMP_H
+#define __INC_MCOMP_H
+
+#include "block.h"
+#include "variance.h"
+
+#ifdef ENTROPY_STATS
+extern void init_mv_ref_counts();
+extern void accum_mv_refs(MB_PREDICTION_MODE, const int near_mv_ref_cts[4]);
+#endif
+
+
+#define MAX_MVSEARCH_STEPS 8                                    // The maximum number of steps in a step search given the largest allowed initial step
+#define MAX_FULL_PEL_VAL ((1 << (MAX_MVSEARCH_STEPS+3)) - 8)    // Max full pel mv specified in 1/8 pel units
+#define MAX_FIRST_STEP (1 << (MAX_MVSEARCH_STEPS-1))            // Maximum size of the first step in full pel units
+
+
+extern void print_mode_context(void);
+extern int vp8_mv_bit_cost(MV *mv, MV *ref, int *mvcost[2], int Weight);
+extern void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride);
+extern void vp8_init3smotion_compensation(MACROBLOCK *x,  int stride);
+
+
+extern int vp8_hex_search
+(
+    MACROBLOCK *x,
+    BLOCK *b,
+    BLOCKD *d,
+    MV *ref_mv,
+    MV *best_mv,
+    int search_param,
+    int error_per_bit,
+    int *num00,
+    vp8_variance_fn_t vf,
+    vp8_sad_fn_t sf,
+    int *mvsadcost[2],
+    int *mvcost[2]
+
+);
+
+typedef int (fractional_mv_step_fp)(MACROBLOCK *x, BLOCK *b, BLOCKD *d, MV *bestmv, MV *ref_mv, int error_per_bit, vp8_subpixvariance_fn_t svf, vp8_variance_fn_t vf, int *mvcost[2]);
+extern fractional_mv_step_fp vp8_find_best_sub_pixel_step_iteratively;
+extern fractional_mv_step_fp vp8_find_best_sub_pixel_step;
+extern fractional_mv_step_fp vp8_find_best_half_pixel_step;
+extern fractional_mv_step_fp vp8_skip_fractional_mv_step;
+
+#define prototype_full_search_sad(sym)\
+    int (sym)\
+    (\
+     MACROBLOCK *x, \
+     BLOCK *b, \
+     BLOCKD *d, \
+     MV *ref_mv, \
+     int error_per_bit, \
+     int distance, \
+     vp8_variance_fn_ptr_t *fn_ptr, \
+     int *mvcost[2], \
+     int *mvsadcost[2] \
+    )
+
+#define prototype_diamond_search_sad(sym)\
+    int (sym)\
+    (\
+     MACROBLOCK *x, \
+     BLOCK *b, \
+     BLOCKD *d, \
+     MV *ref_mv, \
+     MV *best_mv, \
+     int search_param, \
+     int error_per_bit, \
+     int *num00, \
+     vp8_variance_fn_ptr_t *fn_ptr, \
+     int *mvsadcost[2], \
+     int *mvcost[2] \
+    )
+
+#if ARCH_X86 || ARCH_X86_64
+#include "x86/mcomp_x86.h"
+#endif
+
+typedef prototype_full_search_sad(*vp8_full_search_fn_t);
+extern prototype_full_search_sad(vp8_full_search_sad);
+extern prototype_full_search_sad(vp8_full_search_sadx3);
+
+typedef prototype_diamond_search_sad(*vp8_diamond_search_fn_t);
+extern prototype_diamond_search_sad(vp8_diamond_search_sad);
+extern prototype_diamond_search_sad(vp8_diamond_search_sadx4);
+
+#ifndef vp8_search_full_search
+#define vp8_search_full_search vp8_full_search_sad
+#endif
+extern prototype_full_search_sad(vp8_search_full_search);
+
+#ifndef vp8_search_diamond_search
+#define vp8_search_diamond_search vp8_diamond_search_sad
+#endif
+extern prototype_diamond_search_sad(vp8_search_diamond_search);
+
+typedef struct
+{
+    prototype_full_search_sad(*full_search);
+    prototype_diamond_search_sad(*diamond_search);
+} vp8_search_rtcd_vtable_t;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define SEARCH_INVOKE(ctx,fn) (ctx)->fn
+#else
+#define SEARCH_INVOKE(ctx,fn) vp8_search_##fn
+#endif
+
+#endif
diff --git a/vp8/encoder/modecosts.c b/vp8/encoder/modecosts.c
new file mode 100644
index 0000000..73170cf
--- /dev/null
+++ b/vp8/encoder/modecosts.c
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "blockd.h"
+#include "onyx_int.h"
+#include "treewriter.h"
+#include "entropymode.h"
+
+
+void vp8_init_mode_costs(VP8_COMP *c)
+{
+    VP8_COMMON *x = &c->common;
+    {
+        const vp8_tree_p T = vp8_bmode_tree;
+
+        int i = 0;
+
+        do
+        {
+            int j = 0;
+
+            do
+            {
+                vp8_cost_tokens((int *)c->mb.bmode_costs[i][j], x->kf_bmode_prob[i][j], T);
+            }
+            while (++j < VP8_BINTRAMODES);
+        }
+        while (++i < VP8_BINTRAMODES);
+
+        vp8_cost_tokens((int *)c->mb.inter_bmode_costs, x->fc.bmode_prob, T);
+    }
+    vp8_cost_tokens((int *)c->mb.inter_bmode_costs, x->fc.sub_mv_ref_prob, vp8_sub_mv_ref_tree);
+
+    vp8_cost_tokens(c->mb.mbmode_cost[1], x->fc.ymode_prob, vp8_ymode_tree);
+    vp8_cost_tokens(c->mb.mbmode_cost[0], x->kf_ymode_prob, vp8_kf_ymode_tree);
+
+    vp8_cost_tokens(c->mb.intra_uv_mode_cost[1], x->fc.uv_mode_prob, vp8_uv_mode_tree);
+    vp8_cost_tokens(c->mb.intra_uv_mode_cost[0], x->kf_uv_mode_prob, vp8_uv_mode_tree);
+}
diff --git a/vp8/encoder/modecosts.h b/vp8/encoder/modecosts.h
new file mode 100644
index 0000000..5ade265
--- /dev/null
+++ b/vp8/encoder/modecosts.h
@@ -0,0 +1,16 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_MODECOSTS_H
+#define __INC_MODECOSTS_H
+
+void vp8_init_mode_costs(VP8_COMP *x);
+
+#endif
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
new file mode 100644
index 0000000..7662720
--- /dev/null
+++ b/vp8/encoder/onyx_if.c
@@ -0,0 +1,5428 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "onyxc_int.h"
+#include "onyx_int.h"
+#include "systemdependent.h"
+#include "quantize.h"
+#include "alloccommon.h"
+#include "mcomp.h"
+#include "firstpass.h"
+#include "psnr.h"
+#include "vpx_scale/vpxscale.h"
+#include "extend.h"
+#include "ratectrl.h"
+#include "quant_common.h"
+#include "segmentation_common.h"
+#include "g_common.h"
+#include "vpx_scale/yv12extend.h"
+#include "postproc.h"
+#include "vpx_mem/vpx_mem.h"
+#include "swapyv12buffer.h"
+#include "threading.h"
+#include "vpx_ports/vpx_timer.h"
+#include <math.h>
+#include <stdio.h>
+#include <limits.h>
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define IF_RTCD(x) (x)
+#define RTCD(x) &cpi->common.rtcd.x
+#else
+#define IF_RTCD(x) NULL
+#define RTCD(x) NULL
+#endif
+
+extern void vp8cx_init_mv_bits_sadcost();
+extern void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi);
+extern void vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val);
+extern void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi);
+
+extern void vp8_init_loop_filter(VP8_COMMON *cm);
+extern void vp8_loop_filter_frame(VP8_COMMON *cm,    MACROBLOCKD *mbd,  int filt_val);
+extern void vp8_loop_filter_frame_yonly(VP8_COMMON *cm,    MACROBLOCKD *mbd,  int filt_val, int sharpness_lvl);
+extern void vp8_dmachine_specific_config(VP8_COMP *cpi);
+extern void vp8_cmachine_specific_config(VP8_COMP *cpi);
+extern void vp8_calc_auto_iframe_target_size(VP8_COMP *cpi);
+extern void vp8_deblock_frame(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *post, int filt_lvl, int low_var_thresh, int flag);
+extern void print_parms(VP8_CONFIG *ocf, char *filenam);
+extern unsigned int vp8_get_processor_freq();
+extern void print_tree_update_probs();
+extern void vp8cx_create_encoder_threads(VP8_COMP *cpi);
+extern void vp8cx_remove_encoder_threads(VP8_COMP *cpi);
+#if HAVE_ARMV7
+extern void vp8_yv12_copy_frame_func_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc);
+extern void vp8_yv12_copy_src_frame_func_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc);
+#endif
+
+int vp8_estimate_entropy_savings(VP8_COMP *cpi);
+int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, const vp8_variance_rtcd_vtable_t *rtcd);
+int vp8_calc_low_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, const vp8_variance_rtcd_vtable_t *rtcd);
+
+
+static void mode_ref_lf_test_function(VP8_COMP *cpi);
+
+extern const int vp8_gf_interval_table[101];
+
+#if CONFIG_PSNR
+#include "math.h"
+
+extern double vp8_calc_ssim
+(
+    YV12_BUFFER_CONFIG *source,
+    YV12_BUFFER_CONFIG *dest,
+    int lumamask,
+    double *weight
+);
+
+extern double vp8_calc_ssimg
+(
+    YV12_BUFFER_CONFIG *source,
+    YV12_BUFFER_CONFIG *dest,
+    double *ssim_y,
+    double *ssim_u,
+    double *ssim_v
+);
+
+
+#endif
+
+
+#ifdef OUTPUT_YUV_SRC
+FILE *yuv_file;
+#endif
+
+#if 0
+FILE *framepsnr;
+FILE *kf_list;
+FILE *keyfile;
+#endif
+
+#if 0
+extern int skip_true_count;
+extern int skip_false_count;
+#endif
+
+
+#ifdef ENTROPY_STATS
+extern int intra_mode_stats[10][10][10];
+#endif
+
+#ifdef SPEEDSTATS
+unsigned int frames_at_speed[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+unsigned int tot_pm = 0;
+unsigned int cnt_pm = 0;
+unsigned int tot_ef = 0;
+unsigned int cnt_ef = 0;
+#endif
+
+#ifdef MODE_STATS
+extern unsigned __int64 Sectionbits[50];
+extern int y_modes[5]  ;
+extern int uv_modes[4] ;
+extern int b_modes[10]  ;
+
+extern int inter_y_modes[10] ;
+extern int inter_uv_modes[4] ;
+extern unsigned int inter_b_modes[15];
+#endif
+
+extern void (*vp8_short_fdct4x4)(short *input, short *output, int pitch);
+extern void (*vp8_short_fdct8x4)(short *input, short *output, int pitch);
+extern void (*vp8_fast_fdct4x4)(short *input, short *output, int pitch);
+extern void (*vp8_fast_fdct8x4)(short *input, short *output, int pitch);
+
+extern const int vp8_bits_per_mb[2][QINDEX_RANGE];
+
+extern const int qrounding_factors[129];
+extern const int qzbin_factors[129];
+extern void vp8cx_init_quantizer(VP8_COMP *cpi);
+extern const int vp8cx_base_skip_false_prob[128];
+
+
+void vp8_initialize()
+{
+    static int init_done = 0;
+
+    if (!init_done)
+    {
+        vp8_scale_machine_specific_config();
+        vp8_initialize_common();
+        //vp8_dmachine_specific_config();
+        vp8_tokenize_initialize();
+
+        vp8cx_init_mv_bits_sadcost();
+        init_done = 1;
+    }
+}
+#ifdef PACKET_TESTING
+extern FILE *vpxlogc;
+#endif
+
+static void setup_features(VP8_COMP *cpi)
+{
+    // Set up default state for MB feature flags
+    cpi->mb.e_mbd.segmentation_enabled = 0;
+    cpi->mb.e_mbd.update_mb_segmentation_map = 0;
+    cpi->mb.e_mbd.update_mb_segmentation_data = 0;
+    vpx_memset(cpi->mb.e_mbd.mb_segment_tree_probs, 255, sizeof(cpi->mb.e_mbd.mb_segment_tree_probs));
+    vpx_memset(cpi->mb.e_mbd.segment_feature_data, 0, sizeof(cpi->mb.e_mbd.segment_feature_data));
+
+    cpi->mb.e_mbd.mode_ref_lf_delta_enabled = 0;
+    cpi->mb.e_mbd.mode_ref_lf_delta_update = 0;
+    vpx_memset(cpi->mb.e_mbd.ref_lf_deltas, 0, sizeof(cpi->mb.e_mbd.ref_lf_deltas));
+    vpx_memset(cpi->mb.e_mbd.mode_lf_deltas, 0, sizeof(cpi->mb.e_mbd.mode_lf_deltas));
+
+    // jbb trial !
+    mode_ref_lf_test_function(cpi);
+
+}
+
+
+void vp8_dealloc_compressor_data(VP8_COMP *cpi)
+{
+
+    // Delete sementation map
+    if (cpi->segmentation_map != 0)
+        vpx_free(cpi->segmentation_map);
+
+    cpi->segmentation_map = 0;
+
+    if (cpi->active_map != 0)
+        vpx_free(cpi->active_map);
+
+    cpi->active_map = 0;
+
+    // Delete first pass motion map
+    if (cpi->fp_motion_map != 0)
+        vpx_free(cpi->fp_motion_map);
+
+    cpi->fp_motion_map = 0;
+
+    vp8_de_alloc_frame_buffers(&cpi->common);
+
+    vp8_yv12_de_alloc_frame_buffer(&cpi->last_frame_uf);
+    vp8_yv12_de_alloc_frame_buffer(&cpi->scaled_source);
+#if VP8_TEMPORAL_ALT_REF
+    vp8_yv12_de_alloc_frame_buffer(&cpi->alt_ref_buffer.source_buffer);
+#endif
+    {
+        int i;
+
+        for (i = 0; i < MAX_LAG_BUFFERS; i++)
+            vp8_yv12_de_alloc_frame_buffer(&cpi->src_buffer[i].source_buffer);
+
+        cpi->source_buffer_count = 0;
+    }
+
+    vpx_free(cpi->tok);
+    cpi->tok = 0;
+
+}
+
+static void enable_segmentation(VP8_PTR ptr)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(ptr);
+
+    // Set the appropriate feature bit
+    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;
+}
+static void disable_segmentation(VP8_PTR ptr)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(ptr);
+
+    // Clear the appropriate feature bit
+    cpi->mb.e_mbd.segmentation_enabled = 0;
+}
+
+// Valid values for a segment are 0 to 3
+// Segmentation map is arrange as [Rows][Columns]
+static void set_segmentation_map(VP8_PTR ptr, unsigned char *segmentation_map)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(ptr);
+
+    // Copy in the new segmentation map
+    vpx_memcpy(cpi->segmentation_map, segmentation_map, (cpi->common.mb_rows * cpi->common.mb_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;
+}
+
+// The values given for each segment can be either deltas (from the default value chosen for the frame) or absolute values.
+//
+// Valid range for abs values is (0-127 for MB_LVL_ALT_Q) , (0-63 for SEGMENT_ALT_LF)
+// Valid range for delta values are (+/-127 for MB_LVL_ALT_Q) , (+/-63 for SEGMENT_ALT_LF)
+//
+// abs_delta = SEGMENT_DELTADATA (deltas) abs_delta = SEGMENT_ABSDATA (use the absolute values given).
+//
+//
+static void set_segment_data(VP8_PTR ptr, signed char *feature_data, unsigned char abs_delta)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(ptr);
+
+    cpi->mb.e_mbd.mb_segement_abs_delta = abs_delta;
+    vpx_memcpy(cpi->segment_feature_data, feature_data, sizeof(cpi->segment_feature_data));
+}
+
+
+static void segmentation_test_function(VP8_PTR ptr)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(ptr);
+
+    unsigned char *seg_map;
+    signed char feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];
+    int i, j;
+
+    // Create a temporary map for segmentation data.
+    CHECK_MEM_ERROR(seg_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
+
+    // MB loop to set local segmentation map
+    /*for ( i = 0; i < cpi->common.mb_rows; i++ )
+    {
+        for ( j = 0; j < cpi->common.mb_cols; j++ )
+        {
+            //seg_map[(i*cpi->common.mb_cols) + j] = (j % 2) + ((i%2)* 2);
+            //if ( j < cpi->common.mb_cols/2 )
+
+            // Segment 1 around the edge else 0
+            if ( (i == 0) || (j == 0) || (i == (cpi->common.mb_rows-1)) || (j == (cpi->common.mb_cols-1)) )
+                seg_map[(i*cpi->common.mb_cols) + j] = 1;
+            //else if ( (i < 2) || (j < 2) || (i > (cpi->common.mb_rows-3)) || (j > (cpi->common.mb_cols-3)) )
+            //  seg_map[(i*cpi->common.mb_cols) + j] = 2;
+            //else if ( (i < 5) || (j < 5) || (i > (cpi->common.mb_rows-6)) || (j > (cpi->common.mb_cols-6)) )
+            //  seg_map[(i*cpi->common.mb_cols) + j] = 3;
+            else
+                seg_map[(i*cpi->common.mb_cols) + j] = 0;
+        }
+    }*/
+
+    // Set the segmentation Map
+    set_segmentation_map(ptr, seg_map);
+
+    // Activate segmentation.
+    enable_segmentation(ptr);
+
+    // Set up the quant segment data
+    feature_data[MB_LVL_ALT_Q][0] = 0;
+    feature_data[MB_LVL_ALT_Q][1] = 4;
+    feature_data[MB_LVL_ALT_Q][2] = 0;
+    feature_data[MB_LVL_ALT_Q][3] = 0;
+    // Set up the loop segment data
+    feature_data[MB_LVL_ALT_LF][0] = 0;
+    feature_data[MB_LVL_ALT_LF][1] = 0;
+    feature_data[MB_LVL_ALT_LF][2] = 0;
+    feature_data[MB_LVL_ALT_LF][3] = 0;
+
+    // Initialise the feature data structure
+    // SEGMENT_DELTADATA    0, SEGMENT_ABSDATA      1
+    set_segment_data(ptr, &feature_data[0][0], SEGMENT_DELTADATA);
+
+    // Delete sementation map
+    if (seg_map != 0)
+        vpx_free(seg_map);
+
+    seg_map = 0;
+
+}
+
+// A simple function to cyclically refresh the background at a lower Q
+static void cyclic_background_refresh(VP8_COMP *cpi, int Q, int lf_adjustment)
+{
+    unsigned char *seg_map;
+    signed char feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];
+    int i;
+    int block_count = cpi->cyclic_refresh_mode_max_mbs_perframe;
+    int mbs_in_frame = cpi->common.mb_rows * cpi->common.mb_cols;
+
+    // Create a temporary map for segmentation data.
+    CHECK_MEM_ERROR(seg_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
+
+    cpi->cyclic_refresh_q = Q;
+
+    for (i = Q; i > 0; i--)
+    {
+        if (vp8_bits_per_mb[cpi->common.frame_type][i] >= ((vp8_bits_per_mb[cpi->common.frame_type][Q]*(Q + 128)) / 64))
+            //if ( vp8_bits_per_mb[cpi->common.frame_type][i] >= ((vp8_bits_per_mb[cpi->common.frame_type][Q]*((2*Q)+96))/64) )
+        {
+            break;
+        }
+    }
+
+    cpi->cyclic_refresh_q = i;
+
+    // Only update for inter frames
+    if (cpi->common.frame_type != KEY_FRAME)
+    {
+        // Cycle through the macro_block rows
+        // MB loop to set local segmentation map
+        for (i = cpi->cyclic_refresh_mode_index; i < mbs_in_frame; i++)
+        {
+            // If the MB is as a candidate for clean up then mark it for possible boost/refresh (segment 1)
+            // The segment id may get reset to 0 later if the MB gets coded anything other than last frame 0,0
+            // as only (last frame 0,0) MBs are eligable for refresh : that is to say Mbs likely to be background blocks.
+            if (cpi->cyclic_refresh_map[i] == 0)
+            {
+                seg_map[i] = 1;
+            }
+            else
+            {
+                seg_map[i] = 0;
+
+                // Skip blocks that have been refreshed recently anyway.
+                if (cpi->cyclic_refresh_map[i] < 0)
+                    //cpi->cyclic_refresh_map[i] = cpi->cyclic_refresh_map[i] / 16;
+                    cpi->cyclic_refresh_map[i]++;
+            }
+
+
+            if (block_count > 0)
+                block_count--;
+            else
+                break;
+
+        }
+
+        // If we have gone through the frame reset to the start
+        cpi->cyclic_refresh_mode_index = i;
+
+        if (cpi->cyclic_refresh_mode_index >= mbs_in_frame)
+            cpi->cyclic_refresh_mode_index = 0;
+    }
+
+    // Set the segmentation Map
+    set_segmentation_map((VP8_PTR)cpi, seg_map);
+
+    // Activate segmentation.
+    enable_segmentation((VP8_PTR)cpi);
+
+    // Set up the quant segment data
+    feature_data[MB_LVL_ALT_Q][0] = 0;
+    feature_data[MB_LVL_ALT_Q][1] = (cpi->cyclic_refresh_q - Q);
+    feature_data[MB_LVL_ALT_Q][2] = 0;
+    feature_data[MB_LVL_ALT_Q][3] = 0;
+
+    // Set up the loop segment data
+    feature_data[MB_LVL_ALT_LF][0] = 0;
+    feature_data[MB_LVL_ALT_LF][1] = lf_adjustment;
+    feature_data[MB_LVL_ALT_LF][2] = 0;
+    feature_data[MB_LVL_ALT_LF][3] = 0;
+
+    // Initialise the feature data structure
+    // SEGMENT_DELTADATA    0, SEGMENT_ABSDATA      1
+    set_segment_data((VP8_PTR)cpi, &feature_data[0][0], SEGMENT_DELTADATA);
+
+    // Delete sementation map
+    if (seg_map != 0)
+        vpx_free(seg_map);
+
+    seg_map = 0;
+
+}
+
+static void mode_ref_lf_test_function(VP8_COMP *cpi)
+{
+    cpi->mb.e_mbd.mode_ref_lf_delta_enabled = 1;
+    cpi->mb.e_mbd.mode_ref_lf_delta_update = 1;
+
+    vpx_memset(cpi->mb.e_mbd.ref_lf_deltas, 0, sizeof(cpi->mb.e_mbd.ref_lf_deltas));
+    vpx_memset(cpi->mb.e_mbd.mode_lf_deltas, 0, sizeof(cpi->mb.e_mbd.mode_lf_deltas));
+
+    // Test of ref frame deltas
+    cpi->mb.e_mbd.ref_lf_deltas[INTRA_FRAME] = 2;
+    cpi->mb.e_mbd.ref_lf_deltas[LAST_FRAME] = 0;
+    cpi->mb.e_mbd.ref_lf_deltas[GOLDEN_FRAME] = -2;
+    cpi->mb.e_mbd.ref_lf_deltas[ALTREF_FRAME] = -2;
+
+    cpi->mb.e_mbd.mode_lf_deltas[0] = 4;               // BPRED
+    cpi->mb.e_mbd.mode_lf_deltas[1] = -2;              // Zero
+    cpi->mb.e_mbd.mode_lf_deltas[2] = 2;               // New mv
+    cpi->mb.e_mbd.mode_lf_deltas[3] = 4;               // Split mv
+}
+
+void vp8_set_speed_features(VP8_COMP *cpi)
+{
+    SPEED_FEATURES *sf = &cpi->sf;
+    int Mode = cpi->compressor_speed;
+    int Speed = cpi->Speed;
+    int i;
+    VP8_COMMON *cm = &cpi->common;
+
+    // Initialise default mode frequency sampling variables
+    for (i = 0; i < MAX_MODES; i ++)
+    {
+        cpi->mode_check_freq[i] = 0;
+        cpi->mode_test_hit_counts[i] = 0;
+        cpi->mode_chosen_counts[i] = 0;
+    }
+
+    cpi->mbs_tested_so_far = 0;
+
+    // best quality
+    sf->RD = 1;
+    sf->search_method = NSTEP;
+    sf->improved_quant = 1;
+    sf->improved_dct = 1;
+    sf->auto_filter = 1;
+    sf->recode_loop = 1;
+    sf->quarter_pixel_search = 1;
+    sf->half_pixel_search = 1;
+    sf->full_freq[0] = 7;
+    sf->full_freq[1] = 7;
+    sf->min_fs_radius = 8;
+    sf->max_fs_radius = 32;
+    sf->iterative_sub_pixel = 1;
+    sf->optimize_coefficients = 1;
+
+    sf->first_step = 0;
+    sf->max_step_search_steps = MAX_MVSEARCH_STEPS;
+
+    cpi->do_full[0] = 0;
+    cpi->do_full[1] = 0;
+
+    // default thresholds to 0
+    for (i = 0; i < MAX_MODES; i++)
+        sf->thresh_mult[i] = 0;
+
+    switch (Mode)
+    {
+#if !(CONFIG_REALTIME_ONLY)
+    case 0: // best quality mode
+        sf->thresh_mult[THR_ZEROMV   ] = 0;
+        sf->thresh_mult[THR_ZEROG    ] = 0;
+        sf->thresh_mult[THR_ZEROA    ] = 0;
+        sf->thresh_mult[THR_NEARESTMV] = 0;
+        sf->thresh_mult[THR_NEARESTG ] = 0;
+        sf->thresh_mult[THR_NEARESTA ] = 0;
+        sf->thresh_mult[THR_NEARMV   ] = 0;
+        sf->thresh_mult[THR_NEARG    ] = 0;
+        sf->thresh_mult[THR_NEARA    ] = 0;
+
+        sf->thresh_mult[THR_DC       ] = 0;
+
+        sf->thresh_mult[THR_V_PRED   ] = 1000;
+        sf->thresh_mult[THR_H_PRED   ] = 1000;
+        sf->thresh_mult[THR_B_PRED   ] = 2000;
+        sf->thresh_mult[THR_TM       ] = 1000;
+
+        sf->thresh_mult[THR_NEWMV    ] = 1000;
+        sf->thresh_mult[THR_NEWG     ] = 1000;
+        sf->thresh_mult[THR_NEWA     ] = 1000;
+
+        sf->thresh_mult[THR_SPLITMV  ] = 2500;
+        sf->thresh_mult[THR_SPLITG   ] = 5000;
+        sf->thresh_mult[THR_SPLITA   ] = 5000;
+
+        sf->full_freq[0] = 7;
+        sf->full_freq[1] = 15;
+
+        sf->first_step = 0;
+        sf->max_step_search_steps = MAX_MVSEARCH_STEPS;
+
+        if (!(cpi->ref_frame_flags & VP8_LAST_FLAG))
+        {
+            sf->thresh_mult[THR_NEWMV    ] = INT_MAX;
+            sf->thresh_mult[THR_NEARESTMV] = INT_MAX;
+            sf->thresh_mult[THR_ZEROMV   ] = INT_MAX;
+            sf->thresh_mult[THR_NEARMV   ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITMV  ] = INT_MAX;
+        }
+
+        if (!(cpi->ref_frame_flags & VP8_GOLD_FLAG))
+        {
+            sf->thresh_mult[THR_NEARESTG ] = INT_MAX;
+            sf->thresh_mult[THR_ZEROG    ] = INT_MAX;
+            sf->thresh_mult[THR_NEARG    ] = INT_MAX;
+            sf->thresh_mult[THR_NEWG     ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITG   ] = INT_MAX;
+        }
+        else if (!(cpi->ref_frame_flags & VP8_ALT_FLAG))
+        {
+            sf->thresh_mult[THR_NEARESTA ] = INT_MAX;
+            sf->thresh_mult[THR_ZEROA    ] = INT_MAX;
+            sf->thresh_mult[THR_NEARA    ] = INT_MAX;
+            sf->thresh_mult[THR_NEWA     ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITA   ] = INT_MAX;
+        }
+
+        break;
+    case 1:
+    case 3:
+        sf->optimize_coefficients = 0;
+        sf->thresh_mult[THR_NEARESTMV] = 0;
+        sf->thresh_mult[THR_ZEROMV   ] = 0;
+        sf->thresh_mult[THR_DC       ] = 0;
+        sf->thresh_mult[THR_NEARMV   ] = 0;
+        sf->thresh_mult[THR_V_PRED   ] = 1000;
+        sf->thresh_mult[THR_H_PRED   ] = 1000;
+        sf->thresh_mult[THR_B_PRED   ] = 2500;
+        sf->thresh_mult[THR_TM       ] = 1000;
+
+        sf->thresh_mult[THR_NEARESTG ] = 1000;
+        sf->thresh_mult[THR_NEARESTA ] = 1000;
+
+        sf->thresh_mult[THR_ZEROG    ] = 1000;
+        sf->thresh_mult[THR_ZEROA    ] = 1000;
+        sf->thresh_mult[THR_NEARG    ] = 1000;
+        sf->thresh_mult[THR_NEARA    ] = 1000;
+
+        sf->thresh_mult[THR_NEWMV    ] = 1500;
+        sf->thresh_mult[THR_NEWG     ] = 1500;
+        sf->thresh_mult[THR_NEWA     ] = 1500;
+
+        sf->thresh_mult[THR_SPLITMV  ] = 5000;
+        sf->thresh_mult[THR_SPLITG   ] = 10000;
+        sf->thresh_mult[THR_SPLITA   ] = 10000;
+
+        sf->full_freq[0] = 15;
+        sf->full_freq[1] = 31;
+
+        sf->first_step = 0;
+        sf->max_step_search_steps = MAX_MVSEARCH_STEPS;
+
+        if (!(cpi->ref_frame_flags & VP8_LAST_FLAG))
+        {
+            sf->thresh_mult[THR_NEWMV    ] = INT_MAX;
+            sf->thresh_mult[THR_NEARESTMV] = INT_MAX;
+            sf->thresh_mult[THR_ZEROMV   ] = INT_MAX;
+            sf->thresh_mult[THR_NEARMV   ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITMV  ] = INT_MAX;
+        }
+        else if (!(cpi->ref_frame_flags & VP8_GOLD_FLAG))
+        {
+            sf->thresh_mult[THR_NEARESTG ] = INT_MAX;
+            sf->thresh_mult[THR_ZEROG    ] = INT_MAX;
+            sf->thresh_mult[THR_NEARG    ] = INT_MAX;
+            sf->thresh_mult[THR_NEWG     ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITG   ] = INT_MAX;
+        }
+        else if (!(cpi->ref_frame_flags & VP8_ALT_FLAG))
+        {
+            sf->thresh_mult[THR_NEARESTA ] = INT_MAX;
+            sf->thresh_mult[THR_ZEROA    ] = INT_MAX;
+            sf->thresh_mult[THR_NEARA    ] = INT_MAX;
+            sf->thresh_mult[THR_NEWA     ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITA   ] = INT_MAX;
+        }
+
+        if (Speed > 0)
+        {
+            cpi->mode_check_freq[THR_SPLITG] = 4;
+            cpi->mode_check_freq[THR_SPLITA] = 4;
+            cpi->mode_check_freq[THR_SPLITMV] = 2;
+
+            sf->thresh_mult[THR_TM       ] = 1500;
+            sf->thresh_mult[THR_V_PRED   ] = 1500;
+            sf->thresh_mult[THR_H_PRED   ] = 1500;
+            sf->thresh_mult[THR_B_PRED   ] = 5000;
+
+            if (cpi->ref_frame_flags & VP8_LAST_FLAG)
+            {
+                sf->thresh_mult[THR_NEWMV    ] = 2000;
+                sf->thresh_mult[THR_SPLITMV  ] = 10000;
+            }
+
+            if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTG ] = 1500;
+                sf->thresh_mult[THR_ZEROG    ] = 1500;
+                sf->thresh_mult[THR_NEARG    ] = 1500;
+                sf->thresh_mult[THR_NEWG     ] = 2000;
+                sf->thresh_mult[THR_SPLITG   ] = 20000;
+            }
+
+            if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTA ] = 1500;
+                sf->thresh_mult[THR_ZEROA    ] = 1500;
+                sf->thresh_mult[THR_NEARA    ] = 1500;
+                sf->thresh_mult[THR_NEWA     ] = 2000;
+                sf->thresh_mult[THR_SPLITA   ] = 20000;
+            }
+
+            sf->improved_quant = 0;
+            sf->improved_dct = 0;
+
+            sf->first_step = 1;
+            sf->max_step_search_steps = MAX_MVSEARCH_STEPS;
+        }
+
+        if (Speed > 1)
+        {
+            cpi->mode_check_freq[THR_SPLITG] = 15;
+            cpi->mode_check_freq[THR_SPLITA] = 15;
+            cpi->mode_check_freq[THR_SPLITMV] = 7;
+
+            sf->thresh_mult[THR_TM       ] = 2000;
+            sf->thresh_mult[THR_V_PRED   ] = 2000;
+            sf->thresh_mult[THR_H_PRED   ] = 2000;
+            sf->thresh_mult[THR_B_PRED   ] = 7500;
+
+            if (cpi->ref_frame_flags & VP8_LAST_FLAG)
+            {
+                sf->thresh_mult[THR_NEWMV    ] = 2000;
+                sf->thresh_mult[THR_SPLITMV  ] = 25000;
+            }
+
+            if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTG ] = 2000;
+                sf->thresh_mult[THR_ZEROG    ] = 2000;
+                sf->thresh_mult[THR_NEARG    ] = 2000;
+                sf->thresh_mult[THR_NEWG     ] = 2500;
+                sf->thresh_mult[THR_SPLITG   ] = 50000;
+            }
+
+            if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTA ] = 2000;
+                sf->thresh_mult[THR_ZEROA    ] = 2000;
+                sf->thresh_mult[THR_NEARA    ] = 2000;
+                sf->thresh_mult[THR_NEWA     ] = 2500;
+                sf->thresh_mult[THR_SPLITA   ] = 50000;
+            }
+
+            // Only do recode loop on key frames and golden frames
+            sf->recode_loop = 2;
+
+            sf->full_freq[0] = 31;
+            sf->full_freq[1] = 63;
+
+        }
+
+        if (Speed > 2)
+        {
+            sf->auto_filter = 0;                     // Faster selection of loop filter
+            cpi->mode_check_freq[THR_V_PRED] = 2;
+            cpi->mode_check_freq[THR_H_PRED] = 2;
+            cpi->mode_check_freq[THR_B_PRED] = 2;
+
+            if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+            {
+                cpi->mode_check_freq[THR_NEARG] = 2;
+                cpi->mode_check_freq[THR_NEWG] = 4;
+            }
+
+            if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+            {
+                cpi->mode_check_freq[THR_NEARA] = 2;
+                cpi->mode_check_freq[THR_NEWA] = 4;
+            }
+
+            sf->thresh_mult[THR_SPLITA  ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITG  ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITMV  ] = INT_MAX;
+
+            sf->full_freq[0] = 63;
+            sf->full_freq[1] = 127;
+        }
+
+        if (Speed > 3)
+        {
+            cpi->mode_check_freq[THR_V_PRED] = 0;
+            cpi->mode_check_freq[THR_H_PRED] = 0;
+            cpi->mode_check_freq[THR_B_PRED] = 0;
+            cpi->mode_check_freq[THR_NEARG] = 0;
+            cpi->mode_check_freq[THR_NEWG] = 0;
+            cpi->mode_check_freq[THR_NEARA] = 0;
+            cpi->mode_check_freq[THR_NEWA] = 0;
+
+            sf->auto_filter = 1;
+            sf->recode_loop = 0; // recode loop off
+            sf->RD = 0;         // Turn rd off
+            sf->full_freq[0] = INT_MAX;
+            sf->full_freq[1] = INT_MAX;
+        }
+
+        if (Speed > 4)
+        {
+            sf->auto_filter = 0;                     // Faster selection of loop filter
+
+            cpi->mode_check_freq[THR_V_PRED] = 2;
+            cpi->mode_check_freq[THR_H_PRED] = 2;
+            cpi->mode_check_freq[THR_B_PRED] = 2;
+
+            if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+            {
+                cpi->mode_check_freq[THR_NEARG] = 2;
+                cpi->mode_check_freq[THR_NEWG] = 4;
+            }
+
+            if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+            {
+                cpi->mode_check_freq[THR_NEARA] = 2;
+                cpi->mode_check_freq[THR_NEWA] = 4;
+            }
+
+            if (cpi->ref_frame_flags & VP8_LAST_FLAG & VP8_GOLD_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTG ] = 2000;
+                sf->thresh_mult[THR_ZEROG    ] = 2000;
+                sf->thresh_mult[THR_NEARG    ] = 2000;
+                sf->thresh_mult[THR_NEWG     ] = 4000;
+            }
+
+            if (cpi->ref_frame_flags & VP8_LAST_FLAG & VP8_ALT_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTA ] = 2000;
+                sf->thresh_mult[THR_ZEROA    ] = 2000;
+                sf->thresh_mult[THR_NEARA    ] = 2000;
+                sf->thresh_mult[THR_NEWA     ] = 4000;
+            }
+        }
+
+        break;
+#endif
+    case 2:
+        sf->optimize_coefficients = 0;
+        sf->recode_loop = 0;
+        sf->auto_filter = 1;
+        sf->iterative_sub_pixel = 1;
+        sf->thresh_mult[THR_NEARESTMV] = 0;
+        sf->thresh_mult[THR_ZEROMV   ] = 0;
+        sf->thresh_mult[THR_DC       ] = 0;
+        sf->thresh_mult[THR_TM       ] = 0;
+        sf->thresh_mult[THR_NEARMV   ] = 0;
+        sf->thresh_mult[THR_V_PRED   ] = 1000;
+        sf->thresh_mult[THR_H_PRED   ] = 1000;
+        sf->thresh_mult[THR_B_PRED   ] = 2500;
+        sf->thresh_mult[THR_NEARESTG ] = 1000;
+        sf->thresh_mult[THR_ZEROG    ] = 1000;
+        sf->thresh_mult[THR_NEARG    ] = 1000;
+        sf->thresh_mult[THR_NEARESTA ] = 1000;
+        sf->thresh_mult[THR_ZEROA    ] = 1000;
+        sf->thresh_mult[THR_NEARA    ] = 1000;
+        sf->thresh_mult[THR_NEWMV    ] = 2000;
+        sf->thresh_mult[THR_NEWG     ] = 2000;
+        sf->thresh_mult[THR_NEWA     ] = 2000;
+        sf->thresh_mult[THR_SPLITMV  ] = 5000;
+        sf->thresh_mult[THR_SPLITG   ] = 10000;
+        sf->thresh_mult[THR_SPLITA   ] = 10000;
+        sf->full_freq[0] = 15;
+        sf->full_freq[1] = 31;
+        sf->search_method = NSTEP;
+
+        if (!cpi->ref_frame_flags & VP8_LAST_FLAG)
+        {
+            sf->thresh_mult[THR_NEWMV    ] = INT_MAX;
+            sf->thresh_mult[THR_NEARESTMV] = INT_MAX;
+            sf->thresh_mult[THR_ZEROMV   ] = INT_MAX;
+            sf->thresh_mult[THR_NEARMV   ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITMV  ] = INT_MAX;
+        }
+
+        if (!cpi->ref_frame_flags & VP8_GOLD_FLAG)
+        {
+            sf->thresh_mult[THR_NEARESTG ] = INT_MAX;
+            sf->thresh_mult[THR_ZEROG    ] = INT_MAX;
+            sf->thresh_mult[THR_NEARG    ] = INT_MAX;
+            sf->thresh_mult[THR_NEWG     ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITG   ] = INT_MAX;
+        }
+
+        if (!cpi->ref_frame_flags & VP8_ALT_FLAG)
+        {
+            sf->thresh_mult[THR_NEARESTA ] = INT_MAX;
+            sf->thresh_mult[THR_ZEROA    ] = INT_MAX;
+            sf->thresh_mult[THR_NEARA    ] = INT_MAX;
+            sf->thresh_mult[THR_NEWA     ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITA   ] = INT_MAX;
+        }
+
+        if (Speed > 0)
+        {
+            cpi->mode_check_freq[THR_SPLITG] = 4;
+            cpi->mode_check_freq[THR_SPLITA] = 4;
+            cpi->mode_check_freq[THR_SPLITMV] = 2;
+
+            sf->thresh_mult[THR_DC       ] = 0;
+            sf->thresh_mult[THR_TM       ] = 1000;
+            sf->thresh_mult[THR_V_PRED   ] = 2000;
+            sf->thresh_mult[THR_H_PRED   ] = 2000;
+            sf->thresh_mult[THR_B_PRED   ] = 5000;
+
+            if (cpi->ref_frame_flags & VP8_LAST_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTMV] = 0;
+                sf->thresh_mult[THR_ZEROMV   ] = 0;
+                sf->thresh_mult[THR_NEARMV   ] = 0;
+                sf->thresh_mult[THR_NEWMV    ] = 2000;
+                sf->thresh_mult[THR_SPLITMV  ] = 10000;
+            }
+
+            if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTG ] = 1000;
+                sf->thresh_mult[THR_ZEROG    ] = 1000;
+                sf->thresh_mult[THR_NEARG    ] = 1000;
+                sf->thresh_mult[THR_NEWG     ] = 2000;
+                sf->thresh_mult[THR_SPLITG   ] = 20000;
+            }
+
+            if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTA ] = 1000;
+                sf->thresh_mult[THR_ZEROA    ] = 1000;
+                sf->thresh_mult[THR_NEARA    ] = 1000;
+                sf->thresh_mult[THR_NEWA     ] = 2000;
+                sf->thresh_mult[THR_SPLITA   ] = 20000;
+            }
+
+            sf->improved_quant = 0;
+            sf->improved_dct = 0;
+        }
+
+        if (Speed > 1)
+        {
+            cpi->mode_check_freq[THR_SPLITMV] = 7;
+            cpi->mode_check_freq[THR_SPLITG] = 15;
+            cpi->mode_check_freq[THR_SPLITA] = 15;
+
+            sf->thresh_mult[THR_TM       ] = 2000;
+            sf->thresh_mult[THR_V_PRED   ] = 2000;
+            sf->thresh_mult[THR_H_PRED   ] = 2000;
+            sf->thresh_mult[THR_B_PRED   ] = 5000;
+
+            if (cpi->ref_frame_flags & VP8_LAST_FLAG)
+            {
+                sf->thresh_mult[THR_NEWMV    ] = 2000;
+                sf->thresh_mult[THR_SPLITMV  ] = 25000;
+            }
+
+            if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTG ] = 2000;
+                sf->thresh_mult[THR_ZEROG    ] = 2000;
+                sf->thresh_mult[THR_NEARG    ] = 2000;
+                sf->thresh_mult[THR_NEWG     ] = 2500;
+                sf->thresh_mult[THR_SPLITG   ] = 50000;
+            }
+
+            if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTA ] = 2000;
+                sf->thresh_mult[THR_ZEROA    ] = 2000;
+                sf->thresh_mult[THR_NEARA    ] = 2000;
+                sf->thresh_mult[THR_NEWA     ] = 2500;
+                sf->thresh_mult[THR_SPLITA   ] = 50000;
+            }
+
+            sf->full_freq[0] = 31;
+            sf->full_freq[1] = 63;
+        }
+
+        if (Speed > 2)
+        {
+            sf->auto_filter = 0;                     // Faster selection of loop filter
+
+            cpi->mode_check_freq[THR_V_PRED] = 2;
+            cpi->mode_check_freq[THR_H_PRED] = 2;
+            cpi->mode_check_freq[THR_B_PRED] = 2;
+
+            if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+            {
+                cpi->mode_check_freq[THR_NEARG] = 2;
+                cpi->mode_check_freq[THR_NEWG] = 4;
+            }
+
+            if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+            {
+                cpi->mode_check_freq[THR_NEARA] = 2;
+                cpi->mode_check_freq[THR_NEWA] = 4;
+            }
+
+            sf->thresh_mult[THR_SPLITMV  ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITG  ] = INT_MAX;
+            sf->thresh_mult[THR_SPLITA  ] = INT_MAX;
+
+            sf->full_freq[0] = 63;
+            sf->full_freq[1] = 127;
+        }
+
+        if (Speed > 3)
+        {
+            sf->RD = 0;
+            sf->full_freq[0] = INT_MAX;
+            sf->full_freq[1] = INT_MAX;
+
+            sf->auto_filter = 1;
+        }
+
+        if (Speed > 4)
+        {
+            sf->auto_filter = 0;                     // Faster selection of loop filter
+
+#if CONFIG_REALTIME_ONLY
+            sf->search_method = HEX;
+#else
+            sf->search_method = DIAMOND;
+#endif
+
+            cpi->mode_check_freq[THR_V_PRED] = 4;
+            cpi->mode_check_freq[THR_H_PRED] = 4;
+            cpi->mode_check_freq[THR_B_PRED] = 4;
+
+            if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+            {
+                cpi->mode_check_freq[THR_NEARG] = 2;
+                cpi->mode_check_freq[THR_NEWG] = 4;
+            }
+
+            if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+            {
+                cpi->mode_check_freq[THR_NEARA] = 2;
+                cpi->mode_check_freq[THR_NEWA] = 4;
+            }
+
+            sf->thresh_mult[THR_TM       ] = 2000;
+            sf->thresh_mult[THR_B_PRED   ] = 5000;
+
+            if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTG ] = 2000;
+                sf->thresh_mult[THR_ZEROG    ] = 2000;
+                sf->thresh_mult[THR_NEARG    ] = 2000;
+                sf->thresh_mult[THR_NEWG     ] = 4000;
+            }
+
+            if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+            {
+                sf->thresh_mult[THR_NEARESTA ] = 2000;
+                sf->thresh_mult[THR_ZEROA    ] = 2000;
+                sf->thresh_mult[THR_NEARA    ] = 2000;
+                sf->thresh_mult[THR_NEWA     ] = 4000;
+            }
+        }
+
+        if (Speed > 5)
+        {
+            // Disable split MB intra prediction mode
+            sf->thresh_mult[THR_B_PRED] = INT_MAX;
+        }
+
+        if (Speed > 6)
+        {
+            unsigned int i, sum = 0;
+            unsigned int total_mbs = cm->MBs;
+            int thresh;
+            int total_skip;
+
+            int min = 2000;
+            sf->iterative_sub_pixel = 0;
+
+            if (cpi->oxcf.encode_breakout > 2000)
+                min = cpi->oxcf.encode_breakout;
+
+            min >>= 7;
+
+            for (i = 0; i < min; i++)
+            {
+                sum += cpi->error_bins[i];
+            }
+
+            total_skip = sum;
+            sum = 0;
+
+            // i starts from 2 to make sure thresh started from 2048
+            for (; i < 1024; i++)
+            {
+                sum += cpi->error_bins[i];
+
+                if (10 * sum >= (unsigned int)(cpi->Speed - 6)*(total_mbs - total_skip))
+                    break;
+            }
+
+            i--;
+            thresh = (i << 7);
+
+            if (thresh < 2000)
+                thresh = 2000;
+
+            if (cpi->ref_frame_flags & VP8_LAST_FLAG)
+            {
+                sf->thresh_mult[THR_NEWMV] = thresh;
+                sf->thresh_mult[THR_NEARESTMV ] = thresh >> 1;
+                sf->thresh_mult[THR_NEARMV    ] = thresh >> 1;
+            }
+
+            if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+            {
+                sf->thresh_mult[THR_NEWG] = thresh << 1;
+                sf->thresh_mult[THR_NEARESTG ] = thresh;
+                sf->thresh_mult[THR_NEARG    ] = thresh;
+            }
+
+            if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+            {
+                sf->thresh_mult[THR_NEWA] = thresh << 1;
+                sf->thresh_mult[THR_NEARESTA ] = thresh;
+                sf->thresh_mult[THR_NEARA    ] = thresh;
+            }
+
+            // Disable other intra prediction modes
+            sf->thresh_mult[THR_TM] = INT_MAX;
+            sf->thresh_mult[THR_V_PRED] = INT_MAX;
+            sf->thresh_mult[THR_H_PRED] = INT_MAX;
+
+        }
+
+        if (Speed > 8)
+        {
+            sf->quarter_pixel_search = 0;
+        }
+
+        if (Speed > 9)
+        {
+            int Tmp = cpi->Speed - 8;
+
+            if (Tmp > 4)
+                Tmp = 4;
+
+            if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+            {
+                cpi->mode_check_freq[THR_ZEROG] = 1 << (Tmp - 1);
+                cpi->mode_check_freq[THR_NEARESTG] = 1 << (Tmp - 1);
+                cpi->mode_check_freq[THR_NEARG] = 1 << Tmp;
+                cpi->mode_check_freq[THR_NEWG] = 1 << (Tmp + 1);
+            }
+
+            if (cpi->ref_frame_flags & VP8_ALT_FLAG)
+            {
+                cpi->mode_check_freq[THR_ZEROA] = 1 << (Tmp - 1);
+                cpi->mode_check_freq[THR_NEARESTA] = 1 << (Tmp - 1);
+                cpi->mode_check_freq[THR_NEARA] = 1 << Tmp;
+                cpi->mode_check_freq[THR_NEWA] = 1 << (Tmp + 1);
+            }
+
+            cpi->mode_check_freq[THR_NEWMV] = 1 << (Tmp - 1);
+        }
+
+        cm->filter_type = NORMAL_LOOPFILTER;
+
+        if (Speed >= 14)
+            cm->filter_type = SIMPLE_LOOPFILTER;
+
+        if (Speed >= 15)
+        {
+            sf->half_pixel_search = 0;        // This has a big hit on quality. Last resort
+        }
+
+        vpx_memset(cpi->error_bins, 0, sizeof(cpi->error_bins));
+
+    };
+
+    if (cpi->sf.search_method == NSTEP)
+    {
+        vp8_init3smotion_compensation(&cpi->mb, cm->last_frame.y_stride);
+    }
+    else if (cpi->sf.search_method == DIAMOND)
+    {
+        vp8_init_dsmotion_compensation(&cpi->mb, cm->last_frame.y_stride);
+    }
+
+    if (cpi->sf.improved_dct)
+    {
+        cpi->mb.vp8_short_fdct8x4 = FDCT_INVOKE(&cpi->rtcd.fdct, short8x4);
+        cpi->mb.vp8_short_fdct4x4 = FDCT_INVOKE(&cpi->rtcd.fdct, short4x4);
+        cpi->mb.short_fdct8x4rd = FDCT_INVOKE(&cpi->rtcd.fdct, short8x4);
+        cpi->mb.short_fdct4x4rd = FDCT_INVOKE(&cpi->rtcd.fdct, short4x4);
+    }
+    else
+    {
+        cpi->mb.vp8_short_fdct8x4   = FDCT_INVOKE(&cpi->rtcd.fdct, fast8x4);
+        cpi->mb.vp8_short_fdct4x4   = FDCT_INVOKE(&cpi->rtcd.fdct, fast4x4);
+        cpi->mb.short_fdct8x4rd = FDCT_INVOKE(&cpi->rtcd.fdct, fast8x4);
+        cpi->mb.short_fdct4x4rd = FDCT_INVOKE(&cpi->rtcd.fdct, fast4x4);
+    }
+
+    cpi->mb.vp8_short_fdct4x4_ptr = FDCT_INVOKE(&cpi->rtcd.fdct, short4x4);
+    cpi->mb.short_walsh4x4 = FDCT_INVOKE(&cpi->rtcd.fdct, walsh_short4x4);
+
+    if (cpi->sf.improved_quant)
+    {
+        cpi->mb.quantize_b    = QUANTIZE_INVOKE(&cpi->rtcd.quantize, quantb);
+        cpi->mb.quantize_brd  = QUANTIZE_INVOKE(&cpi->rtcd.quantize, quantb);
+    }
+    else
+    {
+        cpi->mb.quantize_b      = QUANTIZE_INVOKE(&cpi->rtcd.quantize, fastquantb);
+        cpi->mb.quantize_brd    = QUANTIZE_INVOKE(&cpi->rtcd.quantize, fastquantb);
+    }
+
+#if CONFIG_RUNTIME_CPU_DETECT
+    cpi->mb.e_mbd.rtcd = &cpi->common.rtcd;
+#endif
+
+    if (cpi->sf.iterative_sub_pixel == 1)
+    {
+        cpi->find_fractional_mv_step = vp8_find_best_sub_pixel_step_iteratively;
+    }
+    else if (cpi->sf.quarter_pixel_search)
+    {
+        cpi->find_fractional_mv_step = vp8_find_best_sub_pixel_step;
+    }
+    else if (cpi->sf.half_pixel_search)
+    {
+        cpi->find_fractional_mv_step = vp8_find_best_half_pixel_step;
+    }
+    else
+    {
+        cpi->find_fractional_mv_step = vp8_skip_fractional_mv_step;
+    }
+
+    if (cpi->sf.optimize_coefficients == 1)
+        cpi->mb.optimize = 1;
+    else
+        cpi->mb.optimize = 0;
+
+    if (cpi->common.full_pixel)
+        cpi->find_fractional_mv_step = vp8_skip_fractional_mv_step;
+
+#ifdef SPEEDSTATS
+    frames_at_speed[cpi->Speed]++;
+#endif
+}
+static void alloc_raw_frame_buffers(VP8_COMP *cpi)
+{
+    int i, buffers;
+
+    buffers = cpi->oxcf.lag_in_frames;
+
+    if (buffers > MAX_LAG_BUFFERS)
+        buffers = MAX_LAG_BUFFERS;
+
+    if (buffers < 1)
+        buffers = 1;
+
+    for (i = 0; i < buffers; i++)
+        if (vp8_yv12_alloc_frame_buffer(&cpi->src_buffer[i].source_buffer,
+                                        cpi->oxcf.Width, cpi->oxcf.Height,
+                                        16))
+            vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                               "Failed to allocate lag buffer");
+
+#if VP8_TEMPORAL_ALT_REF
+
+    if (vp8_yv12_alloc_frame_buffer(&cpi->alt_ref_buffer.source_buffer,
+                                    cpi->oxcf.Width, cpi->oxcf.Height, 16))
+        vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                           "Failed to allocate altref buffer");
+
+#endif
+
+    cpi->source_buffer_count = 0;
+}
+void vp8_alloc_compressor_data(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = & cpi->common;
+
+    int width = cm->Width;
+    int height = cm->Height;
+
+    if (vp8_alloc_frame_buffers(cm, width, height))
+        vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                           "Failed to allocate frame buffers");
+
+    if ((width & 0xf) != 0)
+        width += 16 - (width & 0xf);
+
+    if ((height & 0xf) != 0)
+        height += 16 - (height & 0xf);
+
+
+    if (vp8_yv12_alloc_frame_buffer(&cpi->last_frame_uf,
+                                    width, height, VP8BORDERINPIXELS))
+        vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                           "Failed to allocate last frame buffer");
+
+    if (vp8_yv12_alloc_frame_buffer(&cpi->scaled_source, width, height, 16))
+        vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                           "Failed to allocate scaled source buffer");
+
+
+    if (cpi->tok != 0)
+        vpx_free(cpi->tok);
+
+    {
+        unsigned int tokens = cm->mb_rows * cm->mb_cols * 24 * 16;
+
+        CHECK_MEM_ERROR(cpi->tok, vpx_calloc(tokens, sizeof(*cpi->tok)));
+    }
+
+    // Data used for real time vc mode to see if gf needs refreshing
+    cpi->inter_zz_count = 0;
+    cpi->gf_bad_count = 0;
+    cpi->gf_update_recommended = 0;
+}
+
+
+// Quant MOD
+static const int q_trans[] =
+{
+    0,   1,  2,  3,  4,  5,  7,  8,
+    9,  10, 12, 13, 15, 17, 18, 19,
+    20,  21, 23, 24, 25, 26, 27, 28,
+    29,  30, 31, 33, 35, 37, 39, 41,
+    43,  45, 47, 49, 51, 53, 55, 57,
+    59,  61, 64, 67, 70, 73, 76, 79,
+    82,  85, 88, 91, 94, 97, 100, 103,
+    106, 109, 112, 115, 118, 121, 124, 127,
+};
+
+int vp8_reverse_trans(int x)
+{
+    int i;
+
+    for (i = 0; i < 64; i++)
+        if (q_trans[i] >= x)
+            return i;
+
+    return 63;
+};
+void vp8_new_frame_rate(VP8_COMP *cpi, double framerate)
+{
+    cpi->oxcf.frame_rate             = framerate;
+    cpi->output_frame_rate            = cpi->oxcf.frame_rate;
+    cpi->per_frame_bandwidth          = (int)(cpi->oxcf.target_bandwidth / cpi->output_frame_rate);
+    cpi->av_per_frame_bandwidth        = (int)(cpi->oxcf.target_bandwidth / cpi->output_frame_rate);
+    cpi->min_frame_bandwidth          = (int)(cpi->av_per_frame_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+    cpi->rolling_target_bits          = cpi->av_per_frame_bandwidth;
+    cpi->rolling_actual_bits          = cpi->av_per_frame_bandwidth;
+
+    cpi->long_rolling_target_bits      = cpi->av_per_frame_bandwidth;
+    cpi->long_rolling_actual_bits      = cpi->av_per_frame_bandwidth;
+    cpi->max_gf_interval = (int)(cpi->output_frame_rate / 2) + 2;
+
+    //cpi->max_gf_interval = (int)(cpi->output_frame_rate * 2 / 3) + 1;
+    //cpi->max_gf_interval = 24;
+
+    if (cpi->max_gf_interval < 12)
+        cpi->max_gf_interval = 12;
+
+
+    // Special conditions when altr ref frame enabled
+    if (cpi->oxcf.play_alternate)
+    {
+        if (cpi->max_gf_interval > cpi->oxcf.lag_in_frames - 1)
+            cpi->max_gf_interval = cpi->oxcf.lag_in_frames - 1;
+    }
+}
+
+void vp8_init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(ptr);
+    VP8_COMMON *cm = &cpi->common;
+
+    if (!cpi)
+        return;
+
+    cpi->auto_gold = 1;
+    cpi->auto_adjust_gold_quantizer = 1;
+    cpi->goldquantizer = 1;
+    cpi->goldfreq = 7;
+    cpi->auto_adjust_key_quantizer = 1;
+    cpi->keyquantizer = 1;
+
+    cm->version = oxcf->Version;
+    vp8_setup_version(cm);
+
+    if (oxcf == 0)
+    {
+        cpi->pass                     = 0;
+
+        cpi->auto_worst_q              = 0;
+        cpi->oxcf.best_allowed_q            = MINQ;
+        cpi->oxcf.worst_allowed_q           = MAXQ;
+
+        cpi->oxcf.end_usage                = USAGE_STREAM_FROM_SERVER;
+        cpi->oxcf.starting_buffer_level     =   4;
+        cpi->oxcf.optimal_buffer_level      =   5;
+        cpi->oxcf.maximum_buffer_size       =   6;
+        cpi->oxcf.under_shoot_pct           =  90;
+        cpi->oxcf.allow_df                 =   0;
+        cpi->oxcf.drop_frames_water_mark     =  20;
+
+        cpi->oxcf.allow_spatial_resampling  = 0;
+        cpi->oxcf.resample_down_water_mark   = 40;
+        cpi->oxcf.resample_up_water_mark     = 60;
+
+        cpi->oxcf.fixed_q = cpi->interquantizer;
+
+        cpi->filter_type = NORMAL_LOOPFILTER;
+
+        if (cm->simpler_lpf)
+            cpi->filter_type = SIMPLE_LOOPFILTER;
+
+        cpi->compressor_speed = 1;
+        cpi->horiz_scale = 0;
+        cpi->vert_scale = 0;
+        cpi->oxcf.two_pass_vbrbias = 50;
+        cpi->oxcf.two_pass_vbrmax_section = 400;
+        cpi->oxcf.two_pass_vbrmin_section = 0;
+
+        cpi->oxcf.Sharpness = 0;
+        cpi->oxcf.noise_sensitivity = 0;
+    }
+    else
+        cpi->oxcf = *oxcf;
+
+
+    switch (cpi->oxcf.Mode)
+    {
+
+    case MODE_REALTIME:
+        cpi->pass = 0;
+        cpi->compressor_speed = 2;
+
+        if (cpi->oxcf.cpu_used < -16)
+        {
+            cpi->oxcf.cpu_used = -16;
+        }
+
+        if (cpi->oxcf.cpu_used > 16)
+            cpi->oxcf.cpu_used = 16;
+
+        break;
+
+#if !(CONFIG_REALTIME_ONLY)
+    case MODE_GOODQUALITY:
+        cpi->pass = 0;
+        cpi->compressor_speed = 1;
+
+        if (cpi->oxcf.cpu_used < -5)
+        {
+            cpi->oxcf.cpu_used = -5;
+        }
+
+        if (cpi->oxcf.cpu_used > 5)
+            cpi->oxcf.cpu_used = 5;
+
+        break;
+
+    case MODE_BESTQUALITY:
+        cpi->pass = 0;
+        cpi->compressor_speed = 0;
+        break;
+
+    case MODE_FIRSTPASS:
+        cpi->pass = 1;
+        cpi->compressor_speed = 1;
+        break;
+    case MODE_SECONDPASS:
+        cpi->pass = 2;
+        cpi->compressor_speed = 1;
+
+        if (cpi->oxcf.cpu_used < -5)
+        {
+            cpi->oxcf.cpu_used = -5;
+        }
+
+        if (cpi->oxcf.cpu_used > 5)
+            cpi->oxcf.cpu_used = 5;
+
+        break;
+    case MODE_SECONDPASS_BEST:
+        cpi->pass = 2;
+        cpi->compressor_speed = 0;
+        break;
+#endif
+    }
+
+    if (cpi->pass == 0)
+        cpi->auto_worst_q = 1;
+
+    cpi->oxcf.worst_allowed_q = q_trans[oxcf->worst_allowed_q];
+    cpi->oxcf.best_allowed_q  = q_trans[oxcf->best_allowed_q];
+
+    if (oxcf->fixed_q >= 0)
+    {
+        if (oxcf->worst_allowed_q < 0)
+            cpi->oxcf.fixed_q = q_trans[0];
+        else
+            cpi->oxcf.fixed_q = q_trans[oxcf->worst_allowed_q];
+
+        if (oxcf->alt_q < 0)
+            cpi->oxcf.alt_q = q_trans[0];
+        else
+            cpi->oxcf.alt_q = q_trans[oxcf->alt_q];
+
+        if (oxcf->key_q < 0)
+            cpi->oxcf.key_q = q_trans[0];
+        else
+            cpi->oxcf.key_q = q_trans[oxcf->key_q];
+
+        if (oxcf->gold_q < 0)
+            cpi->oxcf.gold_q = q_trans[0];
+        else
+            cpi->oxcf.gold_q = q_trans[oxcf->gold_q];
+
+    }
+
+    cpi->baseline_gf_interval = cpi->oxcf.alt_freq ? cpi->oxcf.alt_freq : DEFAULT_GF_INTERVAL;
+    cpi->ref_frame_flags = VP8_ALT_FLAG | VP8_GOLD_FLAG | VP8_LAST_FLAG;
+
+    //cpi->use_golden_frame_only = 0;
+    //cpi->use_last_frame_only = 0;
+    cm->refresh_golden_frame = 0;
+    cm->refresh_last_frame = 1;
+    cm->refresh_entropy_probs = 1;
+
+    if (cpi->oxcf.token_partitions >= 0 && cpi->oxcf.token_partitions <= 3)
+        cm->multi_token_partition = (TOKEN_PARTITION) cpi->oxcf.token_partitions;
+
+    setup_features(cpi);
+
+    {
+        int i;
+
+        for (i = 0; i < MAX_MB_SEGMENTS; i++)
+            cpi->segment_encode_breakout[i] = cpi->oxcf.encode_breakout;
+    }
+
+    // At the moment the first order values may not be > MAXQ
+    if (cpi->oxcf.fixed_q > MAXQ)
+        cpi->oxcf.fixed_q = MAXQ;
+
+    // local file playback mode == really big buffer
+    if (cpi->oxcf.end_usage == USAGE_LOCAL_FILE_PLAYBACK)
+    {
+        cpi->oxcf.starting_buffer_level   = 60;
+        cpi->oxcf.optimal_buffer_level    = 60;
+        cpi->oxcf.maximum_buffer_size     = 240;
+
+    }
+
+
+    // Convert target bandwidth from Kbit/s to Bit/s
+    cpi->oxcf.target_bandwidth       *= 1000;
+    cpi->oxcf.starting_buffer_level   *= cpi->oxcf.target_bandwidth;
+
+    if (cpi->oxcf.optimal_buffer_level == 0)
+        cpi->oxcf.optimal_buffer_level = cpi->oxcf.target_bandwidth / 8;
+    else
+        cpi->oxcf.optimal_buffer_level *= cpi->oxcf.target_bandwidth;
+
+    if (cpi->oxcf.maximum_buffer_size == 0)
+        cpi->oxcf.maximum_buffer_size = cpi->oxcf.target_bandwidth / 8;
+    else
+        cpi->oxcf.maximum_buffer_size     *= cpi->oxcf.target_bandwidth;
+
+    cpi->buffer_level                = cpi->oxcf.starting_buffer_level;
+    cpi->bits_off_target              = cpi->oxcf.starting_buffer_level;
+
+    vp8_new_frame_rate(cpi, cpi->oxcf.frame_rate);
+    cpi->worst_quality               = cpi->oxcf.worst_allowed_q;
+    cpi->active_worst_quality         = cpi->oxcf.worst_allowed_q;
+    cpi->avg_frame_qindex             = cpi->oxcf.worst_allowed_q;
+    cpi->best_quality                = cpi->oxcf.best_allowed_q;
+    cpi->active_best_quality          = cpi->oxcf.best_allowed_q;
+    cpi->buffered_mode = (cpi->oxcf.optimal_buffer_level > 0) ? TRUE : FALSE;
+
+
+    cpi->total_actual_bits            = 0;
+    cpi->total_target_vs_actual        = 0;
+
+    // Only allow dropped frames in buffered mode
+    cpi->drop_frames_allowed          = cpi->oxcf.allow_df && cpi->buffered_mode;
+
+    cm->filter_type      = (LOOPFILTERTYPE) cpi->filter_type;
+
+    if (!cm->use_bilinear_mc_filter)
+        cm->mcomp_filter_type = SIXTAP;
+    else
+        cm->mcomp_filter_type = BILINEAR;
+
+    cpi->target_bandwidth = cpi->oxcf.target_bandwidth;
+
+    cm->Width       = cpi->oxcf.Width     ;
+    cm->Height      = cpi->oxcf.Height    ;
+
+    cpi->intra_frame_target = (4 * (cm->Width + cm->Height) / 15) * 1000; // As per VP8
+
+    cm->horiz_scale  = cpi->horiz_scale;
+    cm->vert_scale   = cpi->vert_scale ;
+
+    // VP8 sharpness level mapping 0-7 (vs 0-10 in general VPx dialogs)
+    if (cpi->oxcf.Sharpness > 7)
+        cpi->oxcf.Sharpness = 7;
+
+    cm->sharpness_level = cpi->oxcf.Sharpness;
+
+    if (cm->horiz_scale != NORMAL || cm->vert_scale != NORMAL)
+    {
+        int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs);
+        int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs);
+
+        Scale2Ratio(cm->horiz_scale, &hr, &hs);
+        Scale2Ratio(cm->vert_scale, &vr, &vs);
+
+        // always go to the next whole number
+        cm->Width = (hs - 1 + cpi->oxcf.Width * hr) / hs;
+        cm->Height = (vs - 1 + cpi->oxcf.Height * vr) / vs;
+    }
+
+    if (((cm->Width + 15) & 0xfffffff0) != cm->last_frame.y_width ||
+        ((cm->Height + 15) & 0xfffffff0) != cm->last_frame.y_height ||
+        cm->last_frame.y_width == 0)
+    {
+        alloc_raw_frame_buffers(cpi);
+        vp8_alloc_compressor_data(cpi);
+    }
+
+    // Clamp KF frame size to quarter of data rate
+    if (cpi->intra_frame_target > cpi->target_bandwidth >> 2)
+        cpi->intra_frame_target = cpi->target_bandwidth >> 2;
+
+    if (cpi->oxcf.fixed_q >= 0)
+    {
+        cpi->last_q[0] = cpi->oxcf.fixed_q;
+        cpi->last_q[1] = cpi->oxcf.fixed_q;
+    }
+
+    cpi->Speed = cpi->oxcf.cpu_used;
+
+    // force to allowlag to 0 if lag_in_frames is 0;
+    if (cpi->oxcf.lag_in_frames == 0)
+    {
+        cpi->oxcf.allow_lag = 0;
+    }
+    // Limit on lag buffers as these are not currently dynamically allocated
+    else if (cpi->oxcf.lag_in_frames > MAX_LAG_BUFFERS)
+        cpi->oxcf.lag_in_frames = MAX_LAG_BUFFERS;
+
+    // force play_alternate to 0 if allow_lag is 0, lag_in_frames is too small, Mode is real time or one pass compress enabled.
+    if (cpi->oxcf.allow_lag == 0 || cpi->oxcf.lag_in_frames <= 5 || (cpi->oxcf.Mode < MODE_SECONDPASS))
+    {
+        cpi->oxcf.play_alternate = 0;
+        cpi->ref_frame_flags = cpi->ref_frame_flags & ~VP8_ALT_FLAG;
+    }
+
+    // YX Temp
+    cpi->last_alt_ref_sei    = -1;
+    cpi->is_src_frame_alt_ref = 0;
+
+#if 0
+    // Experimental RD Code
+    cpi->frame_distortion = 0;
+    cpi->last_frame_distortion = 0;
+#endif
+
+#if VP8_TEMPORAL_ALT_REF
+    {
+        int i;
+
+        cpi->fixed_divide[0] = 0;
+
+        for (i = 1; i < 255; i++)
+            cpi->fixed_divide[i] = 0x10000 / i;
+    }
+#endif
+}
+
+/*
+ * This function needs more clean up, i.e. be more tuned torwards
+ * change_config rather than init_config  !!!!!!!!!!!!!!!!
+ * YX - 5/28/2009
+ *
+ */
+
+void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(ptr);
+    VP8_COMMON *cm = &cpi->common;
+
+    if (!cpi)
+        return;
+
+    if (!oxcf)
+        return;
+
+    if (cm->version != oxcf->Version)
+    {
+        cm->version = oxcf->Version;
+        vp8_setup_version(cm);
+    }
+
+    cpi->oxcf = *oxcf;
+
+    switch (cpi->oxcf.Mode)
+    {
+
+    case MODE_REALTIME:
+        cpi->pass = 0;
+        cpi->compressor_speed = 2;
+
+        if (cpi->oxcf.cpu_used < -16)
+        {
+            cpi->oxcf.cpu_used = -16;
+        }
+
+        if (cpi->oxcf.cpu_used > 16)
+            cpi->oxcf.cpu_used = 16;
+
+        break;
+
+#if !(CONFIG_REALTIME_ONLY)
+    case MODE_GOODQUALITY:
+        cpi->pass = 0;
+        cpi->compressor_speed = 1;
+
+        if (cpi->oxcf.cpu_used < -5)
+        {
+            cpi->oxcf.cpu_used = -5;
+        }
+
+        if (cpi->oxcf.cpu_used > 5)
+            cpi->oxcf.cpu_used = 5;
+
+        break;
+
+    case MODE_BESTQUALITY:
+        cpi->pass = 0;
+        cpi->compressor_speed = 0;
+        break;
+
+    case MODE_FIRSTPASS:
+        cpi->pass = 1;
+        cpi->compressor_speed = 1;
+        break;
+    case MODE_SECONDPASS:
+        cpi->pass = 2;
+        cpi->compressor_speed = 1;
+
+        if (cpi->oxcf.cpu_used < -5)
+        {
+            cpi->oxcf.cpu_used = -5;
+        }
+
+        if (cpi->oxcf.cpu_used > 5)
+            cpi->oxcf.cpu_used = 5;
+
+        break;
+    case MODE_SECONDPASS_BEST:
+        cpi->pass = 2;
+        cpi->compressor_speed = 0;
+        break;
+#endif
+    }
+
+    if (cpi->pass == 0)
+        cpi->auto_worst_q = 1;
+
+    cpi->oxcf.worst_allowed_q = q_trans[oxcf->worst_allowed_q];
+    cpi->oxcf.best_allowed_q = q_trans[oxcf->best_allowed_q];
+
+    if (oxcf->fixed_q >= 0)
+    {
+        if (oxcf->worst_allowed_q < 0)
+            cpi->oxcf.fixed_q = q_trans[0];
+        else
+            cpi->oxcf.fixed_q = q_trans[oxcf->worst_allowed_q];
+
+        if (oxcf->alt_q < 0)
+            cpi->oxcf.alt_q = q_trans[0];
+        else
+            cpi->oxcf.alt_q = q_trans[oxcf->alt_q];
+
+        if (oxcf->key_q < 0)
+            cpi->oxcf.key_q = q_trans[0];
+        else
+            cpi->oxcf.key_q = q_trans[oxcf->key_q];
+
+        if (oxcf->gold_q < 0)
+            cpi->oxcf.gold_q = q_trans[0];
+        else
+            cpi->oxcf.gold_q = q_trans[oxcf->gold_q];
+
+    }
+
+    cpi->baseline_gf_interval = cpi->oxcf.alt_freq ? cpi->oxcf.alt_freq : DEFAULT_GF_INTERVAL;
+
+    cpi->ref_frame_flags = VP8_ALT_FLAG | VP8_GOLD_FLAG | VP8_LAST_FLAG;
+
+    //cpi->use_golden_frame_only = 0;
+    //cpi->use_last_frame_only = 0;
+    cm->refresh_golden_frame = 0;
+    cm->refresh_last_frame = 1;
+    cm->refresh_entropy_probs = 1;
+
+    if (cpi->oxcf.token_partitions >= 0 && cpi->oxcf.token_partitions <= 3)
+        cm->multi_token_partition = (TOKEN_PARTITION) cpi->oxcf.token_partitions;
+
+    setup_features(cpi);
+
+    {
+        int i;
+
+        for (i = 0; i < MAX_MB_SEGMENTS; i++)
+            cpi->segment_encode_breakout[i] = cpi->oxcf.encode_breakout;
+    }
+
+    // At the moment the first order values may not be > MAXQ
+    if (cpi->oxcf.fixed_q > MAXQ)
+        cpi->oxcf.fixed_q = MAXQ;
+
+    // local file playback mode == really big buffer
+    if (cpi->oxcf.end_usage == USAGE_LOCAL_FILE_PLAYBACK)
+    {
+        cpi->oxcf.starting_buffer_level   = 60;
+        cpi->oxcf.optimal_buffer_level    = 60;
+        cpi->oxcf.maximum_buffer_size     = 240;
+
+    }
+
+    // Convert target bandwidth from Kbit/s to Bit/s
+    cpi->oxcf.target_bandwidth       *= 1000;
+
+    cpi->oxcf.starting_buffer_level   *= cpi->oxcf.target_bandwidth;
+
+    if (cpi->oxcf.optimal_buffer_level == 0)
+        cpi->oxcf.optimal_buffer_level = cpi->oxcf.target_bandwidth / 8;
+    else
+        cpi->oxcf.optimal_buffer_level *= cpi->oxcf.target_bandwidth;
+
+    if (cpi->oxcf.maximum_buffer_size == 0)
+        cpi->oxcf.maximum_buffer_size = cpi->oxcf.target_bandwidth / 8;
+    else
+        cpi->oxcf.maximum_buffer_size     *= cpi->oxcf.target_bandwidth;
+
+    cpi->buffer_level                = cpi->oxcf.starting_buffer_level;
+    cpi->bits_off_target              = cpi->oxcf.starting_buffer_level;
+
+    vp8_new_frame_rate(cpi, cpi->oxcf.frame_rate);
+    cpi->worst_quality               = cpi->oxcf.worst_allowed_q;
+    cpi->active_worst_quality         = cpi->oxcf.worst_allowed_q;
+    cpi->avg_frame_qindex             = cpi->oxcf.worst_allowed_q;
+    cpi->best_quality                = cpi->oxcf.best_allowed_q;
+    cpi->active_best_quality          = cpi->oxcf.best_allowed_q;
+    cpi->buffered_mode = (cpi->oxcf.optimal_buffer_level > 0) ? TRUE : FALSE;
+
+
+    cpi->total_actual_bits            = 0;
+    cpi->total_target_vs_actual        = 0;
+
+    // Only allow dropped frames in buffered mode
+    cpi->drop_frames_allowed          = cpi->oxcf.allow_df && cpi->buffered_mode;
+
+    cm->filter_type                  = (LOOPFILTERTYPE) cpi->filter_type;
+
+    if (!cm->use_bilinear_mc_filter)
+        cm->mcomp_filter_type = SIXTAP;
+    else
+        cm->mcomp_filter_type = BILINEAR;
+
+    cpi->target_bandwidth = cpi->oxcf.target_bandwidth;
+
+    cm->Width       = cpi->oxcf.Width     ;
+    cm->Height      = cpi->oxcf.Height    ;
+
+    cm->horiz_scale  = cpi->horiz_scale;
+    cm->vert_scale   = cpi->vert_scale ;
+
+    cpi->intra_frame_target           = (4 * (cm->Width + cm->Height) / 15) * 1000; // As per VP8
+
+    // VP8 sharpness level mapping 0-7 (vs 0-10 in general VPx dialogs)
+    if (cpi->oxcf.Sharpness > 7)
+        cpi->oxcf.Sharpness = 7;
+
+    cm->sharpness_level = cpi->oxcf.Sharpness;
+
+    if (cm->horiz_scale != NORMAL || cm->vert_scale != NORMAL)
+    {
+        int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs);
+        int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs);
+
+        Scale2Ratio(cm->horiz_scale, &hr, &hs);
+        Scale2Ratio(cm->vert_scale, &vr, &vs);
+
+        // always go to the next whole number
+        cm->Width = (hs - 1 + cpi->oxcf.Width * hr) / hs;
+        cm->Height = (vs - 1 + cpi->oxcf.Height * vr) / vs;
+    }
+
+    if (((cm->Width + 15) & 0xfffffff0) != cm->last_frame.y_width ||
+        ((cm->Height + 15) & 0xfffffff0) != cm->last_frame.y_height ||
+        cm->last_frame.y_width == 0)
+    {
+        alloc_raw_frame_buffers(cpi);
+        vp8_alloc_compressor_data(cpi);
+    }
+
+    // Clamp KF frame size to quarter of data rate
+    if (cpi->intra_frame_target > cpi->target_bandwidth >> 2)
+        cpi->intra_frame_target = cpi->target_bandwidth >> 2;
+
+    if (cpi->oxcf.fixed_q >= 0)
+    {
+        cpi->last_q[0] = cpi->oxcf.fixed_q;
+        cpi->last_q[1] = cpi->oxcf.fixed_q;
+    }
+
+    cpi->Speed = cpi->oxcf.cpu_used;
+
+    // force to allowlag to 0 if lag_in_frames is 0;
+    if (cpi->oxcf.lag_in_frames == 0)
+    {
+        cpi->oxcf.allow_lag = 0;
+    }
+    // Limit on lag buffers as these are not currently dynamically allocated
+    else if (cpi->oxcf.lag_in_frames > MAX_LAG_BUFFERS)
+        cpi->oxcf.lag_in_frames = MAX_LAG_BUFFERS;
+
+    // force play_alternate to 0 if allow_lag is 0, lag_in_frames is too small, Mode is real time or one pass compress enabled.
+    if (cpi->oxcf.allow_lag == 0 || cpi->oxcf.lag_in_frames <= 5 || (cpi->oxcf.Mode < MODE_SECONDPASS))
+    {
+        cpi->oxcf.play_alternate = 0;
+        cpi->ref_frame_flags = cpi->ref_frame_flags & ~VP8_ALT_FLAG;
+    }
+
+    // YX Temp
+    cpi->last_alt_ref_sei    = -1;
+    cpi->is_src_frame_alt_ref = 0;
+
+#if 0
+    // Experimental RD Code
+    cpi->frame_distortion = 0;
+    cpi->last_frame_distortion = 0;
+#endif
+
+}
+
+#define M_LOG2_E 0.693147180559945309417
+#define log2f(x) (log (x) / (float) M_LOG2_E)
+static void cal_mvsadcosts(int *mvsadcost[2])
+{
+    int i = 1;
+
+    mvsadcost [0] [0] = 300;
+    mvsadcost [1] [0] = 300;
+
+    do
+    {
+        double z = 256 * (2 * (log2f(2 * i) + .6));
+        mvsadcost [0][i] = (int) z;
+        mvsadcost [1][i] = (int) z;
+        mvsadcost [0][-i] = (int) z;
+        mvsadcost [1][-i] = (int) z;
+    }
+    while (++i <= mv_max);
+}
+
+VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf)
+{
+    int i;
+    volatile union
+    {
+        VP8_COMP *cpi;
+        VP8_PTR   ptr;
+    } ctx;
+    
+    VP8_COMP *cpi;
+    VP8_COMMON *cm;
+
+    cpi = ctx.cpi = vpx_memalign(32, sizeof(VP8_COMP));
+    // Check that the CPI instance is valid
+    if (!cpi)
+        return 0;
+
+    cm = &cpi->common;
+
+    vpx_memset(cpi, 0, sizeof(VP8_COMP));
+
+    if (setjmp(cm->error.jmp))
+    {
+        VP8_PTR ptr = ctx.ptr;
+
+        ctx.cpi->common.error.setjmp = 0;
+        vp8_remove_compressor(&ptr);
+        return 0;
+    }
+
+    cpi->common.error.setjmp = 1;
+
+    CHECK_MEM_ERROR(cpi->rdtok, vpx_calloc(256 * 3 / 2, sizeof(TOKENEXTRA)));
+    CHECK_MEM_ERROR(cpi->mb.ss, vpx_calloc(sizeof(search_site), (MAX_MVSEARCH_STEPS * 8) + 1));
+
+    vp8_cmachine_specific_config(cpi);
+    vp8_create_common(&cpi->common);
+
+    vp8_init_config((VP8_PTR)cpi, oxcf);
+
+    memcpy(cpi->base_skip_false_prob, vp8cx_base_skip_false_prob, sizeof(vp8cx_base_skip_false_prob));
+    cpi->common.current_video_frame   = 0;
+    cpi->kf_overspend_bits            = 0;
+    cpi->kf_bitrate_adjustment        = 0;
+    cpi->frames_till_gf_update_due      = 0;
+    cpi->gf_overspend_bits            = 0;
+    cpi->non_gf_bitrate_adjustment     = 0;
+    cpi->prob_last_coded              = 128;
+    cpi->prob_gf_coded                = 128;
+    cpi->prob_intra_coded             = 63;
+
+    // Prime the recent reference frame useage counters.
+    // Hereafter they will be maintained as a sort of moving average
+    cpi->recent_ref_frame_usage[INTRA_FRAME]  = 1;
+    cpi->recent_ref_frame_usage[LAST_FRAME]   = 1;
+    cpi->recent_ref_frame_usage[GOLDEN_FRAME] = 1;
+    cpi->recent_ref_frame_usage[ALTREF_FRAME] = 1;
+
+    // Set reference frame sign bias for ALTREF frame to 1 (for now)
+    cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = 1;
+
+    cpi->gf_decay_rate = 0;
+    cpi->baseline_gf_interval = DEFAULT_GF_INTERVAL;
+
+    cpi->gold_is_last = 0 ;
+    cpi->alt_is_last  = 0 ;
+    cpi->gold_is_alt  = 0 ;
+
+
+
+    // Create the encoder segmentation map and set all entries to 0
+    CHECK_MEM_ERROR(cpi->segmentation_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
+    CHECK_MEM_ERROR(cpi->active_map, vpx_calloc(cpi->common.mb_rows * cpi->common.mb_cols, 1));
+    vpx_memset(cpi->active_map , 1, (cpi->common.mb_rows * cpi->common.mb_cols));
+    cpi->active_map_enabled = 0;
+
+    // Create the first pass motion map structure and set to 0
+    CHECK_MEM_ERROR(cpi->fp_motion_map, vpx_calloc(cpi->common.MBs, 1));
+
+#if 0
+    // Experimental code for lagged and one pass
+    // Initialise one_pass GF frames stats
+    // Update stats used for GF selection
+    if (cpi->pass == 0)
+    {
+        cpi->one_pass_frame_index = 0;
+
+        for (i = 0; i < MAX_LAG_BUFFERS; i++)
+        {
+            cpi->one_pass_frame_stats[i].frames_so_far = 0;
+            cpi->one_pass_frame_stats[i].frame_intra_error = 0.0;
+            cpi->one_pass_frame_stats[i].frame_coded_error = 0.0;
+            cpi->one_pass_frame_stats[i].frame_pcnt_inter = 0.0;
+            cpi->one_pass_frame_stats[i].frame_pcnt_motion = 0.0;
+            cpi->one_pass_frame_stats[i].frame_mvr = 0.0;
+            cpi->one_pass_frame_stats[i].frame_mvr_abs = 0.0;
+            cpi->one_pass_frame_stats[i].frame_mvc = 0.0;
+            cpi->one_pass_frame_stats[i].frame_mvc_abs = 0.0;
+        }
+    }
+#endif
+
+    // Should we use the cyclic refresh method.
+    // Currently this is tied to error resilliant mode
+    cpi->cyclic_refresh_mode_enabled = cpi->oxcf.error_resilient_mode;
+    cpi->cyclic_refresh_mode_max_mbs_perframe = (cpi->common.mb_rows * cpi->common.mb_cols) / 40;
+    cpi->cyclic_refresh_mode_index = 0;
+    cpi->cyclic_refresh_q = 32;
+
+    if (cpi->cyclic_refresh_mode_enabled)
+    {
+        CHECK_MEM_ERROR(cpi->cyclic_refresh_map, vpx_calloc((cpi->common.mb_rows * cpi->common.mb_cols), 1));
+    }
+    else
+        cpi->cyclic_refresh_map = (signed char *) NULL;
+
+    // Test function for segmentation
+    //segmentation_test_function((VP8_PTR) cpi);
+
+    // Loop filter mode / ref deltas test function
+    //mode_ref_lf_test_function(cpi);
+
+#ifdef ENTROPY_STATS
+    init_context_counters();
+#endif
+
+
+#ifdef INTRARDOPT
+    cpi->intra_rd_opt = 1;
+
+#endif
+
+    cpi->frames_since_key = 8;        // Give a sensible default for the first frame.
+    cpi->key_frame_frequency = cpi->oxcf.key_freq;
+
+    cpi->source_alt_ref_pending = FALSE;
+    cpi->source_alt_ref_active = FALSE;
+    cpi->common.refresh_alt_ref_frame = 0;
+
+    cpi->b_calculate_psnr = CONFIG_PSNR;
+#if CONFIG_PSNR
+    cpi->b_calculate_ssimg = 0;
+
+    cpi->count = 0;
+    cpi->bytes = 0;
+
+    if (cpi->b_calculate_psnr)
+    {
+        cpi->total_sq_error = 0.0;
+        cpi->total_sq_error2 = 0.0;
+        cpi->total_y = 0.0;
+        cpi->total_u = 0.0;
+        cpi->total_v = 0.0;
+        cpi->total = 0.0;
+        cpi->totalp_y = 0.0;
+        cpi->totalp_u = 0.0;
+        cpi->totalp_v = 0.0;
+        cpi->totalp = 0.0;
+        cpi->tot_recode_hits = 0;
+        cpi->summed_quality = 0;
+        cpi->summed_weights = 0;
+    }
+
+    if (cpi->b_calculate_ssimg)
+    {
+        cpi->total_ssimg_y = 0;
+        cpi->total_ssimg_u = 0;
+        cpi->total_ssimg_v = 0;
+        cpi->total_ssimg_all = 0;
+    }
+
+#ifndef LLONG_MAX
+#define LLONG_MAX  9223372036854775807LL
+#endif
+    cpi->first_time_stamp_ever = LLONG_MAX;
+
+#endif
+
+    cpi->frames_till_gf_update_due      = 0;
+    cpi->key_frame_count              = 1;
+    cpi->tot_key_frame_bits            = 0;
+
+    cpi->ni_av_qi                     = cpi->oxcf.worst_allowed_q;
+    cpi->ni_tot_qi                    = 0;
+    cpi->ni_frames                   = 0;
+    cpi->total_byte_count             = 0;
+
+    cpi->drop_frame                  = 0;
+    cpi->drop_count                  = 0;
+    cpi->max_drop_count               = 0;
+    cpi->max_consec_dropped_frames     = 4;
+
+    cpi->rate_correction_factor         = 1.0;
+    cpi->key_frame_rate_correction_factor = 1.0;
+    cpi->gf_rate_correction_factor  = 1.0;
+    cpi->est_max_qcorrection_factor  = 1.0;
+
+    cpi->mb.mvcost[0] = &cpi->mb.mvcosts[0][mv_max+1];
+    cpi->mb.mvcost[1] = &cpi->mb.mvcosts[1][mv_max+1];
+    cpi->mb.mvsadcost[0] = &cpi->mb.mvsadcosts[0][mv_max+1];
+    cpi->mb.mvsadcost[1] = &cpi->mb.mvsadcosts[1][mv_max+1];
+
+    cal_mvsadcosts(cpi->mb.mvsadcost);
+
+    for (i = 0; i < KEY_FRAME_CONTEXT; i++)
+    {
+        cpi->prior_key_frame_size[i]     = cpi->intra_frame_target;
+        cpi->prior_key_frame_distance[i] = (int)cpi->output_frame_rate;
+    }
+
+    cpi->check_freq[0] = 15;
+    cpi->check_freq[1] = 15;
+
+#ifdef OUTPUT_YUV_SRC
+    yuv_file = fopen("bd.yuv", "ab");
+#endif
+
+#if 0
+    framepsnr = fopen("framepsnr.stt", "a");
+    kf_list = fopen("kf_list.stt", "w");
+#endif
+
+    cpi->output_pkt_list = oxcf->output_pkt_list;
+
+#if !(CONFIG_REALTIME_ONLY)
+
+    if (cpi->pass == 1)
+    {
+        vp8_init_first_pass(cpi);
+    }
+    else if (cpi->pass == 2)
+    {
+        cpi->stats_in = oxcf->two_pass_stats_in.buf;
+        cpi->stats_in_end = cpi->stats_in
+                            + oxcf->two_pass_stats_in.sz / sizeof(FIRSTPASS_STATS)
+                            - 1;
+        vp8_init_second_pass(cpi);
+    }
+
+#endif
+
+    if (cpi->compressor_speed == 2)
+    {
+        cpi->cpu_freq            = 0; //vp8_get_processor_freq();
+        cpi->avg_encode_time      = 0;
+        cpi->avg_pick_mode_time    = 0;
+    }
+
+    vp8_set_speed_features(cpi);
+
+    // Set starting values of RD threshold multipliers (128 = *1)
+    for (i = 0; i < MAX_MODES; i++)
+    {
+        cpi->rd_thresh_mult[i] = 128;
+    }
+
+#ifdef ENTROPY_STATS
+    init_mv_ref_counts();
+#endif
+
+    vp8cx_create_encoder_threads(cpi);
+
+    cpi->fn_ptr.sdf   = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16);
+    cpi->fn_ptr.vf    = VARIANCE_INVOKE(&cpi->rtcd.variance, var16x16);
+    cpi->fn_ptr.svf   = VARIANCE_INVOKE(&cpi->rtcd.variance, subpixvar16x16);
+    cpi->fn_ptr.sdx3f = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16x3);
+    cpi->fn_ptr.sdx4df = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16x4d);
+
+#if !(CONFIG_REALTIME_ONLY)
+    cpi->full_search_sad = SEARCH_INVOKE(&cpi->rtcd.search, full_search);
+#endif
+    cpi->diamond_search_sad = SEARCH_INVOKE(&cpi->rtcd.search, diamond_search);
+
+    cpi->ready_for_new_frame = 1;
+
+    cpi->source_encode_index = 0;
+
+    // make sure frame 1 is okay
+    cpi->error_bins[0] = cpi->common.MBs;
+
+    //vp8cx_init_quantizer() is first called here. Add check in vp8cx_frame_init_quantizer() so that vp8cx_init_quantizer is only called later
+    //when needed. This will avoid unnecessary calls of vp8cx_init_quantizer() for every frame.
+    vp8cx_init_quantizer(cpi);
+    {
+        vp8_init_loop_filter(cm);
+        cm->last_frame_type = KEY_FRAME;
+        cm->last_filter_type = cm->filter_type;
+        cm->last_sharpness_level = cm->sharpness_level;
+    }
+    cpi->common.error.setjmp = 0;
+    return (VP8_PTR) cpi;
+
+}
+
+
+void vp8_remove_compressor(VP8_PTR *ptr)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(*ptr);
+
+    if (!cpi)
+        return;
+
+    if (cpi && (cpi->common.current_video_frame > 0))
+    {
+#if !(CONFIG_REALTIME_ONLY)
+
+        if (cpi->pass == 2)
+        {
+            vp8_end_second_pass(cpi);
+        }
+
+#endif
+
+#ifdef ENTROPY_STATS
+        print_context_counters();
+        print_tree_update_probs();
+        print_mode_context();
+#endif
+
+#if CONFIG_PSNR
+
+        if (cpi->pass != 1)
+        {
+            FILE *f = fopen("opsnr.stt", "a");
+            double time_encoded = (cpi->source_end_time_stamp - cpi->first_time_stamp_ever) / 10000000.000;
+            double total_encode_time = (cpi->time_receive_data + cpi->time_compress_data)   / 1000.000;
+            double dr = (double)cpi->bytes * (double) 8 / (double)1000  / time_encoded;
+
+            if (cpi->b_calculate_psnr)
+            {
+                double samples = 3.0 / 2 * cpi->count * cpi->common.last_frame.y_width * cpi->common.last_frame.y_height;
+                double total_psnr = vp8_mse2psnr(samples, 255.0, cpi->total_sq_error);
+                double total_psnr2 = vp8_mse2psnr(samples, 255.0, cpi->total_sq_error2);
+                double total_ssim = 100 * pow(cpi->summed_quality / cpi->summed_weights, 8.0);
+
+                fprintf(f, "Bitrate\AVGPsnr\tGLBPsnr\tAVPsnrP\tGLPsnrP\tVPXSSIM\t  Time(us)\n");
+                fprintf(f, "%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f %8.0f\n",
+                        dr, cpi->total / cpi->count, total_psnr, cpi->totalp / cpi->count, total_psnr2, total_ssim,
+                        total_encode_time);
+            }
+
+            if (cpi->b_calculate_ssimg)
+            {
+                fprintf(f, "BitRate\tSSIM_Y\tSSIM_U\tSSIM_V\tSSIM_A\t  Time(us)\n");
+                fprintf(f, "%7.3f\t%6.4f\t%6.4f\t%6.4f\t%6.4f\t%8.0f\n", dr,
+                        cpi->total_ssimg_y / cpi->count, cpi->total_ssimg_u / cpi->count,
+                        cpi->total_ssimg_v / cpi->count, cpi->total_ssimg_all / cpi->count, total_encode_time);
+            }
+
+            fclose(f);
+#if 0
+            f = fopen("qskip.stt", "a");
+            fprintf(f, "minq:%d -maxq:%d skipture:skipfalse = %d:%d\n", cpi->oxcf.best_allowed_q, cpi->oxcf.worst_allowed_q, skiptruecount, skipfalsecount);
+            fclose(f);
+#endif
+
+        }
+
+#endif
+
+
+#ifdef SPEEDSTATS
+
+        if (cpi->compressor_speed == 2)
+        {
+            int i;
+            FILE *f = fopen("cxspeed.stt", "a");
+            cnt_pm /= cpi->common.MBs;
+
+            for (i = 0; i < 16; i++)
+                fprintf(f, "%5d", frames_at_speed[i]);
+
+            fprintf(f, "\n");
+            //fprintf(f, "%10d PM %10d %10d %10d EF %10d %10d %10d\n", cpi->Speed, cpi->avg_pick_mode_time, (tot_pm/cnt_pm), cnt_pm,  cpi->avg_encode_time, 0, 0);
+            fclose(f);
+        }
+
+#endif
+
+
+#ifdef MODE_STATS
+        {
+            extern int count_mb_seg[4];
+            FILE *f = fopen("modes.stt", "a");
+            double dr = (double)cpi->oxcf.frame_rate * (double)bytes * (double)8 / (double)count / (double)1000 ;
+            fprintf(f, "intra_mode in Intra Frames:\n");
+            fprintf(f, "Y: %8d, %8d, %8d, %8d, %8d\n", y_modes[0], y_modes[1], y_modes[2], y_modes[3], y_modes[4]);
+            fprintf(f, "UV:%8d, %8d, %8d, %8d\n", uv_modes[0], uv_modes[1], uv_modes[2], uv_modes[3]);
+            fprintf(f, "B: ");
+            {
+                int i;
+
+                for (i = 0; i < 10; i++)
+                    fprintf(f, "%8d, ", b_modes[i]);
+
+                fprintf(f, "\n");
+
+            }
+
+            fprintf(f, "Modes in Inter Frames:\n");
+            fprintf(f, "Y: %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d, %8d\n",
+                    inter_y_modes[0], inter_y_modes[1], inter_y_modes[2], inter_y_modes[3], inter_y_modes[4],
+                    inter_y_modes[5], inter_y_modes[6], inter_y_modes[7], inter_y_modes[8], inter_y_modes[9]);
+            fprintf(f, "UV:%8d, %8d, %8d, %8d\n", inter_uv_modes[0], inter_uv_modes[1], inter_uv_modes[2], inter_uv_modes[3]);
+            fprintf(f, "B: ");
+            {
+                int i;
+
+                for (i = 0; i < 15; i++)
+                    fprintf(f, "%8d, ", inter_b_modes[i]);
+
+                fprintf(f, "\n");
+
+            }
+            fprintf(f, "P:%8d, %8d, %8d, %8d\n", count_mb_seg[0], count_mb_seg[1], count_mb_seg[2], count_mb_seg[3]);
+            fprintf(f, "PB:%8d, %8d, %8d, %8d\n", inter_b_modes[LEFT4X4], inter_b_modes[ABOVE4X4], inter_b_modes[ZERO4X4], inter_b_modes[NEW4X4]);
+
+
+
+            fclose(f);
+        }
+#endif
+
+#ifdef ENTROPY_STATS
+        {
+            int i, j, k;
+            FILE *fmode = fopen("modecontext.c", "w");
+
+            fprintf(fmode, "\n#include \"entropymode.h\"\n\n");
+            fprintf(fmode, "const unsigned int vp8_kf_default_bmode_counts ");
+            fprintf(fmode, "[VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES] =\n{\n");
+
+            for (i = 0; i < 10; i++)
+            {
+
+                fprintf(fmode, "    { //Above Mode :  %d\n", i);
+
+                for (j = 0; j < 10; j++)
+                {
+
+                    fprintf(fmode, "        {");
+
+                    for (k = 0; k < 10; k++)
+                    {
+                        if (!intra_mode_stats[i][j][k])
+                            fprintf(fmode, " %5d, ", 1);
+                        else
+                            fprintf(fmode, " %5d, ", intra_mode_stats[i][j][k]);
+                    }
+
+                    fprintf(fmode, "}, // left_mode %d\n", j);
+
+                }
+
+                fprintf(fmode, "    },\n");
+
+            }
+
+            fprintf(fmode, "};\n");
+        }
+#endif
+
+
+#if defined(SECTIONBITS_OUTPUT)
+
+        if (0)
+        {
+            int i;
+            FILE *f = fopen("tokenbits.stt", "a");
+
+            for (i = 0; i < 28; i++)
+                fprintf(f, "%8d", (int)(Sectionbits[i] / 256));
+
+            fprintf(f, "\n");
+            fclose(f);
+        }
+
+#endif
+
+#if 0
+        {
+            printf("\n_pick_loop_filter_level:%d\n", cpi->time_pick_lpf / 1000);
+            printf("\n_frames recive_data encod_mb_row compress_frame  Total\n");
+            printf("%6d %10ld %10ld %10ld %10ld\n", cpi->common.current_video_frame, cpi->time_receive_data / 1000, cpi->time_encode_mb_row / 1000, cpi->time_compress_data / 1000, (cpi->time_receive_data + cpi->time_compress_data) / 1000);
+        }
+#endif
+
+    }
+
+    vp8cx_remove_encoder_threads(cpi);
+
+    vp8_dealloc_compressor_data(cpi);
+    vpx_free(cpi->mb.ss);
+    vpx_free(cpi->tok);
+    vpx_free(cpi->rdtok);
+    vpx_free(cpi->cyclic_refresh_map);
+
+    vp8_remove_common(&cpi->common);
+    vpx_free(cpi);
+    *ptr = 0;
+
+#ifdef OUTPUT_YUV_SRC
+    fclose(yuv_file);
+#endif
+
+#if 0
+
+    if (keyfile)
+        fclose(keyfile);
+
+    if (framepsnr)
+        fclose(framepsnr);
+
+    if (kf_list)
+        fclose(kf_list);
+
+#endif
+
+}
+
+
+static uint64_t calc_plane_error(unsigned char *orig, int orig_stride,
+                                 unsigned char *recon, int recon_stride,
+                                 unsigned int cols, unsigned int rows,
+                                 vp8_variance_rtcd_vtable_t *rtcd)
+{
+    unsigned int row, col;
+    uint64_t total_sse = 0;
+    int diff;
+
+    for (row = 0; row + 16 <= rows; row += 16)
+    {
+        for (col = 0; col + 16 <= cols; col += 16)
+        {
+            unsigned int sse;
+
+            VARIANCE_INVOKE(rtcd, mse16x16)(orig + col, orig_stride,
+                                            recon + col, recon_stride,
+                                            &sse);
+            total_sse += sse;
+        }
+
+        /* Handle odd-sized width */
+        if (col < cols)
+        {
+            unsigned int   border_row, border_col;
+            unsigned char *border_orig = orig;
+            unsigned char *border_recon = recon;
+
+            for (border_row = 0; border_row < 16; border_row++)
+            {
+                for (border_col = col; border_col < cols; border_col++)
+                {
+                    diff = border_orig[border_col] - border_recon[border_col];
+                    total_sse += diff * diff;
+                }
+
+                border_orig += orig_stride;
+                border_recon += recon_stride;
+            }
+        }
+
+        orig += orig_stride * 16;
+        recon += recon_stride * 16;
+    }
+
+    /* Handle odd-sized height */
+    for (; row < rows; row++)
+    {
+        for (col = 0; col < cols; col++)
+        {
+            diff = orig[col] - recon[col];
+            total_sse += diff * diff;
+        }
+
+        orig += orig_stride;
+        recon += recon_stride;
+    }
+
+    return total_sse;
+}
+
+
+static void generate_psnr_packet(VP8_COMP *cpi)
+{
+    YV12_BUFFER_CONFIG      *orig = cpi->Source;
+    YV12_BUFFER_CONFIG      *recon = cpi->common.frame_to_show;
+    struct vpx_codec_cx_pkt  pkt;
+    uint64_t                 sse;
+    int                      i;
+    unsigned int             width = cpi->common.Width;
+    unsigned int             height = cpi->common.Height;
+
+    pkt.kind = VPX_CODEC_PSNR_PKT;
+    sse = calc_plane_error(orig->y_buffer, orig->y_stride,
+                           recon->y_buffer, recon->y_stride,
+                           width, height,
+                           IF_RTCD(&cpi->rtcd.variance));
+    pkt.data.psnr.sse[0] = sse;
+    pkt.data.psnr.sse[1] = sse;
+    pkt.data.psnr.samples[0] = width * height;
+    pkt.data.psnr.samples[1] = width * height;
+
+    width = (width + 1) / 2;
+    height = (height + 1) / 2;
+
+    sse = calc_plane_error(orig->u_buffer, orig->uv_stride,
+                           recon->u_buffer, recon->uv_stride,
+                           width, height,
+                           IF_RTCD(&cpi->rtcd.variance));
+    pkt.data.psnr.sse[0] += sse;
+    pkt.data.psnr.sse[2] = sse;
+    pkt.data.psnr.samples[0] += width * height;
+    pkt.data.psnr.samples[2] = width * height;
+
+    sse = calc_plane_error(orig->v_buffer, orig->uv_stride,
+                           recon->v_buffer, recon->uv_stride,
+                           width, height,
+                           IF_RTCD(&cpi->rtcd.variance));
+    pkt.data.psnr.sse[0] += sse;
+    pkt.data.psnr.sse[3] = sse;
+    pkt.data.psnr.samples[0] += width * height;
+    pkt.data.psnr.samples[3] = width * height;
+
+    for (i = 0; i < 4; i++)
+        pkt.data.psnr.psnr[i] = vp8_mse2psnr(pkt.data.psnr.samples[i], 255.0,
+                                             pkt.data.psnr.sse[i]);
+
+    vpx_codec_pkt_list_add(cpi->output_pkt_list, &pkt);
+}
+
+
+int vp8_use_as_reference(VP8_PTR ptr, int ref_frame_flags)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(ptr);
+
+    if (ref_frame_flags > 7)
+        return -1 ;
+
+    cpi->ref_frame_flags = ref_frame_flags;
+    return 0;
+}
+int vp8_update_reference(VP8_PTR ptr, int ref_frame_flags)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(ptr);
+
+    if (ref_frame_flags > 7)
+        return -1 ;
+
+    cpi->common.refresh_golden_frame = 0;
+    cpi->common.refresh_alt_ref_frame = 0;
+    cpi->common.refresh_last_frame   = 0;
+
+    if (ref_frame_flags & VP8_LAST_FLAG)
+        cpi->common.refresh_last_frame = 1;
+
+    if (ref_frame_flags & VP8_GOLD_FLAG)
+        cpi->common.refresh_golden_frame = 1;
+
+    if (ref_frame_flags & VP8_ALT_FLAG)
+        cpi->common.refresh_alt_ref_frame = 1;
+
+    return 0;
+}
+
+int vp8_get_reference(VP8_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(ptr);
+    VP8_COMMON *cm = &cpi->common;
+
+    if (ref_frame_flag == VP8_LAST_FLAG)
+        vp8_yv12_copy_frame_ptr(&cm->last_frame, sd);
+
+    else if (ref_frame_flag == VP8_GOLD_FLAG)
+        vp8_yv12_copy_frame_ptr(&cm->golden_frame, sd);
+
+    else if (ref_frame_flag == VP8_ALT_FLAG)
+        vp8_yv12_copy_frame_ptr(&cm->alt_ref_frame, sd);
+
+    else
+        return -1;
+
+    return 0;
+}
+int vp8_set_reference(VP8_PTR ptr, VP8_REFFRAME ref_frame_flag, YV12_BUFFER_CONFIG *sd)
+{
+    VP8_COMP *cpi = (VP8_COMP *)(ptr);
+    VP8_COMMON *cm = &cpi->common;
+
+    if (ref_frame_flag == VP8_LAST_FLAG)
+        vp8_yv12_copy_frame_ptr(sd, &cm->last_frame);
+
+    else if (ref_frame_flag == VP8_GOLD_FLAG)
+        vp8_yv12_copy_frame_ptr(sd, &cm->golden_frame);
+
+    else if (ref_frame_flag == VP8_ALT_FLAG)
+        vp8_yv12_copy_frame_ptr(sd, &cm->alt_ref_frame);
+
+    else
+        return -1;
+
+    return 0;
+}
+int vp8_update_entropy(VP8_PTR comp, int update)
+{
+    VP8_COMP *cpi = (VP8_COMP *) comp;
+    VP8_COMMON *cm = &cpi->common;
+    cm->refresh_entropy_probs = update;
+
+    return 0;
+}
+
+void vp8_write_yuv_frame(const char *name, YV12_BUFFER_CONFIG *s)
+{
+    FILE *yuv_file = fopen(name, "ab");
+    unsigned char *src = s->y_buffer;
+    int h = s->y_height;
+
+    do
+    {
+        fwrite(src, s->y_width, 1,  yuv_file);
+        src += s->y_stride;
+    }
+    while (--h);
+
+    src = s->u_buffer;
+    h = s->uv_height;
+
+    do
+    {
+        fwrite(src, s->uv_width, 1,  yuv_file);
+        src += s->uv_stride;
+    }
+    while (--h);
+
+    src = s->v_buffer;
+    h = s->uv_height;
+
+    do
+    {
+        fwrite(src, s->uv_width, 1, yuv_file);
+        src += s->uv_stride;
+    }
+    while (--h);
+
+    fclose(yuv_file);
+}
+
+static void scale_and_extend_source(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    // are we resizing the image
+    if (cm->horiz_scale != 0 || cm->vert_scale != 0)
+    {
+#if CONFIG_SPATIAL_RESAMPLING
+        int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs);
+        int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs);
+        int tmp_height;
+
+        if (cm->vert_scale == 3)
+            tmp_height = 9;
+        else
+            tmp_height = 11;
+
+        Scale2Ratio(cm->horiz_scale, &hr, &hs);
+        Scale2Ratio(cm->vert_scale, &vr, &vs);
+
+        vp8_scale_frame(sd, &cpi->scaled_source, cm->temp_scale_frame.y_buffer,
+                        tmp_height, hs, hr, vs, vr, 0);
+
+        cpi->Source = &cpi->scaled_source;
+#endif
+    }
+    // we may need to copy to a buffer so we can extend the image...
+    else if (cm->Width != cm->last_frame.y_width ||
+             cm->Height != cm->last_frame.y_height)
+    {
+        //vp8_yv12_copy_frame_ptr(sd, &cpi->scaled_source);
+#if HAVE_ARMV7
+        vp8_yv12_copy_src_frame_func_neon(sd, &cpi->scaled_source);
+#else
+        vp8_yv12_copy_frame_ptr(sd, &cpi->scaled_source);
+#endif
+
+        cpi->Source = &cpi->scaled_source;
+    }
+
+    vp8_extend_to_multiple_of16(cpi->Source, cm->Width, cm->Height);
+
+}
+static void resize_key_frame(VP8_COMP *cpi)
+{
+#if CONFIG_SPATIAL_RESAMPLING
+    VP8_COMMON *cm = &cpi->common;
+
+    // Do we need to apply resampling for one pass cbr.
+    // In one pass this is more limited than in two pass cbr
+    // The test and any change is only made one per key frame sequence
+    if (cpi->oxcf.allow_spatial_resampling && (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER))
+    {
+        int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs);
+        int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs);
+        int new_width, new_height;
+
+        // If we are below the resample DOWN watermark then scale down a notch.
+        if (cpi->buffer_level < (cpi->oxcf.resample_down_water_mark * cpi->oxcf.optimal_buffer_level / 100))
+        {
+            cm->horiz_scale = (cm->horiz_scale < ONETWO) ? cm->horiz_scale + 1 : ONETWO;
+            cm->vert_scale = (cm->vert_scale < ONETWO) ? cm->vert_scale + 1 : ONETWO;
+        }
+        // Should we now start scaling back up
+        else if (cpi->buffer_level > (cpi->oxcf.resample_up_water_mark * cpi->oxcf.optimal_buffer_level / 100))
+        {
+            cm->horiz_scale = (cm->horiz_scale > NORMAL) ? cm->horiz_scale - 1 : NORMAL;
+            cm->vert_scale = (cm->vert_scale > NORMAL) ? cm->vert_scale - 1 : NORMAL;
+        }
+
+        // Get the new hieght and width
+        Scale2Ratio(cm->horiz_scale, &hr, &hs);
+        Scale2Ratio(cm->vert_scale, &vr, &vs);
+        new_width = ((hs - 1) + (cpi->oxcf.Width * hr)) / hs;
+        new_height = ((vs - 1) + (cpi->oxcf.Height * vr)) / vs;
+
+        // If the image size has changed we need to reallocate the buffers
+        // and resample the source image
+        if ((cm->Width != new_width) || (cm->Height != new_height))
+        {
+            cm->Width = new_width;
+            cm->Height = new_height;
+            vp8_alloc_compressor_data(cpi);
+            scale_and_extend_source(cpi->un_scaled_source, cpi);
+        }
+    }
+
+#endif
+}
+// return of 0 means drop frame
+static int pick_frame_size(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    // First Frame is a special case
+    if (cm->current_video_frame == 0)
+    {
+#if !(CONFIG_REALTIME_ONLY)
+
+        if (cpi->pass == 2)
+            vp8_calc_auto_iframe_target_size(cpi);
+
+        // 1 Pass there is no information on which to base size so use bandwidth per second * fixed fraction
+        else
+#endif
+            cpi->this_frame_target = cpi->oxcf.target_bandwidth / 2;
+
+        // in error resilient mode the first frame is bigger since it likely contains
+        // all the static background
+        if (cpi->oxcf.error_resilient_mode == 1 || (cpi->compressor_speed == 2))
+        {
+            cpi->this_frame_target *= 3;      // 5;
+        }
+
+        // Key frame from VFW/auto-keyframe/first frame
+        cm->frame_type = KEY_FRAME;
+
+    }
+    // Auto key frames (Only two pass will enter here)
+    else if (cm->frame_type == KEY_FRAME)
+    {
+        vp8_calc_auto_iframe_target_size(cpi);
+    }
+    // Forced key frames (by interval or an external signal)
+    else if ((cm->frame_flags & FRAMEFLAGS_KEY) ||
+             (cpi->oxcf.auto_key && (cpi->frames_since_key % cpi->key_frame_frequency == 0)))
+    {
+        // Key frame from VFW/auto-keyframe/first frame
+        cm->frame_type = KEY_FRAME;
+
+        resize_key_frame(cpi);
+
+        // Compute target frame size
+        if (cpi->pass != 2)
+            vp8_calc_iframe_target_size(cpi);
+    }
+    else
+    {
+        // INTER frame: compute target frame size
+        cm->frame_type = INTER_FRAME;
+        vp8_calc_pframe_target_size(cpi);
+
+        // Check if we're dropping the frame:
+        if (cpi->drop_frame)
+        {
+            cpi->drop_frame = FALSE;
+            cpi->drop_count++;
+            return 0;
+        }
+    }
+
+    // Note target_size in bits * 256 per MB
+    cpi->target_bits_per_mb = (cpi->this_frame_target * 256) / cpi->common.MBs;
+
+    return 1;
+}
+static void set_quantizer(VP8_COMP *cpi, int Q)
+{
+    VP8_COMMON *cm = &cpi->common;
+    MACROBLOCKD *mbd = &cpi->mb.e_mbd;
+
+    cm->base_qindex = Q;
+
+    cm->y1dc_delta_q = 0;
+    cm->y2dc_delta_q = 0;
+    cm->y2ac_delta_q = 0;
+    cm->uvdc_delta_q = 0;
+    cm->uvac_delta_q = 0;
+
+    // Set Segment specific quatizers
+    mbd->segment_feature_data[MB_LVL_ALT_Q][0] = cpi->segment_feature_data[MB_LVL_ALT_Q][0];
+    mbd->segment_feature_data[MB_LVL_ALT_Q][1] = cpi->segment_feature_data[MB_LVL_ALT_Q][1];
+    mbd->segment_feature_data[MB_LVL_ALT_Q][2] = cpi->segment_feature_data[MB_LVL_ALT_Q][2];
+    mbd->segment_feature_data[MB_LVL_ALT_Q][3] = cpi->segment_feature_data[MB_LVL_ALT_Q][3];
+}
+
+static void update_alt_ref_frame_and_stats(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    // Update the golden frame buffer
+    vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cm->alt_ref_frame);
+
+    // Select an interval before next GF or altref
+    if (!cpi->auto_gold)
+        cpi->frames_till_gf_update_due = cpi->goldfreq;
+
+    if ((cpi->pass != 2) && cpi->frames_till_gf_update_due)
+    {
+        cpi->current_gf_interval = cpi->frames_till_gf_update_due;
+
+        // Set the bits per frame that we should try and recover in subsequent inter frames
+        // to account for the extra GF spend... note that his does not apply for GF updates
+        // that occur coincident with a key frame as the extra cost of key frames is dealt
+        // with elsewhere.
+
+        cpi->gf_overspend_bits += cpi->projected_frame_size;
+        cpi->non_gf_bitrate_adjustment = cpi->gf_overspend_bits / cpi->frames_till_gf_update_due;
+    }
+
+    // Update data structure that monitors level of reference to last GF
+    vpx_memset(cm->gf_active_flags, 1, (cm->mb_rows * cm->mb_cols));
+    cm->gf_active_count = cm->mb_rows * cm->mb_cols;
+    // this frame refreshes means next frames don't unless specified by user
+
+    cpi->common.frames_since_golden = 0;
+
+    // Clear the alternate reference update pending flag.
+    cpi->source_alt_ref_pending = FALSE;
+
+    // Set the alternate refernce frame active flag
+    cpi->source_alt_ref_active = TRUE;
+
+
+}
+static void update_golden_frame_and_stats(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    // Update the Golden frame reconstruction buffer if signalled and the GF usage counts.
+    if (cm->refresh_golden_frame)
+    {
+        // Update the golden frame buffer
+        vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cm->golden_frame);
+
+        // Select an interval before next GF
+        if (!cpi->auto_gold)
+            cpi->frames_till_gf_update_due = cpi->goldfreq;
+
+        if ((cpi->pass != 2) && (cpi->frames_till_gf_update_due > 0))
+        {
+            cpi->current_gf_interval = cpi->frames_till_gf_update_due;
+
+            // Set the bits per frame that we should try and recover in subsequent inter frames
+            // to account for the extra GF spend... note that his does not apply for GF updates
+            // that occur coincident with a key frame as the extra cost of key frames is dealt
+            // with elsewhere.
+            if ((cm->frame_type != KEY_FRAME) && !cpi->source_alt_ref_active)
+            {
+                // Calcluate GF bits to be recovered
+                // Projected size - av frame bits available for inter frames for clip as a whole
+                cpi->gf_overspend_bits += (cpi->projected_frame_size - cpi->inter_frame_target);
+            }
+
+            cpi->non_gf_bitrate_adjustment = cpi->gf_overspend_bits / cpi->frames_till_gf_update_due;
+
+        }
+
+        // Update data structure that monitors level of reference to last GF
+        vpx_memset(cm->gf_active_flags, 1, (cm->mb_rows * cm->mb_cols));
+        cm->gf_active_count = cm->mb_rows * cm->mb_cols;
+
+        // this frame refreshes means next frames don't unless specified by user
+        cm->refresh_golden_frame = 0;
+        cpi->common.frames_since_golden = 0;
+
+        //if ( cm->frame_type == KEY_FRAME )
+        //{
+        cpi->recent_ref_frame_usage[INTRA_FRAME] = 1;
+        cpi->recent_ref_frame_usage[LAST_FRAME] = 1;
+        cpi->recent_ref_frame_usage[GOLDEN_FRAME] = 1;
+        cpi->recent_ref_frame_usage[ALTREF_FRAME] = 1;
+        //}
+        //else
+        //{
+        //  // Carry a potrtion of count over to begining of next gf sequence
+        //  cpi->recent_ref_frame_usage[INTRA_FRAME] >>= 5;
+        //  cpi->recent_ref_frame_usage[LAST_FRAME] >>= 5;
+        //  cpi->recent_ref_frame_usage[GOLDEN_FRAME] >>= 5;
+        //  cpi->recent_ref_frame_usage[ALTREF_FRAME] >>= 5;
+        //}
+
+        // ******** Fixed Q test code only ************
+        // If we are going to use the ALT reference for the next group of frames set a flag to say so.
+        if (cpi->oxcf.fixed_q >= 0 &&
+            cpi->oxcf.play_alternate && !cpi->common.refresh_alt_ref_frame)
+        {
+            cpi->source_alt_ref_pending = TRUE;
+            cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+        }
+
+        if (!cpi->source_alt_ref_pending)
+            cpi->source_alt_ref_active = FALSE;
+
+        // Decrement count down till next gf
+        if (cpi->frames_till_gf_update_due > 0)
+            cpi->frames_till_gf_update_due--;
+
+    }
+    else if (!cpi->common.refresh_alt_ref_frame)
+    {
+        // Decrement count down till next gf
+        if (cpi->frames_till_gf_update_due > 0)
+            cpi->frames_till_gf_update_due--;
+
+        if (cpi->common.frames_till_alt_ref_frame)
+            cpi->common.frames_till_alt_ref_frame --;
+
+        cpi->common.frames_since_golden ++;
+
+        if (cpi->common.frames_since_golden > 1)
+        {
+            cpi->recent_ref_frame_usage[INTRA_FRAME] += cpi->count_mb_ref_frame_usage[INTRA_FRAME];
+            cpi->recent_ref_frame_usage[LAST_FRAME] += cpi->count_mb_ref_frame_usage[LAST_FRAME];
+            cpi->recent_ref_frame_usage[GOLDEN_FRAME] += cpi->count_mb_ref_frame_usage[GOLDEN_FRAME];
+            cpi->recent_ref_frame_usage[ALTREF_FRAME] += cpi->count_mb_ref_frame_usage[ALTREF_FRAME];
+        }
+    }
+}
+
+// This function updates the reference frame probability estimates that
+// will be used during mode selection
+static void update_rd_ref_frame_probs(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+#if 0
+    const int *const rfct = cpi->recent_ref_frame_usage;
+    const int rf_intra = rfct[INTRA_FRAME];
+    const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
+
+    if (cm->frame_type == KEY_FRAME)
+    {
+        cpi->prob_intra_coded = 255;
+        cpi->prob_last_coded  = 128;
+        cpi->prob_gf_coded  = 128;
+    }
+    else if (!(rf_intra + rf_inter))
+    {
+        // This is a trap in case this function is called with cpi->recent_ref_frame_usage[] blank.
+        cpi->prob_intra_coded = 63;
+        cpi->prob_last_coded  = 128;
+        cpi->prob_gf_coded    = 128;
+    }
+    else
+    {
+        cpi->prob_intra_coded = (rf_intra * 255) / (rf_intra + rf_inter);
+
+        if (cpi->prob_intra_coded < 1)
+            cpi->prob_intra_coded = 1;
+
+        if ((cm->frames_since_golden > 0) || cpi->source_alt_ref_active)
+        {
+            cpi->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
+
+            if (cpi->prob_last_coded < 1)
+                cpi->prob_last_coded = 1;
+
+            cpi->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
+                                 ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
+
+            if (cpi->prob_gf_coded < 1)
+                cpi->prob_gf_coded = 1;
+        }
+    }
+
+#else
+    const int *const rfct = cpi->count_mb_ref_frame_usage;
+    const int rf_intra = rfct[INTRA_FRAME];
+    const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
+
+    if (cm->frame_type == KEY_FRAME)
+    {
+        cpi->prob_intra_coded = 255;
+        cpi->prob_last_coded  = 128;
+        cpi->prob_gf_coded  = 128;
+    }
+    else if (!(rf_intra + rf_inter))
+    {
+        // This is a trap in case this function is called with cpi->recent_ref_frame_usage[] blank.
+        cpi->prob_intra_coded = 63;
+        cpi->prob_last_coded  = 128;
+        cpi->prob_gf_coded    = 128;
+    }
+    else
+    {
+        cpi->prob_intra_coded = (rf_intra * 255) / (rf_intra + rf_inter);
+
+        if (cpi->prob_intra_coded < 1)
+            cpi->prob_intra_coded = 1;
+
+        cpi->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
+
+        if (cpi->prob_last_coded < 1)
+            cpi->prob_last_coded = 1;
+
+        cpi->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
+                             ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
+
+        if (cpi->prob_gf_coded < 1)
+            cpi->prob_gf_coded = 1;
+    }
+
+    // update reference frame costs since we can do better than what we got last frame.
+
+    if (cpi->common.refresh_alt_ref_frame)
+    {
+        cpi->prob_intra_coded += 40;
+        cpi->prob_last_coded = 200;
+        cpi->prob_gf_coded = 1;
+    }
+    else if (cpi->common.frames_since_golden == 0)
+    {
+        cpi->prob_last_coded = 214;
+        cpi->prob_gf_coded = 1;
+    }
+    else if (cpi->common.frames_since_golden == 1)
+    {
+        cpi->prob_last_coded = 192;
+        cpi->prob_gf_coded = 220;
+    }
+    else if (cpi->source_alt_ref_active)
+    {
+        //int dist = cpi->common.frames_till_alt_ref_frame + cpi->common.frames_since_golden;
+        cpi->prob_gf_coded -= 20;
+
+        if (cpi->prob_gf_coded < 10)
+            cpi->prob_gf_coded = 10;
+    }
+
+#endif
+}
+
+
+// 1 = key, 0 = inter
+static int decide_key_frame(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    int code_key_frame = FALSE;
+
+    cpi->kf_boost = 0;
+
+    if (cpi->Speed > 11)
+        return FALSE;
+
+    // Clear down mmx registers
+    vp8_clear_system_state();  //__asm emms;
+
+    if ((cpi->compressor_speed == 2) && (cpi->Speed >= 5) && (cpi->sf.RD == 0))
+    {
+        double change = 1.0 * abs((int)(cpi->intra_error - cpi->last_intra_error)) / (1 + cpi->last_intra_error);
+        double change2 = 1.0 * abs((int)(cpi->prediction_error - cpi->last_prediction_error)) / (1 + cpi->last_prediction_error);
+        double minerror = cm->MBs * 256;
+
+#if 0
+
+        if (10 * cpi->intra_error / (1 + cpi->prediction_error) < 15
+            && cpi->prediction_error > minerror
+            && (change > .25 || change2 > .25))
+        {
+            FILE *f = fopen("intra_inter.stt", "a");
+
+            if (cpi->prediction_error <= 0)
+                cpi->prediction_error = 1;
+
+            fprintf(f, "%d %d %d %d %14.4f\n",
+                    cm->current_video_frame,
+                    (int) cpi->prediction_error,
+                    (int) cpi->intra_error,
+                    (int)((10 * cpi->intra_error) / cpi->prediction_error),
+                    change);
+
+            fclose(f);
+        }
+
+#endif
+
+        cpi->last_intra_error = cpi->intra_error;
+        cpi->last_prediction_error = cpi->prediction_error;
+
+        if (10 * cpi->intra_error / (1 + cpi->prediction_error) < 15
+            && cpi->prediction_error > minerror
+            && (change > .25 || change2 > .25))
+        {
+            /*(change > 1.4 || change < .75)&& cpi->this_frame_percent_intra > cpi->last_frame_percent_intra + 3*/
+            return TRUE;
+        }
+
+        return FALSE;
+
+    }
+
+    // If the following are true we might as well code a key frame
+    if (((cpi->this_frame_percent_intra == 100) &&
+         (cpi->this_frame_percent_intra > (cpi->last_frame_percent_intra + 2))) ||
+        ((cpi->this_frame_percent_intra > 95) &&
+         (cpi->this_frame_percent_intra >= (cpi->last_frame_percent_intra + 5))))
+    {
+        code_key_frame = TRUE;
+    }
+    // in addition if the following are true and this is not a golden frame then code a key frame
+    // Note that on golden frames there often seems to be a pop in intra useage anyway hence this
+    // restriction is designed to prevent spurious key frames. The Intra pop needs to be investigated.
+    else if (((cpi->this_frame_percent_intra > 60) &&
+              (cpi->this_frame_percent_intra > (cpi->last_frame_percent_intra * 2))) ||
+             ((cpi->this_frame_percent_intra > 75) &&
+              (cpi->this_frame_percent_intra > (cpi->last_frame_percent_intra * 3 / 2))) ||
+             ((cpi->this_frame_percent_intra > 90) &&
+              (cpi->this_frame_percent_intra > (cpi->last_frame_percent_intra + 10))))
+    {
+        if (!cm->refresh_golden_frame)
+            code_key_frame = TRUE;
+    }
+
+    return code_key_frame;
+
+}
+
+#if !(CONFIG_REALTIME_ONLY)
+static void Pass1Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags)
+{
+    (void) size;
+    (void) dest;
+    (void) frame_flags;
+    set_quantizer(cpi, 26);
+
+    scale_and_extend_source(cpi->un_scaled_source, cpi);
+    vp8_first_pass(cpi);
+}
+#endif
+
+#if 0
+void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame)
+{
+
+    // write the frame
+    FILE *yframe;
+    int i;
+    char filename[255];
+
+    sprintf(filename, "cx\\y%04d.raw", this_frame);
+    yframe = fopen(filename, "wb");
+
+    for (i = 0; i < frame->y_height; i++)
+        fwrite(frame->y_buffer + i * frame->y_stride, frame->y_width, 1, yframe);
+
+    fclose(yframe);
+    sprintf(filename, "cx\\u%04d.raw", this_frame);
+    yframe = fopen(filename, "wb");
+
+    for (i = 0; i < frame->uv_height; i++)
+        fwrite(frame->u_buffer + i * frame->uv_stride, frame->uv_width, 1, yframe);
+
+    fclose(yframe);
+    sprintf(filename, "cx\\v%04d.raw", this_frame);
+    yframe = fopen(filename, "wb");
+
+    for (i = 0; i < frame->uv_height; i++)
+        fwrite(frame->v_buffer + i * frame->uv_stride, frame->uv_width, 1, yframe);
+
+    fclose(yframe);
+}
+#endif
+// return of 0 means drop frame
+
+#if VP8_TEMPORAL_ALT_REF
+static void vp8cx_temp_blur1_c
+(
+    unsigned char **frames,
+    int frame_count,
+    unsigned char *src,
+    unsigned char *dst,
+    int width,
+    int stride,
+    int height,
+    int strength,
+    int *fixed_divide,
+    unsigned char *motion_map_ptr,
+    unsigned char block_size
+)
+{
+    int byte = 0;           // Buffer offset for the current pixel value being filtered
+    int frame = 0;
+    int modifier = 0;
+    int i, j, k;
+    int block_ofset;
+    int Cols, Rows;
+    unsigned char Shift = (block_size == 16) ? 4 : 3;
+
+    Cols = width / block_size;
+    Rows = height / block_size;
+
+    for (i = 0; i < height; i++)
+    {
+        block_ofset = (i >> Shift) * Cols;
+
+        for (j = 0; j < Cols; j ++)
+        {
+            if (motion_map_ptr[block_ofset] > 2)
+            {
+                vpx_memcpy(&dst[byte], &src[byte], block_size);
+                byte += block_size;
+            }
+            else
+            {
+                for (k = 0; k < block_size; k++)
+                {
+                    int accumulator = 0;
+                    int count = 0;
+                    int src_byte = src[byte];
+
+                    for (frame = 0; frame < frame_count; frame++)
+                    {
+                        // get current frame pixel value
+                        int pixel_value = frames[frame][byte];       // int pixel_value = *frameptr;
+
+                        modifier   = src_byte;                       // modifier   = s[byte];
+                        modifier  -= pixel_value;
+                        modifier  *= modifier;
+                        modifier >>= strength;
+                        modifier  *= 3;
+
+                        if (modifier > 16)
+                            modifier = 16;
+
+                        modifier = 16 - modifier;
+
+                        accumulator += modifier * pixel_value;
+
+                        count += modifier;
+                    }
+
+                    accumulator += (count >> 1);
+                    accumulator *= fixed_divide[count];          // accumulator *= ppi->fixed_divide[count];
+                    accumulator >>= 16;
+
+                    dst[byte] = accumulator;        // d[byte] = accumulator;
+
+                    // move to next pixel
+                    byte++;
+                }
+            }
+
+            block_ofset++;
+        }
+
+        // Step byte on over the UMV border to the start of the next line
+        byte += stride - width;
+    }
+}
+
+static void vp8cx_temp_filter_c
+(
+    VP8_COMP *cpi
+)
+{
+    YV12_BUFFER_CONFIG *temp_source_buffer;
+    int *fixed_divide = cpi->fixed_divide;
+
+    int frame = 0;
+    int max_frames = 11;
+
+    int num_frames_backward = 0;
+    int num_frames_forward = 0;
+    int frames_to_blur_backward = 0;
+    int frames_to_blur_forward = 0;
+    int frames_to_blur = 0;
+    int start_frame = 0;
+
+    int strength = cpi->oxcf.arnr_strength;
+
+    int blur_type = cpi->oxcf.arnr_type;
+
+    int new_max_frames = cpi->oxcf.arnr_max_frames;
+
+    if (new_max_frames > 0)
+        max_frames = new_max_frames;
+
+    num_frames_backward = cpi->last_alt_ref_sei - cpi->source_encode_index;
+
+    if (num_frames_backward < 0)
+        num_frames_backward += cpi->oxcf.lag_in_frames;
+
+    num_frames_forward = cpi->oxcf.lag_in_frames - (num_frames_backward + 1);
+
+    switch (blur_type)
+    {
+    case 1:
+        /////////////////////////////////////////
+        // Backward Blur
+
+        frames_to_blur_backward = num_frames_backward;
+
+        if (frames_to_blur_backward >= max_frames)
+            frames_to_blur_backward = max_frames - 1;
+
+        frames_to_blur = frames_to_blur_backward + 1;
+        break;
+
+    case 2:
+        /////////////////////////////////////////
+        // Forward Blur
+
+        frames_to_blur_forward = num_frames_forward;
+
+        if (frames_to_blur_forward >= max_frames)
+            frames_to_blur_forward = max_frames - 1;
+
+        frames_to_blur = frames_to_blur_forward + 1;
+        break;
+
+    case 3:
+        /////////////////////////////////////////
+        // Center Blur
+        frames_to_blur_forward = num_frames_forward;
+        frames_to_blur_backward = num_frames_backward;
+
+        if (frames_to_blur_forward > frames_to_blur_backward)
+            frames_to_blur_forward = frames_to_blur_backward;
+
+        if (frames_to_blur_backward > frames_to_blur_forward)
+            frames_to_blur_backward = frames_to_blur_forward;
+
+        if (frames_to_blur_forward > (max_frames / 2))
+            frames_to_blur_forward = (max_frames / 2);
+
+        if (frames_to_blur_backward > (max_frames / 2))
+            frames_to_blur_backward = (max_frames / 2);
+
+        frames_to_blur = frames_to_blur_backward + frames_to_blur_forward + 1;
+        break;
+
+    default:
+        /////////////////////////////////////////
+        // At most 4 frames forward Blur
+        frames_to_blur_forward = 4;
+        frames_to_blur_backward = num_frames_backward;
+
+        if (max_frames > 5)
+        {
+            if ((frames_to_blur_backward + frames_to_blur_forward) >= max_frames)
+            {
+                frames_to_blur_backward = max_frames - frames_to_blur_forward - 1;
+            }
+        }
+        else
+        {
+            frames_to_blur_forward = max_frames - 1;
+            frames_to_blur_backward = 0;
+        }
+
+        frames_to_blur = frames_to_blur_backward + frames_to_blur_forward + 1;
+        break;
+    }
+
+    start_frame = (cpi->last_alt_ref_sei + frames_to_blur_forward) % cpi->oxcf.lag_in_frames;
+
+#ifdef DEBUGFWG
+    // DEBUG FWG
+    printf("max:%d FBCK:%d FFWD:%d ftb:%d ftbbck:%d ftbfwd:%d sei:%d lasei:%d start:%d"
+           , max_frames
+           , num_frames_backward
+           , num_frames_forward
+           , frames_to_blur
+           , frames_to_blur_backward
+           , frames_to_blur_forward
+           , cpi->source_encode_index
+           , cpi->last_alt_ref_sei
+           , start_frame);
+#endif
+
+    for (frame = 0; frame < frames_to_blur; frame++)
+    {
+        int which_buffer =  start_frame - frame;
+
+        if (which_buffer < 0)
+            which_buffer += cpi->oxcf.lag_in_frames;
+
+        cpi->frames[frame] = cpi->src_buffer[which_buffer].source_buffer.y_buffer;
+    }
+
+    temp_source_buffer = &cpi->src_buffer[cpi->last_alt_ref_sei].source_buffer;
+
+    // Blur Y
+    vp8cx_temp_blur1_c(
+        cpi->frames,
+        frames_to_blur,
+        temp_source_buffer->y_buffer,  // cpi->Source->y_buffer,
+        cpi->alt_ref_buffer.source_buffer.y_buffer,  // cpi->Source->y_buffer,
+        temp_source_buffer->y_width,
+        temp_source_buffer->y_stride,
+        temp_source_buffer->y_height,
+        //temp_source_buffer->y_height * temp_source_buffer->y_stride,
+        strength,
+        fixed_divide,
+        cpi->fp_motion_map, 16);
+
+    for (frame = 0; frame < frames_to_blur; frame++)
+    {
+        int which_buffer =  cpi->last_alt_ref_sei - frame;
+
+        if (which_buffer < 0)
+            which_buffer += cpi->oxcf.lag_in_frames;
+
+        cpi->frames[frame] = cpi->src_buffer[which_buffer].source_buffer.u_buffer;
+    }
+
+    // Blur U
+    vp8cx_temp_blur1_c(
+        cpi->frames,
+        frames_to_blur,
+        temp_source_buffer->u_buffer,
+        cpi->alt_ref_buffer.source_buffer.u_buffer,  // cpi->Source->u_buffer,
+        temp_source_buffer->uv_width,
+        temp_source_buffer->uv_stride,
+        temp_source_buffer->uv_height,
+        //temp_source_buffer->uv_height * temp_source_buffer->uv_stride,
+        strength,
+        fixed_divide,
+        cpi->fp_motion_map, 8);
+
+    for (frame = 0; frame < frames_to_blur; frame++)
+    {
+        int which_buffer =  cpi->last_alt_ref_sei - frame;
+
+        if (which_buffer < 0)
+            which_buffer += cpi->oxcf.lag_in_frames;
+
+        cpi->frames[frame] = cpi->src_buffer[which_buffer].source_buffer.v_buffer;
+    }
+
+    // Blur V
+    vp8cx_temp_blur1_c(
+        cpi->frames,
+        frames_to_blur,
+        temp_source_buffer->v_buffer,
+        cpi->alt_ref_buffer.source_buffer.v_buffer,  // cpi->Source->v_buffer,
+        temp_source_buffer->uv_width,
+        temp_source_buffer->uv_stride,
+        //temp_source_buffer->uv_height * temp_source_buffer->uv_stride,
+        temp_source_buffer->uv_height,
+        strength,
+        fixed_divide,
+        cpi->fp_motion_map, 8);
+}
+#endif
+
+
+static void encode_frame_to_data_rate(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags)
+{
+    int Q;
+    int frame_over_shoot_limit;
+    int frame_under_shoot_limit;
+
+    int Loop = FALSE;
+    int loop_count;
+    int this_q;
+    int last_zbin_oq;
+
+    int q_low;
+    int q_high;
+    int zbin_oq_high;
+    int zbin_oq_low = 0;
+    int top_index;
+    int bottom_index;
+    VP8_COMMON *cm = &cpi->common;
+    int active_worst_qchanged = FALSE;
+
+    int overshoot_seen = FALSE;
+    int undershoot_seen = FALSE;
+    int drop_mark = cpi->oxcf.drop_frames_water_mark * cpi->oxcf.optimal_buffer_level / 100;
+    int drop_mark75 = drop_mark * 2 / 3;
+    int drop_mark50 = drop_mark / 4;
+    int drop_mark25 = drop_mark / 8;
+
+    // Clear down mmx registers to allow floating point in what follows
+    vp8_clear_system_state();
+
+    // Test code for segmentation of gf/arf (0,0)
+    //segmentation_test_function((VP8_PTR) cpi);
+
+    // For an alt ref frame in 2 pass we skip the call to the second pass function that sets the target bandwidth
+#if !(CONFIG_REALTIME_ONLY)
+
+    if (cpi->pass == 2)
+    {
+        if (cpi->common.refresh_alt_ref_frame)
+        {
+            cpi->per_frame_bandwidth = cpi->gf_bits;                           // Per frame bit target for the alt ref frame
+            cpi->target_bandwidth = cpi->gf_bits * cpi->output_frame_rate;      // per second target bitrate
+        }
+    }
+    else
+#endif
+        cpi->per_frame_bandwidth  = (int)(cpi->target_bandwidth / cpi->output_frame_rate);
+
+    // Default turn off buffer to buffer copying
+    cm->copy_buffer_to_gf = 0;
+    cm->copy_buffer_to_arf = 0;
+
+    // Clear zbin over-quant value and mode boost values.
+    cpi->zbin_over_quant = 0;
+    cpi->zbin_mode_boost = 0;
+
+    // Enable mode based tweaking of the zbin
+    cpi->zbin_mode_boost_enabled = TRUE;
+
+    // Current default encoder behaviour for the altref sign bias
+    if (cpi->source_alt_ref_active)
+        cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = 1;
+    else
+        cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = 0;
+
+    // Check to see if a key frame is signalled
+    // For two pass with auto key frame enabled cm->frame_type may already be set, but not for one pass.
+    if ((cm->current_video_frame == 0) ||
+        (cm->frame_flags & FRAMEFLAGS_KEY) ||
+        (cpi->oxcf.auto_key && (cpi->frames_since_key % cpi->key_frame_frequency == 0)))
+    {
+        // Key frame from VFW/auto-keyframe/first frame
+        cm->frame_type = KEY_FRAME;
+    }
+
+    // Set default state for segment and mode based loop filter update flags
+    cpi->mb.e_mbd.update_mb_segmentation_map = 0;
+    cpi->mb.e_mbd.update_mb_segmentation_data = 0;
+    cpi->mb.e_mbd.mode_ref_lf_delta_update = 0;
+
+    // Set various flags etc to special state if it is a key frame
+    if (cm->frame_type == KEY_FRAME)
+    {
+        int i;
+
+        // If segmentation is enabled force a map update for key frames
+        if (cpi->mb.e_mbd.segmentation_enabled)
+        {
+            cpi->mb.e_mbd.update_mb_segmentation_map = 1;
+            cpi->mb.e_mbd.update_mb_segmentation_data = 1;
+        }
+
+        // If mode or reference frame based loop filter deltas are enabled then force an update for key frames.
+        if (cpi->mb.e_mbd.mode_ref_lf_delta_enabled)
+        {
+            cpi->mb.e_mbd.mode_ref_lf_delta_update = 1;
+        }
+
+        // The alternate reference frame cannot be active for a key frame
+        cpi->source_alt_ref_active = FALSE;
+
+        // Reset the RD threshold multipliers to default of * 1 (128)
+        for (i = 0; i < MAX_MODES; i++)
+        {
+            cpi->rd_thresh_mult[i] = 128;
+        }
+    }
+
+    // Test code for segmentation
+    //if ( (cm->frame_type == KEY_FRAME) || ((cm->current_video_frame % 2) == 0))
+    //if ( (cm->current_video_frame % 2) == 0 )
+    //  enable_segmentation((VP8_PTR)cpi);
+    //else
+    //  disable_segmentation((VP8_PTR)cpi);
+
+#if 0
+    // Experimental code for lagged compress and one pass
+    // Initialise one_pass GF frames stats
+    // Update stats used for GF selection
+    //if ( cpi->pass == 0 )
+    {
+        cpi->one_pass_frame_index = cm->current_video_frame % MAX_LAG_BUFFERS;
+
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frames_so_far = 0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_intra_error = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_coded_error = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_pcnt_inter = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_pcnt_motion = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_mvr = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_mvr_abs = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_mvc = 0.0;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index ].frame_mvc_abs = 0.0;
+    }
+#endif
+
+    update_rd_ref_frame_probs(cpi);
+
+    if (cpi->drop_frames_allowed)
+    {
+        // The reset to decimation 0 is only done here for one pass.
+        // Once it is set two pass leaves decimation on till the next kf.
+        if ((cpi->buffer_level > drop_mark) && (cpi->decimation_factor > 0))
+            cpi->decimation_factor --;
+
+        if (cpi->buffer_level > drop_mark75 && cpi->decimation_factor > 0)
+            cpi->decimation_factor = 1;
+
+        else if (cpi->buffer_level < drop_mark25 && (cpi->decimation_factor == 2 || cpi->decimation_factor == 3))
+        {
+            cpi->decimation_factor = 3;
+        }
+        else if (cpi->buffer_level < drop_mark50 && (cpi->decimation_factor == 1 || cpi->decimation_factor == 2))
+        {
+            cpi->decimation_factor = 2;
+        }
+        else if (cpi->buffer_level < drop_mark75 && (cpi->decimation_factor == 0 || cpi->decimation_factor == 1))
+        {
+            cpi->decimation_factor = 1;
+        }
+
+        //vpx_log("Encoder: Decimation Factor: %d \n",cpi->decimation_factor);
+    }
+
+    // The following decimates the frame rate according to a regular pattern (i.e. to 1/2 or 2/3 frame rate)
+    // This can be used to help prevent buffer under-run in CBR mode. Alternatively it might be desirable in
+    // some situations to drop frame rate but throw more bits at each frame.
+    //
+    // Note that dropping a key frame can be problematic if spatial resampling is also active
+    if (cpi->decimation_factor > 0)
+    {
+        switch (cpi->decimation_factor)
+        {
+        case 1:
+            cpi->per_frame_bandwidth  = cpi->per_frame_bandwidth * 3 / 2;
+            break;
+        case 2:
+            cpi->per_frame_bandwidth  = cpi->per_frame_bandwidth * 5 / 4;
+            break;
+        case 3:
+            cpi->per_frame_bandwidth  = cpi->per_frame_bandwidth * 5 / 4;
+            break;
+        }
+
+        // Note that we should not throw out a key frame (especially when spatial resampling is enabled).
+        if ((cm->frame_type == KEY_FRAME)) // && cpi->oxcf.allow_spatial_resampling )
+        {
+            cpi->decimation_count = cpi->decimation_factor;
+        }
+        else if (cpi->decimation_count > 0)
+        {
+            cpi->decimation_count --;
+            cpi->bits_off_target += cpi->av_per_frame_bandwidth;
+            cm->current_video_frame++;
+            cpi->frames_since_key++;
+
+#if CONFIG_PSNR
+            cpi->count ++;
+#endif
+
+            cpi->buffer_level = cpi->bits_off_target;
+
+            return;
+        }
+        else
+            cpi->decimation_count = cpi->decimation_factor;
+    }
+
+    // Decide how big to make the frame
+    if (!pick_frame_size(cpi))
+    {
+        cm->current_video_frame++;
+        cpi->frames_since_key++;
+        return;
+    }
+
+    // Reduce active_worst_allowed_q for CBR if our buffer is getting too full.
+    // This has a knock on effect on active best quality as well.
+    // For CBR if the buffer reaches its maximum level then we can no longer
+    // save up bits for later frames so we might as well use them up
+    // on the current frame.
+    if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
+        (cpi->buffer_level >= cpi->oxcf.optimal_buffer_level) && cpi->buffered_mode)
+    {
+        int Adjustment = cpi->active_worst_quality / 4;       // Max adjustment is 1/4
+
+        if (Adjustment)
+        {
+            int buff_lvl_step;
+            int tmp_lvl = cpi->buffer_level;
+
+            if (cpi->buffer_level < cpi->oxcf.maximum_buffer_size)
+            {
+                buff_lvl_step = (cpi->oxcf.maximum_buffer_size - cpi->oxcf.optimal_buffer_level) / Adjustment;
+
+                if (buff_lvl_step)
+                {
+                    Adjustment = (cpi->buffer_level - cpi->oxcf.optimal_buffer_level) / buff_lvl_step;
+                    cpi->active_worst_quality -= Adjustment;
+                }
+            }
+            else
+            {
+                cpi->active_worst_quality -= Adjustment;
+            }
+        }
+    }
+
+    // Set an active best quality and if necessary active worst quality
+    if (cpi->pass == 2 || (cm->current_video_frame > 150))
+    {
+        //if ( (cm->frame_type == KEY_FRAME) || cm->refresh_golden_frame  )
+        int Q;
+        int i;
+        int bpm_target;
+
+        Q = cpi->active_worst_quality;
+
+        if ((cm->frame_type == KEY_FRAME) || cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame)
+        {
+            vp8_clear_system_state();
+
+            if (cm->frame_type != KEY_FRAME)
+            {
+                // Where a gf overlays an existing arf then allow active max Q to drift to highest allowed value.
+                //if ( cpi->common.refresh_golden_frame && cpi->source_alt_ref_active )
+                //cpi->active_worst_quality = cpi->worst_quality;
+
+                if (cpi->avg_frame_qindex < cpi->active_worst_quality)
+                    Q = cpi->avg_frame_qindex;
+
+                if (cpi->section_is_low_motion)
+                    bpm_target = (vp8_bits_per_mb[cm->frame_type][Q] * ((Q * 3 / 2) + 128)) / 64;
+                else if (cpi->section_is_fast_motion)
+                    bpm_target = (vp8_bits_per_mb[cm->frame_type][Q] * (Q + 128)) / 64;
+                else
+                    bpm_target = (vp8_bits_per_mb[cm->frame_type][Q] * ((Q * 5 / 4) + 128)) / 64;
+            }
+            // KEY FRAMES
+            else
+            {
+                if (cpi->section_is_low_motion)
+                    bpm_target = (vp8_bits_per_mb[cm->frame_type][Q] * (Q + 240)) / 64; // Approx 2.5 to 4.5 where Q has the range 0-127
+                else
+                    bpm_target = (vp8_bits_per_mb[cm->frame_type][Q] * (Q + 160)) / 64;
+            }
+
+            for (i = Q; i > 0; i--)
+            {
+                if (bpm_target <= vp8_bits_per_mb[cm->frame_type][i])
+                    break;
+            }
+
+            cpi->active_best_quality = i;
+
+            // this entire section could be replaced by a look up table
+#if 0
+            {
+                int Q, best_q[128];
+
+                for (Q = 0; Q < 128; Q++)
+                {
+                    bpm_target = (vp8_bits_per_mb[cm->frame_type][Q] * (Q + 160)) / 64; // Approx 2.5 to 4.5 where Q has the range 0-127
+
+                    for (i = Q; i > 0; i--)
+                    {
+                        if (bpm_target <= vp8_bits_per_mb[cm->frame_type][i])
+                            break;
+                    }
+
+                    best_q[Q] = i;
+                }
+
+                Q += 0;
+            }
+#endif
+
+        }
+        else
+        {
+            vp8_clear_system_state();
+
+            //bpm_target = (vp8_bits_per_mb[cm->frame_type][Q]*(Q+128))/64; // Approx 2 to 4 where Q has the range 0-127
+            bpm_target = (vp8_bits_per_mb[cm->frame_type][Q] * (Q + 192)) / 128; // Approx * 1.5 to 2.5 where Q has range 0-127
+
+            for (i = Q; i > 0; i--)
+            {
+                if (bpm_target <= vp8_bits_per_mb[cm->frame_type][i])
+                    break;
+            }
+
+            cpi->active_best_quality = i;
+        }
+
+        // If CBR and the buffer is as full then it is reasonable to allow higher quality on the frames
+        // to prevent bits just going to waste.
+        if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+        {
+            // Note that the use of >= here elliminates the risk of a devide by 0 error in the else if clause
+            if (cpi->buffer_level >= cpi->oxcf.maximum_buffer_size)
+                cpi->active_best_quality = cpi->best_quality;
+
+            else if (cpi->buffer_level > cpi->oxcf.optimal_buffer_level)
+            {
+                int Fraction = ((cpi->buffer_level - cpi->oxcf.optimal_buffer_level) * 128) / (cpi->oxcf.maximum_buffer_size - cpi->oxcf.optimal_buffer_level);
+                int min_qadjustment = ((cpi->active_best_quality - cpi->best_quality) * Fraction) / 128;
+
+                cpi->active_best_quality -= min_qadjustment;
+            }
+
+        }
+    }
+
+    // Clip the active best and worst quality values to limits
+    if (cpi->active_worst_quality > cpi->worst_quality)
+        cpi->active_worst_quality = cpi->worst_quality;
+
+    if (cpi->active_best_quality < cpi->best_quality)
+        cpi->active_best_quality = cpi->best_quality;
+    else if (cpi->active_best_quality > cpi->active_worst_quality)
+        cpi->active_best_quality = cpi->active_worst_quality;
+
+    // Determine initial Q to try
+    Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+    last_zbin_oq = cpi->zbin_over_quant;
+
+    // Set highest allowed value for Zbin over quant
+    if (cm->frame_type == KEY_FRAME)
+        zbin_oq_high = 0; //ZBIN_OQ_MAX/16
+    else if (cm->refresh_alt_ref_frame || (cm->refresh_golden_frame && !cpi->source_alt_ref_active))
+        zbin_oq_high = 16;
+    else
+        zbin_oq_high = ZBIN_OQ_MAX;
+
+    // Setup background Q adjustment for error resilliant mode
+    if (cpi->cyclic_refresh_mode_enabled)
+        cyclic_background_refresh(cpi, Q, 0);
+
+    vp8_compute_frame_size_bounds(cpi, &frame_under_shoot_limit, &frame_over_shoot_limit);
+
+    // Limit Q range for the adaptive loop (Values not clipped to range 20-60 as in VP8).
+    bottom_index = cpi->active_best_quality;
+    top_index    = cpi->active_worst_quality;
+
+    vp8_save_coding_context(cpi);
+
+    loop_count = 0;
+
+    q_low  = cpi->best_quality;
+    q_high = cpi->worst_quality;
+
+
+    scale_and_extend_source(cpi->un_scaled_source, cpi);
+#if !(CONFIG_REALTIME_ONLY) && CONFIG_POSTPROC
+
+    if (cpi->oxcf.noise_sensitivity > 0)
+    {
+        unsigned char *src;
+        int l = 0;
+
+        switch (cpi->oxcf.noise_sensitivity)
+        {
+        case 1:
+            l = 20;
+            break;
+        case 2:
+            l = 40;
+            break;
+        case 3:
+            l = 60;
+            break;
+        case 4:
+            l = 80;
+            break;
+        case 5:
+            l = 100;
+            break;
+        case 6:
+            l = 150;
+            break;
+        }
+
+
+        if (cm->frame_type == KEY_FRAME)
+        {
+            vp8_de_noise(cpi->Source, cpi->Source, l , 1,  0, RTCD(postproc));
+            cpi->ppi.frame = 0;
+        }
+        else
+        {
+            vp8_de_noise(cpi->Source, cpi->Source, l , 1,  0, RTCD(postproc));
+
+            src = cpi->Source->y_buffer;
+
+            if (cpi->Source->y_stride < 0)
+            {
+                src += cpi->Source->y_stride * (cpi->Source->y_height - 1);
+            }
+
+            //temp_filter(&cpi->ppi,src,src,
+            //  cm->last_frame.y_width * cm->last_frame.y_height,
+            //  cpi->oxcf.noise_sensitivity);
+        }
+    }
+
+#endif
+
+#ifdef OUTPUT_YUV_SRC
+    vp8_write_yuv_frame(cpi->Source);
+#endif
+
+    do
+    {
+        vp8_clear_system_state();  //__asm emms;
+
+        /*
+        if(cpi->is_src_frame_alt_ref)
+            Q = 127;
+            */
+
+        set_quantizer(cpi, Q);
+        this_q = Q;
+
+        // setup skip prob for costing in mode/mv decision
+        if (cpi->common.mb_no_coeff_skip)
+        {
+            cpi->prob_skip_false = cpi->base_skip_false_prob[Q];
+
+            if (cm->frame_type != KEY_FRAME)
+            {
+                if (cpi->common.refresh_alt_ref_frame)
+                {
+                    if (cpi->last_skip_false_probs[2] != 0)
+                        cpi->prob_skip_false = cpi->last_skip_false_probs[2];
+
+                    /*
+                                        if(cpi->last_skip_false_probs[2]!=0 && abs(Q- cpi->last_skip_probs_q[2])<=16 )
+                       cpi->prob_skip_false = cpi->last_skip_false_probs[2];
+                                        else if (cpi->last_skip_false_probs[2]!=0)
+                       cpi->prob_skip_false = (cpi->last_skip_false_probs[2]  + cpi->prob_skip_false ) / 2;
+                       */
+                }
+                else if (cpi->common.refresh_golden_frame)
+                {
+                    if (cpi->last_skip_false_probs[1] != 0)
+                        cpi->prob_skip_false = cpi->last_skip_false_probs[1];
+
+                    /*
+                                        if(cpi->last_skip_false_probs[1]!=0 && abs(Q- cpi->last_skip_probs_q[1])<=16 )
+                       cpi->prob_skip_false = cpi->last_skip_false_probs[1];
+                                        else if (cpi->last_skip_false_probs[1]!=0)
+                       cpi->prob_skip_false = (cpi->last_skip_false_probs[1]  + cpi->prob_skip_false ) / 2;
+                       */
+                }
+                else
+                {
+                    if (cpi->last_skip_false_probs[0] != 0)
+                        cpi->prob_skip_false = cpi->last_skip_false_probs[0];
+
+                    /*
+                    if(cpi->last_skip_false_probs[0]!=0 && abs(Q- cpi->last_skip_probs_q[0])<=16 )
+                        cpi->prob_skip_false = cpi->last_skip_false_probs[0];
+                    else if(cpi->last_skip_false_probs[0]!=0)
+                        cpi->prob_skip_false = (cpi->last_skip_false_probs[0]  + cpi->prob_skip_false ) / 2;
+                        */
+                }
+
+                //as this is for cost estimate, let's make sure it does not go extreme eitehr way
+                if (cpi->prob_skip_false < 5)
+                    cpi->prob_skip_false = 5;
+
+                if (cpi->prob_skip_false > 250)
+                    cpi->prob_skip_false = 250;
+
+                if (cpi->is_src_frame_alt_ref)
+                    cpi->prob_skip_false = 1;
+
+
+            }
+
+#if 0
+
+            if (cpi->pass != 1)
+            {
+                FILE *f = fopen("skip.stt", "a");
+                fprintf(f, "%d, %d, %4d ", cpi->common.refresh_golden_frame, cpi->common.refresh_alt_ref_frame, cpi->prob_skip_false);
+                fclose(f);
+            }
+
+#endif
+
+        }
+
+        if (cm->frame_type == KEY_FRAME)
+            vp8_setup_key_frame(cpi);
+
+        // transform / motion compensation build reconstruction frame
+
+        vp8_encode_frame(cpi);
+        cpi->projected_frame_size -= vp8_estimate_entropy_savings(cpi);
+        cpi->projected_frame_size = (cpi->projected_frame_size > 0) ? cpi->projected_frame_size : 0;
+
+        vp8_clear_system_state();  //__asm emms;
+
+        // Test to see if the stats generated for this frame indicate that we should have coded a key frame
+        // (assuming that we didn't)!
+        if (cpi->pass != 2 && cpi->oxcf.auto_key && cm->frame_type != KEY_FRAME)
+        {
+            if (decide_key_frame(cpi))
+            {
+                vp8_calc_auto_iframe_target_size(cpi);
+
+                // Reset all our sizing numbers and recode
+                cm->frame_type = KEY_FRAME;
+
+                // Clear the Alt reference frame active flag when we have a key frame
+                cpi->source_alt_ref_active = FALSE;
+
+                // If segmentation is enabled force a map update for key frames
+                if (cpi->mb.e_mbd.segmentation_enabled)
+                {
+                    cpi->mb.e_mbd.update_mb_segmentation_map = 1;
+                    cpi->mb.e_mbd.update_mb_segmentation_data = 1;
+                }
+
+                // If mode or reference frame based loop filter deltas are enabled then force an update for key frames.
+                if (cpi->mb.e_mbd.mode_ref_lf_delta_enabled)
+                {
+                    cpi->mb.e_mbd.mode_ref_lf_delta_update = 1;
+                }
+
+                vp8_restore_coding_context(cpi);
+
+                Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+
+                q_low  = cpi->best_quality;
+                q_high = cpi->worst_quality;
+
+                vp8_compute_frame_size_bounds(cpi, &frame_under_shoot_limit, &frame_over_shoot_limit);
+
+                // Limit Q range for the adaptive loop (Values not clipped to range 20-60 as in VP8).
+                bottom_index = cpi->active_best_quality;
+                top_index    = cpi->active_worst_quality;
+
+
+                loop_count++;
+                Loop = TRUE;
+
+                resize_key_frame(cpi);
+                continue;
+            }
+        }
+
+        vp8_clear_system_state();
+
+        if (frame_over_shoot_limit == 0)
+            frame_over_shoot_limit = 1;
+
+        // Are we are overshooting and up against the limit of active max Q.
+        if (((cpi->pass != 2) || (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)) &&
+            (Q == cpi->active_worst_quality)                     &&
+            (cpi->active_worst_quality < cpi->worst_quality)      &&
+            (cpi->projected_frame_size > frame_over_shoot_limit))
+        {
+            int over_size_percent = ((cpi->projected_frame_size - frame_over_shoot_limit) * 100) / frame_over_shoot_limit;
+
+            // If so is there any scope for relaxing it
+            while ((cpi->active_worst_quality < cpi->worst_quality) && (over_size_percent > 0))
+            {
+                cpi->active_worst_quality++;
+                top_index = cpi->active_worst_quality;
+                over_size_percent = (int)(over_size_percent * 0.96);        // Assume 1 qstep = about 4% on frame size.
+            }
+
+            // If we have updated the active max Q do not call vp8_update_rate_correction_factors() this loop.
+            active_worst_qchanged = TRUE;
+        }
+        else
+            active_worst_qchanged = FALSE;
+
+#if !(CONFIG_REALTIME_ONLY)
+
+        // Is the projected frame size out of range and are we allowed to attempt to recode.
+        if (((cpi->sf.recode_loop == 1) ||
+             ((cpi->sf.recode_loop == 2) && (cm->refresh_golden_frame || (cm->frame_type == KEY_FRAME)))) &&
+            (((cpi->projected_frame_size > frame_over_shoot_limit) && (Q < top_index)) ||
+             //((cpi->projected_frame_size > frame_over_shoot_limit ) && (Q == top_index) && (cpi->zbin_over_quant < ZBIN_OQ_MAX)) ||
+             ((cpi->projected_frame_size < frame_under_shoot_limit) && (Q > bottom_index)))
+           )
+        {
+            int last_q = Q;
+            int Retries = 0;
+
+            // Frame size out of permitted range:
+            // Update correction factor & compute new Q to try...
+            if (cpi->projected_frame_size > frame_over_shoot_limit)
+            {
+                //if ( cpi->zbin_over_quant == 0 )
+                q_low = (Q < q_high) ? (Q + 1) : q_high; // Raise Qlow as to at least the current value
+
+                if (cpi->zbin_over_quant > 0)           // If we are using over quant do the same for zbin_oq_low
+                    zbin_oq_low = (cpi->zbin_over_quant < zbin_oq_high) ? (cpi->zbin_over_quant + 1) : zbin_oq_high;
+
+                //if ( undershoot_seen || (Q == MAXQ) )
+                if (undershoot_seen)
+                {
+                    // Update rate_correction_factor unless cpi->active_worst_quality has changed.
+                    if (!active_worst_qchanged)
+                        vp8_update_rate_correction_factors(cpi, 1);
+
+                    Q = (q_high + q_low + 1) / 2;
+
+                    // Adjust cpi->zbin_over_quant (only allowed when Q is max)
+                    if (Q < MAXQ)
+                        cpi->zbin_over_quant = 0;
+                    else
+                    {
+                        zbin_oq_low = (cpi->zbin_over_quant < zbin_oq_high) ? (cpi->zbin_over_quant + 1) : zbin_oq_high;
+                        cpi->zbin_over_quant = (zbin_oq_high + zbin_oq_low) / 2;
+                    }
+                }
+                else
+                {
+                    // Update rate_correction_factor unless cpi->active_worst_quality has changed.
+                    if (!active_worst_qchanged)
+                        vp8_update_rate_correction_factors(cpi, 0);
+
+                    Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+
+                    while (((Q < q_low) || (cpi->zbin_over_quant < zbin_oq_low)) && (Retries < 10))
+                    {
+                        vp8_update_rate_correction_factors(cpi, 0);
+                        Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+                        Retries ++;
+                    }
+                }
+
+                overshoot_seen = TRUE;
+            }
+            else
+            {
+                if (cpi->zbin_over_quant == 0)
+                    q_high = (Q > q_low) ? (Q - 1) : q_low; // Lower q_high if not using over quant
+                else                                    // else lower zbin_oq_high
+                    zbin_oq_high = (cpi->zbin_over_quant > zbin_oq_low) ? (cpi->zbin_over_quant - 1) : zbin_oq_low;
+
+                if (overshoot_seen)
+                {
+                    // Update rate_correction_factor unless cpi->active_worst_quality has changed.
+                    if (!active_worst_qchanged)
+                        vp8_update_rate_correction_factors(cpi, 1);
+
+                    Q = (q_high + q_low) / 2;
+
+                    // Adjust cpi->zbin_over_quant (only allowed when Q is max)
+                    if (Q < MAXQ)
+                        cpi->zbin_over_quant = 0;
+                    else
+                        cpi->zbin_over_quant = (zbin_oq_high + zbin_oq_low) / 2;
+                }
+                else
+                {
+                    // Update rate_correction_factor unless cpi->active_worst_quality has changed.
+                    if (!active_worst_qchanged)
+                        vp8_update_rate_correction_factors(cpi, 0);
+
+                    Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+
+                    while (((Q > q_high) || (cpi->zbin_over_quant > zbin_oq_high)) && (Retries < 10))
+                    {
+                        vp8_update_rate_correction_factors(cpi, 0);
+                        Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+                        Retries ++;
+                    }
+                }
+
+                undershoot_seen = TRUE;
+            }
+
+            // Clamp Q to upper and lower limits:
+            if (Q > q_high)
+                Q = q_high;
+            else if (Q < q_low)
+                Q = q_low;
+
+            // Clamp cpi->zbin_over_quant
+            cpi->zbin_over_quant = (cpi->zbin_over_quant < zbin_oq_low) ? zbin_oq_low : (cpi->zbin_over_quant > zbin_oq_high) ? zbin_oq_high : cpi->zbin_over_quant;
+
+            //Loop = ((Q != last_q) || (last_zbin_oq != cpi->zbin_over_quant)) ? TRUE : FALSE;
+            Loop = ((Q != last_q)) ? TRUE : FALSE;
+            last_zbin_oq = cpi->zbin_over_quant;
+        }
+        else
+#endif
+            Loop = FALSE;
+
+        if (cpi->is_src_frame_alt_ref)
+            Loop = FALSE;
+
+        if (Loop == TRUE)
+        {
+            vp8_restore_coding_context(cpi);
+            loop_count++;
+#if CONFIG_PSNR
+            cpi->tot_recode_hits++;
+#endif
+        }
+    }
+    while (Loop == TRUE);
+
+#if 0
+    // Experimental code for lagged and one pass
+    // Update stats used for one pass GF selection
+    {
+        /*
+            int frames_so_far;
+            double frame_intra_error;
+            double frame_coded_error;
+            double frame_pcnt_inter;
+            double frame_pcnt_motion;
+            double frame_mvr;
+            double frame_mvr_abs;
+            double frame_mvc;
+            double frame_mvc_abs;
+        */
+
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index].frame_coded_error = (double)cpi->prediction_error;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index].frame_intra_error = (double)cpi->intra_error;
+        cpi->one_pass_frame_stats[cpi->one_pass_frame_index].frame_pcnt_inter = (double)(100 - cpi->this_frame_percent_intra) / 100.0;
+    }
+#endif
+
+    // Update the GF useage maps.
+    // This is done after completing the compression of a frame when all modes etc. are finalized but before loop filter
+    vp8_update_gf_useage_maps(cm, &cpi->mb.e_mbd);
+
+    if (cm->frame_type == KEY_FRAME)
+        cm->refresh_last_frame = 1;
+
+    if (0)
+    {
+        FILE *f = fopen("gfactive.stt", "a");
+        fprintf(f, "%8d %8d %8d %8d %8d\n", cm->current_video_frame, (100 * cpi->common.gf_active_count) / (cpi->common.mb_rows * cpi->common.mb_cols), cpi->this_iiratio, cpi->next_iiratio, cm->refresh_golden_frame);
+        fclose(f);
+    }
+
+    // For inter frames the current default behaviour is that when cm->refresh_golden_frame is set we copy the old GF over to the ARF buffer
+    // This is purely an encoder descision at present.
+    if (!cpi->oxcf.error_resilient_mode && cm->refresh_golden_frame)
+        cm->copy_buffer_to_arf  = 2;
+    else
+        cm->copy_buffer_to_arf  = 0;
+
+    if (cm->refresh_last_frame)
+    {
+        vp8_swap_yv12_buffer(&cm->last_frame, &cm->new_frame);
+        cm->frame_to_show = &cm->last_frame;
+    }
+    else
+        cm->frame_to_show = &cm->new_frame;
+
+
+
+    //#pragma omp parallel sections
+    {
+
+        //#pragma omp section
+        {
+
+            struct vpx_usec_timer timer;
+
+            vpx_usec_timer_start(&timer);
+
+            if (cpi->sf.auto_filter == 0)
+                vp8cx_pick_filter_level_fast(cpi->Source, cpi);
+            else
+                vp8cx_pick_filter_level(cpi->Source, cpi);
+
+            vpx_usec_timer_mark(&timer);
+
+            cpi->time_pick_lpf +=  vpx_usec_timer_elapsed(&timer);
+
+            if (cm->no_lpf)
+                cm->filter_level = 0;
+
+            if (cm->filter_level > 0)
+            {
+                vp8cx_set_alt_lf_level(cpi, cm->filter_level);
+                vp8_loop_filter_frame(cm, &cpi->mb.e_mbd, cm->filter_level);
+                cm->last_frame_type = cm->frame_type;
+                cm->last_filter_type = cm->filter_type;
+                cm->last_sharpness_level = cm->sharpness_level;
+            }
+
+            vp8_yv12_extend_frame_borders_ptr(cm->frame_to_show);
+
+            if (cpi->oxcf.error_resilient_mode == 1)
+            {
+                cm->refresh_entropy_probs = 0;
+            }
+
+        }
+//#pragma omp section
+        {
+            // build the bitstream
+            vp8_pack_bitstream(cpi, dest, size);
+        }
+    }
+
+
+    // At this point the new frame has been encoded coded.
+    // If any buffer copy / swaping is signalled it should be done here.
+    if (cm->frame_type == KEY_FRAME)
+    {
+        vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cm->golden_frame);
+        vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cm->alt_ref_frame);
+    }
+    else    // For non key frames
+    {
+        // Code to copy between reference buffers
+        if (cm->copy_buffer_to_arf)
+        {
+            if (cm->copy_buffer_to_arf == 1)
+            {
+                if (cm->refresh_last_frame)
+                    // We copy new_frame here because last and new buffers will already have been swapped if cm->refresh_last_frame is set.
+                    vp8_yv12_copy_frame_ptr(&cm->new_frame, &cm->alt_ref_frame);
+                else
+                    vp8_yv12_copy_frame_ptr(&cm->last_frame, &cm->alt_ref_frame);
+            }
+            else if (cm->copy_buffer_to_arf == 2)
+                vp8_yv12_copy_frame_ptr(&cm->golden_frame, &cm->alt_ref_frame);
+        }
+
+        if (cm->copy_buffer_to_gf)
+        {
+            if (cm->copy_buffer_to_gf == 1)
+            {
+                if (cm->refresh_last_frame)
+                    // We copy new_frame here because last and new buffers will already have been swapped if cm->refresh_last_frame is set.
+                    vp8_yv12_copy_frame_ptr(&cm->new_frame, &cm->golden_frame);
+                else
+                    vp8_yv12_copy_frame_ptr(&cm->last_frame, &cm->golden_frame);
+            }
+            else if (cm->copy_buffer_to_gf == 2)
+                vp8_yv12_copy_frame_ptr(&cm->alt_ref_frame, &cm->golden_frame);
+        }
+    }
+
+    // Update rate control heuristics
+    cpi->total_byte_count += (*size);
+    cpi->projected_frame_size = (*size) << 3;
+
+    if (!active_worst_qchanged)
+        vp8_update_rate_correction_factors(cpi, 2);
+
+    cpi->last_q[cm->frame_type] = cm->base_qindex;
+
+    if (cm->frame_type == KEY_FRAME)
+    {
+        vp8_adjust_key_frame_context(cpi);
+    }
+
+    // Keep a record of ambient average Q.
+    if (cm->frame_type == KEY_FRAME)
+        cpi->avg_frame_qindex = cm->base_qindex;
+    else
+        cpi->avg_frame_qindex = (2 + 3 * cpi->avg_frame_qindex + cm->base_qindex) >> 2;
+
+    // Keep a record from which we can calculate the average Q excluding GF updates and key frames
+    if ((cm->frame_type != KEY_FRAME) && !cm->refresh_golden_frame && !cm->refresh_alt_ref_frame)
+    {
+        cpi->ni_frames++;
+
+        // Calculate the average Q for normal inter frames (not key or GFU frames)
+        // This is used as a basis for setting active worst quality.
+        if (cpi->ni_frames > 150)
+        {
+            cpi->ni_tot_qi += Q;
+            cpi->ni_av_qi = (cpi->ni_tot_qi / cpi->ni_frames);
+        }
+        // Early in the clip ... average the current frame Q value with the default
+        // entered by the user as a dampening measure
+        else
+        {
+            cpi->ni_tot_qi += Q;
+            cpi->ni_av_qi = ((cpi->ni_tot_qi / cpi->ni_frames) + cpi->worst_quality + 1) / 2;
+        }
+
+        // If the average Q is higher than what was used in the last frame
+        // (after going through the recode loop to keep the frame size within range)
+        // then use the last frame value - 1.
+        // The -1 is designed to stop Q and hence the data rate, from progressively
+        // falling away during difficult sections, but at the same time reduce the number of
+        // itterations around the recode loop.
+        if (Q > cpi->ni_av_qi)
+            cpi->ni_av_qi = Q - 1;
+
+    }
+
+#if 0
+
+    // If the frame was massively oversize and we are below optimal buffer level drop next frame
+    if ((cpi->drop_frames_allowed) &&
+        (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
+        (cpi->buffer_level < cpi->oxcf.drop_frames_water_mark * cpi->oxcf.optimal_buffer_level / 100) &&
+        (cpi->projected_frame_size > (4 * cpi->this_frame_target)))
+    {
+        cpi->drop_frame = TRUE;
+    }
+
+#endif
+
+    // Set the count for maximum consequative dropped frames based upon the ratio of
+    // this frame size to the target average per frame bandwidth.
+    // (cpi->av_per_frame_bandwidth > 0) is just a sanity check to prevent / 0.
+    if (cpi->drop_frames_allowed && (cpi->av_per_frame_bandwidth > 0))
+    {
+        cpi->max_drop_count = cpi->projected_frame_size / cpi->av_per_frame_bandwidth;
+
+        if (cpi->max_drop_count > cpi->max_consec_dropped_frames)
+            cpi->max_drop_count = cpi->max_consec_dropped_frames;
+    }
+
+    // Update the buffer level variable.
+    if (cpi->common.refresh_alt_ref_frame)
+        cpi->bits_off_target -= cpi->projected_frame_size;
+    else
+        cpi->bits_off_target += cpi->av_per_frame_bandwidth - cpi->projected_frame_size;
+
+    // Rolling monitors of whether we are over or underspending used to help regulate min and Max Q in two pass.
+    cpi->rolling_target_bits = ((cpi->rolling_target_bits * 3) + cpi->this_frame_target + 2) / 4;
+    cpi->rolling_actual_bits = ((cpi->rolling_actual_bits * 3) + cpi->projected_frame_size + 2) / 4;
+    cpi->long_rolling_target_bits = ((cpi->long_rolling_target_bits * 31) + cpi->this_frame_target + 16) / 32;
+    cpi->long_rolling_actual_bits = ((cpi->long_rolling_actual_bits * 31) + cpi->projected_frame_size + 16) / 32;
+
+    // Actual bits spent
+    cpi->total_actual_bits    += cpi->projected_frame_size;
+
+    // Debug stats
+    cpi->total_target_vs_actual += (cpi->this_frame_target - cpi->projected_frame_size);
+
+    cpi->buffer_level = cpi->bits_off_target;
+
+    // Update bits left to the kf and gf groups to account for overshoot or undershoot on these frames
+    if (cm->frame_type == KEY_FRAME)
+    {
+        cpi->kf_group_bits += cpi->this_frame_target - cpi->projected_frame_size;
+
+        if (cpi->kf_group_bits < 0)
+            cpi->kf_group_bits = 0 ;
+    }
+    else if (cm->refresh_golden_frame || cm->refresh_alt_ref_frame)
+    {
+        cpi->gf_group_bits += cpi->this_frame_target - cpi->projected_frame_size;
+
+        if (cpi->gf_group_bits < 0)
+            cpi->gf_group_bits = 0 ;
+    }
+
+    if (cm->frame_type != KEY_FRAME)
+    {
+        if (cpi->common.refresh_alt_ref_frame)
+        {
+            cpi->last_skip_false_probs[2] = cpi->prob_skip_false;
+            cpi->last_skip_probs_q[2] = cm->base_qindex;
+        }
+        else if (cpi->common.refresh_golden_frame)
+        {
+            cpi->last_skip_false_probs[1] = cpi->prob_skip_false;
+            cpi->last_skip_probs_q[1] = cm->base_qindex;
+        }
+        else
+        {
+            cpi->last_skip_false_probs[0] = cpi->prob_skip_false;
+            cpi->last_skip_probs_q[0] = cm->base_qindex;
+
+            //update the baseline
+            cpi->base_skip_false_prob[cm->base_qindex] = cpi->prob_skip_false;
+
+        }
+    }
+
+#if CONFIG_PSNR
+
+    if (0)
+    {
+        FILE *f = fopen("tmp.stt", "a");
+
+        vp8_clear_system_state();  //__asm emms;
+
+        if (cpi->total_coded_error_left != 0.0)
+            fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %6ld %6ld %6ld %6ld %5ld %5ld %5ld %8ld %8.2f %10d %10.3f %10.3f %8ld\n", cpi->common.current_video_frame, cpi->this_frame_target, cpi->projected_frame_size, (cpi->projected_frame_size - cpi->this_frame_target), (int)cpi->total_target_vs_actual, (cpi->oxcf.starting_buffer_level - cpi->bits_off_target), (int)cpi->total_actual_bits, cm->base_qindex, cpi->active_best_quality, cpi->active_worst_quality,  cpi->avg_frame_qindex, cpi->zbin_over_quant, cm->refresh_golden_frame, cm->refresh_alt_ref_frame, cm->frame_type, cpi->gfu_boost, cpi->est_max_qcorrection_factor, (int)cpi->bits_left, cpi->total_coded_error_left, (double)cpi->bits_left / cpi->total_coded_error_left,  cpi->tot_recode_hits);
+        else
+            fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %6ld %6ld %6ld %6ld %5ld %5ld %5ld %8ld %8.2f %10d %10.3f %8ld\n", cpi->common.current_video_frame, cpi->this_frame_target, cpi->projected_frame_size, (cpi->projected_frame_size - cpi->this_frame_target), (int)cpi->total_target_vs_actual, (cpi->oxcf.starting_buffer_level - cpi->bits_off_target), (int)cpi->total_actual_bits, cm->base_qindex, cpi->active_best_quality, cpi->active_worst_quality,  cpi->avg_frame_qindex, cpi->zbin_over_quant, cm->refresh_golden_frame, cm->refresh_alt_ref_frame, cm->frame_type, cpi->gfu_boost, cpi->est_max_qcorrection_factor, (int)cpi->bits_left, cpi->total_coded_error_left,   cpi->tot_recode_hits);
+
+        fclose(f);
+
+        {
+            FILE *fmodes = fopen("Modes.stt", "a");
+            int i;
+
+            fprintf(fmodes, "%6d:%1d:%1d:%1d ", cpi->common.current_video_frame, cm->frame_type, cm->refresh_golden_frame, cm->refresh_alt_ref_frame);
+
+            for (i = 0; i < MAX_MODES; i++)
+                fprintf(fmodes, "%5d ", cpi->mode_chosen_counts[i]);
+
+            fprintf(fmodes, "\n");
+
+            fclose(fmodes);
+        }
+    }
+
+#endif
+
+    // If this was a kf or Gf note the Q
+    if ((cm->frame_type == KEY_FRAME) || cm->refresh_golden_frame || cm->refresh_alt_ref_frame)
+        cm->last_kf_gf_q = cm->base_qindex;
+
+    if (cm->refresh_golden_frame == 1)
+        cm->frame_flags = cm->frame_flags | FRAMEFLAGS_GOLDEN;
+    else
+        cm->frame_flags = cm->frame_flags&~FRAMEFLAGS_GOLDEN;
+
+    if (cm->refresh_alt_ref_frame == 1)
+        cm->frame_flags = cm->frame_flags | FRAMEFLAGS_ALTREF;
+    else
+        cm->frame_flags = cm->frame_flags&~FRAMEFLAGS_ALTREF;
+
+
+    if (cm->refresh_last_frame & cm->refresh_golden_frame) // both refreshed
+        cpi->gold_is_last = 1;
+    else if (cm->refresh_last_frame ^ cm->refresh_golden_frame) // 1 refreshed but not the other
+        cpi->gold_is_last = 0;
+
+    if (cm->refresh_last_frame & cm->refresh_alt_ref_frame) // both refreshed
+        cpi->alt_is_last = 1;
+    else if (cm->refresh_last_frame ^ cm->refresh_alt_ref_frame) // 1 refreshed but not the other
+        cpi->alt_is_last = 0;
+
+    if (cm->refresh_alt_ref_frame & cm->refresh_golden_frame) // both refreshed
+        cpi->gold_is_alt = 1;
+    else if (cm->refresh_alt_ref_frame ^ cm->refresh_golden_frame) // 1 refreshed but not the other
+        cpi->gold_is_alt = 0;
+
+    cpi->ref_frame_flags = VP8_ALT_FLAG | VP8_GOLD_FLAG | VP8_LAST_FLAG;
+
+    if (cpi->gold_is_last)
+        cpi->ref_frame_flags &= !VP8_GOLD_FLAG;
+
+    if (cpi->alt_is_last)
+        cpi->ref_frame_flags &= !VP8_ALT_FLAG;
+
+    if (cpi->gold_is_alt)
+        cpi->ref_frame_flags &= !VP8_ALT_FLAG;
+
+
+    if (cpi->oxcf.error_resilient_mode)
+    {
+        // Is this an alternate reference update
+        if (cpi->common.refresh_alt_ref_frame)
+            vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cm->alt_ref_frame);
+
+        if (cpi->common.refresh_golden_frame)
+            vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cm->golden_frame);
+    }
+    else
+    {
+        if (cpi->oxcf.play_alternate && cpi->common.refresh_alt_ref_frame)
+            // Update the alternate reference frame and stats as appropriate.
+            update_alt_ref_frame_and_stats(cpi);
+        else
+            // Update the Golden frame and golden frame and stats as appropriate.
+            update_golden_frame_and_stats(cpi);
+    }
+
+    if (cm->frame_type == KEY_FRAME)
+    {
+        // Tell the caller that the frame was coded as a key frame
+        *frame_flags = cm->frame_flags | FRAMEFLAGS_KEY;
+
+        // As this frame is a key frame  the next defaults to an inter frame.
+        cm->frame_type = INTER_FRAME;
+
+        cpi->last_frame_percent_intra = 100;
+    }
+    else
+    {
+        *frame_flags = cm->frame_flags&~FRAMEFLAGS_KEY;
+
+        cpi->last_frame_percent_intra = cpi->this_frame_percent_intra;
+    }
+
+    // Clear the one shot update flags for segmentation map and mode/ref loop filter deltas.
+    cpi->mb.e_mbd.update_mb_segmentation_map = 0;
+    cpi->mb.e_mbd.update_mb_segmentation_data = 0;
+    cpi->mb.e_mbd.mode_ref_lf_delta_update = 0;
+
+
+    // Dont increment frame counters if this was an altref buffer update not a real frame
+    if (cm->show_frame)
+    {
+        cm->current_video_frame++;
+        cpi->frames_since_key++;
+    }
+
+    // reset to normal state now that we are done.
+
+
+
+    if (0)
+    {
+        char filename[512];
+        FILE *recon_file;
+        sprintf(filename, "enc%04d.yuv", (int) cm->current_video_frame);
+        recon_file = fopen(filename, "wb");
+        fwrite(cm->last_frame.buffer_alloc, cm->last_frame.frame_size, 1, recon_file);
+        fclose(recon_file);
+    }
+
+    // DEBUG
+    //vp8_write_yuv_frame("encoder_recon.yuv", cm->frame_to_show);
+
+
+}
+
+int vp8_is_gf_update_needed(VP8_PTR ptr)
+{
+    VP8_COMP *cpi = (VP8_COMP *) ptr;
+    int ret_val;
+
+    ret_val = cpi->gf_update_recommended;
+    cpi->gf_update_recommended = 0;
+
+    return ret_val;
+}
+
+void vp8_check_gf_quality(VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+    int gf_active_pct = (100 * cm->gf_active_count) / (cm->mb_rows * cm->mb_cols);
+    int gf_ref_usage_pct = (cpi->count_mb_ref_frame_usage[GOLDEN_FRAME] * 100) / (cm->mb_rows * cm->mb_cols);
+    int last_ref_zz_useage = (cpi->inter_zz_count * 100) / (cm->mb_rows * cm->mb_cols);
+
+    // Gf refresh is not currently being signalled
+    if (cpi->gf_update_recommended == 0)
+    {
+        if (cpi->common.frames_since_golden > 7)
+        {
+            // Low use of gf
+            if ((gf_active_pct < 10) || ((gf_active_pct + gf_ref_usage_pct) < 15))
+            {
+                // ...but last frame zero zero usage is reasonbable so a new gf might be appropriate
+                if (last_ref_zz_useage >= 25)
+                {
+                    cpi->gf_bad_count ++;
+
+                    if (cpi->gf_bad_count >= 8)   // Check that the condition is stable
+                    {
+                        cpi->gf_update_recommended = 1;
+                        cpi->gf_bad_count = 0;
+                    }
+                }
+                else
+                    cpi->gf_bad_count = 0;        // Restart count as the background is not stable enough
+            }
+            else
+                cpi->gf_bad_count = 0;            // Gf useage has picked up so reset count
+        }
+    }
+    // If the signal is set but has not been read should we cancel it.
+    else if (last_ref_zz_useage < 15)
+    {
+        cpi->gf_update_recommended = 0;
+        cpi->gf_bad_count = 0;
+    }
+
+#if 0
+
+    if (0)
+    {
+        FILE *f = fopen("gfneeded.stt", "a");
+        fprintf(f, "%10d %10d %10d %10d %10ld \n",
+                cm->current_video_frame,
+                cpi->common.frames_since_golden,
+                gf_active_pct, gf_ref_usage_pct,
+                cpi->gf_update_recommended);
+        fclose(f);
+    }
+
+#endif
+}
+
+#if !(CONFIG_REALTIME_ONLY)
+static void Pass2Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags)
+{
+    double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100);
+
+    if (!cpi->common.refresh_alt_ref_frame)
+        vp8_second_pass(cpi);
+
+    encode_frame_to_data_rate(cpi, size, dest, frame_flags);
+    cpi->bits_left -= 8 * *size;
+
+    if (!cpi->common.refresh_alt_ref_frame)
+        cpi->bits_left += (long long)(two_pass_min_rate / cpi->oxcf.frame_rate);
+}
+#endif
+
+//For ARM NEON, d8-d15 are callee-saved registers, and need to be saved by us.
+#if HAVE_ARMV7
+extern void vp8_push_neon(INT64 *store);
+extern void vp8_pop_neon(INT64 *store);
+static INT64 store_reg[8];
+#endif
+int vp8_receive_raw_frame(VP8_PTR ptr, unsigned int frame_flags, YV12_BUFFER_CONFIG *sd, INT64 time_stamp, INT64 end_time)
+{
+    VP8_COMP *cpi = (VP8_COMP *) ptr;
+    VP8_COMMON *cm = &cpi->common;
+    struct vpx_usec_timer  timer;
+
+    if (!cpi)
+        return -1;
+
+#if HAVE_ARMV7
+    vp8_push_neon(store_reg);
+#endif
+
+    vpx_usec_timer_start(&timer);
+
+    // no more room for frames;
+    if (cpi->source_buffer_count != 0 && cpi->source_buffer_count >= cpi->oxcf.lag_in_frames)
+    {
+#if HAVE_ARMV7
+        vp8_pop_neon(store_reg);
+#endif
+        return -1;
+    }
+
+    //printf("in-cpi->source_buffer_count: %d\n", cpi->source_buffer_count);
+
+    cm->clr_type = sd->clrtype;
+
+    // make a copy of the frame for use later...
+#if !(CONFIG_REALTIME_ONLY)
+
+    if (cpi->oxcf.allow_lag)
+    {
+        int which_buffer =  cpi->source_encode_index - 1;
+        SOURCE_SAMPLE *s;
+
+        if (which_buffer == -1)
+            which_buffer = cpi->oxcf.lag_in_frames - 1;
+
+        if (cpi->source_buffer_count < cpi->oxcf.lag_in_frames - 1)
+            which_buffer = cpi->source_buffer_count;
+
+        s = &cpi->src_buffer[which_buffer];
+
+        s->source_time_stamp = time_stamp;
+        s->source_end_time_stamp = end_time;
+        s->source_frame_flags = frame_flags;
+        vp8_yv12_copy_frame_ptr(sd, &s->source_buffer);
+
+        cpi->source_buffer_count ++;
+    }
+    else
+#endif
+    {
+        SOURCE_SAMPLE *s;
+        s = &cpi->src_buffer[0];
+        s->source_end_time_stamp = end_time;
+        s->source_time_stamp = time_stamp;
+        s->source_frame_flags = frame_flags;
+#if HAVE_ARMV7
+        vp8_yv12_copy_src_frame_func_neon(sd, &s->source_buffer);
+#else
+        vp8_yv12_copy_frame_ptr(sd, &s->source_buffer);
+#endif
+        cpi->source_buffer_count = 1;
+    }
+
+    vpx_usec_timer_mark(&timer);
+    cpi->time_receive_data += vpx_usec_timer_elapsed(&timer);
+
+#if HAVE_ARMV7
+    vp8_pop_neon(store_reg);
+#endif
+
+    return 0;
+}
+int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned long *size, unsigned char *dest, INT64 *time_stamp, INT64 *time_end, int flush)
+{
+
+    VP8_COMP *cpi = (VP8_COMP *) ptr;
+    VP8_COMMON *cm = &cpi->common;
+    struct vpx_usec_timer  tsctimer;
+    struct vpx_usec_timer  ticktimer;
+    struct vpx_usec_timer  cmptimer;
+
+    if (!cpi)
+        return -1;
+
+#if HAVE_ARMV7
+    vp8_push_neon(store_reg);
+#endif
+
+    vpx_usec_timer_start(&cmptimer);
+
+
+    // flush variable tells us that even though we have less than 10 frames
+    // in our buffer we need to start producing compressed frames.
+    // Probably because we are at the end of a file....
+    if ((cpi->source_buffer_count == cpi->oxcf.lag_in_frames && cpi->oxcf.lag_in_frames > 0)
+        || (!cpi->oxcf.allow_lag && cpi->source_buffer_count > 0)
+        || (flush && cpi->source_buffer_count > 0))
+    {
+
+        SOURCE_SAMPLE *s;
+
+        s = &cpi->src_buffer[cpi->source_encode_index];
+        cpi->source_time_stamp = s->source_time_stamp;
+        cpi->source_end_time_stamp = s->source_end_time_stamp;
+
+#if !(CONFIG_REALTIME_ONLY)
+
+        // Should we code an alternate reference frame
+        if (cpi->oxcf.error_resilient_mode == 0 &&
+            cpi->oxcf.play_alternate &&
+            cpi->source_alt_ref_pending  &&
+            (cpi->frames_till_gf_update_due < cpi->source_buffer_count) &&
+            cpi->oxcf.lag_in_frames != 0)
+        {
+            cpi->last_alt_ref_sei = (cpi->source_encode_index + cpi->frames_till_gf_update_due) % cpi->oxcf.lag_in_frames;
+
+#if VP8_TEMPORAL_ALT_REF
+
+            if (cpi->oxcf.arnr_max_frames > 0)
+            {
+#if 0
+                // my attempt at a loop that tests the results of strength filter.
+                int start_frame = cpi->last_alt_ref_sei - 3;
+
+                int i, besti = -1, pastin = cpi->oxcf.arnr_strength;
+
+                int besterr;
+
+                if (start_frame < 0)
+                    start_frame += cpi->oxcf.lag_in_frames;
+
+                besterr = vp8_calc_low_ss_err(&cpi->src_buffer[cpi->last_alt_ref_sei].source_buffer,
+                                              &cpi->src_buffer[start_frame].source_buffer, IF_RTCD(&cpi->rtcd.variance));
+
+                for (i = 0; i < 7; i++)
+                {
+                    int thiserr;
+                    cpi->oxcf.arnr_strength = i;
+                    vp8cx_temp_filter_c(cpi);
+
+                    thiserr = vp8_calc_low_ss_err(&cpi->alt_ref_buffer.source_buffer,
+                                                  &cpi->src_buffer[start_frame].source_buffer, IF_RTCD(&cpi->rtcd.variance));
+
+                    if (10 * thiserr < besterr * 8)
+                    {
+                        besterr = thiserr;
+                        besti = i;
+                    }
+                }
+
+                if (besti != -1)
+                {
+                    cpi->oxcf.arnr_strength = besti;
+                    vp8cx_temp_filter_c(cpi);
+                    s = &cpi->alt_ref_buffer;
+
+                    // FWG not sure if I need to copy this data for the Alt Ref frame
+                    s->source_time_stamp = cpi->src_buffer[cpi->last_alt_ref_sei].source_time_stamp;
+                    s->source_end_time_stamp = cpi->src_buffer[cpi->last_alt_ref_sei].source_end_time_stamp;
+                    s->source_frame_flags = cpi->src_buffer[cpi->last_alt_ref_sei].source_frame_flags;
+                }
+                else
+                    s = &cpi->src_buffer[cpi->last_alt_ref_sei];
+
+#else
+                vp8cx_temp_filter_c(cpi);
+                s = &cpi->alt_ref_buffer;
+
+                // FWG not sure if I need to copy this data for the Alt Ref frame
+                s->source_time_stamp = cpi->src_buffer[cpi->last_alt_ref_sei].source_time_stamp;
+                s->source_end_time_stamp = cpi->src_buffer[cpi->last_alt_ref_sei].source_end_time_stamp;
+                s->source_frame_flags = cpi->src_buffer[cpi->last_alt_ref_sei].source_frame_flags;
+
+#endif
+            }
+            else
+#endif
+                s = &cpi->src_buffer[cpi->last_alt_ref_sei];
+
+            cm->frames_till_alt_ref_frame = cpi->frames_till_gf_update_due;
+            cm->refresh_alt_ref_frame = 1;
+            cm->refresh_golden_frame = 0;
+            cm->refresh_last_frame = 0;
+            cm->show_frame = 0;
+            cpi->source_alt_ref_pending = FALSE;   // Clear Pending altf Ref flag.
+            cpi->is_src_frame_alt_ref = 0;
+        }
+        else
+#endif
+        {
+            cm->show_frame = 1;
+#if !(CONFIG_REALTIME_ONLY)
+
+            if (cpi->oxcf.allow_lag)
+            {
+                if (cpi->source_encode_index ==  cpi->last_alt_ref_sei)
+                {
+#if VP8_TEMPORAL_ALT_REF
+
+                    if (cpi->oxcf.arnr_max_frames == 0)
+                    {
+                        cpi->is_src_frame_alt_ref = 1; // copy alt ref
+                    }
+                    else
+                    {
+                        cpi->is_src_frame_alt_ref = 0;
+                    }
+
+#else
+                    cpi->is_src_frame_alt_ref = 1;
+#endif
+                    cpi->last_alt_ref_sei    = -1;
+                }
+                else
+                    cpi->is_src_frame_alt_ref = 0;
+
+                cpi->source_encode_index = (cpi->source_encode_index + 1) % cpi->oxcf.lag_in_frames;
+            }
+
+#endif
+            cpi->source_buffer_count--;
+        }
+
+        cpi->un_scaled_source = &s->source_buffer;
+        cpi->Source = &s->source_buffer;
+        cpi->source_frame_flags = s->source_frame_flags;
+
+        *time_stamp = cpi->source_time_stamp;
+        *time_end = cpi->source_end_time_stamp;
+    }
+    else
+    {
+        *size = 0;
+#if !(CONFIG_REALTIME_ONLY)
+
+        if (flush && cpi->pass == 1 && !cpi->first_pass_done)
+        {
+            vp8_end_first_pass(cpi);    /* get last stats packet */
+            cpi->first_pass_done = 1;
+        }
+
+#endif
+
+#if HAVE_ARMV7
+        vp8_pop_neon(store_reg);
+#endif
+        return -1;
+    }
+
+    *frame_flags = cpi->source_frame_flags;
+
+#if CONFIG_PSNR
+
+    if (cpi->source_time_stamp < cpi->first_time_stamp_ever)
+        cpi->first_time_stamp_ever = cpi->source_time_stamp;
+
+#endif
+
+    // adjust frame rates based on timestamps given
+    if (!cm->refresh_alt_ref_frame)
+    {
+        if (cpi->last_time_stamp_seen == 0)
+        {
+            double this_fps = 10000000.000 / (cpi->source_end_time_stamp - cpi->source_time_stamp);
+
+            vp8_new_frame_rate(cpi, this_fps);
+        }
+        else
+        {
+            long long nanosecs = cpi->source_time_stamp - cpi->last_time_stamp_seen;
+            double this_fps = 10000000.000 / nanosecs;
+
+            vp8_new_frame_rate(cpi, (7 * cpi->oxcf.frame_rate + this_fps) / 8);
+
+        }
+
+        cpi->last_time_stamp_seen = cpi->source_time_stamp;
+    }
+
+    if (cpi->compressor_speed == 2)
+    {
+        vp8_check_gf_quality(cpi);
+    }
+
+    if (!cpi)
+    {
+#if HAVE_ARMV7
+        vp8_pop_neon(store_reg);
+#endif
+        return 0;
+    }
+
+    if (cpi->compressor_speed == 2)
+    {
+        vpx_usec_timer_start(&tsctimer);
+        vpx_usec_timer_start(&ticktimer);
+    }
+
+    // start with a 0 size frame
+    *size = 0;
+
+    // Clear down mmx registers
+    vp8_clear_system_state();  //__asm emms;
+
+    cm->frame_type = INTER_FRAME;
+    cm->frame_flags = *frame_flags;
+
+#if 0
+
+    if (cm->refresh_alt_ref_frame)
+    {
+        //cm->refresh_golden_frame = 1;
+        cm->refresh_golden_frame = 0;
+        cm->refresh_last_frame = 0;
+    }
+    else
+    {
+        cm->refresh_golden_frame = 0;
+        cm->refresh_last_frame = 1;
+    }
+
+#endif
+
+#if !(CONFIG_REALTIME_ONLY)
+
+    if (cpi->pass == 1)
+    {
+        Pass1Encode(cpi, size, dest, frame_flags);
+    }
+    else if (cpi->pass == 2)
+    {
+        Pass2Encode(cpi, size, dest, frame_flags);
+    }
+    else
+#endif
+        encode_frame_to_data_rate(cpi, size, dest, frame_flags);
+
+    if (cpi->compressor_speed == 2)
+    {
+        unsigned int duration, duration2;
+        vpx_usec_timer_mark(&tsctimer);
+        vpx_usec_timer_mark(&ticktimer);
+
+        duration = vpx_usec_timer_elapsed(&ticktimer);
+        duration2 = (unsigned int)((double)duration / 2);
+
+        if (cm->frame_type != KEY_FRAME)
+        {
+            if (cpi->avg_encode_time == 0)
+                cpi->avg_encode_time = duration;
+            else
+                cpi->avg_encode_time = (7 * cpi->avg_encode_time + duration) >> 3;
+        }
+
+        if (duration2)
+        {
+            //if(*frame_flags!=1)
+            {
+
+                if (cpi->avg_pick_mode_time == 0)
+                    cpi->avg_pick_mode_time = duration2;
+                else
+                    cpi->avg_pick_mode_time = (7 * cpi->avg_pick_mode_time + duration2) >> 3;
+            }
+        }
+
+    }
+
+    if (cm->refresh_entropy_probs == 0)
+    {
+        vpx_memcpy(&cm->fc, &cm->lfc, sizeof(cm->fc));
+    }
+
+    // if its a dropped frame honor the requests on subsequent frames
+    if (*size > 0)
+    {
+
+        // return to normal state
+        cpi->ref_frame_flags = VP8_ALT_FLAG | VP8_GOLD_FLAG | VP8_LAST_FLAG;
+
+        cm->refresh_entropy_probs = 1;
+        cm->refresh_alt_ref_frame = 0;
+        cm->refresh_golden_frame = 0;
+        cm->refresh_last_frame = 1;
+        cm->frame_type = INTER_FRAME;
+
+    }
+
+    cpi->ready_for_new_frame = 1;
+
+    vpx_usec_timer_mark(&cmptimer);
+    cpi->time_compress_data += vpx_usec_timer_elapsed(&cmptimer);
+
+    if (cpi->b_calculate_psnr && cpi->pass != 1 && cm->show_frame)
+        generate_psnr_packet(cpi);
+
+#if CONFIG_PSNR
+
+    if (cpi->pass != 1)
+    {
+        cpi->bytes += *size;
+
+        if (cm->show_frame)
+        {
+
+            cpi->count ++;
+
+            if (cpi->b_calculate_psnr)
+            {
+                double y, u, v;
+                double sq_error;
+                double frame_psnr = vp8_calc_psnr(cpi->Source, cm->frame_to_show, &y, &u, &v, &sq_error);
+
+                cpi->total_y += y;
+                cpi->total_u += u;
+                cpi->total_v += v;
+                cpi->total_sq_error += sq_error;
+                cpi->total  += frame_psnr;
+                {
+                    double y2, u2, v2, frame_psnr2, frame_ssim2 = 0;
+                    double weight = 0;
+
+                    vp8_deblock(cm->frame_to_show, &cm->post_proc_buffer, cm->filter_level * 10 / 6, 1, 0, IF_RTCD(&cm->rtcd.postproc));
+                    vp8_clear_system_state();
+                    frame_psnr2 = vp8_calc_psnr(cpi->Source, &cm->post_proc_buffer, &y2, &u2, &v2, &sq_error);
+                    frame_ssim2 = vp8_calc_ssim(cpi->Source, &cm->post_proc_buffer, 1, &weight);
+
+                    cpi->summed_quality += frame_ssim2 * weight;
+                    cpi->summed_weights += weight;
+
+                    cpi->totalp_y += y2;
+                    cpi->totalp_u += u2;
+                    cpi->totalp_v += v2;
+                    cpi->totalp  += frame_psnr2;
+                    cpi->total_sq_error2 += sq_error;
+
+                }
+            }
+
+            if (cpi->b_calculate_ssimg)
+            {
+                double y, u, v, frame_all;
+                frame_all =  vp8_calc_ssimg(cpi->Source, cm->frame_to_show, &y, &u, &v);
+                cpi->total_ssimg_y += y;
+                cpi->total_ssimg_u += u;
+                cpi->total_ssimg_v += v;
+                cpi->total_ssimg_all += frame_all;
+            }
+
+        }
+    }
+
+#if 0
+
+    if (cpi->common.frame_type != 0 && cpi->common.base_qindex == cpi->oxcf.worst_allowed_q)
+    {
+        skiptruecount += cpi->skip_true_count;
+        skipfalsecount += cpi->skip_false_count;
+    }
+
+#endif
+#if 0
+
+    if (cpi->pass != 1)
+    {
+        FILE *f = fopen("skip.stt", "a");
+        fprintf(f, "frame:%4d flags:%4x Q:%4d P:%4d Size:%5d\n", cpi->common.current_video_frame, *frame_flags, cpi->common.base_qindex, cpi->prob_skip_false, *size);
+
+        if (cpi->is_src_frame_alt_ref == 1)
+            fprintf(f, "skipcount: %4d framesize: %d\n", cpi->skip_true_count , *size);
+
+        fclose(f);
+    }
+
+#endif
+#endif
+
+#if HAVE_ARMV7
+    vp8_pop_neon(store_reg);
+#endif
+
+    return 0;
+}
+
+int vp8_get_preview_raw_frame(VP8_PTR comp, YV12_BUFFER_CONFIG *dest, int deblock_level, int noise_level, int flags)
+{
+    VP8_COMP *cpi = (VP8_COMP *) comp;
+
+    if (cpi->common.refresh_alt_ref_frame)
+        return -1;
+    else
+    {
+        int ret;
+#if CONFIG_POSTPROC
+        ret = vp8_post_proc_frame(&cpi->common, dest, deblock_level, noise_level, flags);
+#else
+
+        if (cpi->common.frame_to_show)
+        {
+            *dest = *cpi->common.frame_to_show;
+            dest->y_width = cpi->common.Width;
+            dest->y_height = cpi->common.Height;
+            dest->uv_height = cpi->common.Height / 2;
+            ret = 0;
+        }
+        else
+        {
+            ret = -1;
+        }
+
+#endif //!CONFIG_POSTPROC
+        vp8_clear_system_state();
+        return ret;
+    }
+}
+
+int vp8_set_roimap(VP8_PTR comp, unsigned char *map, unsigned int rows, unsigned int cols, int delta_q[4], int delta_lf[4], unsigned int threshold[4])
+{
+    VP8_COMP *cpi = (VP8_COMP *) comp;
+    signed char feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];
+
+    if (cpi->common.mb_rows != rows || cpi->common.mb_cols != cols)
+        return -1;
+
+    if (!map)
+    {
+        disable_segmentation((VP8_PTR)cpi);
+        return 0;
+    }
+
+    // Set the segmentation Map
+    set_segmentation_map((VP8_PTR)cpi, map);
+
+    // Activate segmentation.
+    enable_segmentation((VP8_PTR)cpi);
+
+    // Set up the quant segment data
+    feature_data[MB_LVL_ALT_Q][0] = delta_q[0];
+    feature_data[MB_LVL_ALT_Q][1] = delta_q[1];
+    feature_data[MB_LVL_ALT_Q][2] = delta_q[2];
+    feature_data[MB_LVL_ALT_Q][3] = delta_q[3];
+
+    // Set up the loop segment data s
+    feature_data[MB_LVL_ALT_LF][0] = delta_lf[0];
+    feature_data[MB_LVL_ALT_LF][1] = delta_lf[1];
+    feature_data[MB_LVL_ALT_LF][2] = delta_lf[2];
+    feature_data[MB_LVL_ALT_LF][3] = delta_lf[3];
+
+    cpi->segment_encode_breakout[0] = threshold[0];
+    cpi->segment_encode_breakout[1] = threshold[1];
+    cpi->segment_encode_breakout[2] = threshold[2];
+    cpi->segment_encode_breakout[3] = threshold[3];
+
+    // Initialise the feature data structure
+    // SEGMENT_DELTADATA    0, SEGMENT_ABSDATA      1
+    set_segment_data((VP8_PTR)cpi, &feature_data[0][0], SEGMENT_DELTADATA);
+
+    return 0;
+}
+
+int vp8_set_active_map(VP8_PTR comp, unsigned char *map, unsigned int rows, unsigned int cols)
+{
+    VP8_COMP *cpi = (VP8_COMP *) comp;
+
+    if (rows == cpi->common.mb_rows && cols == cpi->common.mb_cols)
+    {
+        if (map)
+        {
+            vpx_memcpy(cpi->active_map, map, rows * cols);
+            cpi->active_map_enabled = 1;
+        }
+        else
+            cpi->active_map_enabled = 0;
+
+        return 0;
+    }
+    else
+    {
+        //cpi->active_map_enabled = 0;
+        return -1 ;
+    }
+}
+
+int vp8_set_internal_size(VP8_PTR comp, VPX_SCALING horiz_mode, VPX_SCALING vert_mode)
+{
+    VP8_COMP *cpi = (VP8_COMP *) comp;
+
+    if (horiz_mode >= NORMAL && horiz_mode <= ONETWO)
+        cpi->common.horiz_scale = horiz_mode;
+    else
+        return -1;
+
+    if (vert_mode >= NORMAL && vert_mode <= ONETWO)
+        cpi->common.vert_scale  = vert_mode;
+    else
+        return -1;
+
+    return 0;
+}
+
+
+
+int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, const vp8_variance_rtcd_vtable_t *rtcd)
+{
+    int i, j;
+    int Total = 0;
+
+    unsigned char *src = source->y_buffer;
+    unsigned char *dst = dest->y_buffer;
+    (void)rtcd;
+
+    // Loop through the Y plane raw and reconstruction data summing (square differences)
+    for (i = 0; i < source->y_height; i += 16)
+    {
+        for (j = 0; j < source->y_width; j += 16)
+        {
+            unsigned int sse;
+            Total += VARIANCE_INVOKE(rtcd, mse16x16)(src + j, source->y_stride, dst + j, dest->y_stride, &sse);
+        }
+
+        src += 16 * source->y_stride;
+        dst += 16 * dest->y_stride;
+    }
+
+    return Total;
+}
+int vp8_calc_low_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, const vp8_variance_rtcd_vtable_t *rtcd)
+{
+    int i, j;
+    int Total = 0;
+
+    unsigned char *src = source->y_buffer;
+    unsigned char *dst = dest->y_buffer;
+    (void)rtcd;
+
+    // Loop through the Y plane raw and reconstruction data summing (square differences)
+    for (i = 0; i < source->y_height; i += 16)
+    {
+        for (j = 0; j < source->y_width; j += 16)
+        {
+            unsigned int sse, sse2, sum2;
+            VARIANCE_INVOKE(rtcd, mse16x16)(src + j, source->y_stride, dst + j, dest->y_stride, &sse);
+
+            if (sse < 8096)
+                Total += sse;
+        }
+
+        src += 16 * source->y_stride;
+        dst += 16 * dest->y_stride;
+    }
+
+    return Total;
+}
+
+int vp8_get_speed(VP8_PTR c)
+{
+    VP8_COMP   *cpi = (VP8_COMP *) c;
+    return cpi->Speed;
+}
+int vp8_get_quantizer(VP8_PTR c)
+{
+    VP8_COMP   *cpi = (VP8_COMP *) c;
+    return cpi->common.base_qindex;
+}
diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
new file mode 100644
index 0000000..29b120e
--- /dev/null
+++ b/vp8/encoder/onyx_int.h
@@ -0,0 +1,670 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_VP8_INT_H
+#define __INC_VP8_INT_H
+
+#include <stdio.h>
+#include "vpx_ports/config.h"
+#include "onyx.h"
+#include "treewriter.h"
+#include "tokenize.h"
+#include "onyxc_int.h"
+#include "preproc.h"
+#include "variance.h"
+#include "dct.h"
+#include "encodemb.h"
+#include "quantize.h"
+#include "entropy.h"
+#include "threading.h"
+#include "vpx_ports/mem.h"
+#include "vpx_codec/internal/vpx_codec_internal.h"
+#include "mcomp.h"
+
+#define INTRARDOPT
+//#define SPEEDSTATS 1
+#define MIN_GF_INTERVAL             4
+#define DEFAULT_GF_INTERVAL         7
+
+#define KEY_FRAME_CONTEXT 5
+
+#define MAX_LAG_BUFFERS (CONFIG_REALTIME_ONLY? 1 : 25)
+
+#define AF_THRESH   25
+#define AF_THRESH2  100
+#define ARF_DECAY_THRESH 12
+#define MAX_MODES 20
+
+#define MIN_THRESHMULT  32
+#define MAX_THRESHMULT  512
+
+#define GF_ZEROMV_ZBIN_BOOST 24
+#define ZBIN_OQ_MAX 192
+
+#define VP8_TEMPORAL_ALT_REF 1
+
+typedef struct
+{
+    int kf_indicated;
+    unsigned int frames_since_key;
+    unsigned int frames_since_golden;
+    int filter_level;
+    int frames_till_gf_update_due;
+    int recent_ref_frame_usage[MAX_REF_FRAMES];
+
+    MV_CONTEXT mvc[2];
+    int mvcosts[2][MVvals+1];
+
+#ifdef MODE_STATS
+    // Stats
+    int y_modes[5];
+    int uv_modes[4];
+    int b_modes[10];
+    int inter_y_modes[10];
+    int inter_uv_modes[4];
+    int inter_b_modes[10];
+#endif
+
+    vp8_prob ymode_prob[4], uv_mode_prob[3];   /* interframe intra mode probs */
+    vp8_prob kf_ymode_prob[4], kf_uv_mode_prob[3];   /* keyframe "" */
+
+    int ymode_count[5], uv_mode_count[4];  /* intra MB type cts this frame */
+
+    int count_mb_ref_frame_usage[MAX_REF_FRAMES];
+
+    int this_frame_percent_intra;
+    int last_frame_percent_intra;
+
+
+} CODING_CONTEXT;
+
+typedef struct
+{
+    double frame;
+    double intra_error;
+    double coded_error;
+    double ssim_weighted_pred_err;
+    double pcnt_inter;
+    double pcnt_motion;
+    double pcnt_second_ref;
+    double MVr;
+    double mvr_abs;
+    double MVc;
+    double mvc_abs;
+    double MVrv;
+    double MVcv;
+    double mv_in_out_count;
+    double duration;
+    double count;
+}
+FIRSTPASS_STATS;
+
+typedef struct
+{
+    int frames_so_far;
+    double frame_intra_error;
+    double frame_coded_error;
+    double frame_pcnt_inter;
+    double frame_pcnt_motion;
+    double frame_mvr;
+    double frame_mvr_abs;
+    double frame_mvc;
+    double frame_mvc_abs;
+
+} ONEPASS_FRAMESTATS;
+
+
+typedef enum
+{
+    THR_ZEROMV         = 0,
+    THR_DC             = 1,
+
+    THR_NEARESTMV      = 2,
+    THR_NEARMV         = 3,
+
+    THR_ZEROG          = 4,
+    THR_NEARESTG       = 5,
+
+    THR_ZEROA          = 6,
+    THR_NEARESTA       = 7,
+
+    THR_NEARG          = 8,
+    THR_NEARA          = 9,
+
+    THR_V_PRED         = 10,
+    THR_H_PRED         = 11,
+    THR_TM             = 12,
+
+    THR_NEWMV          = 13,
+    THR_NEWG           = 14,
+    THR_NEWA           = 15,
+
+    THR_SPLITMV        = 16,
+    THR_SPLITG         = 17,
+    THR_SPLITA         = 18,
+
+    THR_B_PRED         = 19,
+}
+THR_MODES;
+
+typedef enum
+{
+    DIAMOND = 0,
+    NSTEP = 1,
+    HEX = 2
+} SEARCH_METHODS;
+
+typedef struct
+{
+    int RD;
+    SEARCH_METHODS search_method;
+    int improved_quant;
+    int improved_dct;
+    int auto_filter;
+    int recode_loop;
+    int iterative_sub_pixel;
+    int half_pixel_search;
+    int quarter_pixel_search;
+    int thresh_mult[MAX_MODES];
+    int full_freq[2];
+    int min_fs_radius;
+    int max_fs_radius;
+    int max_step_search_steps;
+    int first_step;
+    int optimize_coefficients;
+
+} SPEED_FEATURES;
+
+typedef struct
+{
+    MACROBLOCK  mb;
+    int mb_row;
+    TOKENEXTRA *tp;
+    int segment_counts[MAX_MB_SEGMENTS];
+    int totalrate;
+    int current_mb_col;
+} MB_ROW_COMP;
+
+typedef struct
+{
+    TOKENEXTRA *start;
+    TOKENEXTRA *stop;
+} TOKENLIST;
+
+typedef struct
+{
+    int ithread;
+    void *ptr1;
+    void *ptr2;
+} ENCODETHREAD_DATA;
+typedef struct
+{
+    int ithread;
+    void *ptr1;
+} LPFTHREAD_DATA;
+
+typedef struct
+{
+    INT64  source_time_stamp;
+    INT64  source_end_time_stamp;
+
+    DECLARE_ALIGNED(16, YV12_BUFFER_CONFIG, source_buffer);
+    unsigned int source_frame_flags;
+} SOURCE_SAMPLE;
+
+typedef struct VP8_ENCODER_RTCD
+{
+    VP8_COMMON_RTCD            *common;
+    vp8_variance_rtcd_vtable_t  variance;
+    vp8_fdct_rtcd_vtable_t      fdct;
+    vp8_encodemb_rtcd_vtable_t  encodemb;
+    vp8_quantize_rtcd_vtable_t  quantize;
+    vp8_search_rtcd_vtable_t    search;
+} VP8_ENCODER_RTCD;
+
+typedef struct
+{
+
+    DECLARE_ALIGNED(16, short, Y1quant[QINDEX_RANGE][4][4]);
+    DECLARE_ALIGNED(16, short, Y1zbin[QINDEX_RANGE][4][4]);
+    DECLARE_ALIGNED(16, short, Y1round[QINDEX_RANGE][4][4]);
+
+    DECLARE_ALIGNED(16, short, Y2quant[QINDEX_RANGE][4][4]);
+    DECLARE_ALIGNED(16, short, Y2zbin[QINDEX_RANGE][4][4]);
+    DECLARE_ALIGNED(16, short, Y2round[QINDEX_RANGE][4][4]);
+
+    DECLARE_ALIGNED(16, short, UVquant[QINDEX_RANGE][4][4]);
+    DECLARE_ALIGNED(16, short, UVzbin[QINDEX_RANGE][4][4]);
+    DECLARE_ALIGNED(16, short, UVround[QINDEX_RANGE][4][4]);
+
+    DECLARE_ALIGNED(16, short, zrun_zbin_boost_y1[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, zrun_zbin_boost_y2[QINDEX_RANGE][16]);
+    DECLARE_ALIGNED(16, short, zrun_zbin_boost_uv[QINDEX_RANGE][16]);
+
+
+    MACROBLOCK mb;
+    VP8_COMMON common;
+    vp8_writer bc, bc2;
+    // bool_writer *bc2;
+
+    VP8_CONFIG oxcf;
+
+    YV12_BUFFER_CONFIG *Source;
+    YV12_BUFFER_CONFIG *un_scaled_source;
+    INT64 source_time_stamp;
+    INT64 source_end_time_stamp;
+    unsigned int source_frame_flags;
+    YV12_BUFFER_CONFIG scaled_source;
+
+    int source_buffer_count;
+    int source_encode_index;
+    int source_alt_ref_pending;
+    int source_alt_ref_active;
+
+    int last_alt_ref_sei;
+    int is_src_frame_alt_ref;
+
+    int gold_is_last; // golden frame same as last frame ( short circuit gold searches)
+    int alt_is_last;  // Alt reference frame same as last ( short circuit altref search)
+    int gold_is_alt;  // don't do both alt and gold search ( just do gold).
+
+    //int refresh_alt_ref_frame;
+    SOURCE_SAMPLE src_buffer[MAX_LAG_BUFFERS];
+
+    YV12_BUFFER_CONFIG last_frame_uf;
+
+    char *Dest;
+
+    TOKENEXTRA *tok;
+    unsigned int tok_count;
+
+
+    unsigned int frames_since_key;
+    unsigned int key_frame_frequency;
+    unsigned int next_key;
+
+    unsigned int mode_check_freq[MAX_MODES];
+    unsigned int mode_test_hit_counts[MAX_MODES];
+    unsigned int mode_chosen_counts[MAX_MODES];
+    unsigned int mbs_tested_so_far;
+
+    unsigned int check_freq[2];
+    unsigned int do_full[2];
+
+    int rd_thresh_mult[MAX_MODES];
+    int rd_baseline_thresh[MAX_MODES];
+    int rd_threshes[MAX_MODES];
+    int mvcostbase;
+    int mvcostmultiplier;
+    int subseqblockweight;
+    int errthresh;
+
+#ifdef INTRARDOPT
+    int RDMULT;
+    int RDDIV ;
+
+    TOKENEXTRA *rdtok;
+    int intra_rd_opt;
+    vp8_writer rdbc;
+    int intra_mode_costs[10];
+#endif
+
+
+    CODING_CONTEXT coding_context;
+
+    // Rate targetting variables
+    long long prediction_error;
+    long long last_prediction_error;
+    long long intra_error;
+    long long last_intra_error;
+    long long last_auto_filter_prediction_error;
+
+#if 0
+    // Experimental RD code
+    long long frame_distortion;
+    long long last_frame_distortion;
+#endif
+
+    int last_mb_distortion;
+
+    int frames_since_auto_filter;
+
+    int this_frame_target;
+    int projected_frame_size;
+    int last_q[2];                   // Separate values for Intra/Inter
+    int target_bits_per_mb;
+
+    double rate_correction_factor;
+    double key_frame_rate_correction_factor;
+    double gf_rate_correction_factor;
+    double est_max_qcorrection_factor;
+
+    int frames_till_gf_update_due;      // Count down till next GF
+    int current_gf_interval;          // GF interval chosen when we coded the last GF
+
+    int gf_overspend_bits;            // Total bits overspent becasue of GF boost (cumulative)
+
+    int gf_group_bits;                // Projected Bits available for a group of frames including 1 GF or ARF
+    int gf_bits;                     // Bits for the golden frame or ARF - 2 pass only
+    int mid_gf_extra_bits;             // A few extra bits for the frame half way between two gfs.
+
+    int kf_group_bits;                // Projected total bits available for a key frame group of frames
+    int kf_group_error_left;           // Error score of frames still to be coded in kf group
+    int kf_bits;                     // Bits for the key frame in a key frame group - 2 pass only
+
+    int non_gf_bitrate_adjustment;     // Used in the few frames following a GF to recover the extra bits spent in that GF
+    int initial_gf_use;               // percentage use of gf 2 frames after gf
+
+    int gf_group_error_left;           // Remaining error from uncoded frames in a gf group. Two pass use only
+
+    int kf_overspend_bits;            // Extra bits spent on key frames that need to be recovered on inter frames
+    int kf_bitrate_adjustment;        // Current number of bit s to try and recover on each inter frame.
+    int max_gf_interval;
+    int baseline_gf_interval;
+    int gf_decay_rate;
+
+    INT64 key_frame_count;
+    INT64 tot_key_frame_bits;
+    int prior_key_frame_size[KEY_FRAME_CONTEXT];
+    int prior_key_frame_distance[KEY_FRAME_CONTEXT];
+    int per_frame_bandwidth;          // Current section per frame bandwidth target
+    int av_per_frame_bandwidth;        // Average frame size target for clip
+    int min_frame_bandwidth;          // Minimum allocation that should be used for any frame
+    int last_key_frame_size;
+    int intra_frame_target;
+    int inter_frame_target;
+    double output_frame_rate;
+    long long last_time_stamp_seen;
+    long long first_time_stamp_ever;
+
+    int ni_av_qi;
+    int ni_tot_qi;
+    int ni_frames;
+    int avg_frame_qindex;
+
+    int zbin_over_quant;
+    int zbin_mode_boost;
+    int zbin_mode_boost_enabled;
+
+    INT64 total_byte_count;
+
+    int buffered_mode;
+
+    int buffer_level;
+    int bits_off_target;
+
+    int rolling_target_bits;
+    int rolling_actual_bits;
+
+    int long_rolling_target_bits;
+    int long_rolling_actual_bits;
+
+    long long total_actual_bits;
+    int total_target_vs_actual;        // debug stats
+
+    int worst_quality;
+    int active_worst_quality;
+    int best_quality;
+    int active_best_quality;
+
+    int drop_frames_allowed;          // Are we permitted to drop frames?
+    int drop_frame;                  // Drop this frame?
+    int drop_count;                  // How many frames have we dropped?
+    int max_drop_count;               // How many frames should we drop?
+    int max_consec_dropped_frames;     // Limit number of consecutive frames that can be dropped.
+
+
+    int ymode_count [VP8_YMODES];        /* intra MB type cts this frame */
+    int uv_mode_count[VP8_UV_MODES];       /* intra MB type cts this frame */
+
+    unsigned int MVcount [2] [MVvals];  /* (row,col) MV cts this frame */
+
+    unsigned int coef_counts [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens];  /* for this frame */
+    //DECLARE_ALIGNED(16, int, coef_counts_backup [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens]);   //not used any more
+    //save vp8_tree_probs_from_distribution result for each frame to avoid repeat calculation
+    vp8_prob frame_coef_probs [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1];
+    unsigned int frame_branch_ct [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1][2];
+
+    /* Second compressed data partition contains coefficient data. */
+
+    unsigned char *output_partition2;
+    size_t output_partition2size;
+
+    pre_proc_instance ppi;
+
+    int frames_to_key;
+    int gfu_boost;
+    int kf_boost;
+    int last_boost;
+    double total_error_left;
+    double total_intra_error_left;
+    double total_coded_error_left;
+    double start_tot_err_left;
+    double min_error;
+
+    double modified_total_error_left;
+    double avg_iiratio;
+
+    int target_bandwidth;
+    long long bits_left;
+    FIRSTPASS_STATS total_stats;
+    FIRSTPASS_STATS this_frame_stats;
+    FIRSTPASS_STATS *stats_in, *stats_in_end;
+    struct vpx_codec_pkt_list  *output_pkt_list;
+    int                          first_pass_done;
+    unsigned char *fp_motion_map;
+    FILE *fp_motion_mapfile;
+    int fpmm_pos;
+
+#if 0
+    // Experimental code for lagged and one pass
+    ONEPASS_FRAMESTATS one_pass_frame_stats[MAX_LAG_BUFFERS];
+    int one_pass_frame_index;
+#endif
+
+    int decimation_factor;
+    int decimation_count;
+
+    // for real time encoding
+    int avg_encode_time;              //microsecond
+    int avg_pick_mode_time;            //microsecond
+    int Speed;
+    unsigned int cpu_freq;           //Mhz
+    int compressor_speed;
+
+    int interquantizer;
+    int auto_gold;
+    int auto_adjust_gold_quantizer;
+    int goldquantizer;
+    int goldfreq;
+    int auto_adjust_key_quantizer;
+    int keyquantizer;
+    int auto_worst_q;
+    int filter_type;
+    int cpu_used;
+    int chroma_boost;
+    int horiz_scale;
+    int vert_scale;
+    int pass;
+
+
+    int prob_intra_coded;
+    int prob_last_coded;
+    int prob_gf_coded;
+    int prob_skip_false;
+    int last_skip_false_probs[3];
+    int last_skip_probs_q[3];
+    int recent_ref_frame_usage[MAX_REF_FRAMES];
+
+    int count_mb_ref_frame_usage[MAX_REF_FRAMES];
+    int this_frame_percent_intra;
+    int last_frame_percent_intra;
+
+    int last_key_frame_q;
+    int last_kffilt_lvl;
+
+    int ref_frame_flags;
+
+    int exp[512];
+
+    SPEED_FEATURES sf;
+    int error_bins[1024];
+
+    int inter_lvl;
+    int intra_lvl;
+    int motion_lvl;
+    int motion_speed;
+    int motion_var;
+    int next_iiratio;
+    int this_iiratio;
+    int this_frame_modified_error;
+
+    double norm_intra_err_per_mb;
+    double norm_inter_err_per_mb;
+    double norm_iidiff_per_mb;
+
+    int last_best_mode_index;          // Record of mode index chosen for previous macro block.
+    int last_auto_filt_val;
+    int last_auto_filt_q;
+
+    // Data used for real time conferencing mode to help determine if it would be good to update the gf
+    int inter_zz_count;
+    int gf_bad_count;
+    int gf_update_recommended;
+    int skip_true_count;
+    int skip_false_count;
+
+    int alt_qcount;
+
+    int ready_for_new_frame;
+
+    unsigned char *segmentation_map;
+    signed char segment_feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS];            // Segment data (can be deltas or absolute values)
+    int  segment_encode_breakout[MAX_MB_SEGMENTS];                    // segment threashold for encode breakout
+
+    unsigned char *active_map;
+    unsigned int active_map_enabled;
+    // Video conferencing cyclic refresh mode flags etc
+    // This is a mode designed to clean up the background over time in live encoding scenarious. It uses segmentation
+    int cyclic_refresh_mode_enabled;
+    int cyclic_refresh_mode_max_mbs_perframe;
+    int cyclic_refresh_mode_index;
+    int cyclic_refresh_q;
+    signed char *cyclic_refresh_map;
+
+    // multithread data
+    int current_mb_col_main;
+    int processor_core_count;
+    int b_multi_threaded;
+    int encoding_thread_count;
+
+#if CONFIG_MULTITHREAD
+    pthread_t *h_encoding_thread;
+#endif
+    MB_ROW_COMP *mb_row_ei;
+    ENCODETHREAD_DATA *en_thread_data;
+
+#if CONFIG_MULTITHREAD
+    //events
+    sem_t *h_event_mbrencoding;
+    sem_t h_event_main;
+#endif
+
+    TOKENLIST *tplist;
+    // end of multithread data
+
+
+    fractional_mv_step_fp *find_fractional_mv_step;
+    vp8_full_search_fn_t full_search_sad;
+    vp8_diamond_search_fn_t diamond_search_sad;
+    vp8_variance_fn_ptr_t fn_ptr;
+    unsigned int time_receive_data;
+    unsigned int time_compress_data;
+    unsigned int time_pick_lpf;
+    unsigned int time_encode_mb_row;
+
+    unsigned int tempdata1;
+    unsigned int tempdata2;
+
+    int base_skip_false_prob[128];
+    unsigned int section_is_low_motion;
+    unsigned int section_benefits_from_aggresive_q;
+    unsigned int section_is_fast_motion;
+    unsigned int section_intra_rating;
+
+    double section_max_qfactor;
+
+
+#if CONFIG_RUNTIME_CPU_DETECT
+    VP8_ENCODER_RTCD            rtcd;
+#endif
+#if VP8_TEMPORAL_ALT_REF
+    SOURCE_SAMPLE alt_ref_buffer;
+    unsigned char *frames[MAX_LAG_BUFFERS];
+    int fixed_divide[255];
+#endif
+
+#if CONFIG_PSNR
+    int    count;
+    double total_y;
+    double total_u;
+    double total_v;
+    double total ;
+    double total_sq_error;
+    double totalp_y;
+    double totalp_u;
+    double totalp_v;
+    double totalp;
+    double total_sq_error2;
+    int    bytes;
+    double summed_quality;
+    double summed_weights;
+    unsigned int tot_recode_hits;
+
+
+    double total_ssimg_y;
+    double total_ssimg_u;
+    double total_ssimg_v;
+    double total_ssimg_all;
+
+    int b_calculate_ssimg;
+#endif
+    int b_calculate_psnr;
+} VP8_COMP;
+
+void control_data_rate(VP8_COMP *cpi);
+
+void vp8_encode_frame(VP8_COMP *cpi);
+
+void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size);
+
+int rd_cost_intra_mb(MACROBLOCKD *x);
+
+void vp8_tokenize_mb(VP8_COMP *, MACROBLOCKD *, TOKENEXTRA **);
+
+void vp8_set_speed_features(VP8_COMP *cpi);
+
+#if CONFIG_DEBUG
+#define CHECK_MEM_ERROR(lval,expr) do {\
+        lval = (expr); \
+        if(!lval) \
+            vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,\
+                               "Failed to allocate "#lval" at %s:%d", \
+                               __FILE__,__LINE__);\
+    } while(0)
+#else
+#define CHECK_MEM_ERROR(lval,expr) do {\
+        lval = (expr); \
+        if(!lval) \
+            vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,\
+                               "Failed to allocate "#lval);\
+    } while(0)
+#endif
+#endif
diff --git a/vp8/encoder/parms.cpp b/vp8/encoder/parms.cpp
new file mode 100644
index 0000000..66fdafb
--- /dev/null
+++ b/vp8/encoder/parms.cpp
@@ -0,0 +1,106 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#if 0
+
+#include <map>
+#include <string>
+#include <fstream>
+extern "C"
+{
+    #include "onyx.h"
+}
+
+
+using namespace std;
+
+typedef map<string,int> Parms;
+
+#define ALLPARMS(O,DOTHIS) \
+    DOTHIS(O,  interquantizer             )\
+    DOTHIS(O,  auto_gold                   )\
+    DOTHIS(O,  auto_adjust_gold_quantizer    )\
+    DOTHIS(O,  goldquantizer              )\
+    DOTHIS(O,  goldfreq                   )\
+    DOTHIS(O,  auto_key                    )\
+    DOTHIS(O,  auto_adjust_key_quantizer     )\
+    DOTHIS(O,  keyquantizer               )\
+    DOTHIS(O,  keyfreq                    )\
+    DOTHIS(O,  pass                       )\
+    DOTHIS(O,  fixed_q                     )\
+    DOTHIS(O,  target_bandwidth            )\
+    DOTHIS(O,  auto_worst_q                 )\
+    DOTHIS(O,  worst_quality               )\
+    DOTHIS(O,  best_allowed_q               )\
+    DOTHIS(O,  end_usage                   )\
+    DOTHIS(O,  starting_buffer_level        )\
+    DOTHIS(O,  optimal_buffer_level         )\
+    DOTHIS(O,  maximum_buffer_size          )\
+    DOTHIS(O,  under_shoot_pct              )\
+    DOTHIS(O,  allow_df                    )\
+    DOTHIS(O,  drop_frames_water_mark        )\
+    DOTHIS(O,  max_allowed_datarate         )\
+    DOTHIS(O,  two_pass_vbrbias             )\
+    DOTHIS(O,  two_pass_vbrmin_section       )\
+    DOTHIS(O,  two_pass_vbrmax_section       )\
+    DOTHIS(O,  filter_type                 )\
+    DOTHIS(O,  compressor_speed            )\
+    DOTHIS(O,  mbpitch_feature             )\
+    DOTHIS(O,  allow_spatial_resampling     )\
+    DOTHIS(O,  resample_down_water_mark      )\
+    DOTHIS(O,  resample_up_water_mark        )\
+    DOTHIS(O,  noise_sensitivity           )\
+    DOTHIS(O,  horiz_scale                 )\
+    DOTHIS(O,  vert_scale                  )
+
+
+#define GET(O,V) O->V = x[#V];
+#define PUT(O,V) x[#V] = O->V;
+
+
+extern "C" void get_parms(VP8_CONFIG *ocf,char *filename)
+{
+
+    Parms x;
+    int value;
+    string variable;
+    string equal;
+
+    ifstream config_file(filename);
+
+    ALLPARMS(ocf, PUT);
+
+    // store all the parms in a map (really simple parsing)
+    while(!config_file.eof() && config_file.is_open())
+    {
+        config_file >> variable;
+        config_file >> equal;
+
+        if(equal != "=")
+            continue;
+
+        config_file >> value;
+
+        x[variable] = value;
+    }
+
+    ALLPARMS(ocf, GET);
+
+}
+
+#define PRINT(O,V) debug_file<<#V <<" = " << O->V <<"\n";
+extern "C" void print_parms(VP8_CONFIG *ocf,char *filename)
+{
+    ofstream debug_file(filename,ios_base::app);
+    ALLPARMS(ocf, PRINT);
+    debug_file << "=============================================="<<"\n";
+}
+
+#endif
diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c
new file mode 100644
index 0000000..d61e2ce
--- /dev/null
+++ b/vp8/encoder/pickinter.c
@@ -0,0 +1,923 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <limits.h>
+#include "vpx_ports/config.h"
+#include "onyx_int.h"
+#include "modecosts.h"
+#include "encodeintra.h"
+#include "entropymode.h"
+#include "pickinter.h"
+#include "findnearmv.h"
+#include "encodemb.h"
+#include "reconinter.h"
+#include "reconintra.h"
+#include "reconintra4x4.h"
+#include "g_common.h"
+#include "variance.h"
+#include "mcomp.h"
+
+#include "vpx_mem/vpx_mem.h"
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define IF_RTCD(x) (x)
+#else
+#define IF_RTCD(x)  NULL
+#endif
+
+extern int VP8_UVSSE(MACROBLOCK *x, const vp8_variance_rtcd_vtable_t *rtcd);
+
+#ifdef SPEEDSTATS
+extern unsigned int cnt_pm;
+#endif
+
+extern const MV_REFERENCE_FRAME vp8_ref_frame_order[MAX_MODES];
+extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
+
+
+extern unsigned int (*vp8_get16x16pred_error)(unsigned char *src_ptr, int src_stride, unsigned char *ref_ptr, int ref_stride);
+extern unsigned int (*vp8_get4x4sse_cs)(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride);
+extern int vp8_rd_pick_best_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x, MV *best_ref_mv, int best_rd, int *, int *, int *, int, int *mvcost[2], int, int fullpixel);
+extern int vp8_cost_mv_ref(MB_PREDICTION_MODE m, const int near_mv_ref_ct[4]);
+extern void vp8_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, MV *mv);
+
+
+int vp8_skip_fractional_mv_step(MACROBLOCK *mb, BLOCK *b, BLOCKD *d, MV *bestmv, MV *ref_mv, int error_per_bit, vp8_subpixvariance_fn_t svf, vp8_variance_fn_t vf, int *mvcost[2])
+{
+    (void) b;
+    (void) d;
+    (void) ref_mv;
+    (void) error_per_bit;
+    (void) svf;
+    (void) vf;
+    (void) mvcost;
+    bestmv->row <<= 3;
+    bestmv->col <<= 3;
+    return 0;
+}
+
+
+static int get_inter_mbpred_error(MACROBLOCK *mb, vp8_subpixvariance_fn_t svf, vp8_variance_fn_t vf, unsigned int *sse)
+{
+
+    BLOCK *b = &mb->block[0];
+    BLOCKD *d = &mb->e_mbd.block[0];
+    unsigned char *what = (*(b->base_src) + b->src);
+    int what_stride = b->src_stride;
+    unsigned char *in_what = *(d->base_pre) + d->pre ;
+    int in_what_stride = d->pre_stride;
+    int xoffset = d->bmi.mv.as_mv.col & 7;
+    int yoffset = d->bmi.mv.as_mv.row & 7;
+
+    in_what += (d->bmi.mv.as_mv.row >> 3) * d->pre_stride + (d->bmi.mv.as_mv.col >> 3);
+
+    if (xoffset | yoffset)
+    {
+        return svf(in_what, in_what_stride, xoffset, yoffset, what, what_stride, sse);
+    }
+    else
+    {
+        return vf(what, what_stride, in_what, in_what_stride, sse);
+    }
+
+}
+
+unsigned int vp8_get16x16pred_error_c
+(
+    unsigned char *src_ptr,
+    int src_stride,
+    unsigned char *ref_ptr,
+    int ref_stride,
+    int max_sad
+)
+{
+    unsigned pred_error = 0;
+    int i, j;
+    int sum = 0;
+
+    for (i = 0; i < 16; i++)
+    {
+        int diff;
+
+        for (j = 0; j < 16; j++)
+        {
+            diff = src_ptr[j] - ref_ptr[j];
+            sum += diff;
+            pred_error += diff * diff;
+        }
+
+        src_ptr += src_stride;
+        ref_ptr += ref_stride;
+    }
+
+    pred_error -= sum * sum / 256;
+    return pred_error;
+}
+
+
+unsigned int vp8_get4x4sse_cs_c
+(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    int max_sad
+)
+{
+    int distortion = 0;
+    int r, c;
+
+    for (r = 0; r < 4; r++)
+    {
+        for (c = 0; c < 4; c++)
+        {
+            int diff = src_ptr[c] - ref_ptr[c];
+            distortion += diff * diff;
+        }
+
+        src_ptr += source_stride;
+        ref_ptr += recon_stride;
+    }
+
+    return distortion;
+}
+
+static int get_prediction_error(BLOCK *be, BLOCKD *b, const vp8_variance_rtcd_vtable_t *rtcd)
+{
+    unsigned char *sptr;
+    unsigned char *dptr;
+    sptr = (*(be->base_src) + be->src);
+    dptr = b->predictor;
+
+    return VARIANCE_INVOKE(rtcd, get4x4sse_cs)(sptr, be->src_stride, dptr, 16, 0x7fffffff);
+
+}
+
+static int pick_intra4x4block(
+    const VP8_ENCODER_RTCD *rtcd,
+    MACROBLOCK *x,
+    BLOCK *be,
+    BLOCKD *b,
+    B_PREDICTION_MODE *best_mode,
+    B_PREDICTION_MODE above,
+    B_PREDICTION_MODE left,
+    ENTROPY_CONTEXT *a,
+    ENTROPY_CONTEXT *l,
+
+    int *bestrate,
+    int *bestdistortion)
+{
+    B_PREDICTION_MODE mode;
+    int best_rd = INT_MAX;       // 1<<30
+    int rate;
+    int distortion;
+    unsigned int *mode_costs;
+    (void) l;
+    (void) a;
+
+    if (x->e_mbd.frame_type == KEY_FRAME)
+    {
+        mode_costs = x->bmode_costs[above][left];
+    }
+    else
+    {
+        mode_costs = x->inter_bmode_costs;
+    }
+
+    for (mode = B_DC_PRED; mode <= B_HE_PRED /*B_HU_PRED*/; mode++)
+    {
+        int this_rd;
+
+        rate = mode_costs[mode];
+        vp8_predict_intra4x4(b, mode, b->predictor);
+        distortion = get_prediction_error(be, b, &rtcd->variance);
+        this_rd = RD_ESTIMATE(x->rdmult, x->rddiv, rate, distortion);
+
+        if (this_rd < best_rd)
+        {
+            *bestrate = rate;
+            *bestdistortion = distortion;
+            best_rd = this_rd;
+            *best_mode = mode;
+        }
+    }
+
+    b->bmi.mode = (B_PREDICTION_MODE)(*best_mode);
+    vp8_encode_intra4x4block(rtcd, x, be, b, b->bmi.mode);
+    return best_rd;
+}
+
+
+int vp8_pick_intra4x4mby_modes(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *mb, int *Rate, int *best_dist)
+{
+    MACROBLOCKD *const xd = &mb->e_mbd;
+    int i;
+    TEMP_CONTEXT t;
+    int cost = mb->mbmode_cost [xd->frame_type] [B_PRED];
+    int error = RD_ESTIMATE(mb->rdmult, mb->rddiv, cost, 0); // Rd estimate for the cost of the block prediction mode
+    int distortion = 0;
+
+    vp8_intra_prediction_down_copy(xd);
+    vp8_setup_temp_context(&t, xd->above_context[Y1CONTEXT], xd->left_context[Y1CONTEXT], 4);
+
+    for (i = 0; i < 16; i++)
+    {
+        MODE_INFO *const mic = xd->mode_info_context;
+        const int mis = xd->mode_info_stride;
+        const B_PREDICTION_MODE A = vp8_above_bmi(mic, i, mis)->mode;
+        const B_PREDICTION_MODE L = vp8_left_bmi(mic, i)->mode;
+        B_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode);
+        int UNINITIALIZED_IS_SAFE(r), UNINITIALIZED_IS_SAFE(d);
+
+        error += pick_intra4x4block(rtcd,
+                                    mb, mb->block + i, xd->block + i, &best_mode, A, L,
+                                    t.a + vp8_block2above[i],
+                                    t.l + vp8_block2left[i], &r, &d);
+
+        cost += r;
+        distortion += d;
+
+        mic->bmi[i].mode = xd->block[i].bmi.mode = best_mode;
+
+        // Break out case where we have already exceeded best so far value that was bassed in
+        if (distortion > *best_dist)
+            break;
+    }
+
+    for (i = 0; i < 16; i++)
+        xd->block[i].bmi.mv.as_int = 0;
+
+    *Rate = cost;
+
+    if (i == 16)
+        *best_dist = distortion;
+    else
+        *best_dist = INT_MAX;
+
+
+    return error;
+}
+
+int vp8_pick_intra_mbuv_mode(MACROBLOCK *mb)
+{
+
+    MACROBLOCKD *x = &mb->e_mbd;
+    unsigned char *uabove_row = x->dst.u_buffer - x->dst.uv_stride;
+    unsigned char *vabove_row = x->dst.v_buffer - x->dst.uv_stride;
+    unsigned char *usrc_ptr = (mb->block[16].src + *mb->block[16].base_src);
+    unsigned char *vsrc_ptr = (mb->block[20].src + *mb->block[20].base_src);
+    int uvsrc_stride = mb->block[16].src_stride;
+    unsigned char uleft_col[8];
+    unsigned char vleft_col[8];
+    unsigned char utop_left = uabove_row[-1];
+    unsigned char vtop_left = vabove_row[-1];
+    int i, j;
+    int expected_udc;
+    int expected_vdc;
+    int shift;
+    int Uaverage = 0;
+    int Vaverage = 0;
+    int diff;
+    int pred_error[4] = {0, 0, 0, 0}, best_error = INT_MAX;
+    MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode);
+
+
+    for (i = 0; i < 8; i++)
+    {
+        uleft_col[i] = x->dst.u_buffer [i* x->dst.uv_stride -1];
+        vleft_col[i] = x->dst.v_buffer [i* x->dst.uv_stride -1];
+    }
+
+    if (!x->up_available && !x->left_available)
+    {
+        expected_udc = 128;
+        expected_vdc = 128;
+    }
+    else
+    {
+        shift = 2;
+
+        if (x->up_available)
+        {
+
+            for (i = 0; i < 8; i++)
+            {
+                Uaverage += uabove_row[i];
+                Vaverage += vabove_row[i];
+            }
+
+            shift ++;
+
+        }
+
+        if (x->left_available)
+        {
+            for (i = 0; i < 8; i++)
+            {
+                Uaverage += uleft_col[i];
+                Vaverage += vleft_col[i];
+            }
+
+            shift ++;
+
+        }
+
+        expected_udc = (Uaverage + (1 << (shift - 1))) >> shift;
+        expected_vdc = (Vaverage + (1 << (shift - 1))) >> shift;
+    }
+
+
+    for (i = 0; i < 8; i++)
+    {
+        for (j = 0; j < 8; j++)
+        {
+
+            int predu = uleft_col[i] + uabove_row[j] - utop_left;
+            int predv = vleft_col[i] + vabove_row[j] - vtop_left;
+            int u_p, v_p;
+
+            u_p = usrc_ptr[j];
+            v_p = vsrc_ptr[j];
+
+            if (predu < 0)
+                predu = 0;
+
+            if (predu > 255)
+                predu = 255;
+
+            if (predv < 0)
+                predv = 0;
+
+            if (predv > 255)
+                predv = 255;
+
+
+            diff = u_p - expected_udc;
+            pred_error[DC_PRED] += diff * diff;
+            diff = v_p - expected_vdc;
+            pred_error[DC_PRED] += diff * diff;
+
+
+            diff = u_p - uabove_row[j];
+            pred_error[V_PRED] += diff * diff;
+            diff = v_p - vabove_row[j];
+            pred_error[V_PRED] += diff * diff;
+
+
+            diff = u_p - uleft_col[i];
+            pred_error[H_PRED] += diff * diff;
+            diff = v_p - vleft_col[i];
+            pred_error[H_PRED] += diff * diff;
+
+
+            diff = u_p - predu;
+            pred_error[TM_PRED] += diff * diff;
+            diff = v_p - predv;
+            pred_error[TM_PRED] += diff * diff;
+
+
+        }
+
+        usrc_ptr += uvsrc_stride;
+        vsrc_ptr += uvsrc_stride;
+
+        if (i == 3)
+        {
+            usrc_ptr = (mb->block[18].src + *mb->block[18].base_src);
+            vsrc_ptr = (mb->block[22].src + *mb->block[22].base_src);
+        }
+
+
+
+    }
+
+
+    for (i = DC_PRED; i <= TM_PRED; i++)
+    {
+        if (best_error > pred_error[i])
+        {
+            best_error = pred_error[i];
+            best_mode = (MB_PREDICTION_MODE)i;
+        }
+    }
+
+
+    mb->e_mbd.mbmi.uv_mode = best_mode;
+    return best_error;
+
+}
+
+
+int vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int *returnintra)
+{
+    BLOCK *b = &x->block[0];
+    BLOCKD *d = &x->e_mbd.block[0];
+    MACROBLOCKD *xd = &x->e_mbd;
+    B_MODE_INFO best_bmodes[16];
+    MB_MODE_INFO best_mbmode;
+    MV best_ref_mv1;
+    MV mode_mv[MB_MODE_COUNT];
+    MB_PREDICTION_MODE this_mode;
+    int num00;
+    int i;
+    int mdcounts[4];
+    int best_rd = INT_MAX; // 1 << 30;
+    int best_intra_rd = INT_MAX;
+    int mode_index;
+    int ref_frame_cost[MAX_REF_FRAMES];
+    int rate;
+    int rate2;
+    int distortion2;
+    int bestsme;
+    //int all_rds[MAX_MODES];         // Experimental debug code.
+    int best_mode_index = 0;
+    int sse = INT_MAX;
+
+    MV nearest_mv[4];
+    MV near_mv[4];
+    MV best_ref_mv[4];
+    int MDCounts[4][4];
+    unsigned char *y_buffer[4];
+    unsigned char *u_buffer[4];
+    unsigned char *v_buffer[4];
+
+    int skip_mode[4] = {0, 0, 0, 0};
+
+    vpx_memset(mode_mv, 0, sizeof(mode_mv));
+    vpx_memset(nearest_mv, 0, sizeof(nearest_mv));
+    vpx_memset(near_mv, 0, sizeof(near_mv));
+
+
+    // set up all the refframe dependent pointers.
+    if (cpi->ref_frame_flags & VP8_LAST_FLAG)
+    {
+        vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context, &nearest_mv[LAST_FRAME], &near_mv[LAST_FRAME],
+                          &best_ref_mv[LAST_FRAME], MDCounts[LAST_FRAME], LAST_FRAME, cpi->common.ref_frame_sign_bias);
+
+        y_buffer[LAST_FRAME] = cpi->common.last_frame.y_buffer + recon_yoffset;
+        u_buffer[LAST_FRAME] = cpi->common.last_frame.u_buffer + recon_uvoffset;
+        v_buffer[LAST_FRAME] = cpi->common.last_frame.v_buffer + recon_uvoffset;
+    }
+    else
+        skip_mode[LAST_FRAME] = 1;
+
+    if (cpi->ref_frame_flags & VP8_GOLD_FLAG)
+    {
+        vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context, &nearest_mv[GOLDEN_FRAME], &near_mv[GOLDEN_FRAME],
+                          &best_ref_mv[GOLDEN_FRAME], MDCounts[GOLDEN_FRAME], GOLDEN_FRAME, cpi->common.ref_frame_sign_bias);
+
+        y_buffer[GOLDEN_FRAME] = cpi->common.golden_frame.y_buffer + recon_yoffset;
+        u_buffer[GOLDEN_FRAME] = cpi->common.golden_frame.u_buffer + recon_uvoffset;
+        v_buffer[GOLDEN_FRAME] = cpi->common.golden_frame.v_buffer + recon_uvoffset;
+    }
+    else
+        skip_mode[GOLDEN_FRAME] = 1;
+
+    if (cpi->ref_frame_flags & VP8_ALT_FLAG && cpi->source_alt_ref_active)
+    {
+        vp8_find_near_mvs(&x->e_mbd, x->e_mbd.mode_info_context, &nearest_mv[ALTREF_FRAME], &near_mv[ALTREF_FRAME],
+                          &best_ref_mv[ALTREF_FRAME], MDCounts[ALTREF_FRAME], ALTREF_FRAME, cpi->common.ref_frame_sign_bias);
+
+        y_buffer[ALTREF_FRAME] = cpi->common.alt_ref_frame.y_buffer + recon_yoffset;
+        u_buffer[ALTREF_FRAME] = cpi->common.alt_ref_frame.u_buffer + recon_uvoffset;
+        v_buffer[ALTREF_FRAME] = cpi->common.alt_ref_frame.v_buffer + recon_uvoffset;
+    }
+    else
+        skip_mode[ALTREF_FRAME] = 1;
+
+    cpi->mbs_tested_so_far++;          // Count of the number of MBs tested so far this frame
+
+    *returnintra = best_intra_rd;
+    x->skip = 0;
+
+    ref_frame_cost[INTRA_FRAME]   = vp8_cost_zero(cpi->prob_intra_coded);
+
+    // Special case treatment when GF and ARF are not sensible options for reference
+    if (cpi->ref_frame_flags == VP8_LAST_FLAG)
+    {
+        ref_frame_cost[LAST_FRAME]    = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_zero(255);
+        ref_frame_cost[GOLDEN_FRAME]  = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_one(255)
+                                        + vp8_cost_zero(128);
+        ref_frame_cost[ALTREF_FRAME]  = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_one(255)
+                                        + vp8_cost_one(128);
+    }
+    else
+    {
+        ref_frame_cost[LAST_FRAME]    = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_zero(cpi->prob_last_coded);
+        ref_frame_cost[GOLDEN_FRAME]  = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_one(cpi->prob_last_coded)
+                                        + vp8_cost_zero(cpi->prob_gf_coded);
+        ref_frame_cost[ALTREF_FRAME]  = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_one(cpi->prob_last_coded)
+                                        + vp8_cost_one(cpi->prob_gf_coded);
+    }
+
+
+
+    best_rd = INT_MAX;
+
+    x->e_mbd.mbmi.ref_frame = INTRA_FRAME;
+
+    // if we encode a new mv this is important
+    // find the best new motion vector
+    for (mode_index = 0; mode_index < MAX_MODES; mode_index++)
+    {
+        int frame_cost;
+        int this_rd = INT_MAX;
+
+        if (best_rd <= cpi->rd_threshes[mode_index])
+            continue;
+
+        x->e_mbd.mbmi.ref_frame = vp8_ref_frame_order[mode_index];
+
+        if (skip_mode[x->e_mbd.mbmi.ref_frame])
+            continue;
+
+        // Check to see if the testing frequency for this mode is at its max
+        // If so then prevent it from being tested and increase the threshold for its testing
+        if (cpi->mode_test_hit_counts[mode_index] && (cpi->mode_check_freq[mode_index] > 1))
+        {
+            //if ( (cpi->mbs_tested_so_far / cpi->mode_test_hit_counts[mode_index]) <= cpi->mode_check_freq[mode_index] )
+            if (cpi->mbs_tested_so_far <= (cpi->mode_check_freq[mode_index] * cpi->mode_test_hit_counts[mode_index]))
+            {
+                // Increase the threshold for coding this mode to make it less likely to be chosen
+                cpi->rd_thresh_mult[mode_index] += 4;
+
+                if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
+                    cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
+
+                cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+
+                continue;
+            }
+        }
+
+        // We have now reached the point where we are going to test the current mode so increment the counter for the number of times it has been tested
+        cpi->mode_test_hit_counts[mode_index] ++;
+
+        rate2 = 0;
+        distortion2 = 0;
+
+        this_mode = vp8_mode_order[mode_index];
+        
+        // Experimental debug code.
+        //all_rds[mode_index] = -1;
+
+        x->e_mbd.mbmi.mode = this_mode;
+        x->e_mbd.mbmi.uv_mode = DC_PRED;
+
+        // Work out the cost assosciated with selecting the reference frame
+        frame_cost = ref_frame_cost[x->e_mbd.mbmi.ref_frame];
+        rate2 += frame_cost;
+
+        // everything but intra
+        if (x->e_mbd.mbmi.ref_frame)
+        {
+            x->e_mbd.pre.y_buffer = y_buffer[x->e_mbd.mbmi.ref_frame];
+            x->e_mbd.pre.u_buffer = u_buffer[x->e_mbd.mbmi.ref_frame];
+            x->e_mbd.pre.v_buffer = v_buffer[x->e_mbd.mbmi.ref_frame];
+            mode_mv[NEARESTMV] = nearest_mv[x->e_mbd.mbmi.ref_frame];
+            mode_mv[NEARMV] = near_mv[x->e_mbd.mbmi.ref_frame];
+            best_ref_mv1 = best_ref_mv[x->e_mbd.mbmi.ref_frame];
+            memcpy(mdcounts, MDCounts[x->e_mbd.mbmi.ref_frame], sizeof(mdcounts));
+        }
+
+        //Only consider ZEROMV/ALTREF_FRAME for alt ref frame.
+        if (cpi->is_src_frame_alt_ref)
+        {
+            if (this_mode != ZEROMV || x->e_mbd.mbmi.ref_frame != ALTREF_FRAME)
+                continue;
+        }
+
+        switch (this_mode)
+        {
+        case B_PRED:
+            distortion2 = *returndistortion;                    // Best so far passed in as breakout value to vp8_pick_intra4x4mby_modes
+            vp8_pick_intra4x4mby_modes(IF_RTCD(&cpi->rtcd), x, &rate, &distortion2);
+            rate2 += rate;
+            distortion2 = VARIANCE_INVOKE(&cpi->rtcd.variance, get16x16prederror)(x->src.y_buffer, x->src.y_stride, x->e_mbd.predictor, 16, 0x7fffffff);
+
+            if (distortion2 == INT_MAX)
+            {
+                this_rd = INT_MAX;
+            }
+            else
+            {
+                this_rd = RD_ESTIMATE(x->rdmult, x->rddiv, rate2, distortion2);
+
+                if (this_rd < best_intra_rd)
+                {
+                    best_intra_rd = this_rd;
+                    *returnintra = best_intra_rd ;
+                }
+            }
+
+            break;
+
+        case SPLITMV:
+
+            // Split MV modes currently not supported when RD is nopt enabled.
+            break;
+
+        case DC_PRED:
+        case V_PRED:
+        case H_PRED:
+        case TM_PRED:
+            vp8_build_intra_predictors_mby_ptr(&x->e_mbd);
+            distortion2 = VARIANCE_INVOKE(&cpi->rtcd.variance, get16x16prederror)(x->src.y_buffer, x->src.y_stride, x->e_mbd.predictor, 16, 0x7fffffff);
+            rate2 += x->mbmode_cost[x->e_mbd.frame_type][x->e_mbd.mbmi.mode];
+            this_rd = RD_ESTIMATE(x->rdmult, x->rddiv, rate2, distortion2);
+
+            if (this_rd < best_intra_rd)
+            {
+                best_intra_rd = this_rd;
+                *returnintra = best_intra_rd ;
+            }
+
+            break;
+
+        case NEWMV:
+        {
+            int thissme;
+            int step_param;
+            int further_steps;
+            int n = 0;
+            int sadpb = x->sadperbit16;
+
+            // Further step/diamond searches as necessary
+            if (cpi->Speed < 8)
+            {
+                step_param = cpi->sf.first_step + ((cpi->Speed > 5) ? 1 : 0);
+                further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
+            }
+            else
+            {
+                step_param = cpi->sf.first_step + 2;
+                further_steps = 0;
+            }
+
+#if 0
+
+            // Initial step Search
+            bestsme = vp8_diamond_search_sad(x, b, d, &best_ref_mv1, &d->bmi.mv.as_mv, step_param, x->errorperbit, &num00, &cpi->fn_ptr, cpi->mb.mvsadcost, cpi->mb.mvcost);
+            mode_mv[NEWMV].row = d->bmi.mv.as_mv.row;
+            mode_mv[NEWMV].col = d->bmi.mv.as_mv.col;
+
+            // Further step searches
+            while (n < further_steps)
+            {
+                n++;
+
+                if (num00)
+                    num00--;
+                else
+                {
+                    thissme = vp8_diamond_search_sad(x, b, d, &best_ref_mv1, &d->bmi.mv.as_mv, step_param + n, x->errorperbit, &num00, &cpi->fn_ptr, cpi->mb.mvsadcost, x->mvcost);
+
+                    if (thissme < bestsme)
+                    {
+                        bestsme = thissme;
+                        mode_mv[NEWMV].row = d->bmi.mv.as_mv.row;
+                        mode_mv[NEWMV].col = d->bmi.mv.as_mv.col;
+                    }
+                    else
+                    {
+                        d->bmi.mv.as_mv.row = mode_mv[NEWMV].row;
+                        d->bmi.mv.as_mv.col = mode_mv[NEWMV].col;
+                    }
+                }
+            }
+
+#else
+
+            if (cpi->sf.search_method == HEX)
+            {
+                bestsme = vp8_hex_search(x, b, d, &best_ref_mv1, &d->bmi.mv.as_mv, step_param, sadpb/*x->errorperbit*/, &num00, cpi->fn_ptr.vf, cpi->fn_ptr.sdf, x->mvsadcost, x->mvcost);
+                mode_mv[NEWMV].row = d->bmi.mv.as_mv.row;
+                mode_mv[NEWMV].col = d->bmi.mv.as_mv.col;
+            }
+            else
+            {
+                bestsme = cpi->diamond_search_sad(x, b, d, &best_ref_mv1, &d->bmi.mv.as_mv, step_param, sadpb / 2/*x->errorperbit*/, &num00, &cpi->fn_ptr, x->mvsadcost, x->mvcost); //sadpb < 9
+                mode_mv[NEWMV].row = d->bmi.mv.as_mv.row;
+                mode_mv[NEWMV].col = d->bmi.mv.as_mv.col;
+
+                // Further step/diamond searches as necessary
+                n = 0;
+                //further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
+
+                n = num00;
+                num00 = 0;
+
+                while (n < further_steps)
+                {
+                    n++;
+
+                    if (num00)
+                        num00--;
+                    else
+                    {
+                        thissme = cpi->diamond_search_sad(x, b, d, &best_ref_mv1, &d->bmi.mv.as_mv, step_param + n, sadpb / 4/*x->errorperbit*/, &num00, &cpi->fn_ptr, x->mvsadcost, x->mvcost); //sadpb = 9
+
+                        if (thissme < bestsme)
+                        {
+                            bestsme = thissme;
+                            mode_mv[NEWMV].row = d->bmi.mv.as_mv.row;
+                            mode_mv[NEWMV].col = d->bmi.mv.as_mv.col;
+                        }
+                        else
+                        {
+                            d->bmi.mv.as_mv.row = mode_mv[NEWMV].row;
+                            d->bmi.mv.as_mv.col = mode_mv[NEWMV].col;
+                        }
+                    }
+                }
+            }
+
+#endif
+        }
+
+        if (bestsme < INT_MAX)
+            cpi->find_fractional_mv_step(x, b, d, &d->bmi.mv.as_mv, &best_ref_mv1, x->errorperbit, cpi->fn_ptr.svf, cpi->fn_ptr.vf, cpi->mb.mvcost);
+
+        mode_mv[NEWMV].row = d->bmi.mv.as_mv.row;
+        mode_mv[NEWMV].col = d->bmi.mv.as_mv.col;
+
+        // mv cost;
+        rate2 += vp8_mv_bit_cost(&mode_mv[NEWMV], &best_ref_mv1, cpi->mb.mvcost, 128);
+
+
+        case NEARESTMV:
+        case NEARMV:
+
+            if (mode_mv[this_mode].row == 0 && mode_mv[this_mode].col == 0)
+                continue;
+
+        case ZEROMV:
+
+            // Trap vectors that reach beyond the UMV borders
+            // Note that ALL New MV, Nearest MV Near MV and Zero MV code drops through to this point
+            // because of the lack of break statements in the previous two cases.
+            if (((mode_mv[this_mode].row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].row >> 3) > x->mv_row_max) ||
+                ((mode_mv[this_mode].col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].col >> 3) > x->mv_col_max))
+                continue;
+
+            rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
+            x->e_mbd.mbmi.mode = this_mode;
+            x->e_mbd.mbmi.mv.as_mv = mode_mv[this_mode];
+            x->e_mbd.block[0].bmi.mode = this_mode;
+            x->e_mbd.block[0].bmi.mv.as_int = x->e_mbd.mbmi.mv.as_int;
+
+            distortion2 = get_inter_mbpred_error(x, cpi->fn_ptr.svf, cpi->fn_ptr.vf, (unsigned int *)(&sse));
+
+            this_rd = RD_ESTIMATE(x->rdmult, x->rddiv, rate2, distortion2);
+
+            if (cpi->active_map_enabled && x->active_ptr[0] == 0)
+            {
+                x->skip = 1;
+            }
+            else if (sse < x->encode_breakout)
+            {
+                // Check u and v to make sure skip is ok
+                int sse2 = 0;
+
+                sse2 = VP8_UVSSE(x, IF_RTCD(&cpi->rtcd.variance));
+
+                if (sse2 * 2 < x->encode_breakout)
+                    x->skip = 1;
+                else
+                    x->skip = 0;
+            }
+
+            break;
+        default:
+            break;
+        }
+
+        // Experimental debug code.
+        //all_rds[mode_index] = this_rd;
+
+        if (this_rd < best_rd || x->skip)
+        {
+            // Note index of best mode
+            best_mode_index = mode_index;
+
+            *returnrate = rate2;
+            *returndistortion = distortion2;
+            best_rd = this_rd;
+            vpx_memcpy(&best_mbmode, &x->e_mbd.mbmi, sizeof(MB_MODE_INFO));
+
+            if (this_mode == B_PRED || this_mode == SPLITMV)
+                for (i = 0; i < 16; i++)
+                {
+                    vpx_memcpy(&best_bmodes[i], &x->e_mbd.block[i].bmi, sizeof(B_MODE_INFO));
+                }
+            else
+            {
+                best_bmodes[0].mv = x->e_mbd.block[0].bmi.mv;
+            }
+
+            // Testing this mode gave rise to an improvement in best error score. Lower threshold a bit for next time
+            cpi->rd_thresh_mult[mode_index] = (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ? cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
+            cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+        }
+
+        // If the mode did not help improve the best error case then raise the threshold for testing that mode next time around.
+        else
+        {
+            cpi->rd_thresh_mult[mode_index] += 4;
+
+            if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
+                cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
+
+            cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+        }
+
+        if (x->skip)
+            break;
+    }
+
+    // Reduce the activation RD thresholds for the best choice mode
+    if ((cpi->rd_baseline_thresh[best_mode_index] > 0) && (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2)))
+    {
+        int best_adjustment = (cpi->rd_thresh_mult[best_mode_index] >> 3);
+
+        cpi->rd_thresh_mult[best_mode_index] = (cpi->rd_thresh_mult[best_mode_index] >= (MIN_THRESHMULT + best_adjustment)) ? cpi->rd_thresh_mult[best_mode_index] - best_adjustment : MIN_THRESHMULT;
+        cpi->rd_threshes[best_mode_index] = (cpi->rd_baseline_thresh[best_mode_index] >> 7) * cpi->rd_thresh_mult[best_mode_index];
+    }
+
+    // Keep a record of best mode index for use in next loop
+    cpi->last_best_mode_index = best_mode_index;
+
+    if (best_mbmode.mode <= B_PRED)
+    {
+        x->e_mbd.mbmi.ref_frame = INTRA_FRAME;
+        vp8_pick_intra_mbuv_mode(x);
+        best_mbmode.uv_mode = x->e_mbd.mbmi.uv_mode;
+    }
+
+
+    {
+        int this_rdbin = (*returndistortion >> 7);
+
+        if (this_rdbin >= 1024)
+        {
+            this_rdbin = 1023;
+        }
+
+        cpi->error_bins[this_rdbin] ++;
+    }
+
+
+    if (cpi->is_src_frame_alt_ref && (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME))
+    {
+        best_mbmode.mode = ZEROMV;
+        best_mbmode.ref_frame = ALTREF_FRAME;
+        best_mbmode.mv.as_int = 0;
+        best_mbmode.uv_mode = 0;
+        best_mbmode.mb_skip_coeff = (cpi->common.mb_no_coeff_skip) ? 1 : 0;
+        best_mbmode.partitioning = 0;
+        best_mbmode.dc_diff = 0;
+
+        vpx_memcpy(&x->e_mbd.mbmi, &best_mbmode, sizeof(MB_MODE_INFO));
+
+        for (i = 0; i < 16; i++)
+        {
+            vpx_memset(&x->e_mbd.block[i].bmi, 0, sizeof(B_MODE_INFO));
+        }
+
+        x->e_mbd.mbmi.mv.as_int = 0;
+
+        return best_rd;
+    }
+
+
+    // macroblock modes
+    vpx_memcpy(&x->e_mbd.mbmi, &best_mbmode, sizeof(MB_MODE_INFO));
+
+    if (x->e_mbd.mbmi.mode == B_PRED || x->e_mbd.mbmi.mode == SPLITMV)
+        for (i = 0; i < 16; i++)
+        {
+            vpx_memcpy(&x->e_mbd.block[i].bmi, &best_bmodes[i], sizeof(B_MODE_INFO));
+
+        }
+    else
+    {
+        vp8_set_mbmode_and_mvs(x, x->e_mbd.mbmi.mode, &best_bmodes[0].mv.as_mv);
+    }
+
+    x->e_mbd.mbmi.mv.as_mv = x->e_mbd.block[15].bmi.mv.as_mv;
+
+    return best_rd;
+}
diff --git a/vp8/encoder/pickinter.h b/vp8/encoder/pickinter.h
new file mode 100644
index 0000000..fb28837
--- /dev/null
+++ b/vp8/encoder/pickinter.h
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_PICKINTER_H
+#define __INC_PICKINTER_H
+#include "vpx_ports/config.h"
+#include "onyxc_int.h"
+
+#define RD_ESTIMATE(RM,DM,R,D) ( ((128+(R)*(RM)) >> 8) + (DM)*(D) )
+extern int vp8_pick_intra4x4mby_modes(const VP8_ENCODER_RTCD *, MACROBLOCK *mb, int *Rate, int *Distortion);
+extern int vp8_pick_intra_mbuv_mode(MACROBLOCK *mb);
+extern int vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int *returnintra);
+#endif
diff --git a/vp8/encoder/picklpf.c b/vp8/encoder/picklpf.c
new file mode 100644
index 0000000..bbd7840
--- /dev/null
+++ b/vp8/encoder/picklpf.c
@@ -0,0 +1,435 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "onyxc_int.h"
+#include "onyx_int.h"
+#include "quantize.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_scale/yv12extend.h"
+#include "vpx_scale/vpxscale.h"
+#include "alloccommon.h"
+
+extern void vp8_loop_filter_frame(VP8_COMMON *cm,    MACROBLOCKD *mbd,  int filt_val);
+extern void vp8_loop_filter_frame_yonly(VP8_COMMON *cm,    MACROBLOCKD *mbd,  int filt_val, int sharpness_lvl);
+extern int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, const vp8_variance_rtcd_vtable_t *rtcd);
+#if HAVE_ARMV7
+extern void vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc);
+#endif
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define IF_RTCD(x) (x)
+#else
+#define IF_RTCD(x) NULL
+#endif
+
+extern void
+(*vp8_yv12_copy_partial_frame_ptr)(YV12_BUFFER_CONFIG *src_ybc,
+                                   YV12_BUFFER_CONFIG *dst_ybc,
+                                   int Fraction);
+void
+vp8_yv12_copy_partial_frame(YV12_BUFFER_CONFIG *src_ybc, YV12_BUFFER_CONFIG *dst_ybc, int Fraction)
+{
+    unsigned char *src_y, *dst_y;
+    int yheight;
+    int ystride;
+    int border;
+    int yoffset;
+    int linestocopy;
+
+    border   = src_ybc->border;
+    yheight  = src_ybc->y_height;
+    ystride  = src_ybc->y_stride;
+
+    linestocopy = (yheight >> (Fraction + 4));
+
+    if (linestocopy < 1)
+        linestocopy = 1;
+
+    linestocopy <<= 4;
+
+    yoffset  = ystride * ((yheight >> 5) * 16 - 8);
+    src_y = src_ybc->y_buffer + yoffset;
+    dst_y = dst_ybc->y_buffer + yoffset;
+
+    vpx_memcpy(dst_y, src_y, ystride *(linestocopy + 16));
+}
+
+static int vp8_calc_partial_ssl_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, int Fraction, const vp8_variance_rtcd_vtable_t *rtcd)
+{
+    int i, j;
+    int Total = 0;
+    int srcoffset, dstoffset;
+    unsigned char *src = source->y_buffer;
+    unsigned char *dst = dest->y_buffer;
+
+    int linestocopy = (source->y_height >> (Fraction + 4));
+    (void)rtcd;
+
+    if (linestocopy < 1)
+        linestocopy = 1;
+
+    linestocopy <<= 4;
+
+
+    srcoffset = source->y_stride   * (dest->y_height >> 5) * 16;
+    dstoffset = dest->y_stride     * (dest->y_height >> 5) * 16;
+
+    src += srcoffset;
+    dst += dstoffset;
+
+    // Loop through the Y plane raw and reconstruction data summing (square differences)
+    for (i = 0; i < linestocopy; i += 16)
+    {
+        for (j = 0; j < source->y_width; j += 16)
+        {
+            unsigned int sse;
+            Total += VARIANCE_INVOKE(rtcd, mse16x16)(src + j, source->y_stride, dst + j, dest->y_stride, &sse);
+        }
+
+        src += 16 * source->y_stride;
+        dst += 16 * dest->y_stride;
+    }
+
+    return Total;
+}
+
+extern void vp8_loop_filter_partial_frame
+(
+    VP8_COMMON *cm,
+    MACROBLOCKD *mbd,
+    int default_filt_lvl,
+    int sharpness_lvl,
+    int Fraction
+);
+
+// Enforce a minimum filter level based upon baseline Q
+static int get_min_filter_level(VP8_COMP *cpi, int base_qindex)
+{
+    int min_filter_level;
+
+    if (cpi->source_alt_ref_active && cpi->common.refresh_golden_frame && !cpi->common.refresh_alt_ref_frame)
+        min_filter_level = 0;
+    else
+    {
+        if (base_qindex <= 6)
+            min_filter_level = 0;
+        else if (base_qindex <= 16)
+            min_filter_level = 1;
+        else
+            min_filter_level = (base_qindex / 8);
+    }
+
+    return min_filter_level;
+}
+
+// Enforce a maximum filter level based upon baseline Q
+static int get_max_filter_level(VP8_COMP *cpi, int base_qindex)
+{
+    // PGW August 2006: Highest filter values almost always a bad idea
+
+    // jbb chg: 20100118 - not so any more with this overquant stuff allow high values
+    // with lots of intra coming in.
+    int max_filter_level = MAX_LOOP_FILTER ;//* 3 / 4;
+
+    if (cpi->section_intra_rating > 8)
+        max_filter_level = MAX_LOOP_FILTER * 3 / 4;
+
+    (void) cpi;
+    (void) base_qindex;
+
+    return max_filter_level;
+}
+
+void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    int best_err = 0;
+    int filt_err = 0;
+    int min_filter_level = 0;
+    int max_filter_level = MAX_LOOP_FILTER * 3 / 4;   // PGW August 2006: Highest filter values almost always a bad idea
+    int filt_val;
+    int best_filt_val = cm->filter_level;
+
+    //  Make a copy of the unfiltered / processed recon buffer
+    //vp8_yv12_copy_frame_ptr( cm->frame_to_show, &cpi->last_frame_uf  );
+    vp8_yv12_copy_partial_frame_ptr(cm->frame_to_show, &cpi->last_frame_uf, 3);
+
+    if (cm->frame_type == KEY_FRAME)
+        cm->sharpness_level = 0;
+    else
+        cm->sharpness_level = cpi->oxcf.Sharpness;
+
+    // Enforce a minimum filter level based upon Q
+    min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
+    max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
+
+    // Start the search at the previous frame filter level unless it is now out of range.
+    if (cm->filter_level < min_filter_level)
+        cm->filter_level = min_filter_level;
+    else if (cm->filter_level > max_filter_level)
+        cm->filter_level = max_filter_level;
+
+    filt_val = cm->filter_level;
+    best_filt_val = filt_val;
+
+    // Set up alternate filter values
+
+    // Get the err using the previous frame's filter value.
+    vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val, 0  , 3);
+    cm->last_frame_type = cm->frame_type;
+    cm->last_filter_type = cm->filter_type;
+    cm->last_sharpness_level = cm->sharpness_level;
+
+    best_err = vp8_calc_partial_ssl_err(sd, cm->frame_to_show, 3, IF_RTCD(&cpi->rtcd.variance));
+
+    //  Re-instate the unfiltered frame
+    vp8_yv12_copy_partial_frame_ptr(&cpi->last_frame_uf, cm->frame_to_show, 3);
+
+    filt_val -= (1 + ((filt_val > 10) ? 1 : 0));
+
+    // Search lower filter levels
+    while (filt_val >= min_filter_level)
+    {
+        // Apply the loop filter
+        vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val, 0, 3);
+        cm->last_frame_type = cm->frame_type;
+        cm->last_filter_type = cm->filter_type;
+        cm->last_sharpness_level = cm->sharpness_level;
+
+        // Get the err for filtered frame
+        filt_err = vp8_calc_partial_ssl_err(sd, cm->frame_to_show, 3, IF_RTCD(&cpi->rtcd.variance));
+
+
+        //  Re-instate the unfiltered frame
+        vp8_yv12_copy_partial_frame_ptr(&cpi->last_frame_uf, cm->frame_to_show, 3);
+
+
+        // Update the best case record or exit loop.
+        if (filt_err < best_err)
+        {
+            best_err = filt_err;
+            best_filt_val = filt_val;
+        }
+        else
+            break;
+
+        // Adjust filter level
+        filt_val -= (1 + ((filt_val > 10) ? 1 : 0));
+    }
+
+    // Search up (note that we have already done filt_val = cm->filter_level)
+    filt_val = cm->filter_level + (1 + ((filt_val > 10) ? 1 : 0));
+
+    if (best_filt_val == cm->filter_level)
+    {
+        // Resist raising filter level for very small gains
+        best_err -= (best_err >> 10);
+
+        while (filt_val < max_filter_level)
+        {
+            // Apply the loop filter
+            vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val, 0, 3);
+            cm->last_frame_type = cm->frame_type;
+            cm->last_filter_type = cm->filter_type;
+            cm->last_sharpness_level = cm->sharpness_level;
+
+            // Get the err for filtered frame
+            filt_err = vp8_calc_partial_ssl_err(sd, cm->frame_to_show, 3, IF_RTCD(&cpi->rtcd.variance));
+
+            //  Re-instate the unfiltered frame
+            vp8_yv12_copy_partial_frame_ptr(&cpi->last_frame_uf, cm->frame_to_show, 3);
+
+            // Update the best case record or exit loop.
+            if (filt_err < best_err)
+            {
+                // Do not raise filter level if improvement is < 1 part in 4096
+                best_err = filt_err - (filt_err >> 10);
+
+                best_filt_val = filt_val;
+            }
+            else
+                break;
+
+            // Adjust filter level
+            filt_val += (1 + ((filt_val > 10) ? 1 : 0));
+        }
+    }
+
+    cm->filter_level = best_filt_val;
+
+    if (cm->filter_level < min_filter_level)
+        cm->filter_level = min_filter_level;
+
+    if (cm->filter_level > max_filter_level)
+        cm->filter_level = max_filter_level;
+}
+
+// Stub function for now Alt LF not used
+void vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val)
+{
+    MACROBLOCKD *mbd = &cpi->mb.e_mbd;
+    (void) filt_val;
+
+    mbd->segment_feature_data[MB_LVL_ALT_LF][0] = cpi->segment_feature_data[MB_LVL_ALT_LF][0];
+    mbd->segment_feature_data[MB_LVL_ALT_LF][1] = cpi->segment_feature_data[MB_LVL_ALT_LF][1];
+    mbd->segment_feature_data[MB_LVL_ALT_LF][2] = cpi->segment_feature_data[MB_LVL_ALT_LF][2];
+    mbd->segment_feature_data[MB_LVL_ALT_LF][3] = cpi->segment_feature_data[MB_LVL_ALT_LF][3];
+}
+
+void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi)
+{
+    VP8_COMMON *cm = &cpi->common;
+
+    int best_err = 0;
+    int filt_err = 0;
+    int min_filter_level;
+    int max_filter_level;
+    int prediction_difference = (int)(100 * abs((int)(cpi->last_auto_filter_prediction_error - cpi->prediction_error)) / (1 + cpi->prediction_error));
+
+    int filter_step;
+    int filt_high = 0;
+    int filt_mid = cm->filter_level;      // Start search at previous frame filter level
+    int filt_low = 0;
+    int filt_best;
+    int filt_direction = 0;
+
+    int Bias = 0;                       // Bias against raising loop filter and in favour of lowering it
+
+    //  Make a copy of the unfiltered / processed recon buffer
+#if HAVE_ARMV7
+    vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(cm->frame_to_show, &cpi->last_frame_uf);
+#else
+    vp8_yv12_copy_frame_ptr(cm->frame_to_show, &cpi->last_frame_uf);
+#endif
+
+    if (cm->frame_type == KEY_FRAME)
+        cm->sharpness_level = 0;
+    else
+        cm->sharpness_level = cpi->oxcf.Sharpness;
+
+    // Enforce a minimum filter level based upon Q
+    min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
+    max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
+
+    // Start the search at the previous frame filter level unless it is now out of range.
+    filt_mid = cm->filter_level;
+
+    if (filt_mid < min_filter_level)
+        filt_mid = min_filter_level;
+    else if (filt_mid > max_filter_level)
+        filt_mid = max_filter_level;
+
+    // Define the initial step size
+    filter_step = (filt_mid < 16) ? 4 : filt_mid / 4;
+
+    // Get baseline error score
+    vp8cx_set_alt_lf_level(cpi, filt_mid);
+    vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_mid, 0);
+    cm->last_frame_type = cm->frame_type;
+    cm->last_filter_type = cm->filter_type;
+    cm->last_sharpness_level = cm->sharpness_level;
+
+    best_err = vp8_calc_ss_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
+    filt_best = filt_mid;
+
+    //  Re-instate the unfiltered frame
+#if HAVE_ARMV7
+    vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(&cpi->last_frame_uf, cm->frame_to_show);
+#else
+    vp8_yv12_copy_frame_yonly_ptr(&cpi->last_frame_uf, cm->frame_to_show);
+#endif
+
+    while (filter_step > 0)
+    {
+        Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step; //PGW change 12/12/06 for small images
+
+        // jbb chg: 20100118 - in sections with lots of new material coming in don't bias as much to a low filter value
+        if (cpi->section_intra_rating < 20)
+            Bias = Bias * cpi->section_intra_rating / 20;
+
+        filt_high = ((filt_mid + filter_step) > max_filter_level) ? max_filter_level : (filt_mid + filter_step);
+        filt_low = ((filt_mid - filter_step) < min_filter_level) ? min_filter_level : (filt_mid - filter_step);
+
+        if ((filt_direction <= 0) && (filt_low != filt_mid))
+        {
+            // Get Low filter error score
+            vp8cx_set_alt_lf_level(cpi, filt_low);
+            vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_low, 0);
+            cm->last_frame_type = cm->frame_type;
+            cm->last_filter_type = cm->filter_type;
+            cm->last_sharpness_level = cm->sharpness_level;
+
+            filt_err = vp8_calc_ss_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
+
+            //  Re-instate the unfiltered frame
+#if HAVE_ARMV7
+            vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(&cpi->last_frame_uf, cm->frame_to_show);
+#else
+            vp8_yv12_copy_frame_yonly_ptr(&cpi->last_frame_uf, cm->frame_to_show);
+#endif
+
+            // If value is close to the best so far then bias towards a lower loop filter value.
+            if ((filt_err - Bias) < best_err)
+            {
+                // Was it actually better than the previous best?
+                if (filt_err < best_err)
+                    best_err = filt_err;
+
+                filt_best = filt_low;
+            }
+        }
+
+        // Now look at filt_high
+        if ((filt_direction >= 0) && (filt_high != filt_mid))
+        {
+            vp8cx_set_alt_lf_level(cpi, filt_high);
+            vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_high, 0);
+            cm->last_frame_type = cm->frame_type;
+            cm->last_filter_type = cm->filter_type;
+            cm->last_sharpness_level = cm->sharpness_level;
+
+            filt_err = vp8_calc_ss_err(sd, cm->frame_to_show, IF_RTCD(&cpi->rtcd.variance));
+
+            //  Re-instate the unfiltered frame
+#if HAVE_ARMV7
+            vp8_yv12_copy_frame_yonly_no_extend_frame_borders_neon(&cpi->last_frame_uf, cm->frame_to_show);
+#else
+            vp8_yv12_copy_frame_yonly_ptr(&cpi->last_frame_uf, cm->frame_to_show);
+#endif
+
+            // Was it better than the previous best?
+            if (filt_err < (best_err - Bias))
+            {
+                best_err = filt_err;
+                filt_best = filt_high;
+            }
+        }
+
+        // Half the step distance if the best filter value was the same as last time
+        if (filt_best == filt_mid)
+        {
+            filter_step = filter_step / 2;
+            filt_direction = 0;
+        }
+        else
+        {
+            filt_direction = (filt_best < filt_mid) ? -1 : 1;
+            filt_mid = filt_best;
+        }
+    }
+
+    cm->filter_level = filt_best;
+    cpi->last_auto_filt_val = filt_best;
+    cpi->last_auto_filt_q  = cm->base_qindex;
+
+    cpi->last_auto_filter_prediction_error = cpi->prediction_error;
+    cpi->frames_since_auto_filter = 0;
+}
diff --git a/vp8/encoder/ppc/csystemdependent.c b/vp8/encoder/ppc/csystemdependent.c
new file mode 100644
index 0000000..f99277f
--- /dev/null
+++ b/vp8/encoder/ppc/csystemdependent.c
@@ -0,0 +1,168 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "variance.h"
+#include "onyx_int.h"
+
+SADFunction *vp8_sad16x16;
+SADFunction *vp8_sad16x8;
+SADFunction *vp8_sad8x16;
+SADFunction *vp8_sad8x8;
+SADFunction *vp8_sad4x4;
+
+variance_function *vp8_variance4x4;
+variance_function *vp8_variance8x8;
+variance_function *vp8_variance8x16;
+variance_function *vp8_variance16x8;
+variance_function *vp8_variance16x16;
+
+variance_function *vp8_mse16x16;
+
+sub_pixel_variance_function *vp8_sub_pixel_variance4x4;
+sub_pixel_variance_function *vp8_sub_pixel_variance8x8;
+sub_pixel_variance_function *vp8_sub_pixel_variance8x16;
+sub_pixel_variance_function *vp8_sub_pixel_variance16x8;
+sub_pixel_variance_function *vp8_sub_pixel_variance16x16;
+
+int (*vp8_block_error)(short *coeff, short *dqcoeff);
+int (*vp8_mbblock_error)(MACROBLOCK *mb, int dc);
+
+int (*vp8_mbuverror)(MACROBLOCK *mb);
+unsigned int (*vp8_get_mb_ss)(short *);
+void (*vp8_short_fdct4x4)(short *input, short *output, int pitch);
+void (*vp8_short_fdct8x4)(short *input, short *output, int pitch);
+void (*vp8_fast_fdct4x4)(short *input, short *output, int pitch);
+void (*vp8_fast_fdct8x4)(short *input, short *output, int pitch);
+void (*short_walsh4x4)(short *input, short *output, int pitch);
+
+void (*vp8_subtract_b)(BLOCK *be, BLOCKD *bd, int pitch);
+void (*vp8_subtract_mby)(short *diff, unsigned char *src, unsigned char *pred, int stride);
+void (*vp8_subtract_mbuv)(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride);
+void (*vp8_fast_quantize_b)(BLOCK *b, BLOCKD *d);
+
+unsigned int (*vp8_get16x16pred_error)(unsigned char *src_ptr, int src_stride, unsigned char *ref_ptr, int ref_stride);
+unsigned int (*vp8_get8x8var)(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+unsigned int (*vp8_get16x16var)(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+unsigned int (*vp8_get4x4sse_cs)(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride);
+
+// c imports
+extern int block_error_c(short *coeff, short *dqcoeff);
+extern int vp8_mbblock_error_c(MACROBLOCK *mb, int dc);
+
+extern int vp8_mbuverror_c(MACROBLOCK *mb);
+extern unsigned int vp8_get8x8var_c(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+extern void short_fdct4x4_c(short *input, short *output, int pitch);
+extern void short_fdct8x4_c(short *input, short *output, int pitch);
+extern void vp8_short_walsh4x4_c(short *input, short *output, int pitch);
+
+extern void vp8_subtract_b_c(BLOCK *be, BLOCKD *bd, int pitch);
+extern void subtract_mby_c(short *diff, unsigned char *src, unsigned char *pred, int stride);
+extern void subtract_mbuv_c(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride);
+extern void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d);
+
+extern SADFunction sad16x16_c;
+extern SADFunction sad16x8_c;
+extern SADFunction sad8x16_c;
+extern SADFunction sad8x8_c;
+extern SADFunction sad4x4_c;
+
+extern variance_function variance16x16_c;
+extern variance_function variance8x16_c;
+extern variance_function variance16x8_c;
+extern variance_function variance8x8_c;
+extern variance_function variance4x4_c;
+extern variance_function mse16x16_c;
+
+extern sub_pixel_variance_function sub_pixel_variance4x4_c;
+extern sub_pixel_variance_function sub_pixel_variance8x8_c;
+extern sub_pixel_variance_function sub_pixel_variance8x16_c;
+extern sub_pixel_variance_function sub_pixel_variance16x8_c;
+extern sub_pixel_variance_function sub_pixel_variance16x16_c;
+
+extern unsigned int vp8_get_mb_ss_c(short *);
+extern unsigned int vp8_get16x16pred_error_c(unsigned char *src_ptr, int src_stride, unsigned char *ref_ptr, int ref_stride);
+extern unsigned int vp8_get8x8var_c(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+extern unsigned int vp8_get16x16var_c(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+extern unsigned int vp8_get4x4sse_cs_c(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride);
+
+// ppc
+extern int vp8_block_error_ppc(short *coeff, short *dqcoeff);
+
+extern void vp8_short_fdct4x4_ppc(short *input, short *output, int pitch);
+extern void vp8_short_fdct8x4_ppc(short *input, short *output, int pitch);
+
+extern void vp8_subtract_mby_ppc(short *diff, unsigned char *src, unsigned char *pred, int stride);
+extern void vp8_subtract_mbuv_ppc(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride);
+
+extern SADFunction vp8_sad16x16_ppc;
+extern SADFunction vp8_sad16x8_ppc;
+extern SADFunction vp8_sad8x16_ppc;
+extern SADFunction vp8_sad8x8_ppc;
+extern SADFunction vp8_sad4x4_ppc;
+
+extern variance_function vp8_variance16x16_ppc;
+extern variance_function vp8_variance8x16_ppc;
+extern variance_function vp8_variance16x8_ppc;
+extern variance_function vp8_variance8x8_ppc;
+extern variance_function vp8_variance4x4_ppc;
+extern variance_function vp8_mse16x16_ppc;
+
+extern sub_pixel_variance_function vp8_sub_pixel_variance4x4_ppc;
+extern sub_pixel_variance_function vp8_sub_pixel_variance8x8_ppc;
+extern sub_pixel_variance_function vp8_sub_pixel_variance8x16_ppc;
+extern sub_pixel_variance_function vp8_sub_pixel_variance16x8_ppc;
+extern sub_pixel_variance_function vp8_sub_pixel_variance16x16_ppc;
+
+extern unsigned int vp8_get8x8var_ppc(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+extern unsigned int vp8_get16x16var_ppc(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+
+void vp8_cmachine_specific_config(void)
+{
+    // Pure C:
+    vp8_mbuverror               = vp8_mbuverror_c;
+    vp8_fast_quantize_b           = vp8_fast_quantize_b_c;
+    vp8_short_fdct4x4            = vp8_short_fdct4x4_ppc;
+    vp8_short_fdct8x4            = vp8_short_fdct8x4_ppc;
+    vp8_fast_fdct4x4             = vp8_short_fdct4x4_ppc;
+    vp8_fast_fdct8x4             = vp8_short_fdct8x4_ppc;
+    short_walsh4x4               = vp8_short_walsh4x4_c;
+
+    vp8_variance4x4             = vp8_variance4x4_ppc;
+    vp8_variance8x8             = vp8_variance8x8_ppc;
+    vp8_variance8x16            = vp8_variance8x16_ppc;
+    vp8_variance16x8            = vp8_variance16x8_ppc;
+    vp8_variance16x16           = vp8_variance16x16_ppc;
+    vp8_mse16x16                = vp8_mse16x16_ppc;
+
+    vp8_sub_pixel_variance4x4     = vp8_sub_pixel_variance4x4_ppc;
+    vp8_sub_pixel_variance8x8     = vp8_sub_pixel_variance8x8_ppc;
+    vp8_sub_pixel_variance8x16    = vp8_sub_pixel_variance8x16_ppc;
+    vp8_sub_pixel_variance16x8    = vp8_sub_pixel_variance16x8_ppc;
+    vp8_sub_pixel_variance16x16   = vp8_sub_pixel_variance16x16_ppc;
+
+    vp8_get_mb_ss                 = vp8_get_mb_ss_c;
+    vp8_get16x16pred_error       = vp8_get16x16pred_error_c;
+    vp8_get8x8var               = vp8_get8x8var_ppc;
+    vp8_get16x16var             = vp8_get16x16var_ppc;
+    vp8_get4x4sse_cs            = vp8_get4x4sse_cs_c;
+
+    vp8_sad16x16                = vp8_sad16x16_ppc;
+    vp8_sad16x8                 = vp8_sad16x8_ppc;
+    vp8_sad8x16                 = vp8_sad8x16_ppc;
+    vp8_sad8x8                  = vp8_sad8x8_ppc;
+    vp8_sad4x4                  = vp8_sad4x4_ppc;
+
+    vp8_block_error              = vp8_block_error_ppc;
+    vp8_mbblock_error            = vp8_mbblock_error_c;
+
+    vp8_subtract_b               = vp8_subtract_b_c;
+    vp8_subtract_mby             = vp8_subtract_mby_ppc;
+    vp8_subtract_mbuv            = vp8_subtract_mbuv_ppc;
+}
diff --git a/vp8/encoder/ppc/encodemb_altivec.asm b/vp8/encoder/ppc/encodemb_altivec.asm
new file mode 100644
index 0000000..e0e976d
--- /dev/null
+++ b/vp8/encoder/ppc/encodemb_altivec.asm
@@ -0,0 +1,152 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl vp8_subtract_mbuv_ppc
+    .globl vp8_subtract_mby_ppc
+
+;# r3 short *diff
+;# r4 unsigned char *usrc
+;# r5 unsigned char *vsrc
+;# r6 unsigned char *pred
+;# r7 int stride
+vp8_subtract_mbuv_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xf000
+    mtspr   256, r12            ;# set VRSAVE
+
+    li      r9, 256
+    add     r3, r3, r9
+    add     r3, r3, r9
+    add     r6, r6, r9
+
+    li      r10, 16
+    li      r9,  4
+    mtctr   r9
+
+    vspltisw v0, 0
+
+mbu_loop:
+    lvsl    v5, 0, r4           ;# permutate value for alignment
+    lvx     v1, 0, r4           ;# src
+    lvx     v2, 0, r6           ;# pred
+
+    add     r4, r4, r7
+    addi    r6, r6, 16
+
+    vperm   v1, v1, v0, v5
+
+    vmrghb  v3, v0, v1          ;# unpack high src  to short
+    vmrghb  v4, v0, v2          ;# unpack high pred to short
+
+    lvsl    v5, 0, r4           ;# permutate value for alignment
+    lvx     v1, 0, r4           ;# src
+
+    add     r4, r4, r7
+
+    vsubshs v3, v3, v4
+
+    stvx    v3, 0, r3           ;# store out diff
+
+    vperm   v1, v1, v0, v5
+
+    vmrghb  v3, v0, v1          ;# unpack high src  to short
+    vmrglb  v4, v0, v2          ;# unpack high pred to short
+
+    vsubshs v3, v3, v4
+
+    stvx    v3, r10, r3         ;# store out diff
+
+    addi    r3, r3, 32
+
+    bdnz    mbu_loop
+
+    mtctr   r9
+
+mbv_loop:
+    lvsl    v5, 0, r5           ;# permutate value for alignment
+    lvx     v1, 0, r5           ;# src
+    lvx     v2, 0, r6           ;# pred
+
+    add     r5, r5, r7
+    addi    r6, r6, 16
+
+    vperm   v1, v1, v0, v5
+
+    vmrghb  v3, v0, v1          ;# unpack high src  to short
+    vmrghb  v4, v0, v2          ;# unpack high pred to short
+
+    lvsl    v5, 0, r5           ;# permutate value for alignment
+    lvx     v1, 0, r5           ;# src
+
+    add     r5, r5, r7
+
+    vsubshs v3, v3, v4
+
+    stvx    v3, 0, r3           ;# store out diff
+
+    vperm   v1, v1, v0, v5
+
+    vmrghb  v3, v0, v1          ;# unpack high src  to short
+    vmrglb  v4, v0, v2          ;# unpack high pred to short
+
+    vsubshs v3, v3, v4
+
+    stvx    v3, r10, r3         ;# store out diff
+
+    addi    r3, r3, 32
+
+    bdnz    mbv_loop
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+;# r3 short *diff
+;# r4 unsigned char *src
+;# r5 unsigned char *pred
+;# r6 int stride
+vp8_subtract_mby_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xf800
+    mtspr   256, r12            ;# set VRSAVE
+
+    li      r10, 16
+    mtctr   r10
+
+    vspltisw v0, 0
+
+mby_loop:
+    lvx     v1, 0, r4           ;# src
+    lvx     v2, 0, r5           ;# pred
+
+    add     r4, r4, r6
+    addi    r5, r5, 16
+
+    vmrghb  v3, v0, v1          ;# unpack high src  to short
+    vmrghb  v4, v0, v2          ;# unpack high pred to short
+
+    vsubshs v3, v3, v4
+
+    stvx    v3, 0, r3           ;# store out diff
+
+    vmrglb  v3, v0, v1          ;# unpack low src  to short
+    vmrglb  v4, v0, v2          ;# unpack low pred to short
+
+    vsubshs v3, v3, v4
+
+    stvx    v3, r10, r3         ;# store out diff
+
+    addi    r3, r3, 32
+
+    bdnz    mby_loop
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
diff --git a/vp8/encoder/ppc/fdct_altivec.asm b/vp8/encoder/ppc/fdct_altivec.asm
new file mode 100644
index 0000000..eaab14c
--- /dev/null
+++ b/vp8/encoder/ppc/fdct_altivec.asm
@@ -0,0 +1,204 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl vp8_short_fdct4x4_ppc
+    .globl vp8_short_fdct8x4_ppc
+
+.macro load_c V, LABEL, OFF, R0, R1
+    lis     \R0, \LABEL@ha
+    la      \R1, \LABEL@l(\R0)
+    lvx     \V, \OFF, \R1
+.endm
+
+;# Forward and inverse DCTs are nearly identical; only differences are
+;#   in normalization (fwd is twice unitary, inv is half unitary)
+;#   and that they are of course transposes of each other.
+;#
+;#   The following three accomplish most of implementation and
+;#   are used only by ppc_idct.c and ppc_fdct.c.
+.macro prologue
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xfffc
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    li      r6, 16
+
+    load_c v0, dct_tab, 0, r9, r10
+    lvx     v1,   r6, r10
+    addi    r10, r10, 32
+    lvx     v2,    0, r10
+    lvx     v3,   r6, r10
+
+    load_c v4, ppc_dctperm_tab,  0, r9, r10
+    load_c v5, ppc_dctperm_tab, r6, r9, r10
+
+    load_c v6, round_tab, 0, r10, r9
+.endm
+
+.macro epilogue
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+.endm
+
+;# Do horiz xf on two rows of coeffs  v8 = a0 a1 a2 a3  b0 b1 b2 b3.
+;#   a/A are the even rows 0,2   b/B are the odd rows 1,3
+;#   For fwd transform, indices are horizontal positions, then frequencies.
+;#   For inverse transform, frequencies then positions.
+;#   The two resulting  A0..A3  B0..B3  are later combined
+;#   and vertically transformed.
+
+.macro two_rows_horiz Dst
+    vperm   v9, v8, v8, v4      ;# v9 = a2 a3 a0 a1  b2 b3 b0 b1
+
+    vmsumshm v10, v0, v8, v6
+    vmsumshm v10, v1, v9, v10
+    vsraw   v10, v10, v7        ;# v10 = A0 A1  B0 B1
+
+    vmsumshm v11, v2, v8, v6
+    vmsumshm v11, v3, v9, v11
+    vsraw   v11, v11, v7        ;# v11 = A2 A3  B2 B3
+
+    vpkuwum v10, v10, v11       ;# v10  = A0 A1  B0 B1  A2 A3  B2 B3
+    vperm   \Dst, v10, v10, v5  ;# Dest = A0 B0  A1 B1  A2 B2  A3 B3
+.endm
+
+;# Vertical xf on two rows. DCT values in comments are for inverse transform;
+;#   forward transform uses transpose.
+
+.macro two_rows_vert Ceven, Codd
+    vspltw  v8, \Ceven, 0       ;# v8 = c00 c10  or  c02 c12 four times
+    vspltw  v9, \Codd,  0       ;# v9 = c20 c30  or  c22 c32 ""
+    vmsumshm v8, v8, v12, v6
+    vmsumshm v8, v9, v13, v8
+    vsraw   v10, v8, v7
+
+    vspltw  v8, \Codd,  1       ;# v8 = c01 c11  or  c03 c13
+    vspltw  v9, \Ceven, 1       ;# v9 = c21 c31  or  c23 c33
+    vmsumshm v8, v8, v12, v6
+    vmsumshm v8, v9, v13, v8
+    vsraw   v8, v8, v7
+
+    vpkuwum v8, v10, v8         ;# v8 = rows 0,1  or 2,3
+.endm
+
+.macro two_rows_h Dest
+    stw     r0,  0(r8)
+    lwz     r0,  4(r3)
+    stw     r0,  4(r8)
+    lwzux   r0, r3,r5
+    stw     r0,  8(r8)
+    lwz     r0,  4(r3)
+    stw     r0, 12(r8)
+    lvx     v8,  0,r8
+    two_rows_horiz \Dest
+.endm
+
+    .align 2
+;# r3 short *input
+;# r4 short *output
+;# r5 int pitch
+vp8_short_fdct4x4_ppc:
+
+    prologue
+
+    vspltisw v7, 14             ;# == 14, fits in 5 signed bits
+    addi    r8, r1, 0
+
+
+    lwz     r0, 0(r3)
+    two_rows_h v12                ;# v12 = H00 H10  H01 H11  H02 H12  H03 H13
+
+    lwzux   r0, r3, r5
+    two_rows_h v13                ;# v13 = H20 H30  H21 H31  H22 H32  H23 H33
+
+    lvx     v6, r6, r9          ;# v6 = Vround
+    vspltisw v7, -16            ;# == 16 == -16, only low 5 bits matter
+
+    two_rows_vert v0, v1
+    stvx    v8, 0, r4
+    two_rows_vert v2, v3
+    stvx    v8, r6, r4
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 short *input
+;# r4 short *output
+;# r5 int pitch
+vp8_short_fdct8x4_ppc:
+    prologue
+
+    vspltisw v7, 14             ;# == 14, fits in 5 signed bits
+    addi    r8,  r1, 0
+    addi    r10, r3, 0
+
+    lwz     r0, 0(r3)
+    two_rows_h v12                ;# v12 = H00 H10  H01 H11  H02 H12  H03 H13
+
+    lwzux   r0, r3, r5
+    two_rows_h v13                ;# v13 = H20 H30  H21 H31  H22 H32  H23 H33
+
+    lvx     v6, r6, r9          ;# v6 = Vround
+    vspltisw v7, -16            ;# == 16 == -16, only low 5 bits matter
+
+    two_rows_vert v0, v1
+    stvx    v8, 0, r4
+    two_rows_vert v2, v3
+    stvx    v8, r6, r4
+
+    ;# Next block
+    addi    r3, r10, 8
+    addi    r4, r4, 32
+    lvx     v6, 0, r9           ;# v6 = Hround
+
+    vspltisw v7, 14             ;# == 14, fits in 5 signed bits
+    addi    r8, r1, 0
+
+    lwz     r0, 0(r3)
+    two_rows_h v12                ;# v12 = H00 H10  H01 H11  H02 H12  H03 H13
+
+    lwzux   r0, r3, r5
+    two_rows_h v13                ;# v13 = H20 H30  H21 H31  H22 H32  H23 H33
+
+    lvx     v6, r6, r9          ;# v6 = Vround
+    vspltisw v7, -16            ;# == 16 == -16, only low 5 bits matter
+
+    two_rows_vert v0, v1
+    stvx    v8, 0, r4
+    two_rows_vert v2, v3
+    stvx    v8, r6, r4
+
+    epilogue
+
+    blr
+
+    .data
+    .align 4
+ppc_dctperm_tab:
+    .byte 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11
+    .byte 0,1,4,5, 2,3,6,7, 8,9,12,13, 10,11,14,15
+
+    .align 4
+dct_tab:
+    .short  23170, 23170,-12540,-30274, 23170, 23170,-12540,-30274
+    .short  23170, 23170, 30274, 12540, 23170, 23170, 30274, 12540
+
+    .short  23170,-23170, 30274,-12540, 23170,-23170, 30274,-12540
+    .short -23170, 23170, 12540,-30274,-23170, 23170, 12540,-30274
+
+    .align 4
+round_tab:
+    .long (1 << (14-1)), (1 << (14-1)), (1 << (14-1)), (1 << (14-1))
+    .long (1 << (16-1)), (1 << (16-1)), (1 << (16-1)), (1 << (16-1))
diff --git a/vp8/encoder/ppc/rdopt_altivec.asm b/vp8/encoder/ppc/rdopt_altivec.asm
new file mode 100644
index 0000000..917bfe0
--- /dev/null
+++ b/vp8/encoder/ppc/rdopt_altivec.asm
@@ -0,0 +1,50 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl vp8_block_error_ppc
+
+    .align 2
+;# r3 short *Coeff
+;# r4 short *dqcoeff
+vp8_block_error_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xf800
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    stw     r5, 12(r1)          ;# tranfer dc to vector register
+
+    lvx     v0, 0, r3           ;# Coeff
+    lvx     v1, 0, r4           ;# dqcoeff
+
+    li      r10, 16
+
+    vspltisw v3, 0
+
+    vsubshs v0, v0, v1
+
+    vmsumshm v2, v0, v0, v3     ;# multiply differences
+
+    lvx     v0, r10, r3         ;# Coeff
+    lvx     v1, r10, r4         ;# dqcoeff
+
+    vsubshs v0, v0, v1
+
+    vmsumshm v1, v0, v0, v2     ;# multiply differences
+    vsumsws v1, v1, v3          ;# sum up
+
+    stvx    v1, 0, r1
+    lwz     r3, 12(r1)          ;# return value
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
diff --git a/vp8/encoder/ppc/sad_altivec.asm b/vp8/encoder/ppc/sad_altivec.asm
new file mode 100644
index 0000000..1102ccf
--- /dev/null
+++ b/vp8/encoder/ppc/sad_altivec.asm
@@ -0,0 +1,276 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl vp8_sad16x16_ppc
+    .globl vp8_sad16x8_ppc
+    .globl vp8_sad8x16_ppc
+    .globl vp8_sad8x8_ppc
+    .globl vp8_sad4x4_ppc
+
+.macro load_aligned_16 V R O
+    lvsl    v3,  0, \R          ;# permutate value for alignment
+
+    lvx     v1,  0, \R
+    lvx     v2, \O, \R
+
+    vperm   \V, v1, v2, v3
+.endm
+
+.macro prologue
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffc0
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1, -32(r1)         ;# create space on the stack
+
+    li      r10, 16             ;# load offset and loop counter
+
+    vspltisw v8, 0              ;# zero out total to start
+.endm
+
+.macro epilogue
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+.endm
+
+.macro SAD_16
+    ;# v6 = abs (v4 - v5)
+    vsububs v6, v4, v5
+    vsububs v7, v5, v4
+    vor     v6, v6, v7
+
+    ;# v8 += abs (v4 - v5)
+    vsum4ubs v8, v6, v8
+.endm
+
+.macro sad_16_loop loop_label
+    lvsl    v3,  0, r5          ;# only needs to be done once per block
+
+    ;# preload a line of data before getting into the loop
+    lvx     v4, 0, r3
+    lvx     v1,  0, r5
+    lvx     v2, r10, r5
+
+    add     r5, r5, r6
+    add     r3, r3, r4
+
+    vperm   v5, v1, v2, v3
+
+    .align 4
+\loop_label:
+    ;# compute difference on first row
+    vsububs v6, v4, v5
+    vsububs v7, v5, v4
+
+    ;# load up next set of data
+    lvx     v9, 0, r3
+    lvx     v1,  0, r5
+    lvx     v2, r10, r5
+
+    ;# perform abs() of difference
+    vor     v6, v6, v7
+    add     r3, r3, r4
+
+    ;# add to the running tally
+    vsum4ubs v8, v6, v8
+
+    ;# now onto the next line
+    vperm   v5, v1, v2, v3
+    add     r5, r5, r6
+    lvx     v4, 0, r3
+
+    ;# compute difference on second row
+    vsububs v6, v9, v5
+    lvx     v1,  0, r5
+    vsububs v7, v5, v9
+    lvx     v2, r10, r5
+    vor     v6, v6, v7
+    add     r3, r3, r4
+    vsum4ubs v8, v6, v8
+    vperm   v5, v1, v2, v3
+    add     r5, r5, r6
+
+    bdnz    \loop_label
+
+    vspltisw v7, 0
+
+    vsumsws v8, v8, v7
+
+    stvx    v8, 0, r1
+    lwz     r3, 12(r1)
+.endm
+
+.macro sad_8_loop loop_label
+    .align 4
+\loop_label:
+    ;# only one of the inputs should need to be aligned.
+    load_aligned_16 v4, r3, r10
+    load_aligned_16 v5, r5, r10
+
+    ;# move onto the next line
+    add     r3, r3, r4
+    add     r5, r5, r6
+
+    ;# only one of the inputs should need to be aligned.
+    load_aligned_16 v6, r3, r10
+    load_aligned_16 v7, r5, r10
+
+    ;# move onto the next line
+    add     r3, r3, r4
+    add     r5, r5, r6
+
+    vmrghb  v4, v4, v6
+    vmrghb  v5, v5, v7
+
+    SAD_16
+
+    bdnz    \loop_label
+
+    vspltisw v7, 0
+
+    vsumsws v8, v8, v7
+
+    stvx    v8, 0, r1
+    lwz     r3, 12(r1)
+.endm
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  src_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  ref_stride
+;#
+;# r3 return value
+vp8_sad16x16_ppc:
+
+    prologue
+
+    li      r9, 8
+    mtctr   r9
+
+    sad_16_loop sad16x16_loop
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  src_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  ref_stride
+;#
+;# r3 return value
+vp8_sad16x8_ppc:
+
+    prologue
+
+    li      r9, 4
+    mtctr   r9
+
+    sad_16_loop sad16x8_loop
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  src_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  ref_stride
+;#
+;# r3 return value
+vp8_sad8x16_ppc:
+
+    prologue
+
+    li      r9, 8
+    mtctr   r9
+
+    sad_8_loop sad8x16_loop
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  src_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  ref_stride
+;#
+;# r3 return value
+vp8_sad8x8_ppc:
+
+    prologue
+
+    li      r9, 4
+    mtctr   r9
+
+    sad_8_loop sad8x8_loop
+
+    epilogue
+
+    blr
+
+.macro transfer_4x4 I P
+    lwz     r0, 0(\I)
+    add     \I, \I, \P
+
+    lwz     r7, 0(\I)
+    add     \I, \I, \P
+
+    lwz     r8, 0(\I)
+    add     \I, \I, \P
+
+    lwz     r9, 0(\I)
+
+    stw     r0,  0(r1)
+    stw     r7,  4(r1)
+    stw     r8,  8(r1)
+    stw     r9, 12(r1)
+.endm
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  src_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  ref_stride
+;#
+;# r3 return value
+vp8_sad4x4_ppc:
+
+    prologue
+
+    transfer_4x4 r3, r4
+    lvx     v4, 0, r1
+
+    transfer_4x4 r5, r6
+    lvx     v5, 0, r1
+
+    vspltisw v8, 0              ;# zero out total to start
+
+    ;# v6 = abs (v4 - v5)
+    vsububs v6, v4, v5
+    vsububs v7, v5, v4
+    vor     v6, v6, v7
+
+    ;# v8 += abs (v4 - v5)
+    vsum4ubs v7, v6, v8
+    vsumsws v7, v7, v8
+
+    stvx    v7, 0, r1
+    lwz     r3, 12(r1)
+
+    epilogue
+
+    blr
diff --git a/vp8/encoder/ppc/variance_altivec.asm b/vp8/encoder/ppc/variance_altivec.asm
new file mode 100644
index 0000000..952bf72
--- /dev/null
+++ b/vp8/encoder/ppc/variance_altivec.asm
@@ -0,0 +1,374 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl vp8_get8x8var_ppc
+    .globl vp8_get16x16var_ppc
+    .globl vp8_mse16x16_ppc
+    .globl vp8_variance16x16_ppc
+    .globl vp8_variance16x8_ppc
+    .globl vp8_variance8x16_ppc
+    .globl vp8_variance8x8_ppc
+    .globl vp8_variance4x4_ppc
+
+.macro load_aligned_16 V R O
+    lvsl    v3,  0, \R          ;# permutate value for alignment
+
+    lvx     v1,  0, \R
+    lvx     v2, \O, \R
+
+    vperm   \V, v1, v2, v3
+.endm
+
+.macro prologue
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffc0
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1, -32(r1)         ;# create space on the stack
+
+    li      r10, 16             ;# load offset and loop counter
+
+    vspltisw v7, 0              ;# zero for merging
+    vspltisw v8, 0              ;# zero out total to start
+    vspltisw v9, 0              ;# zero out total for dif^2
+.endm
+
+.macro epilogue
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+.endm
+
+.macro compute_sum_sse
+    ;# Compute sum first.  Unpack to so signed subract
+    ;#  can be used.  Only have a half word signed
+    ;#  subract.  Do high, then low.
+    vmrghb  v2, v7, v4
+    vmrghb  v3, v7, v5
+    vsubshs v2, v2, v3
+    vsum4shs v8, v2, v8
+
+    vmrglb  v2, v7, v4
+    vmrglb  v3, v7, v5
+    vsubshs v2, v2, v3
+    vsum4shs v8, v2, v8
+
+    ;# Now compute sse.
+    vsububs v2, v4, v5
+    vsububs v3, v5, v4
+    vor     v2, v2, v3
+
+    vmsumubm v9, v2, v2, v9
+.endm
+
+.macro variance_16 DS loop_label store_sum
+\loop_label:
+    ;# only one of the inputs should need to be aligned.
+    load_aligned_16 v4, r3, r10
+    load_aligned_16 v5, r5, r10
+
+    ;# move onto the next line
+    add     r3, r3, r4
+    add     r5, r5, r6
+
+    compute_sum_sse
+
+    bdnz    \loop_label
+
+    vsumsws v8, v8, v7
+    vsumsws v9, v9, v7
+
+    stvx    v8, 0, r1
+    lwz     r3, 12(r1)
+
+    stvx    v9, 0, r1
+    lwz     r4, 12(r1)
+
+.if \store_sum
+    stw     r3, 0(r8)           ;# sum
+.endif
+    stw     r4, 0(r7)           ;# sse
+
+    mullw   r3, r3, r3          ;# sum*sum
+    srawi   r3, r3, \DS         ;# (sum*sum) >> DS
+    subf    r3, r3, r4          ;# sse - ((sum*sum) >> DS)
+.endm
+
+.macro variance_8 DS loop_label store_sum
+\loop_label:
+    ;# only one of the inputs should need to be aligned.
+    load_aligned_16 v4, r3, r10
+    load_aligned_16 v5, r5, r10
+
+    ;# move onto the next line
+    add     r3, r3, r4
+    add     r5, r5, r6
+
+    ;# only one of the inputs should need to be aligned.
+    load_aligned_16 v6, r3, r10
+    load_aligned_16 v0, r5, r10
+
+    ;# move onto the next line
+    add     r3, r3, r4
+    add     r5, r5, r6
+
+    vmrghb  v4, v4, v6
+    vmrghb  v5, v5, v0
+
+    compute_sum_sse
+
+    bdnz    \loop_label
+
+    vsumsws v8, v8, v7
+    vsumsws v9, v9, v7
+
+    stvx    v8, 0, r1
+    lwz     r3, 12(r1)
+
+    stvx    v9, 0, r1
+    lwz     r4, 12(r1)
+
+.if \store_sum
+    stw     r3, 0(r8)           ;# sum
+.endif
+    stw     r4, 0(r7)           ;# sse
+
+    mullw   r3, r3, r3          ;# sum*sum
+    srawi   r3, r3, \DS         ;# (sum*sum) >> 8
+    subf    r3, r3, r4          ;# sse - ((sum*sum) >> 8)
+.endm
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *SSE
+;# r8 int *Sum
+;#
+;# r3 return value
+vp8_get8x8var_ppc:
+
+    prologue
+
+    li      r9, 4
+    mtctr   r9
+
+    variance_8 6, get8x8var_loop, 1
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *SSE
+;# r8 int *Sum
+;#
+;# r3 return value
+vp8_get16x16var_ppc:
+
+    prologue
+
+    mtctr   r10
+
+    variance_16 8, get16x16var_loop, 1
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *sse
+;#
+;# r 3 return value
+vp8_mse16x16_ppc:
+    prologue
+
+    mtctr   r10
+
+mse16x16_loop:
+    ;# only one of the inputs should need to be aligned.
+    load_aligned_16 v4, r3, r10
+    load_aligned_16 v5, r5, r10
+
+    ;# move onto the next line
+    add     r3, r3, r4
+    add     r5, r5, r6
+
+    ;# Now compute sse.
+    vsububs v2, v4, v5
+    vsububs v3, v5, v4
+    vor     v2, v2, v3
+
+    vmsumubm v9, v2, v2, v9
+
+    bdnz    mse16x16_loop
+
+    vsumsws v9, v9, v7
+
+    stvx    v9, 0, r1
+    lwz     r3, 12(r1)
+
+    stvx    v9, 0, r1
+    lwz     r3, 12(r1)
+
+    stw     r3, 0(r7)           ;# sse
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *sse
+;#
+;# r3 return value
+vp8_variance16x16_ppc:
+
+    prologue
+
+    mtctr   r10
+
+    variance_16 8, variance16x16_loop, 0
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *sse
+;#
+;# r3 return value
+vp8_variance16x8_ppc:
+
+    prologue
+
+    li      r9, 8
+    mtctr   r9
+
+    variance_16 7, variance16x8_loop, 0
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *sse
+;#
+;# r3 return value
+vp8_variance8x16_ppc:
+
+    prologue
+
+    li      r9, 8
+    mtctr   r9
+
+    variance_8 7, variance8x16_loop, 0
+
+    epilogue
+
+    blr
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *sse
+;#
+;# r3 return value
+vp8_variance8x8_ppc:
+
+    prologue
+
+    li      r9, 4
+    mtctr   r9
+
+    variance_8 6, variance8x8_loop, 0
+
+    epilogue
+
+    blr
+
+.macro transfer_4x4 I P
+    lwz     r0, 0(\I)
+    add     \I, \I, \P
+
+    lwz     r10,0(\I)
+    add     \I, \I, \P
+
+    lwz     r8, 0(\I)
+    add     \I, \I, \P
+
+    lwz     r9, 0(\I)
+
+    stw     r0,  0(r1)
+    stw     r10, 4(r1)
+    stw     r8,  8(r1)
+    stw     r9, 12(r1)
+.endm
+
+    .align 2
+;# r3 unsigned char *src_ptr
+;# r4 int  source_stride
+;# r5 unsigned char *ref_ptr
+;# r6 int  recon_stride
+;# r7 unsigned int *sse
+;#
+;# r3 return value
+vp8_variance4x4_ppc:
+
+    prologue
+
+    transfer_4x4 r3, r4
+    lvx     v4, 0, r1
+
+    transfer_4x4 r5, r6
+    lvx     v5, 0, r1
+
+    compute_sum_sse
+
+    vsumsws v8, v8, v7
+    vsumsws v9, v9, v7
+
+    stvx    v8, 0, r1
+    lwz     r3, 12(r1)
+
+    stvx    v9, 0, r1
+    lwz     r4, 12(r1)
+
+    stw     r4, 0(r7)           ;# sse
+
+    mullw   r3, r3, r3          ;# sum*sum
+    srawi   r3, r3, 4           ;# (sum*sum) >> 4
+    subf    r3, r3, r4          ;# sse - ((sum*sum) >> 4)
+
+    epilogue
+
+    blr
diff --git a/vp8/encoder/ppc/variance_subpixel_altivec.asm b/vp8/encoder/ppc/variance_subpixel_altivec.asm
new file mode 100644
index 0000000..148a8d2
--- /dev/null
+++ b/vp8/encoder/ppc/variance_subpixel_altivec.asm
@@ -0,0 +1,864 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+    .globl vp8_sub_pixel_variance4x4_ppc
+    .globl vp8_sub_pixel_variance8x8_ppc
+    .globl vp8_sub_pixel_variance8x16_ppc
+    .globl vp8_sub_pixel_variance16x8_ppc
+    .globl vp8_sub_pixel_variance16x16_ppc
+
+.macro load_c V, LABEL, OFF, R0, R1
+    lis     \R0, \LABEL@ha
+    la      \R1, \LABEL@l(\R0)
+    lvx     \V, \OFF, \R1
+.endm
+
+.macro load_vfilter V0, V1
+    load_c \V0, vfilter_b, r6, r12, r10
+
+    addi    r6,  r6, 16
+    lvx     \V1, r6, r10
+.endm
+
+.macro HProlog jump_label
+    ;# load up horizontal filter
+    slwi.   r5, r5, 4           ;# index into horizontal filter array
+
+    ;# index to the next set of vectors in the row.
+    li      r10, 16
+
+    ;# downshift by 7 ( divide by 128 ) at the end
+    vspltish v19, 7
+
+    ;# If there isn't any filtering to be done for the horizontal, then
+    ;#  just skip to the second pass.
+    beq     \jump_label
+
+    load_c v20, hfilter_b, r5, r12, r0
+
+    ;# setup constants
+    ;# v14 permutation value for alignment
+    load_c v28, b_hperm_b, 0, r12, r0
+
+    ;# index to the next set of vectors in the row.
+    li      r12, 32
+
+    ;# rounding added in on the multiply
+    vspltisw v21, 8
+    vspltisw v18, 3
+    vslw    v18, v21, v18       ;# 0x00000040000000400000004000000040
+
+    slwi.   r6, r6, 5           ;# index into vertical filter array
+.endm
+
+;# Filters a horizontal line
+;# expects:
+;#  r3  src_ptr
+;#  r4  pitch
+;#  r10 16
+;#  r12 32
+;#  v17 perm intput
+;#  v18 rounding
+;#  v19 shift
+;#  v20 filter taps
+;#  v21 tmp
+;#  v22 tmp
+;#  v23 tmp
+;#  v24 tmp
+;#  v25 tmp
+;#  v26 tmp
+;#  v27 tmp
+;#  v28 perm output
+;#
+
+.macro hfilter_8 V, hp, lp, increment_counter
+    lvsl    v17,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 9 bytes wide, output is 8 bytes.
+    lvx     v21,   0, r3
+    lvx     v22, r10, r3
+
+.if \increment_counter
+    add     r3, r3, r4
+.endif
+    vperm   v21, v21, v22, v17
+
+    vperm   v24, v21, v21, \hp  ;# v20 = 0123 1234 2345 3456
+    vperm   v25, v21, v21, \lp  ;# v21 = 4567 5678 6789 789A
+
+    vmsummbm v24, v20, v24, v18
+    vmsummbm v25, v20, v25, v18
+
+    vpkswus v24, v24, v25       ;# v24 = 0 4 8 C 1 5 9 D (16-bit)
+
+    vsrh    v24, v24, v19       ;# divide v0, v1 by 128
+
+    vpkuhus \V, v24, v24        ;# \V = scrambled 8-bit result
+.endm
+
+.macro vfilter_16 P0 P1
+    vmuleub v22, \P0, v20       ;# 64 + 4 positive taps
+    vadduhm v22, v18, v22
+    vmuloub v23, \P0, v20
+    vadduhm v23, v18, v23
+
+    vmuleub v24, \P1, v21
+    vadduhm v22, v22, v24       ;# Re = evens, saturation unnecessary
+    vmuloub v25, \P1, v21
+    vadduhm v23, v23, v25       ;# Ro = odds
+
+    vsrh    v22, v22, v19       ;# divide by 128
+    vsrh    v23, v23, v19       ;# v16 v17 = evens, odds
+    vmrghh  \P0, v22, v23       ;# v18 v19 = 16-bit result in order
+    vmrglh  v23, v22, v23
+    vpkuhus \P0, \P0, v23       ;# P0 = 8-bit result
+.endm
+
+.macro compute_sum_sse src, ref, sum, sse, t1, t2, z0
+    ;# Compute sum first.  Unpack to so signed subract
+    ;#  can be used.  Only have a half word signed
+    ;#  subract.  Do high, then low.
+    vmrghb  \t1, \z0, \src
+    vmrghb  \t2, \z0, \ref
+    vsubshs \t1, \t1, \t2
+    vsum4shs \sum, \t1, \sum
+
+    vmrglb  \t1, \z0, \src
+    vmrglb  \t2, \z0, \ref
+    vsubshs \t1, \t1, \t2
+    vsum4shs \sum, \t1, \sum
+
+    ;# Now compute sse.
+    vsububs \t1, \src, \ref
+    vsububs \t2, \ref, \src
+    vor     \t1, \t1, \t2
+
+    vmsumubm \sse, \t1, \t1, \sse
+.endm
+
+.macro variance_final sum, sse, z0, DS
+    vsumsws \sum, \sum, \z0
+    vsumsws \sse, \sse, \z0
+
+    stvx    \sum, 0, r1
+    lwz     r3, 12(r1)
+
+    stvx    \sse, 0, r1
+    lwz     r4, 12(r1)
+
+    stw     r4, 0(r9)           ;# sse
+
+    mullw   r3, r3, r3          ;# sum*sum
+    srawi   r3, r3, \DS         ;# (sum*sum) >> 8
+    subf    r3, r3, r4          ;# sse - ((sum*sum) >> 8)
+.endm
+
+.macro compute_sum_sse_16 V, increment_counter
+    load_and_align_16  v16, r7, r8, \increment_counter
+    compute_sum_sse \V, v16, v18, v19, v20, v21, v23
+.endm
+
+.macro load_and_align_16 V, R, P, increment_counter
+    lvsl    v17,  0, \R         ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v21,   0, \R
+    lvx     v22, r10, \R
+
+.if \increment_counter
+    add     \R, \R, \P
+.endif
+
+    vperm   \V, v21, v22, v17
+.endm
+
+    .align 2
+;# r3 unsigned char  *src_ptr
+;# r4 int  src_pixels_per_line
+;# r5 int  xoffset
+;# r6 int  yoffset
+;# r7 unsigned char *dst_ptr
+;# r8 int dst_pixels_per_line
+;# r9 unsigned int *sse
+;#
+;# r3 return value
+vp8_sub_pixel_variance4x4_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xf830
+    ori     r12, r12, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    HProlog second_pass_4x4_pre_copy_b
+
+    ;# Load up permutation constants
+    load_c v10, b_0123_b, 0, r12, r0
+    load_c v11, b_4567_b, 0, r12, r0
+
+    hfilter_8 v0, v10, v11, 1
+    hfilter_8 v1, v10, v11, 1
+    hfilter_8 v2, v10, v11, 1
+    hfilter_8 v3, v10, v11, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     compute_sum_sse_4x4_b
+
+    hfilter_8 v4, v10, v11, 0
+
+    b   second_pass_4x4_b
+
+second_pass_4x4_pre_copy_b:
+    slwi    r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_16 v0, r3, r4, 1
+    load_and_align_16 v1, r3, r4, 1
+    load_and_align_16 v2, r3, r4, 1
+    load_and_align_16 v3, r3, r4, 1
+    load_and_align_16 v4, r3, r4, 0
+
+second_pass_4x4_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18       ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+
+compute_sum_sse_4x4_b:
+    vspltish v18, 0             ;# sum
+    vspltish v19, 0             ;# sse
+    vspltish v23, 0             ;# unpack
+    li      r10, 16
+
+    load_and_align_16 v4, r7, r8, 1
+    load_and_align_16 v5, r7, r8, 1
+    load_and_align_16 v6, r7, r8, 1
+    load_and_align_16 v7, r7, r8, 1
+
+    vmrghb  v0, v0, v1
+    vmrghb  v1, v2, v3
+
+    vmrghb  v2, v4, v5
+    vmrghb  v3, v6, v7
+
+    load_c v10, b_hilo_b, 0, r12, r0
+
+    vperm   v0, v0, v1, v10
+    vperm   v1, v2, v3, v10
+
+    compute_sum_sse v0, v1, v18, v19, v20, v21, v23
+
+    variance_final v18, v19, v23, 4
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;# r3 unsigned char  *src_ptr
+;# r4 int  src_pixels_per_line
+;# r5 int  xoffset
+;# r6 int  yoffset
+;# r7 unsigned char *dst_ptr
+;# r8 int dst_pixels_per_line
+;# r9 unsigned int *sse
+;#
+;# r3 return value
+vp8_sub_pixel_variance8x8_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xfff0
+    ori     r12, r12, 0xffff
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    HProlog second_pass_8x8_pre_copy_b
+
+    ;# Load up permutation constants
+    load_c v10, b_0123_b, 0, r12, r0
+    load_c v11, b_4567_b, 0, r12, r0
+
+    hfilter_8 v0, v10, v11, 1
+    hfilter_8 v1, v10, v11, 1
+    hfilter_8 v2, v10, v11, 1
+    hfilter_8 v3, v10, v11, 1
+    hfilter_8 v4, v10, v11, 1
+    hfilter_8 v5, v10, v11, 1
+    hfilter_8 v6, v10, v11, 1
+    hfilter_8 v7, v10, v11, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     compute_sum_sse_8x8_b
+
+    hfilter_8 v8, v10, v11, 0
+
+    b   second_pass_8x8_b
+
+second_pass_8x8_pre_copy_b:
+    slwi.   r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_16 v0, r3, r4, 1
+    load_and_align_16 v1, r3, r4, 1
+    load_and_align_16 v2, r3, r4, 1
+    load_and_align_16 v3, r3, r4, 1
+    load_and_align_16 v4, r3, r4, 1
+    load_and_align_16 v5, r3, r4, 1
+    load_and_align_16 v6, r3, r4, 1
+    load_and_align_16 v7, r3, r4, 1
+    load_and_align_16 v8, r3, r4, 0
+
+    beq     compute_sum_sse_8x8_b
+
+second_pass_8x8_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0, v1
+    vfilter_16 v1, v2
+    vfilter_16 v2, v3
+    vfilter_16 v3, v4
+    vfilter_16 v4, v5
+    vfilter_16 v5, v6
+    vfilter_16 v6, v7
+    vfilter_16 v7, v8
+
+compute_sum_sse_8x8_b:
+    vspltish v18, 0             ;# sum
+    vspltish v19, 0             ;# sse
+    vspltish v23, 0             ;# unpack
+    li      r10, 16
+
+    vmrghb  v0, v0, v1
+    vmrghb  v1, v2, v3
+    vmrghb  v2, v4, v5
+    vmrghb  v3, v6, v7
+
+    load_and_align_16 v4,  r7, r8, 1
+    load_and_align_16 v5,  r7, r8, 1
+    load_and_align_16 v6,  r7, r8, 1
+    load_and_align_16 v7,  r7, r8, 1
+    load_and_align_16 v8,  r7, r8, 1
+    load_and_align_16 v9,  r7, r8, 1
+    load_and_align_16 v10, r7, r8, 1
+    load_and_align_16 v11, r7, r8, 0
+
+    vmrghb  v4, v4,  v5
+    vmrghb  v5, v6,  v7
+    vmrghb  v6, v8,  v9
+    vmrghb  v7, v10, v11
+
+    compute_sum_sse v0, v4, v18, v19, v20, v21, v23
+    compute_sum_sse v1, v5, v18, v19, v20, v21, v23
+    compute_sum_sse v2, v6, v18, v19, v20, v21, v23
+    compute_sum_sse v3, v7, v18, v19, v20, v21, v23
+
+    variance_final v18, v19, v23, 6
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+    blr
+
+    .align 2
+;# r3 unsigned char  *src_ptr
+;# r4 int  src_pixels_per_line
+;# r5 int  xoffset
+;# r6 int  yoffset
+;# r7 unsigned char *dst_ptr
+;# r8 int dst_pixels_per_line
+;# r9 unsigned int *sse
+;#
+;# r3 return value
+vp8_sub_pixel_variance8x16_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xfffc
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1,-32(r1)          ;# create space on the stack
+
+    HProlog second_pass_8x16_pre_copy_b
+
+    ;# Load up permutation constants
+    load_c v29, b_0123_b, 0, r12, r0
+    load_c v30, b_4567_b, 0, r12, r0
+
+    hfilter_8 v0,  v29, v30, 1
+    hfilter_8 v1,  v29, v30, 1
+    hfilter_8 v2,  v29, v30, 1
+    hfilter_8 v3,  v29, v30, 1
+    hfilter_8 v4,  v29, v30, 1
+    hfilter_8 v5,  v29, v30, 1
+    hfilter_8 v6,  v29, v30, 1
+    hfilter_8 v7,  v29, v30, 1
+    hfilter_8 v8,  v29, v30, 1
+    hfilter_8 v9,  v29, v30, 1
+    hfilter_8 v10, v29, v30, 1
+    hfilter_8 v11, v29, v30, 1
+    hfilter_8 v12, v29, v30, 1
+    hfilter_8 v13, v29, v30, 1
+    hfilter_8 v14, v29, v30, 1
+    hfilter_8 v15, v29, v30, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     compute_sum_sse_8x16_b
+
+    hfilter_8 v16, v29, v30, 0
+
+    b   second_pass_8x16_b
+
+second_pass_8x16_pre_copy_b:
+    slwi.   r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_16 v0,  r3, r4, 1
+    load_and_align_16 v1,  r3, r4, 1
+    load_and_align_16 v2,  r3, r4, 1
+    load_and_align_16 v3,  r3, r4, 1
+    load_and_align_16 v4,  r3, r4, 1
+    load_and_align_16 v5,  r3, r4, 1
+    load_and_align_16 v6,  r3, r4, 1
+    load_and_align_16 v7,  r3, r4, 1
+    load_and_align_16 v8,  r3, r4, 1
+    load_and_align_16 v9,  r3, r4, 1
+    load_and_align_16 v10, r3, r4, 1
+    load_and_align_16 v11, r3, r4, 1
+    load_and_align_16 v12, r3, r4, 1
+    load_and_align_16 v13, r3, r4, 1
+    load_and_align_16 v14, r3, r4, 1
+    load_and_align_16 v15, r3, r4, 1
+    load_and_align_16 v16, r3, r4, 0
+
+    beq     compute_sum_sse_8x16_b
+
+second_pass_8x16_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+    vfilter_16 v4,  v5
+    vfilter_16 v5,  v6
+    vfilter_16 v6,  v7
+    vfilter_16 v7,  v8
+    vfilter_16 v8,  v9
+    vfilter_16 v9,  v10
+    vfilter_16 v10, v11
+    vfilter_16 v11, v12
+    vfilter_16 v12, v13
+    vfilter_16 v13, v14
+    vfilter_16 v14, v15
+    vfilter_16 v15, v16
+
+compute_sum_sse_8x16_b:
+    vspltish v18, 0             ;# sum
+    vspltish v19, 0             ;# sse
+    vspltish v23, 0             ;# unpack
+    li      r10, 16
+
+    vmrghb  v0, v0,  v1
+    vmrghb  v1, v2,  v3
+    vmrghb  v2, v4,  v5
+    vmrghb  v3, v6,  v7
+    vmrghb  v4, v8,  v9
+    vmrghb  v5, v10, v11
+    vmrghb  v6, v12, v13
+    vmrghb  v7, v14, v15
+
+    load_and_align_16 v8,  r7, r8, 1
+    load_and_align_16 v9,  r7, r8, 1
+    load_and_align_16 v10, r7, r8, 1
+    load_and_align_16 v11, r7, r8, 1
+    load_and_align_16 v12, r7, r8, 1
+    load_and_align_16 v13, r7, r8, 1
+    load_and_align_16 v14, r7, r8, 1
+    load_and_align_16 v15, r7, r8, 1
+
+    vmrghb  v8,  v8,  v9
+    vmrghb  v9,  v10, v11
+    vmrghb  v10, v12, v13
+    vmrghb  v11, v14, v15
+
+    compute_sum_sse v0, v8,  v18, v19, v20, v21, v23
+    compute_sum_sse v1, v9,  v18, v19, v20, v21, v23
+    compute_sum_sse v2, v10, v18, v19, v20, v21, v23
+    compute_sum_sse v3, v11, v18, v19, v20, v21, v23
+
+    load_and_align_16 v8,  r7, r8, 1
+    load_and_align_16 v9,  r7, r8, 1
+    load_and_align_16 v10, r7, r8, 1
+    load_and_align_16 v11, r7, r8, 1
+    load_and_align_16 v12, r7, r8, 1
+    load_and_align_16 v13, r7, r8, 1
+    load_and_align_16 v14, r7, r8, 1
+    load_and_align_16 v15, r7, r8, 0
+
+    vmrghb  v8,  v8,  v9
+    vmrghb  v9,  v10, v11
+    vmrghb  v10, v12, v13
+    vmrghb  v11, v14, v15
+
+    compute_sum_sse v4, v8,  v18, v19, v20, v21, v23
+    compute_sum_sse v5, v9,  v18, v19, v20, v21, v23
+    compute_sum_sse v6, v10, v18, v19, v20, v21, v23
+    compute_sum_sse v7, v11, v18, v19, v20, v21, v23
+
+    variance_final v18, v19, v23, 7
+
+    addi    r1, r1, 32          ;# recover stack
+    mtspr   256, r11            ;# reset old VRSAVE
+    blr
+
+;# Filters a horizontal line
+;# expects:
+;#  r3  src_ptr
+;#  r4  pitch
+;#  r10 16
+;#  r12 32
+;#  v17 perm intput
+;#  v18 rounding
+;#  v19 shift
+;#  v20 filter taps
+;#  v21 tmp
+;#  v22 tmp
+;#  v23 tmp
+;#  v24 tmp
+;#  v25 tmp
+;#  v26 tmp
+;#  v27 tmp
+;#  v28 perm output
+;#
+.macro hfilter_16 V, increment_counter
+
+    lvsl    v17,  0, r3         ;# permutate value for alignment
+
+    ;# input to filter is 21 bytes wide, output is 16 bytes.
+    ;#  input will can span three vectors if not aligned correctly.
+    lvx     v21,   0, r3
+    lvx     v22, r10, r3
+    lvx     v23, r12, r3
+
+.if \increment_counter
+    add     r3, r3, r4
+.endif
+    vperm   v21, v21, v22, v17
+    vperm   v22, v22, v23, v17  ;# v8 v9 = 21 input pixels left-justified
+
+    ;# set 0
+    vmsummbm v24, v20, v21, v18 ;# taps times elements
+
+    ;# set 1
+    vsldoi  v23, v21, v22, 1
+    vmsummbm v25, v20, v23, v18
+
+    ;# set 2
+    vsldoi  v23, v21, v22, 2
+    vmsummbm v26, v20, v23, v18
+
+    ;# set 3
+    vsldoi  v23, v21, v22, 3
+    vmsummbm v27, v20, v23, v18
+
+    vpkswus v24, v24, v25       ;# v24 = 0 4 8 C 1 5 9 D (16-bit)
+    vpkswus v25, v26, v27       ;# v25 = 2 6 A E 3 7 B F
+
+    vsrh    v24, v24, v19       ;# divide v0, v1 by 128
+    vsrh    v25, v25, v19
+
+    vpkuhus \V, v24, v25        ;# \V = scrambled 8-bit result
+    vperm   \V, \V, v0, v28     ;# \V = correctly-ordered result
+.endm
+
+    .align 2
+;# r3 unsigned char  *src_ptr
+;# r4 int  src_pixels_per_line
+;# r5 int  xoffset
+;# r6 int  yoffset
+;# r7 unsigned char *dst_ptr
+;# r8 int dst_pixels_per_line
+;# r9 unsigned int *sse
+;#
+;# r3 return value
+vp8_sub_pixel_variance16x8_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1, -32(r1)         ;# create space on the stack
+
+    HProlog second_pass_16x8_pre_copy_b
+
+    hfilter_16 v0, 1
+    hfilter_16 v1, 1
+    hfilter_16 v2, 1
+    hfilter_16 v3, 1
+    hfilter_16 v4, 1
+    hfilter_16 v5, 1
+    hfilter_16 v6, 1
+    hfilter_16 v7, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     compute_sum_sse_16x8_b
+
+    hfilter_16 v8, 0
+
+    b   second_pass_16x8_b
+
+second_pass_16x8_pre_copy_b:
+    slwi.   r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_16  v0,  r3, r4, 1
+    load_and_align_16  v1,  r3, r4, 1
+    load_and_align_16  v2,  r3, r4, 1
+    load_and_align_16  v3,  r3, r4, 1
+    load_and_align_16  v4,  r3, r4, 1
+    load_and_align_16  v5,  r3, r4, 1
+    load_and_align_16  v6,  r3, r4, 1
+    load_and_align_16  v7,  r3, r4, 1
+    load_and_align_16  v8,  r3, r4, 1
+
+    beq     compute_sum_sse_16x8_b
+
+second_pass_16x8_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+    vfilter_16 v4,  v5
+    vfilter_16 v5,  v6
+    vfilter_16 v6,  v7
+    vfilter_16 v7,  v8
+
+compute_sum_sse_16x8_b:
+    vspltish v18, 0             ;# sum
+    vspltish v19, 0             ;# sse
+    vspltish v23, 0             ;# unpack
+    li      r10, 16
+
+    compute_sum_sse_16 v0, 1
+    compute_sum_sse_16 v1, 1
+    compute_sum_sse_16 v2, 1
+    compute_sum_sse_16 v3, 1
+    compute_sum_sse_16 v4, 1
+    compute_sum_sse_16 v5, 1
+    compute_sum_sse_16 v6, 1
+    compute_sum_sse_16 v7, 0
+
+    variance_final v18, v19, v23, 7
+
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .align 2
+;# r3 unsigned char  *src_ptr
+;# r4 int  src_pixels_per_line
+;# r5 int  xoffset
+;# r6 int  yoffset
+;# r7 unsigned char *dst_ptr
+;# r8 int dst_pixels_per_line
+;# r9 unsigned int *sse
+;#
+;# r3 return value
+vp8_sub_pixel_variance16x16_ppc:
+    mfspr   r11, 256            ;# get old VRSAVE
+    oris    r12, r11, 0xffff
+    ori     r12, r12, 0xfff8
+    mtspr   256, r12            ;# set VRSAVE
+
+    stwu    r1, -32(r1)         ;# create space on the stack
+
+    HProlog second_pass_16x16_pre_copy_b
+
+    hfilter_16 v0,  1
+    hfilter_16 v1,  1
+    hfilter_16 v2,  1
+    hfilter_16 v3,  1
+    hfilter_16 v4,  1
+    hfilter_16 v5,  1
+    hfilter_16 v6,  1
+    hfilter_16 v7,  1
+    hfilter_16 v8,  1
+    hfilter_16 v9,  1
+    hfilter_16 v10, 1
+    hfilter_16 v11, 1
+    hfilter_16 v12, 1
+    hfilter_16 v13, 1
+    hfilter_16 v14, 1
+    hfilter_16 v15, 1
+
+    ;# Finished filtering main horizontal block.  If there is no
+    ;#  vertical filtering, jump to storing the data.  Otherwise
+    ;#  load up and filter the additional line that is needed
+    ;#  for the vertical filter.
+    beq     compute_sum_sse_16x16_b
+
+    hfilter_16 v16, 0
+
+    b   second_pass_16x16_b
+
+second_pass_16x16_pre_copy_b:
+    slwi.   r6, r6, 5           ;# index into vertical filter array
+
+    load_and_align_16  v0,  r3, r4, 1
+    load_and_align_16  v1,  r3, r4, 1
+    load_and_align_16  v2,  r3, r4, 1
+    load_and_align_16  v3,  r3, r4, 1
+    load_and_align_16  v4,  r3, r4, 1
+    load_and_align_16  v5,  r3, r4, 1
+    load_and_align_16  v6,  r3, r4, 1
+    load_and_align_16  v7,  r3, r4, 1
+    load_and_align_16  v8,  r3, r4, 1
+    load_and_align_16  v9,  r3, r4, 1
+    load_and_align_16  v10, r3, r4, 1
+    load_and_align_16  v11, r3, r4, 1
+    load_and_align_16  v12, r3, r4, 1
+    load_and_align_16  v13, r3, r4, 1
+    load_and_align_16  v14, r3, r4, 1
+    load_and_align_16  v15, r3, r4, 1
+    load_and_align_16  v16, r3, r4, 0
+
+    beq     compute_sum_sse_16x16_b
+
+second_pass_16x16_b:
+    vspltish v20, 8
+    vspltish v18, 3
+    vslh    v18, v20, v18   ;# 0x0040 0040 0040 0040 0040 0040 0040 0040
+
+    load_vfilter v20, v21
+
+    vfilter_16 v0,  v1
+    vfilter_16 v1,  v2
+    vfilter_16 v2,  v3
+    vfilter_16 v3,  v4
+    vfilter_16 v4,  v5
+    vfilter_16 v5,  v6
+    vfilter_16 v6,  v7
+    vfilter_16 v7,  v8
+    vfilter_16 v8,  v9
+    vfilter_16 v9,  v10
+    vfilter_16 v10, v11
+    vfilter_16 v11, v12
+    vfilter_16 v12, v13
+    vfilter_16 v13, v14
+    vfilter_16 v14, v15
+    vfilter_16 v15, v16
+
+compute_sum_sse_16x16_b:
+    vspltish v18, 0             ;# sum
+    vspltish v19, 0             ;# sse
+    vspltish v23, 0             ;# unpack
+    li      r10, 16
+
+    compute_sum_sse_16 v0,  1
+    compute_sum_sse_16 v1,  1
+    compute_sum_sse_16 v2,  1
+    compute_sum_sse_16 v3,  1
+    compute_sum_sse_16 v4,  1
+    compute_sum_sse_16 v5,  1
+    compute_sum_sse_16 v6,  1
+    compute_sum_sse_16 v7,  1
+    compute_sum_sse_16 v8,  1
+    compute_sum_sse_16 v9,  1
+    compute_sum_sse_16 v10, 1
+    compute_sum_sse_16 v11, 1
+    compute_sum_sse_16 v12, 1
+    compute_sum_sse_16 v13, 1
+    compute_sum_sse_16 v14, 1
+    compute_sum_sse_16 v15, 0
+
+    variance_final v18, v19, v23, 8
+
+    addi    r1, r1, 32          ;# recover stack
+
+    mtspr   256, r11            ;# reset old VRSAVE
+
+    blr
+
+    .data
+
+    .align 4
+hfilter_b:
+    .byte   128,  0,  0,  0,128,  0,  0,  0,128,  0,  0,  0,128,  0,  0,  0
+    .byte   112, 16,  0,  0,112, 16,  0,  0,112, 16,  0,  0,112, 16,  0,  0
+    .byte    96, 32,  0,  0, 96, 32,  0,  0, 96, 32,  0,  0, 96, 32,  0,  0
+    .byte    80, 48,  0,  0, 80, 48,  0,  0, 80, 48,  0,  0, 80, 48,  0,  0
+    .byte    64, 64,  0,  0, 64, 64,  0,  0, 64, 64,  0,  0, 64, 64,  0,  0
+    .byte    48, 80,  0,  0, 48, 80,  0,  0, 48, 80,  0,  0, 48, 80,  0,  0
+    .byte    32, 96,  0,  0, 32, 96,  0,  0, 32, 96,  0,  0, 32, 96,  0,  0
+    .byte    16,112,  0,  0, 16,112,  0,  0, 16,112,  0,  0, 16,112,  0,  0
+
+    .align 4
+vfilter_b:
+    .byte   128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128
+    .byte     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    .byte   112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112
+    .byte    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+    .byte    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96
+    .byte    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
+    .byte    80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
+    .byte    48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
+    .byte    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+    .byte    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+    .byte    48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48
+    .byte    80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80
+    .byte    32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32
+    .byte    96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96
+    .byte    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+    .byte   112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112
+
+    .align 4
+b_hperm_b:
+    .byte     0,  4,  8, 12,  1,  5,  9, 13,  2,  6, 10, 14,  3,  7, 11, 15
+
+    .align 4
+b_0123_b:
+    .byte     0,  1,  2,  3,  1,  2,  3,  4,  2,  3,  4,  5,  3,  4,  5,  6
+
+    .align 4
+b_4567_b:
+    .byte     4,  5,  6,  7,  5,  6,  7,  8,  6,  7,  8,  9,  7,  8,  9, 10
+
+b_hilo_b:
+    .byte     0,  1,  2,  3,  4,  5,  6,  7, 16, 17, 18, 19, 20, 21, 22, 23
diff --git a/vp8/encoder/preproc.c b/vp8/encoder/preproc.c
new file mode 100644
index 0000000..d2a13dc
--- /dev/null
+++ b/vp8/encoder/preproc.c
@@ -0,0 +1,250 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/****************************************************************************
+*
+*   Module Title :     preproc.c
+*
+*   Description  :     Simple pre-processor.
+*
+****************************************************************************/
+
+/****************************************************************************
+*  Header Files
+****************************************************************************/
+
+#include "memory.h"
+#include "preproc7.h"
+#include "vpx_mem/vpx_mem.h"
+
+/****************************************************************************
+*  Macros
+****************************************************************************/
+#define FRAMECOUNT 7
+#define ROUNDUP32(X) ( ( ( (unsigned long) X ) + 31 )&( 0xFFFFFFE0 ) )
+
+/****************************************************************************
+*  Imports
+****************************************************************************/
+extern void vp8_get_processor_flags(int *mmx_enabled, int *xmm_enabled, int *wmt_enabled);
+
+/****************************************************************************
+*  Exported Global Variables
+****************************************************************************/
+void (*temp_filter)(pre_proc_instance *ppi, unsigned char *s, unsigned char *d, int bytes, int strength);
+void temp_filter_mmx
+(
+    pre_proc_instance *ppi,
+    unsigned char *s,
+    unsigned char *d,
+    int bytes,
+    int strength
+);
+void temp_filter_wmt
+(
+    pre_proc_instance *ppi,
+    unsigned char *s,
+    unsigned char *d,
+    int bytes,
+    int strength
+);
+
+/****************************************************************************
+ *
+ *  ROUTINE       : temp_filter_c
+ *
+ *  INPUTS        : pre_proc_instance *ppi : Pointer to pre-processor instance.
+ *                  unsigned char *s     : Pointer to source frame.
+ *                  unsigned char *d     : Pointer to destination frame.
+ *                  int bytes            : Number of bytes to filter.
+ *                  int strength         : Strength of filter to apply.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Performs a closesness adjusted temporarl blur
+ *
+ *  SPECIAL NOTES : Destination frame can be same as source frame.
+ *
+ ****************************************************************************/
+void temp_filter_c
+(
+    pre_proc_instance *ppi,
+    unsigned char *s,
+    unsigned char *d,
+    int bytes,
+    int strength
+)
+{
+    int byte = 0;
+    unsigned char *frameptr = ppi->frame_buffer;
+
+    if (ppi->frame == 0)
+    {
+        do
+        {
+            int frame = 0;
+
+            do
+            {
+                *frameptr = s[byte];
+                ++frameptr;
+                ++frame;
+            }
+            while (frame < FRAMECOUNT);
+
+            d[byte] = s[byte];
+
+            ++byte;
+        }
+        while (byte < bytes);
+    }
+    else
+    {
+        int modifier;
+        int offset = (ppi->frame % FRAMECOUNT);
+
+        do
+        {
+            int accumulator = 0;
+            int count = 0;
+            int frame = 0;
+
+            frameptr[offset] = s[byte];
+
+            do
+            {
+                int pixel_value = *frameptr;
+
+                modifier   = s[byte];
+                modifier  -= pixel_value;
+                modifier  *= modifier;
+                modifier >>= strength;
+                modifier  *= 3;
+
+                if (modifier > 16)
+                    modifier = 16;
+
+                modifier = 16 - modifier;
+
+                accumulator += modifier * pixel_value;
+
+                count += modifier;
+
+                frameptr++;
+
+                ++frame;
+            }
+            while (frame < FRAMECOUNT);
+
+            accumulator += (count >> 1);
+            accumulator *= ppi->fixed_divide[count];
+            accumulator >>= 16;
+
+            d[byte] = accumulator;
+
+            ++byte;
+        }
+        while (byte < bytes);
+    }
+
+    ++ppi->frame;
+}
+/****************************************************************************
+ *
+ *  ROUTINE       : delete_pre_proc
+ *
+ *  INPUTS        : pre_proc_instance *ppi : Pointer to pre-processor instance.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Deletes a pre-processing instance.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+void delete_pre_proc(pre_proc_instance *ppi)
+{
+    if (ppi->frame_buffer_alloc)
+        vpx_free(ppi->frame_buffer_alloc);
+
+    ppi->frame_buffer_alloc = 0;
+    ppi->frame_buffer      = 0;
+
+    if (ppi->fixed_divide_alloc)
+        vpx_free(ppi->fixed_divide_alloc);
+
+    ppi->fixed_divide_alloc = 0;
+    ppi->fixed_divide      = 0;
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : init_pre_proc
+ *
+ *  INPUTS        : pre_proc_instance *ppi : Pointer to pre-processor instance.
+ *                  int frame_size        : Number of bytes in one frame.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : int: 1 if successful, 0 if failed.
+ *
+ *  FUNCTION      : Initializes prepprocessor instance.
+ *
+ *  SPECIAL NOTES : None.
+ *
+ ****************************************************************************/
+int init_pre_proc7(pre_proc_instance *ppi, int frame_size)
+{
+    int i;
+    int mmx_enabled;
+    int xmm_enabled;
+    int wmt_enabled;
+
+    vp8_get_processor_flags(&mmx_enabled, &xmm_enabled, &wmt_enabled);
+
+    if (wmt_enabled)
+        temp_filter = temp_filter_wmt;
+    else if (mmx_enabled)
+        temp_filter = temp_filter_mmx;
+    else
+        temp_filter = temp_filter_c;
+
+
+    delete_pre_proc(ppi);
+
+    ppi->frame_buffer_alloc = vpx_malloc(32 + frame_size * FRAMECOUNT * sizeof(unsigned char));
+
+    if (!ppi->frame_buffer_alloc)
+    {
+        delete_pre_proc(ppi);
+        return 0;
+    }
+
+    ppi->frame_buffer = (unsigned char *) ROUNDUP32(ppi->frame_buffer_alloc);
+
+    ppi->fixed_divide_alloc = vpx_malloc(32 + 255 * sizeof(unsigned int));
+
+    if (!ppi->fixed_divide_alloc)
+    {
+        delete_pre_proc(ppi);
+        return 0;
+    }
+
+    ppi->fixed_divide = (unsigned int *) ROUNDUP32(ppi->fixed_divide_alloc);
+
+    for (i = 1; i < 255; i++)
+        ppi->fixed_divide[i] = 0x10000 / i;
+
+    return 1;
+}
diff --git a/vp8/encoder/psnr.c b/vp8/encoder/psnr.c
new file mode 100644
index 0000000..0e34cec
--- /dev/null
+++ b/vp8/encoder/psnr.c
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_scale/yv12config.h"
+#include "math.h"
+#include "systemdependent.h" /* for vp8_clear_system_state() */
+
+#define MAX_PSNR 60
+
+double vp8_mse2psnr(double Samples, double Peak, double Mse)
+{
+    double psnr;
+
+    if ((double)Mse > 0.0)
+        psnr = 10.0 * log10(Peak * Peak * Samples / Mse);
+    else
+        psnr = MAX_PSNR;      // Limit to prevent / 0
+
+    if (psnr > MAX_PSNR)
+        psnr = MAX_PSNR;
+
+    return psnr;
+}
+
+double vp8_calc_psnr(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, double *YPsnr, double *UPsnr, double *VPsnr, double *sq_error)
+{
+    int i, j;
+    int Diff;
+    double frame_psnr;
+    double Total;
+    double grand_total;
+    unsigned char *src = source->y_buffer;
+    unsigned char *dst = dest->y_buffer;
+
+    Total = 0.0;
+    grand_total = 0.0;
+
+    // Loop throught the Y plane raw and reconstruction data summing (square differences)
+    for (i = 0; i < source->y_height; i++)
+    {
+
+        for (j = 0; j < source->y_width; j++)
+        {
+            Diff        = (int)(src[j]) - (int)(dst[j]);
+            Total      += Diff * Diff;
+        }
+
+        src += source->y_stride;
+        dst += dest->y_stride;
+    }
+
+    // Work out Y PSNR
+    *YPsnr = vp8_mse2psnr(source->y_height * source->y_width, 255.0, Total);
+    grand_total += Total;
+    Total = 0;
+
+
+    // Loop through the U plane
+    src = source->u_buffer;
+    dst = dest->u_buffer;
+
+    for (i = 0; i < source->uv_height; i++)
+    {
+
+        for (j = 0; j < source->uv_width; j++)
+        {
+            Diff        = (int)(src[j]) - (int)(dst[j]);
+            Total      += Diff * Diff;
+        }
+
+        src += source->uv_stride;
+        dst += dest->uv_stride;
+    }
+
+    // Work out U PSNR
+    *UPsnr = vp8_mse2psnr(source->uv_height * source->uv_width, 255.0, Total);
+    grand_total += Total;
+    Total = 0;
+
+
+    // V PSNR
+    src = source->v_buffer;
+    dst = dest->v_buffer;
+
+    for (i = 0; i < source->uv_height; i++)
+    {
+
+        for (j = 0; j < source->uv_width; j++)
+        {
+            Diff        = (int)(src[j]) - (int)(dst[j]);
+            Total      += Diff * Diff;
+        }
+
+        src += source->uv_stride;
+        dst += dest->uv_stride;
+    }
+
+    // Work out UV PSNR
+    *VPsnr = vp8_mse2psnr(source->uv_height * source->uv_width, 255.0, Total);
+    grand_total += Total;
+    Total = 0;
+
+    // Work out total PSNR
+    frame_psnr = vp8_mse2psnr(source->y_height * source->y_width * 3 / 2 , 255.0, grand_total);
+
+    *sq_error = 1.0 * grand_total;
+
+    return frame_psnr;
+}
diff --git a/vp8/encoder/psnr.h b/vp8/encoder/psnr.h
new file mode 100644
index 0000000..9f6ca0b
--- /dev/null
+++ b/vp8/encoder/psnr.h
@@ -0,0 +1,17 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_PSNR_H
+#define __INC_PSNR_H
+
+extern double vp8_mse2psnr(double Samples, double Peak, double Mse);
+extern double vp8_calc_psnr(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, double *YPsnr, double *UPsnr, double *VPsnr, double *sq_error);
+
+#endif
diff --git a/vp8/encoder/quantize.c b/vp8/encoder/quantize.c
new file mode 100644
index 0000000..6028ebf
--- /dev/null
+++ b/vp8/encoder/quantize.c
@@ -0,0 +1,249 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <math.h>
+#include "vpx_mem/vpx_mem.h"
+
+#include "quantize.h"
+#include "entropy.h"
+#include "predictdc.h"
+
+void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d)
+{
+    int i, rc, eob;
+    int zbin;
+    int x, y, z, sz;
+    short *coeff_ptr  = &b->coeff[0];
+    short *zbin_ptr   = &b->zbin[0][0];
+    short *round_ptr  = &b->round[0][0];
+    short *quant_ptr  = &b->quant[0][0];
+    short *qcoeff_ptr = d->qcoeff;
+    short *dqcoeff_ptr = d->dqcoeff;
+    short *dequant_ptr = &d->dequant[0][0];
+
+    vpx_memset(qcoeff_ptr, 0, 32);
+    vpx_memset(dqcoeff_ptr, 0, 32);
+
+    eob = -1;
+
+    for (i = 0; i < 16; i++)
+    {
+        rc   = vp8_default_zig_zag1d[i];
+        z    = coeff_ptr[rc];
+        zbin = zbin_ptr[rc] ;
+
+        sz = (z >> 31);                                 // sign of z
+        x  = (z ^ sz) - sz;                             // x = abs(z)
+
+        if (x >= zbin)
+        {
+            y  = ((x + round_ptr[rc]) * quant_ptr[rc]) >> 16; // quantize (x)
+            x  = (y ^ sz) - sz;                         // get the sign back
+            qcoeff_ptr[rc] = x;                          // write to destination
+            dqcoeff_ptr[rc] = x * dequant_ptr[rc];        // dequantized value
+
+            if (y)
+            {
+                eob = i;                                // last nonzero coeffs
+            }
+        }
+    }
+
+    d->eob = eob + 1;
+
+}
+
+void vp8_regular_quantize_b(BLOCK *b, BLOCKD *d)
+{
+    int i, rc, eob;
+    int zbin;
+    int x, y, z, sz;
+    short *zbin_boost_ptr = &b->zrun_zbin_boost[0];
+    short *coeff_ptr  = &b->coeff[0];
+    short *zbin_ptr   = &b->zbin[0][0];
+    short *round_ptr  = &b->round[0][0];
+    short *quant_ptr  = &b->quant[0][0];
+    short *qcoeff_ptr = d->qcoeff;
+    short *dqcoeff_ptr = d->dqcoeff;
+    short *dequant_ptr = &d->dequant[0][0];
+    short zbin_oq_value = b->zbin_extra;
+
+    vpx_memset(qcoeff_ptr, 0, 32);
+    vpx_memset(dqcoeff_ptr, 0, 32);
+
+    eob = -1;
+
+    for (i = 0; i < 16; i++)
+    {
+        rc   = vp8_default_zig_zag1d[i];
+        z    = coeff_ptr[rc];
+
+        //if ( i == 0 )
+        //    zbin = zbin_ptr[rc] + *zbin_boost_ptr + zbin_oq_value/2;
+        //else
+        zbin = zbin_ptr[rc] + *zbin_boost_ptr + zbin_oq_value;
+
+        zbin_boost_ptr ++;
+        sz = (z >> 31);                                 // sign of z
+        x  = (z ^ sz) - sz;                             // x = abs(z)
+
+        if (x >= zbin)
+        {
+            y  = ((x + round_ptr[rc]) * quant_ptr[rc]) >> 16; // quantize (x)
+            x  = (y ^ sz) - sz;                         // get the sign back
+            qcoeff_ptr[rc]  = x;                         // write to destination
+            dqcoeff_ptr[rc] = x * dequant_ptr[rc];        // dequantized value
+
+            if (y)
+            {
+                eob = i;                                // last nonzero coeffs
+                zbin_boost_ptr = &b->zrun_zbin_boost[0];    // reset zero runlength
+            }
+        }
+    }
+
+    d->eob = eob + 1;
+}
+void vp8_quantize_mby(MACROBLOCK *x)
+{
+    int i;
+
+    if (x->e_mbd.mbmi.mode != B_PRED && x->e_mbd.mbmi.mode != SPLITMV)
+    {
+        for (i = 0; i < 16; i++)
+        {
+            x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+            x->e_mbd.mbmi.mb_skip_coeff &= (x->e_mbd.block[i].eob < 2);
+        }
+
+        x->quantize_b(&x->block[24], &x->e_mbd.block[24]);
+        x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[24].eob);
+
+    }
+    else
+    {
+        for (i = 0; i < 16; i++)
+        {
+            x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+            x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+        }
+    }
+}
+
+void vp8_quantize_mb(MACROBLOCK *x)
+{
+    int i;
+
+    x->e_mbd.mbmi.mb_skip_coeff = 1;
+
+    if (x->e_mbd.mbmi.mode != B_PRED && x->e_mbd.mbmi.mode != SPLITMV)
+    {
+        for (i = 0; i < 16; i++)
+        {
+            x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+            x->e_mbd.mbmi.mb_skip_coeff &= (x->e_mbd.block[i].eob < 2);
+        }
+
+        for (i = 16; i < 25; i++)
+        {
+            x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+            x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+        }
+    }
+    else
+    {
+        for (i = 0; i < 24; i++)
+        {
+            x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+            x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+        }
+    }
+
+}
+
+
+void vp8_quantize_mbuv(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 16; i < 24; i++)
+    {
+        x->quantize_b(&x->block[i], &x->e_mbd.block[i]);
+        x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+    }
+}
+
+// This function is not currently called
+void vp8_quantize_mbrd(MACROBLOCK *x)
+{
+    int i;
+
+    x->e_mbd.mbmi.mb_skip_coeff = 1;
+
+    if (x->e_mbd.mbmi.mode != B_PRED && x->e_mbd.mbmi.mode != SPLITMV)
+    {
+        for (i = 0; i < 16; i++)
+        {
+            x->quantize_brd(&x->block[i], &x->e_mbd.block[i]);
+            x->e_mbd.mbmi.mb_skip_coeff &= (x->e_mbd.block[i].eob < 2);
+        }
+
+        for (i = 16; i < 25; i++)
+        {
+            x->quantize_brd(&x->block[i], &x->e_mbd.block[i]);
+            x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+        }
+    }
+    else
+    {
+        for (i = 0; i < 24; i++)
+        {
+            x->quantize_brd(&x->block[i], &x->e_mbd.block[i]);
+            x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+        }
+    }
+}
+
+void vp8_quantize_mbuvrd(MACROBLOCK *x)
+{
+    int i;
+
+    for (i = 16; i < 24; i++)
+    {
+        x->quantize_brd(&x->block[i], &x->e_mbd.block[i]);
+        x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+    }
+}
+
+void vp8_quantize_mbyrd(MACROBLOCK *x)
+{
+    int i;
+
+    if (x->e_mbd.mbmi.mode != B_PRED && x->e_mbd.mbmi.mode != SPLITMV)
+    {
+        for (i = 0; i < 16; i++)
+        {
+            x->quantize_brd(&x->block[i], &x->e_mbd.block[i]);
+            x->e_mbd.mbmi.mb_skip_coeff &= (x->e_mbd.block[i].eob < 2);
+        }
+
+        x->quantize_brd(&x->block[24], &x->e_mbd.block[24]);
+        x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[24].eob);
+
+    }
+    else
+    {
+        for (i = 0; i < 16; i++)
+        {
+            x->quantize_brd(&x->block[i], &x->e_mbd.block[i]);
+            x->e_mbd.mbmi.mb_skip_coeff &= (!x->e_mbd.block[i].eob);
+        }
+    }
+}
diff --git a/vp8/encoder/quantize.h b/vp8/encoder/quantize.h
new file mode 100644
index 0000000..868e8e3
--- /dev/null
+++ b/vp8/encoder/quantize.h
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_QUANTIZE_H
+#define __INC_QUANTIZE_H
+
+#include "block.h"
+
+#define prototype_quantize_block(sym) \
+    void (sym)(BLOCK *b,BLOCKD *d)
+
+#if ARCH_ARM
+#include "arm/quantize_arm.h"
+#endif
+
+#ifndef vp8_quantize_quantb
+#define vp8_quantize_quantb vp8_regular_quantize_b
+#endif
+extern prototype_quantize_block(vp8_quantize_quantb);
+
+#ifndef vp8_quantize_fastquantb
+#define vp8_quantize_fastquantb vp8_fast_quantize_b_c
+#endif
+extern prototype_quantize_block(vp8_quantize_fastquantb);
+
+typedef struct
+{
+    prototype_quantize_block(*quantb);
+    prototype_quantize_block(*fastquantb);
+} vp8_quantize_rtcd_vtable_t;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define QUANTIZE_INVOKE(ctx,fn) (ctx)->fn
+#else
+#define QUANTIZE_INVOKE(ctx,fn) vp8_quantize_##fn
+#endif
+
+extern void vp8_quantize_mb(MACROBLOCK *x);
+extern void vp8_quantize_mbuv(MACROBLOCK *x);
+extern void vp8_quantize_mby(MACROBLOCK *x);
+extern void vp8_quantize_mbyrd(MACROBLOCK *x);
+extern void vp8_quantize_mbuvrd(MACROBLOCK *x);
+extern void vp8_quantize_mbrd(MACROBLOCK *x);
+
+#endif
diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c
new file mode 100644
index 0000000..05040d3
--- /dev/null
+++ b/vp8/encoder/ratectrl.c
@@ -0,0 +1,1552 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+
+#include "math.h"
+#include "common.h"
+#include "ratectrl.h"
+#include "entropymode.h"
+#include "vpx_mem/vpx_mem.h"
+#include "systemdependent.h"
+#include "encodemv.h"
+
+
+#define MIN_BPB_FACTOR          0.01
+#define MAX_BPB_FACTOR          50
+
+extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
+extern const MV_REFERENCE_FRAME vp8_ref_frame_order[MAX_MODES];
+
+
+
+#ifdef MODE_STATS
+extern int y_modes[5];
+extern int uv_modes[4];
+extern int b_modes[10];
+
+extern int inter_y_modes[10];
+extern int inter_uv_modes[4];
+extern int inter_b_modes[10];
+#endif
+
+// Bits Per MB at different Q (Multiplied by 512)
+#define BPER_MB_NORMBITS    9
+
+const int vp8_bits_per_mb[2][QINDEX_RANGE] =
+{
+    // (Updated 19 March 08) Baseline estimate of INTRA-frame Bits Per MB at each Q:
+    {
+        674781, 606845, 553905, 524293, 500428, 452540, 435379, 414719,
+        390970, 371082, 359416, 341807, 336957, 317263, 303724, 298402,
+        285688, 275237, 268455, 262560, 256038, 248734, 241087, 237615,
+        229247, 225211, 219112, 213920, 211559, 202714, 198482, 193401,
+        187866, 183453, 179212, 175965, 171852, 167235, 163972, 160560,
+        156032, 154349, 151390, 148725, 145708, 142311, 139981, 137700,
+        134084, 131863, 129746, 128498, 126077, 123461, 121290, 117782,
+        114883, 112332, 108410, 105685, 103434, 101192,  98587,  95959,
+        94059,  92017,  89970,  87936,  86142,  84801,  82736,  81106,
+        79668,  78135,  76641,  75103,  73943,  72693,  71401,  70098,
+        69165,  67901,  67170,  65987,  64923,  63534,  62378,  61302,
+        59921,  58941,  57844,  56782,  55960,  54973,  54257,  53454,
+        52230,  50938,  49962,  49190,  48288,  47270,  46738,  46037,
+        45020,  44027,  43216,  42287,  41594,  40702,  40081,  39414,
+        38282,  37627,  36987,  36375,  35808,  35236,  34710,  34162,
+        33659,  33327,  32751,  32384,  31936,  31461,  30982,  30582,
+    },
+
+    // (Updated 19 March 08) Baseline estimate of INTER-frame Bits Per MB at each Q:
+    {
+        497401, 426316, 372064, 352732, 335763, 283921, 273848, 253321,
+        233181, 217727, 210030, 196685, 194836, 178396, 167753, 164116,
+        154119, 146929, 142254, 138488, 133591, 127741, 123166, 120226,
+        114188, 111756, 107882, 104749, 102522,  96451,  94424,  90905,
+        87286,  84931,  82111,  80534,  77610,  74700,  73037,  70715,
+        68006,  67235,  65374,  64009,  62134,  60180,  59105,  57691,
+        55509,  54512,  53318,  52693,  51194,  49840,  48944,  46980,
+        45668,  44177,  42348,  40994,  39859,  38889,  37717,  36391,
+        35482,  34622,  33795,  32756,  32002,  31492,  30573,  29737,
+        29152,  28514,  27941,  27356,  26859,  26329,  25874,  25364,
+        24957,  24510,  24290,  23689,  23380,  22845,  22481,  22066,
+        21587,  21219,  20880,  20452,  20260,  19926,  19661,  19334,
+        18915,  18391,  18046,  17833,  17441,  17105,  16888,  16729,
+        16383,  16023,  15706,  15442,  15222,  14938,  14673,  14452,
+        14005,  13807,  13611,  13447,  13223,  13102,  12963,  12801,
+        12627,  12534,  12356,  12228,  12056,  11907,  11746,  11643,
+    }
+};
+
+const int vp8_kf_boost_qadjustment[QINDEX_RANGE] =
+{
+    128, 129, 130, 131, 132, 133, 134, 135,
+    136, 137, 138, 139, 140, 141, 142, 143,
+    144, 145, 146, 147, 148, 149, 150, 151,
+    152, 153, 154, 155, 156, 157, 158, 159,
+    160, 161, 162, 163, 164, 165, 166, 167,
+    168, 169, 170, 171, 172, 173, 174, 175,
+    176, 177, 178, 179, 180, 181, 182, 183,
+    184, 185, 186, 187, 188, 189, 190, 191,
+    192, 193, 194, 195, 196, 197, 198, 199,
+    200, 200, 201, 201, 202, 203, 203, 203,
+    204, 204, 205, 205, 206, 206, 207, 207,
+    208, 208, 209, 209, 210, 210, 211, 211,
+    212, 212, 213, 213, 214, 214, 215, 215,
+    216, 216, 217, 217, 218, 218, 219, 219,
+    220, 220, 220, 220, 220, 220, 220, 220,
+    220, 220, 220, 220, 220, 220, 220, 220,
+};
+
+//#define GFQ_ADJUSTMENT (Q+100)
+#define GFQ_ADJUSTMENT vp8_gf_boost_qadjustment[Q]
+const int vp8_gf_boost_qadjustment[QINDEX_RANGE] =
+{
+    80, 82, 84, 86, 88, 90, 92, 94,
+    96, 97, 98, 99, 100, 101, 102, 103,
+    104, 105, 106, 107, 108, 109, 110, 111,
+    112, 113, 114, 115, 116, 117, 118, 119,
+    120, 121, 122, 123, 124, 125, 126, 127,
+    128, 129, 130, 131, 132, 133, 134, 135,
+    136, 137, 138, 139, 140, 141, 142, 143,
+    144, 145, 146, 147, 148, 149, 150, 151,
+    152, 153, 154, 155, 156, 157, 158, 159,
+    160, 161, 162, 163, 164, 165, 166, 167,
+    168, 169, 170, 171, 172, 173, 174, 175,
+    176, 177, 178, 179, 180, 181, 182, 183,
+    184, 184, 185, 185, 186, 186, 187, 187,
+    188, 188, 189, 189, 190, 190, 191, 191,
+    192, 192, 193, 193, 194, 194, 194, 194,
+    195, 195, 196, 196, 197, 197, 198, 198
+};
+
+/*
+const int vp8_gf_boost_qadjustment[QINDEX_RANGE] =
+{
+    100,101,102,103,104,105,105,106,
+    106,107,107,108,109,109,110,111,
+    112,113,114,115,116,117,118,119,
+    120,121,122,123,124,125,126,127,
+    128,129,130,131,132,133,134,135,
+    136,137,138,139,140,141,142,143,
+    144,145,146,147,148,149,150,151,
+    152,153,154,155,156,157,158,159,
+    160,161,162,163,164,165,166,167,
+    168,169,170,170,171,171,172,172,
+    173,173,173,174,174,174,175,175,
+    175,176,176,176,177,177,177,177,
+    178,178,179,179,180,180,181,181,
+    182,182,183,183,184,184,185,185,
+    186,186,187,187,188,188,189,189,
+    190,190,191,191,192,192,193,193,
+};
+*/
+
+const int vp8_kf_gf_boost_qlimits[QINDEX_RANGE] =
+{
+    150, 155, 160, 165, 170, 175, 180, 185,
+    190, 195, 200, 205, 210, 215, 220, 225,
+    230, 235, 240, 245, 250, 255, 260, 265,
+    270, 275, 280, 285, 290, 295, 300, 305,
+    310, 320, 330, 340, 350, 360, 370, 380,
+    390, 400, 410, 420, 430, 440, 450, 460,
+    470, 480, 490, 500, 510, 520, 530, 540,
+    550, 560, 570, 580, 590, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+    600, 600, 600, 600, 600, 600, 600, 600,
+};
+
+// % adjustment to target kf size based on seperation from previous frame
+const int vp8_kf_boost_seperationt_adjustment[16] =
+{
+    30,   40,   50,   55,   60,   65,   70,   75,
+    80,   85,   90,   95,  100,  100,  100,  100,
+};
+
+
+const int vp8_gf_adjust_table[101] =
+{
+    100,
+    115, 130, 145, 160, 175, 190, 200, 210, 220, 230,
+    240, 260, 270, 280, 290, 300, 310, 320, 330, 340,
+    350, 360, 370, 380, 390, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+    400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+};
+
+const int vp8_gf_intra_useage_adjustment[20] =
+{
+    125, 120, 115, 110, 105, 100,  95,  85,  80,  75,
+    70,  65,  60,  55,  50,  50,  50,  50,  50,  50,
+};
+
+const int vp8_gf_interval_table[101] =
+{
+    7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+};
+
+static const unsigned int prior_key_frame_weight[KEY_FRAME_CONTEXT] = { 1, 2, 3, 4, 5 };
+
+
+void vp8_save_coding_context(VP8_COMP *cpi)
+{
+    CODING_CONTEXT *const cc = & cpi->coding_context;
+
+    // Stores a snapshot of key state variables which can subsequently be
+    // restored with a call to vp8_restore_coding_context. These functions are
+    // intended for use in a re-code loop in vp8_compress_frame where the
+    // quantizer value is adjusted between loop iterations.
+
+    cc->frames_since_key          = cpi->frames_since_key;
+    cc->filter_level             = cpi->common.filter_level;
+    cc->frames_till_gf_update_due   = cpi->frames_till_gf_update_due;
+    cc->frames_since_golden       = cpi->common.frames_since_golden;
+
+    vp8_copy(cc->mvc,      cpi->common.fc.mvc);
+    vp8_copy(cc->mvcosts,  cpi->mb.mvcosts);
+
+    vp8_copy(cc->kf_ymode_prob,   cpi->common.kf_ymode_prob);
+    vp8_copy(cc->ymode_prob,   cpi->common.fc.ymode_prob);
+    vp8_copy(cc->kf_uv_mode_prob,  cpi->common.kf_uv_mode_prob);
+    vp8_copy(cc->uv_mode_prob,  cpi->common.fc.uv_mode_prob);
+
+    vp8_copy(cc->ymode_count, cpi->ymode_count);
+    vp8_copy(cc->uv_mode_count, cpi->uv_mode_count);
+
+
+    // Stats
+#ifdef MODE_STATS
+    vp8_copy(cc->y_modes,       y_modes);
+    vp8_copy(cc->uv_modes,      uv_modes);
+    vp8_copy(cc->b_modes,       b_modes);
+    vp8_copy(cc->inter_y_modes,  inter_y_modes);
+    vp8_copy(cc->inter_uv_modes, inter_uv_modes);
+    vp8_copy(cc->inter_b_modes,  inter_b_modes);
+#endif
+
+    cc->this_frame_percent_intra = cpi->this_frame_percent_intra;
+}
+
+
+void vp8_restore_coding_context(VP8_COMP *cpi)
+{
+    CODING_CONTEXT *const cc = & cpi->coding_context;
+
+    // Restore key state variables to the snapshot state stored in the
+    // previous call to vp8_save_coding_context.
+
+    cpi->frames_since_key         =   cc->frames_since_key;
+    cpi->common.filter_level     =   cc->filter_level;
+    cpi->frames_till_gf_update_due  =   cc->frames_till_gf_update_due;
+    cpi->common.frames_since_golden       =   cc->frames_since_golden;
+
+    vp8_copy(cpi->common.fc.mvc, cc->mvc);
+
+    vp8_copy(cpi->mb.mvcosts, cc->mvcosts);
+
+    vp8_copy(cpi->common.kf_ymode_prob,   cc->kf_ymode_prob);
+    vp8_copy(cpi->common.fc.ymode_prob,   cc->ymode_prob);
+    vp8_copy(cpi->common.kf_uv_mode_prob,  cc->kf_uv_mode_prob);
+    vp8_copy(cpi->common.fc.uv_mode_prob,  cc->uv_mode_prob);
+
+    vp8_copy(cpi->ymode_count, cc->ymode_count);
+    vp8_copy(cpi->uv_mode_count, cc->uv_mode_count);
+
+    // Stats
+#ifdef MODE_STATS
+    vp8_copy(y_modes, cc->y_modes);
+    vp8_copy(uv_modes, cc->uv_modes);
+    vp8_copy(b_modes, cc->b_modes);
+    vp8_copy(inter_y_modes, cc->inter_y_modes);
+    vp8_copy(inter_uv_modes, cc->inter_uv_modes);
+    vp8_copy(inter_b_modes, cc->inter_b_modes);
+#endif
+
+
+    cpi->this_frame_percent_intra = cc->this_frame_percent_intra;
+}
+
+
+void vp8_setup_key_frame(VP8_COMP *cpi)
+{
+    // Setup for Key frame:
+
+    vp8_default_coef_probs(& cpi->common);
+    vp8_kf_default_bmode_probs(cpi->common.kf_bmode_prob);
+
+    vpx_memcpy(cpi->common.fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context));
+    {
+        int flag[2] = {1, 1};
+        vp8_build_component_cost_table(cpi->mb.mvcost, cpi->mb.mvsadcost, (const MV_CONTEXT *) cpi->common.fc.mvc, flag);
+    }
+
+    vpx_memset(cpi->common.fc.pre_mvc, 0, sizeof(cpi->common.fc.pre_mvc));  //initialize pre_mvc to all zero.
+
+    //cpi->common.filter_level = 0;      // Reset every key frame.
+    cpi->common.filter_level = cpi->common.base_qindex * 3 / 8 ;
+
+    // Provisional interval before next GF
+    if (cpi->auto_gold)
+        //cpi->frames_till_gf_update_due = DEFAULT_GF_INTERVAL;
+        cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+    else
+        cpi->frames_till_gf_update_due = cpi->goldfreq;
+
+    cpi->common.refresh_golden_frame = TRUE;
+}
+
+void vp8_calc_auto_iframe_target_size(VP8_COMP *cpi)
+{
+    // boost defaults to half second
+    int kf_boost;
+
+    // Clear down mmx registers to allow floating point in what follows
+    vp8_clear_system_state();  //__asm emms;
+
+    if (cpi->oxcf.fixed_q >= 0)
+    {
+        vp8_calc_iframe_target_size(cpi);
+        return;
+    }
+
+    if (cpi->pass == 2)
+    {
+        cpi->this_frame_target = cpi->per_frame_bandwidth;      // New Two pass RC
+    }
+    else
+    {
+        // Boost depends somewhat on frame rate
+        kf_boost = (int)(2 * cpi->output_frame_rate - 16);
+
+        // adjustment up based on q
+        kf_boost = kf_boost * vp8_kf_boost_qadjustment[cpi->ni_av_qi] / 100;
+
+        // frame separation adjustment ( down)
+        if (cpi->frames_since_key  < cpi->output_frame_rate / 2)
+            kf_boost = (int)(kf_boost * cpi->frames_since_key / (cpi->output_frame_rate / 2));
+
+        if (kf_boost < 16)
+            kf_boost = 16;
+
+        // Reset the active worst quality to the baseline value for key frames.
+        cpi->active_worst_quality = cpi->worst_quality;
+
+        cpi->this_frame_target = ((16 + kf_boost)  * cpi->per_frame_bandwidth) >> 4;
+    }
+
+
+    // Should the next frame be an altref frame
+    if (cpi->pass != 2)
+    {
+        // For now Alt ref is not allowed except in 2 pass modes.
+        cpi->source_alt_ref_pending = FALSE;
+
+        /*if ( cpi->oxcf.fixed_q == -1)
+        {
+            if ( cpi->oxcf.play_alternate && ( (cpi->last_boost/2) > (100+(AF_THRESH*cpi->frames_till_gf_update_due)) ) )
+                cpi->source_alt_ref_pending = TRUE;
+            else
+                cpi->source_alt_ref_pending = FALSE;
+        }*/
+    }
+
+    if (0)
+    {
+        FILE *f;
+
+        f = fopen("kf_boost.stt", "a");
+        //fprintf(f, " %8d %10d %10d %10d %10d %10d %10d\n",
+        //  cpi->common.current_video_frame,  cpi->target_bandwidth, cpi->frames_to_key, kf_boost_qadjustment[cpi->ni_av_qi], cpi->kf_boost, (cpi->this_frame_target *100 / cpi->per_frame_bandwidth), cpi->this_frame_target );
+
+        fprintf(f, " %8u %10d %10d %10d\n",
+                cpi->common.current_video_frame,  cpi->gfu_boost, cpi->baseline_gf_interval, cpi->source_alt_ref_pending);
+
+        fclose(f);
+    }
+}
+
+//  Do the best we can to define the parameteres for the next GF based on what information we have available.
+static void calc_gf_params(VP8_COMP *cpi)
+{
+    int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
+    int Boost = 0;
+
+    int gf_frame_useage = 0;      // Golden frame useage since last GF
+    int tot_mbs = cpi->recent_ref_frame_usage[INTRA_FRAME]  +
+                  cpi->recent_ref_frame_usage[LAST_FRAME]   +
+                  cpi->recent_ref_frame_usage[GOLDEN_FRAME] +
+                  cpi->recent_ref_frame_usage[ALTREF_FRAME];
+
+    int pct_gf_active = (100 * cpi->common.gf_active_count) / (cpi->common.mb_rows * cpi->common.mb_cols);
+
+    // Reset the last boost indicator
+    //cpi->last_boost = 100;
+
+    if (tot_mbs)
+        gf_frame_useage = (cpi->recent_ref_frame_usage[GOLDEN_FRAME] + cpi->recent_ref_frame_usage[ALTREF_FRAME]) * 100 / tot_mbs;
+
+    if (pct_gf_active > gf_frame_useage)
+        gf_frame_useage = pct_gf_active;
+
+    // Not two pass
+    if (cpi->pass != 2)
+    {
+        // Single Pass lagged mode: TBD
+        if (FALSE)
+        {
+        }
+
+        // Single Pass compression: Has to use current and historical data
+        else
+        {
+#if 0
+            // Experimental code
+            int index = cpi->one_pass_frame_index;
+            int frames_to_scan = (cpi->max_gf_interval <= MAX_LAG_BUFFERS) ? cpi->max_gf_interval : MAX_LAG_BUFFERS;
+
+            /*
+            // *************** Experimental code - incomplete
+            double decay_val = 1.0;
+            double IIAccumulator = 0.0;
+            double last_iiaccumulator = 0.0;
+            double IIRatio;
+
+            cpi->one_pass_frame_index = cpi->common.current_video_frame%MAX_LAG_BUFFERS;
+
+            for ( i = 0; i < (frames_to_scan - 1); i++ )
+            {
+                if ( index < 0 )
+                    index = MAX_LAG_BUFFERS;
+                index --;
+
+                if ( cpi->one_pass_frame_stats[index].frame_coded_error > 0.0 )
+                {
+                    IIRatio = cpi->one_pass_frame_stats[index].frame_intra_error / cpi->one_pass_frame_stats[index].frame_coded_error;
+
+                    if ( IIRatio > 30.0 )
+                        IIRatio = 30.0;
+                }
+                else
+                    IIRatio = 30.0;
+
+                IIAccumulator += IIRatio * decay_val;
+
+                decay_val = decay_val * cpi->one_pass_frame_stats[index].frame_pcnt_inter;
+
+                if (    (i > MIN_GF_INTERVAL) &&
+                        ((IIAccumulator - last_iiaccumulator) < 2.0) )
+                {
+                    break;
+                }
+                last_iiaccumulator = IIAccumulator;
+            }
+
+            Boost = IIAccumulator*100.0/16.0;
+            cpi->baseline_gf_interval = i;
+
+            */
+#else
+
+            /*************************************************************/
+            // OLD code
+
+            // Adjust boost based upon ambient Q
+            Boost = GFQ_ADJUSTMENT;
+
+            // Adjust based upon most recently measure intra useage
+            Boost = Boost * vp8_gf_intra_useage_adjustment[(cpi->this_frame_percent_intra < 15) ? cpi->this_frame_percent_intra : 14] / 100;
+
+            // Adjust gf boost based upon GF usage since last GF
+            Boost = Boost * vp8_gf_adjust_table[gf_frame_useage] / 100;
+#endif
+        }
+
+        // golden frame boost without recode loop often goes awry.  be safe by keeping numbers down.
+        if (!cpi->sf.recode_loop)
+        {
+            if (cpi->compressor_speed == 2)
+                Boost = Boost / 2;
+        }
+
+        // Apply an upper limit based on Q for 1 pass encodes
+        if (Boost > vp8_kf_gf_boost_qlimits[Q] && (cpi->pass == 0))
+            Boost = vp8_kf_gf_boost_qlimits[Q];
+
+        // Apply lower limits to boost.
+        else if (Boost < 110)
+            Boost = 110;
+
+        // Note the boost used
+        cpi->last_boost = Boost;
+
+    }
+
+    // Estimate next interval
+    // This is updated once the real frame size/boost is known.
+    if (cpi->oxcf.fixed_q == -1)
+    {
+        if (cpi->pass == 2)         // 2 Pass
+        {
+            cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+        }
+        else                            // 1 Pass
+        {
+            cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+
+            if (cpi->last_boost > 750)
+                cpi->frames_till_gf_update_due++;
+
+            if (cpi->last_boost > 1000)
+                cpi->frames_till_gf_update_due++;
+
+            if (cpi->last_boost > 1250)
+                cpi->frames_till_gf_update_due++;
+
+            if (cpi->last_boost >= 1500)
+                cpi->frames_till_gf_update_due ++;
+
+            if (vp8_gf_interval_table[gf_frame_useage] > cpi->frames_till_gf_update_due)
+                cpi->frames_till_gf_update_due = vp8_gf_interval_table[gf_frame_useage];
+
+            if (cpi->frames_till_gf_update_due > cpi->max_gf_interval)
+                cpi->frames_till_gf_update_due = cpi->max_gf_interval;
+        }
+    }
+    else
+        cpi->frames_till_gf_update_due = cpi->baseline_gf_interval;
+
+    // ARF on or off
+    if (cpi->pass != 2)
+    {
+        // For now Alt ref is not allowed except in 2 pass modes.
+        cpi->source_alt_ref_pending = FALSE;
+
+        /*if ( cpi->oxcf.fixed_q == -1)
+        {
+            if ( cpi->oxcf.play_alternate && (cpi->last_boost > (100 + (AF_THRESH*cpi->frames_till_gf_update_due)) ) )
+                cpi->source_alt_ref_pending = TRUE;
+            else
+                cpi->source_alt_ref_pending = FALSE;
+        }*/
+    }
+}
+/* This is equvialent to estimate_bits_at_q without the rate_correction_factor. */
+static int baseline_bits_at_q(int frame_kind, int Q, int MBs)
+{
+    int Bpm = vp8_bits_per_mb[frame_kind][Q];
+
+    /* Attempt to retain reasonable accuracy without overflow. The cutoff is
+     * chosen such that the maximum product of Bpm and MBs fits 31 bits. The
+     * largest Bpm takes 20 bits.
+     */
+    if (MBs > (1 << 11))
+        return (Bpm >> BPER_MB_NORMBITS) * MBs;
+    else
+        return (Bpm * MBs) >> BPER_MB_NORMBITS;
+}
+
+void vp8_calc_iframe_target_size(VP8_COMP *cpi)
+{
+    int Q;
+    int Boost = 100;
+
+    Q = (cpi->oxcf.fixed_q >= 0) ? cpi->oxcf.fixed_q : cpi->avg_frame_qindex;
+
+    if (cpi->auto_adjust_key_quantizer == 1)
+    {
+        // If (auto_adjust_key_quantizer==1) then a lower Q is selected for key-frames.
+        // The enhanced Q is calculated so as to boost the key frame size by a factor
+        // specified in kf_boost_qadjustment. Also, can adjust based on distance
+        // between key frames.
+
+        // Adjust boost based upon ambient Q
+        Boost = vp8_kf_boost_qadjustment[Q];
+
+        // Make the Key frame boost less if the seperation from the previous key frame is small
+        if (cpi->frames_since_key < 16)
+            Boost = Boost * vp8_kf_boost_seperationt_adjustment[cpi->frames_since_key] / 100;
+        else
+            Boost = Boost * vp8_kf_boost_seperationt_adjustment[15] / 100;
+
+        // Apply limits on boost
+        if (Boost > vp8_kf_gf_boost_qlimits[Q])
+            Boost = vp8_kf_gf_boost_qlimits[Q];
+        else if (Boost < 120)
+            Boost = 120;
+    }
+
+    // Keep a record of the boost that was used
+    cpi->last_boost = Boost;
+
+    // Should the next frame be an altref frame
+    if (cpi->pass != 2)
+    {
+        // For now Alt ref is not allowed except in 2 pass modes.
+        cpi->source_alt_ref_pending = FALSE;
+
+        /*if ( cpi->oxcf.fixed_q == -1)
+        {
+            if ( cpi->oxcf.play_alternate && ( (cpi->last_boost/2) > (100+(AF_THRESH*cpi->frames_till_gf_update_due)) ) )
+                cpi->source_alt_ref_pending = TRUE;
+            else
+                cpi->source_alt_ref_pending = FALSE;
+        }*/
+    }
+
+    if (cpi->oxcf.fixed_q >= 0)
+    {
+        cpi->this_frame_target = (baseline_bits_at_q(0, Q, cpi->common.MBs) * Boost) / 100;
+    }
+    else
+    {
+
+        int bits_per_mb_at_this_q ;
+
+        if (cpi->oxcf.error_resilient_mode == 1)
+        {
+            cpi->this_frame_target = 2 * cpi->av_per_frame_bandwidth;
+            return;
+        }
+
+        // Rate targetted scenario:
+        // Be careful of 32-bit OVERFLOW if restructuring the caluclation of cpi->this_frame_target
+        bits_per_mb_at_this_q = (int)(.5 +
+                                      cpi->key_frame_rate_correction_factor * vp8_bits_per_mb[0][Q]);
+
+        cpi->this_frame_target = (((bits_per_mb_at_this_q * cpi->common.MBs) >> BPER_MB_NORMBITS) * Boost) / 100;
+
+        // Reset the active worst quality to the baseline value for key frames.
+        if (cpi->pass < 2)
+            cpi->active_worst_quality = cpi->worst_quality;
+    }
+}
+
+
+
+void vp8_calc_pframe_target_size(VP8_COMP *cpi)
+{
+    int min_frame_target;
+    int Adjustment;
+
+    // Set the min frame bandwidth.
+    //min_frame_target = estimate_min_frame_size( cpi );
+    min_frame_target = 0;
+
+    if (cpi->pass == 2)
+    {
+        min_frame_target = cpi->min_frame_bandwidth;
+
+        if (min_frame_target < (cpi->av_per_frame_bandwidth >> 5))
+            min_frame_target = cpi->av_per_frame_bandwidth >> 5;
+    }
+    else if (min_frame_target < cpi->per_frame_bandwidth / 4)
+        min_frame_target = cpi->per_frame_bandwidth / 4;
+
+
+    // Special alt reference frame case
+    if (cpi->common.refresh_alt_ref_frame)
+    {
+        if (cpi->pass == 2)
+        {
+            cpi->per_frame_bandwidth = cpi->gf_bits;                       // Per frame bit target for the alt ref frame
+            cpi->this_frame_target = cpi->per_frame_bandwidth;
+        }
+
+        /* One Pass ??? TBD */
+        /*else
+        {
+            int frames_in_section;
+            int allocation_chunks;
+            int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
+            int alt_boost;
+            int max_arf_rate;
+
+            alt_boost = (cpi->gfu_boost * 3 * GFQ_ADJUSTMENT) / (2 * 100);
+            alt_boost += (cpi->frames_till_gf_update_due * 50);
+
+            // If alt ref is not currently active then we have a pottential double hit with GF and ARF so reduce the boost a bit.
+            // A similar thing is done on GFs that preceed a arf update.
+            if ( !cpi->source_alt_ref_active )
+                alt_boost = alt_boost * 3 / 4;
+
+            frames_in_section = cpi->frames_till_gf_update_due+1;                                   // Standard frames + GF
+            allocation_chunks = (frames_in_section * 100) + alt_boost;
+
+            // Normalize Altboost and allocations chunck down to prevent overflow
+            while ( alt_boost > 1000 )
+            {
+                alt_boost /= 2;
+                allocation_chunks /= 2;
+            }
+
+            else
+            {
+                int bits_in_section;
+
+                if ( cpi->kf_overspend_bits > 0 )
+                {
+                    Adjustment = (cpi->kf_bitrate_adjustment <= cpi->kf_overspend_bits) ? cpi->kf_bitrate_adjustment : cpi->kf_overspend_bits;
+
+                    if ( Adjustment > (cpi->per_frame_bandwidth - min_frame_target) )
+                        Adjustment = (cpi->per_frame_bandwidth - min_frame_target);
+
+                    cpi->kf_overspend_bits -= Adjustment;
+
+                    // Calculate an inter frame bandwidth target for the next few frames designed to recover
+                    // any extra bits spent on the key frame.
+                    cpi->inter_frame_target = cpi->per_frame_bandwidth - Adjustment;
+                    if ( cpi->inter_frame_target < min_frame_target )
+                        cpi->inter_frame_target = min_frame_target;
+                }
+                else
+                    cpi->inter_frame_target = cpi->per_frame_bandwidth;
+
+                bits_in_section = cpi->inter_frame_target * frames_in_section;
+
+                // Avoid loss of precision but avoid overflow
+                if ( (bits_in_section>>7) > allocation_chunks )
+                    cpi->this_frame_target = alt_boost * (bits_in_section / allocation_chunks);
+                else
+                    cpi->this_frame_target = (alt_boost * bits_in_section) / allocation_chunks;
+            }
+        }
+        */
+    }
+
+    // Normal frames (gf,and inter)
+    else
+    {
+        // 2 pass
+        if (cpi->pass == 2)
+        {
+            cpi->this_frame_target = cpi->per_frame_bandwidth;
+        }
+        // 1 pass
+        else
+        {
+            // Make rate adjustment to recover bits spent in key frame
+            // Test to see if the key frame inter data rate correction should still be in force
+            if (cpi->kf_overspend_bits > 0)
+            {
+                Adjustment = (cpi->kf_bitrate_adjustment <= cpi->kf_overspend_bits) ? cpi->kf_bitrate_adjustment : cpi->kf_overspend_bits;
+
+                if (Adjustment > (cpi->per_frame_bandwidth - min_frame_target))
+                    Adjustment = (cpi->per_frame_bandwidth - min_frame_target);
+
+                cpi->kf_overspend_bits -= Adjustment;
+
+                // Calculate an inter frame bandwidth target for the next few frames designed to recover
+                // any extra bits spent on the key frame.
+                cpi->this_frame_target = cpi->per_frame_bandwidth - Adjustment;
+
+                if (cpi->this_frame_target < min_frame_target)
+                    cpi->this_frame_target = min_frame_target;
+            }
+            else
+                cpi->this_frame_target = cpi->per_frame_bandwidth;
+
+            // If appropriate make an adjustment to recover bits spent on a recent GF
+            if ((cpi->gf_overspend_bits > 0) && (cpi->this_frame_target > min_frame_target))
+            {
+                int Adjustment = (cpi->non_gf_bitrate_adjustment <= cpi->gf_overspend_bits) ? cpi->non_gf_bitrate_adjustment : cpi->gf_overspend_bits;
+
+                if (Adjustment > (cpi->this_frame_target - min_frame_target))
+                    Adjustment = (cpi->this_frame_target - min_frame_target);
+
+                cpi->gf_overspend_bits -= Adjustment;
+                cpi->this_frame_target -= Adjustment;
+            }
+
+            // Apply small + and - boosts for non gf frames
+            if ((cpi->last_boost > 150) && (cpi->frames_till_gf_update_due > 0) &&
+                (cpi->current_gf_interval >= (MIN_GF_INTERVAL << 1)))
+            {
+                // % Adjustment limited to the range 1% to 10%
+                Adjustment = (cpi->last_boost - 100) >> 5;
+
+                if (Adjustment < 1)
+                    Adjustment = 1;
+                else if (Adjustment > 10)
+                    Adjustment = 10;
+
+                // Convert to bits
+                Adjustment = (cpi->this_frame_target * Adjustment) / 100;
+
+                if (Adjustment > (cpi->this_frame_target - min_frame_target))
+                    Adjustment = (cpi->this_frame_target - min_frame_target);
+
+                if (cpi->common.frames_since_golden == (cpi->current_gf_interval >> 1))
+                    cpi->this_frame_target += ((cpi->current_gf_interval - 1) * Adjustment);
+                else
+                    cpi->this_frame_target -= Adjustment;
+            }
+        }
+    }
+
+    // Set a reduced data rate target for our initial Q calculation.
+    // This should help to save bits during earier sections.
+    if ((cpi->oxcf.under_shoot_pct > 0) && (cpi->oxcf.under_shoot_pct <= 100))
+        cpi->this_frame_target = (cpi->this_frame_target * cpi->oxcf.under_shoot_pct) / 100;
+
+    // Sanity check that the total sum of adjustments is not above the maximum allowed
+    // That is that having allowed for KF and GF penalties we have not pushed the
+    // current interframe target to low. If the adjustment we apply here is not capable of recovering
+    // all the extra bits we have spent in the KF or GF then the remainder will have to be recovered over
+    // a longer time span via other buffer / rate control mechanisms.
+    if (cpi->this_frame_target < min_frame_target)
+        cpi->this_frame_target = min_frame_target;
+
+    if (!cpi->common.refresh_alt_ref_frame)
+        // Note the baseline target data rate for this inter frame.
+        cpi->inter_frame_target = cpi->this_frame_target;
+
+    // One Pass specific code
+    if (cpi->pass == 0)
+    {
+        // Adapt target frame size with respect to any buffering constraints:
+        if (cpi->buffered_mode)
+        {
+            int one_percent_bits = 1 + cpi->oxcf.optimal_buffer_level / 100;
+
+            if ((cpi->buffer_level < cpi->oxcf.optimal_buffer_level) || (cpi->bits_off_target < cpi->oxcf.optimal_buffer_level))
+            {
+                int percent_low = 0;
+
+                // Decide whether or not we need to adjust the frame data rate target.
+                //
+                // If we are are below the optimal buffer fullness level and adherence
+                // to buffering contraints is important to the end useage then adjust
+                // the per frame target.
+                if ((cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) && (cpi->buffer_level < cpi->oxcf.optimal_buffer_level))
+                {
+                    percent_low = (cpi->oxcf.optimal_buffer_level - cpi->buffer_level) / one_percent_bits;
+
+                    if (percent_low > 100)
+                        percent_low = 100;
+                    else if (percent_low < 0)
+                        percent_low = 0;
+                }
+                // Are we overshooting the long term clip data rate...
+                else if (cpi->bits_off_target < 0)
+                {
+                    // Adjust per frame data target downwards to compensate.
+                    percent_low = (int)(100 * -cpi->bits_off_target / (cpi->total_byte_count * 8));
+
+                    if (percent_low > 100)
+                        percent_low = 100;
+                    else if (percent_low < 0)
+                        percent_low = 0;
+                }
+
+                // lower the target bandwidth for this frame.
+                cpi->this_frame_target = (cpi->this_frame_target * (100 - (percent_low / 2))) / 100;
+
+                // Are we using allowing control of active_worst_allowed_q according to buffer level.
+                if (cpi->auto_worst_q)
+                {
+                    int critical_buffer_level;
+
+                    // For streaming applications the most important factor is cpi->buffer_level as this takes
+                    // into account the specified short term buffering constraints. However, hitting the long
+                    // term clip data rate target is also important.
+                    if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+                    {
+                        // Take the smaller of cpi->buffer_level and cpi->bits_off_target
+                        critical_buffer_level = (cpi->buffer_level < cpi->bits_off_target) ? cpi->buffer_level : cpi->bits_off_target;
+                    }
+                    // For local file playback short term buffering contraints are less of an issue
+                    else
+                    {
+                        // Consider only how we are doing for the clip as a whole
+                        critical_buffer_level = cpi->bits_off_target;
+                    }
+
+                    // Set the active worst quality based upon the selected buffer fullness number.
+                    if (critical_buffer_level < cpi->oxcf.optimal_buffer_level)
+                    {
+                        if (critical_buffer_level > (cpi->oxcf.optimal_buffer_level / 4))
+                        {
+                            int qadjustment_range = cpi->worst_quality - cpi->ni_av_qi;
+                            int above_base = (critical_buffer_level - (cpi->oxcf.optimal_buffer_level / 4));
+
+                            // Step active worst quality down from cpi->ni_av_qi when (critical_buffer_level == cpi->optimal_buffer_level)
+                            // to cpi->oxcf.worst_allowed_q when (critical_buffer_level == cpi->optimal_buffer_level/4)
+                            cpi->active_worst_quality = cpi->worst_quality - ((qadjustment_range * above_base) / (cpi->oxcf.optimal_buffer_level * 3 / 4));
+                        }
+                        else
+                        {
+                            cpi->active_worst_quality = cpi->worst_quality;
+                        }
+                    }
+                    else
+                    {
+                        cpi->active_worst_quality = cpi->ni_av_qi;
+                    }
+                }
+                else
+                {
+                    cpi->active_worst_quality = cpi->worst_quality;
+                }
+            }
+            else
+            {
+                int percent_high;
+
+                if (cpi->bits_off_target > cpi->oxcf.optimal_buffer_level)
+                {
+                    percent_high = (int)(100 * (cpi->bits_off_target - cpi->oxcf.optimal_buffer_level) / (cpi->total_byte_count * 8));
+
+                    if (percent_high > 100)
+                        percent_high = 100;
+                    else if (percent_high < 0)
+                        percent_high = 0;
+
+                    cpi->this_frame_target = (cpi->this_frame_target * (100 + (percent_high / 2))) / 100;
+
+                }
+
+                // Are we allowing control of active_worst_allowed_q according to bufferl level.
+                if (cpi->auto_worst_q)
+                {
+                    // When using the relaxed buffer model stick to the user specified value
+                    cpi->active_worst_quality = cpi->ni_av_qi;
+                }
+                else
+                {
+                    cpi->active_worst_quality = cpi->worst_quality;
+                }
+            }
+
+            // Set active_best_quality to prevent quality rising too high
+            cpi->active_best_quality = cpi->best_quality;
+
+            // Worst quality obviously must not be better than best quality
+            if (cpi->active_worst_quality <= cpi->active_best_quality)
+                cpi->active_worst_quality = cpi->active_best_quality + 1;
+
+        }
+        // Unbuffered mode (eg. video conferencing)
+        else
+        {
+            // Set the active worst quality
+            cpi->active_worst_quality = cpi->worst_quality;
+        }
+    }
+
+    // Test to see if we have to drop a frame
+    // The auto-drop frame code is only used in buffered mode.
+    // In unbufferd mode (eg vide conferencing) the descision to
+    // code or drop a frame is made outside the codec in response to real
+    // world comms or buffer considerations.
+    if (cpi->drop_frames_allowed && cpi->buffered_mode &&
+        (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) &&
+        ((cpi->common.frame_type != KEY_FRAME))) //|| !cpi->oxcf.allow_spatial_resampling) )
+    {
+        // Check for a buffer underun-crisis in which case we have to drop a frame
+        if ((cpi->buffer_level < 0))
+        {
+#if 0
+            FILE *f = fopen("dec.stt", "a");
+            fprintf(f, "%10d %10d %10d %10d ***** BUFFER EMPTY\n",
+                    (int) cpi->common.current_video_frame,
+                    cpi->decimation_factor, cpi->common.horiz_scale,
+                    (cpi->buffer_level * 100) / cpi->oxcf.optimal_buffer_level);
+            fclose(f);
+#endif
+            //vpx_log("Decoder: Drop frame due to bandwidth: %d \n",cpi->buffer_level, cpi->av_per_frame_bandwidth);
+
+            cpi->drop_frame = TRUE;
+        }
+
+#if 0
+        // Check for other drop frame crtieria (Note 2 pass cbr uses decimation on whole KF sections)
+        else if ((cpi->buffer_level < cpi->oxcf.drop_frames_water_mark * cpi->oxcf.optimal_buffer_level / 100) &&
+                 (cpi->drop_count < cpi->max_drop_count) && (cpi->pass == 0))
+        {
+            cpi->drop_frame = TRUE;
+        }
+
+#endif
+
+        if (cpi->drop_frame)
+        {
+            // Update the buffer level variable.
+            cpi->bits_off_target += cpi->av_per_frame_bandwidth;
+            cpi->buffer_level = cpi->bits_off_target;
+        }
+        else
+            cpi->drop_count = 0;
+    }
+
+    // Adjust target frame size for Golden Frames:
+    if (cpi->oxcf.error_resilient_mode == 0 &&
+        (cpi->frames_till_gf_update_due == 0) && !cpi->drop_frame)
+    {
+        //int Boost = 0;
+        int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
+
+        int gf_frame_useage = 0;      // Golden frame useage since last GF
+        int tot_mbs = cpi->recent_ref_frame_usage[INTRA_FRAME]  +
+                      cpi->recent_ref_frame_usage[LAST_FRAME]   +
+                      cpi->recent_ref_frame_usage[GOLDEN_FRAME] +
+                      cpi->recent_ref_frame_usage[ALTREF_FRAME];
+
+        int pct_gf_active = (100 * cpi->common.gf_active_count) / (cpi->common.mb_rows * cpi->common.mb_cols);
+
+        // Reset the last boost indicator
+        //cpi->last_boost = 100;
+
+        if (tot_mbs)
+            gf_frame_useage = (cpi->recent_ref_frame_usage[GOLDEN_FRAME] + cpi->recent_ref_frame_usage[ALTREF_FRAME]) * 100 / tot_mbs;
+
+        if (pct_gf_active > gf_frame_useage)
+            gf_frame_useage = pct_gf_active;
+
+        // Is a fixed manual GF frequency being used
+        if (!cpi->auto_gold)
+            cpi->common.refresh_golden_frame = TRUE;
+        else
+        {
+            // For one pass throw a GF if recent frame intra useage is low or the GF useage is high
+            if ((cpi->pass == 0) && (cpi->this_frame_percent_intra < 15 || gf_frame_useage >= 5))
+                cpi->common.refresh_golden_frame = TRUE;
+
+            // Two pass GF descision
+            else if (cpi->pass == 2)
+                cpi->common.refresh_golden_frame = TRUE;
+        }
+
+#if 0
+
+        // Debug stats
+        if (0)
+        {
+            FILE *f;
+
+            f = fopen("gf_useaget.stt", "a");
+            fprintf(f, " %8ld %10ld %10ld %10ld %10ld\n",
+                    cpi->common.current_video_frame,  cpi->gfu_boost, GFQ_ADJUSTMENT, cpi->gfu_boost, gf_frame_useage);
+            fclose(f);
+        }
+
+#endif
+
+        if (cpi->common.refresh_golden_frame == TRUE)
+        {
+            int isize_adjustment = 0;
+#if 0
+
+            if (0)   // p_gw
+            {
+                FILE *f;
+
+                f = fopen("GFexit.stt", "a");
+                fprintf(f, "%8ld GF coded\n", cpi->common.current_video_frame);
+                fclose(f);
+            }
+
+#endif
+            cpi->initial_gf_use = 0;
+
+            if (cpi->auto_adjust_gold_quantizer)
+            {
+                calc_gf_params(cpi);
+            }
+
+            // If we are using alternate ref instead of gf then do not apply the boost
+            // It will instead be applied to the altref update
+            // Jims modified boost
+            if (!cpi->source_alt_ref_active)
+            {
+                if (cpi->oxcf.fixed_q < 0)
+                {
+                    if (cpi->pass == 2)
+                    {
+                        cpi->this_frame_target = cpi->per_frame_bandwidth;          // The spend on the GF is defined in the two pass code for two pass encodes
+                    }
+                    else
+                    {
+                        int Boost = cpi->last_boost;
+                        int frames_in_section = cpi->frames_till_gf_update_due + 1;
+                        int allocation_chunks = (frames_in_section * 100) + (Boost - 100);
+                        int bits_in_section = cpi->inter_frame_target * frames_in_section;
+
+                        // Normalize Altboost and allocations chunck down to prevent overflow
+                        while (Boost > 1000)
+                        {
+                            Boost /= 2;
+                            allocation_chunks /= 2;
+                        }
+
+                        // Avoid loss of precision but avoid overflow
+                        if ((bits_in_section >> 7) > allocation_chunks)
+                            cpi->this_frame_target = Boost * (bits_in_section / allocation_chunks);
+                        else
+                            cpi->this_frame_target = (Boost * bits_in_section) / allocation_chunks;
+                    }
+                }
+                else
+                    cpi->this_frame_target = (baseline_bits_at_q(1, Q, cpi->common.MBs) * cpi->last_boost) / 100;
+
+            }
+            // If there is an active ARF at this location use the minimum bits on this frame
+            else
+            {
+                cpi->this_frame_target = 0;           // Minimial spend on gf that is replacing an arf
+            }
+
+            cpi->current_gf_interval = cpi->frames_till_gf_update_due;
+
+        }
+    }
+}
+
+
+void vp8_update_rate_correction_factors(VP8_COMP *cpi, int damp_var)
+{
+    int    Q = cpi->common.base_qindex;
+    int    correction_factor = 100;
+    double rate_correction_factor;
+    double adjustment_limit;
+
+    int    projected_size_based_on_q = 0;
+
+    // Clear down mmx registers to allow floating point in what follows
+    vp8_clear_system_state();  //__asm emms;
+
+    if (cpi->common.frame_type == KEY_FRAME)
+    {
+        rate_correction_factor = cpi->key_frame_rate_correction_factor;
+    }
+    else
+    {
+        if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
+            rate_correction_factor = cpi->gf_rate_correction_factor;
+        else
+            rate_correction_factor = cpi->rate_correction_factor;
+    }
+
+    // Work out how big we would have expected the frame to be at this Q given the current correction factor.
+    // Stay in double to avoid int overflow when values are large
+    //projected_size_based_on_q = ((int)(.5 + rate_correction_factor * vp8_bits_per_mb[cpi->common.frame_type][Q]) * cpi->common.MBs) >> BPER_MB_NORMBITS;
+    projected_size_based_on_q = (int)(((.5 + rate_correction_factor * vp8_bits_per_mb[cpi->common.frame_type][Q]) * cpi->common.MBs) / (1 << BPER_MB_NORMBITS));
+
+    // Make some allowance for cpi->zbin_over_quant
+    if (cpi->zbin_over_quant > 0)
+    {
+        int Z = cpi->zbin_over_quant;
+        double Factor = 0.99;
+        double factor_adjustment = 0.01 / 256.0; //(double)ZBIN_OQ_MAX;
+
+        while (Z > 0)
+        {
+            Z --;
+            projected_size_based_on_q *= (int)Factor;
+            Factor += factor_adjustment;
+
+            if (Factor  >= 0.999)
+                Factor = 0.999;
+        }
+    }
+
+    // Work out a size correction factor.
+    //if ( cpi->this_frame_target > 0 )
+    //  correction_factor = (100 * cpi->projected_frame_size) / cpi->this_frame_target;
+    if (projected_size_based_on_q > 0)
+        correction_factor = (100 * cpi->projected_frame_size) / projected_size_based_on_q;
+
+    // More heavily damped adjustment used if we have been oscillating either side of target
+    switch (damp_var)
+    {
+    case 0:
+        adjustment_limit = 0.75;
+        break;
+    case 1:
+        adjustment_limit = 0.375;
+        break;
+    case 2:
+    default:
+        adjustment_limit = 0.25;
+        break;
+    }
+
+    //if ( (correction_factor > 102) && (Q < cpi->active_worst_quality) )
+    if (correction_factor > 102)
+    {
+        // We are not already at the worst allowable quality
+        correction_factor = (int)(100.5 + ((correction_factor - 100) * adjustment_limit));
+        rate_correction_factor = ((rate_correction_factor * correction_factor) / 100);
+
+        // Keep rate_correction_factor within limits
+        if (rate_correction_factor > MAX_BPB_FACTOR)
+            rate_correction_factor = MAX_BPB_FACTOR;
+    }
+    //else if ( (correction_factor < 99) && (Q > cpi->active_best_quality) )
+    else if (correction_factor < 99)
+    {
+        // We are not already at the best allowable quality
+        correction_factor = (int)(100.5 - ((100 - correction_factor) * adjustment_limit));
+        rate_correction_factor = ((rate_correction_factor * correction_factor) / 100);
+
+        // Keep rate_correction_factor within limits
+        if (rate_correction_factor < MIN_BPB_FACTOR)
+            rate_correction_factor = MIN_BPB_FACTOR;
+    }
+
+    if (cpi->common.frame_type == KEY_FRAME)
+        cpi->key_frame_rate_correction_factor = rate_correction_factor;
+    else
+    {
+        if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
+            cpi->gf_rate_correction_factor = rate_correction_factor;
+        else
+            cpi->rate_correction_factor = rate_correction_factor;
+    }
+}
+
+static int estimate_bits_at_q(VP8_COMP *cpi, int Q)
+{
+    int Bpm = (int)(.5 + cpi->rate_correction_factor * vp8_bits_per_mb[INTER_FRAME][Q]);
+
+    /* Attempt to retain reasonable accuracy without overflow. The cutoff is
+     * chosen such that the maximum product of Bpm and MBs fits 31 bits. The
+     * largest Bpm takes 20 bits.
+     */
+    if (cpi->common.MBs > (1 << 11))
+        return (Bpm >> BPER_MB_NORMBITS) * cpi->common.MBs;
+    else
+        return (Bpm * cpi->common.MBs) >> BPER_MB_NORMBITS;
+
+}
+
+
+int vp8_regulate_q(VP8_COMP *cpi, int target_bits_per_frame)
+{
+    int Q = cpi->active_worst_quality;
+
+    // Reset Zbin OQ value
+    cpi->zbin_over_quant = 0;
+
+    if (cpi->oxcf.fixed_q >= 0)
+    {
+        Q = cpi->oxcf.fixed_q;
+
+        if (cpi->common.frame_type == KEY_FRAME)
+        {
+            Q = cpi->oxcf.key_q;
+        }
+        else if (cpi->common.refresh_alt_ref_frame)
+        {
+            Q = cpi->oxcf.alt_q;
+        }
+        else if (cpi->common.refresh_golden_frame)
+        {
+            Q = cpi->oxcf.gold_q;
+        }
+
+    }
+    else
+    {
+        int i;
+        int last_error = INT_MAX;
+        int target_bits_per_mb;
+        int bits_per_mb_at_this_q;
+        double correction_factor;
+
+        // Select the appropriate correction factor based upon type of frame.
+        if (cpi->common.frame_type == KEY_FRAME)
+            correction_factor = cpi->key_frame_rate_correction_factor;
+        else
+        {
+            if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
+                correction_factor = cpi->gf_rate_correction_factor;
+            else
+                correction_factor = cpi->rate_correction_factor;
+        }
+
+        // Calculate required scaling factor based on target frame size and size of frame produced using previous Q
+        if (target_bits_per_frame >= (INT_MAX >> BPER_MB_NORMBITS))
+            target_bits_per_mb = (target_bits_per_frame / cpi->common.MBs) << BPER_MB_NORMBITS;       // Case where we would overflow int
+        else
+            target_bits_per_mb = (target_bits_per_frame << BPER_MB_NORMBITS) / cpi->common.MBs;
+
+        i = cpi->active_best_quality;
+
+        do
+        {
+            bits_per_mb_at_this_q = (int)(.5 + correction_factor * vp8_bits_per_mb[cpi->common.frame_type][i]);
+
+            if (bits_per_mb_at_this_q <= target_bits_per_mb)
+            {
+                if ((target_bits_per_mb - bits_per_mb_at_this_q) <= last_error)
+                    Q = i;
+                else
+                    Q = i - 1;
+
+                break;
+            }
+            else
+                last_error = bits_per_mb_at_this_q - target_bits_per_mb;
+        }
+        while (++i <= cpi->active_worst_quality);
+
+
+        // If we are at MAXQ then enable Q over-run which seeks to claw back additional bits through things like
+        // the RD multiplier and zero bin size.
+        if (Q >= MAXQ)
+        {
+            int zbin_oqmax;
+
+            double Factor = 0.99;
+            double factor_adjustment = 0.01 / 256.0; //(double)ZBIN_OQ_MAX;
+
+            if (cpi->common.frame_type == KEY_FRAME)
+                zbin_oqmax = 0; //ZBIN_OQ_MAX/16
+            else if (cpi->common.refresh_alt_ref_frame || (cpi->common.refresh_golden_frame && !cpi->source_alt_ref_active))
+                zbin_oqmax = 16;
+            else
+                zbin_oqmax = ZBIN_OQ_MAX;
+
+            /*{
+                double Factor = (double)target_bits_per_mb/(double)bits_per_mb_at_this_q;
+                double Oq;
+
+                Factor = Factor/1.2683;
+
+                Oq = pow( Factor, (1.0/-0.165) );
+
+                if ( Oq > zbin_oqmax )
+                    Oq = zbin_oqmax;
+
+                cpi->zbin_over_quant = (int)Oq;
+            }*/
+
+            // Each incrment in the zbin is assumed to have a fixed effect on bitrate. This is not of course true.
+            // The effect will be highly clip dependent and may well have sudden steps.
+            // The idea here is to acheive higher effective quantizers than the normal maximum by expanding the zero
+            // bin and hence decreasing the number of low magnitude non zero coefficients.
+            while (cpi->zbin_over_quant < zbin_oqmax)
+            {
+                cpi->zbin_over_quant ++;
+
+                if (cpi->zbin_over_quant > zbin_oqmax)
+                    cpi->zbin_over_quant = zbin_oqmax;
+
+                bits_per_mb_at_this_q *= (int)Factor;                   // Each over-ruin step is assumed to equate to approximately 3% reduction in bitrate
+                Factor += factor_adjustment;
+
+                if (Factor  >= 0.999)
+                    Factor = 0.999;
+
+                if (bits_per_mb_at_this_q <= target_bits_per_mb)    // Break out if we get down to the target rate
+                    break;
+            }
+
+        }
+    }
+
+    return Q;
+}
+
+static int estimate_min_frame_size(VP8_COMP *cpi)
+{
+    double correction_factor;
+    int bits_per_mb_at_max_q;
+
+    // This funtion returns a default value for the first few frames untill the correction factor has had time to adapt.
+    if (cpi->common.current_video_frame < 10)
+    {
+        if (cpi->pass == 2)
+            return (cpi->min_frame_bandwidth);
+        else
+            return cpi->per_frame_bandwidth / 3;
+    }
+
+    /*  // Select the appropriate correction factor based upon type of frame.
+        if ( cpi->common.frame_type == KEY_FRAME )
+            correction_factor = cpi->key_frame_rate_correction_factor;
+        else
+        {
+            if ( cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame )
+                correction_factor = cpi->gf_rate_correction_factor;
+            else
+                correction_factor = cpi->rate_correction_factor;
+        }*/
+
+    // We estimate at half the value we get from vp8_bits_per_mb
+    correction_factor = cpi->rate_correction_factor / 2.0;
+
+    bits_per_mb_at_max_q = (int)(.5 + correction_factor * vp8_bits_per_mb[cpi->common.frame_type][MAXQ]);
+
+    return (bits_per_mb_at_max_q * cpi->common.MBs) >> BPER_MB_NORMBITS;
+}
+
+void vp8_adjust_key_frame_context(VP8_COMP *cpi)
+{
+    int i;
+    int av_key_frames_per_second;
+
+    // Average key frame frequency and size
+    unsigned int total_weight = 0;
+    unsigned int av_key_frame_frequency = 0;
+    unsigned int av_key_frame_bits = 0;
+
+    unsigned int output_frame_rate = (unsigned int)(100 * cpi->output_frame_rate);
+    unsigned int target_bandwidth = (unsigned int)(100 * cpi->target_bandwidth);
+
+    // Clear down mmx registers to allow floating point in what follows
+    vp8_clear_system_state();  //__asm emms;
+
+    // Update the count of total key frame bits
+    cpi->tot_key_frame_bits += cpi->projected_frame_size;
+
+    // First key frame at start of sequence is a special case. We have no frequency data.
+    if (cpi->key_frame_count == 1)
+    {
+        av_key_frame_frequency = (int)cpi->output_frame_rate * 2;            // Assume a default of 1 kf every 2 seconds
+        av_key_frame_bits = cpi->projected_frame_size;
+        av_key_frames_per_second  = output_frame_rate / av_key_frame_frequency;  // Note output_frame_rate not cpi->output_frame_rate
+    }
+    else
+    {
+        // reset keyframe context and calculate weighted average of last KEY_FRAME_CONTEXT keyframes
+        for (i = 0; i < KEY_FRAME_CONTEXT; i++)
+        {
+            if (i < KEY_FRAME_CONTEXT - 1)
+            {
+                cpi->prior_key_frame_size[i]     = cpi->prior_key_frame_size[i+1];
+                cpi->prior_key_frame_distance[i] = cpi->prior_key_frame_distance[i+1];
+            }
+            else
+            {
+                cpi->prior_key_frame_size[KEY_FRAME_CONTEXT - 1]     = cpi->projected_frame_size;
+                cpi->prior_key_frame_distance[KEY_FRAME_CONTEXT - 1] = cpi->frames_since_key;
+            }
+
+            av_key_frame_bits      += prior_key_frame_weight[i] * cpi->prior_key_frame_size[i];
+            av_key_frame_frequency += prior_key_frame_weight[i] * cpi->prior_key_frame_distance[i];
+            total_weight         += prior_key_frame_weight[i];
+        }
+
+        av_key_frame_bits       /= total_weight;
+        av_key_frame_frequency  /= total_weight;
+        av_key_frames_per_second  = output_frame_rate / av_key_frame_frequency;
+
+    }
+
+    // Do we have any key frame overspend to recover?
+    if ((cpi->pass != 2) && (cpi->projected_frame_size > cpi->per_frame_bandwidth))
+    {
+        // Update the count of key frame overspend to be recovered in subsequent frames
+        // A portion of the KF overspend is treated as gf overspend (and hence recovered more quickly)
+        // as the kf is also a gf. Otherwise the few frames following each kf tend to get more bits
+        // allocated than those following other gfs.
+        cpi->kf_overspend_bits += (cpi->projected_frame_size - cpi->per_frame_bandwidth) * 7 / 8;
+        cpi->gf_overspend_bits += (cpi->projected_frame_size - cpi->per_frame_bandwidth) * 1 / 8;
+
+        // Work out how much to try and recover per frame.
+        // For one pass we estimate the number of frames to spread it over based upon past history.
+        // For two pass we know how many frames there will be till the next kf.
+        if (cpi->pass == 2)
+        {
+            if (cpi->frames_to_key > 16)
+                cpi->kf_bitrate_adjustment = cpi->kf_overspend_bits / (int)cpi->frames_to_key;
+            else
+                cpi->kf_bitrate_adjustment = cpi->kf_overspend_bits / 16;
+        }
+        else
+            cpi->kf_bitrate_adjustment = cpi->kf_overspend_bits / (int)av_key_frame_frequency;
+    }
+
+    cpi->frames_since_key = 0;
+    cpi->last_key_frame_size = cpi->projected_frame_size;
+    cpi->key_frame_count++;
+}
+
+void vp8_compute_frame_size_bounds(VP8_COMP *cpi, int *frame_under_shoot_limit, int *frame_over_shoot_limit)
+{
+    // Set-up bounds on acceptable frame size:
+    if (cpi->oxcf.fixed_q >= 0)
+    {
+        // Fixed Q scenario: frame size never outranges target (there is no target!)
+        *frame_under_shoot_limit = 0;
+        *frame_over_shoot_limit  = INT_MAX;
+    }
+    else
+    {
+        if (cpi->common.frame_type == KEY_FRAME)
+        {
+            *frame_over_shoot_limit  = cpi->this_frame_target * 9 / 8;
+            *frame_under_shoot_limit = cpi->this_frame_target * 7 / 8;
+        }
+        else
+        {
+            if (cpi->common.refresh_alt_ref_frame || cpi->common.refresh_golden_frame)
+            {
+                *frame_over_shoot_limit  = cpi->this_frame_target * 9 / 8;
+                *frame_under_shoot_limit = cpi->this_frame_target * 7 / 8;
+            }
+            else
+            {
+                // For CBR take buffer fullness into account
+                if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+                {
+                    if (cpi->buffer_level >= ((cpi->oxcf.optimal_buffer_level + cpi->oxcf.maximum_buffer_size) >> 1))
+                    {
+                        // Buffer is too full so relax overshoot and tighten undershoot
+                        *frame_over_shoot_limit  = cpi->this_frame_target * 12 / 8;
+                        *frame_under_shoot_limit = cpi->this_frame_target * 6 / 8;
+                    }
+                    else if (cpi->buffer_level <= (cpi->oxcf.optimal_buffer_level >> 1))
+                    {
+                        // Buffer is too low so relax undershoot and tighten overshoot
+                        *frame_over_shoot_limit  = cpi->this_frame_target * 10 / 8;
+                        *frame_under_shoot_limit = cpi->this_frame_target * 4 / 8;
+                    }
+                    else
+                    {
+                        *frame_over_shoot_limit  = cpi->this_frame_target * 11 / 8;
+                        *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
+                    }
+                }
+                // VBR
+                // Note that tighter restrictions here can help quality but hurt encode speed
+                else
+                {
+                    *frame_over_shoot_limit  = cpi->this_frame_target * 11 / 8;
+                    *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
+                }
+            }
+        }
+    }
+}
diff --git a/vp8/encoder/ratectrl.h b/vp8/encoder/ratectrl.h
new file mode 100644
index 0000000..588c7a8
--- /dev/null
+++ b/vp8/encoder/ratectrl.h
@@ -0,0 +1,26 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#if !defined __INC_RATECTRL_H
+
+#include "onyx_int.h"
+
+extern void vp8_save_coding_context(VP8_COMP *cpi);
+extern void vp8_restore_coding_context(VP8_COMP *cpi);
+
+extern void vp8_setup_key_frame(VP8_COMP *cpi);
+extern void vp8_calc_iframe_target_size(VP8_COMP *cpi);
+extern void vp8_calc_pframe_target_size(VP8_COMP *cpi);
+extern void vp8_update_rate_correction_factors(VP8_COMP *cpi, int damp_var);
+extern int vp8_regulate_q(VP8_COMP *cpi, int target_bits_per_frame);
+extern void vp8_adjust_key_frame_context(VP8_COMP *cpi);
+extern void vp8_compute_frame_size_bounds(VP8_COMP *cpi, int *frame_under_shoot_limit, int *frame_over_shoot_limit);
+
+#endif
diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c
new file mode 100644
index 0000000..0846996
--- /dev/null
+++ b/vp8/encoder/rdopt.c
@@ -0,0 +1,2212 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <stdio.h>
+#include <math.h>
+#include <limits.h>
+#include <assert.h>
+#include "pragmas.h"
+
+#include "tokenize.h"
+#include "treewriter.h"
+#include "onyx_int.h"
+#include "modecosts.h"
+#include "encodeintra.h"
+#include "entropymode.h"
+#include "reconinter.h"
+#include "reconintra.h"
+#include "reconintra4x4.h"
+#include "findnearmv.h"
+#include "encodemb.h"
+#include "quantize.h"
+#include "idct.h"
+#include "g_common.h"
+#include "variance.h"
+#include "mcomp.h"
+
+#include "vpx_mem/vpx_mem.h"
+#include "dct.h"
+#include "systemdependent.h"
+
+#define DIAMONDSEARCH 1
+#if CONFIG_RUNTIME_CPU_DETECT
+#define IF_RTCD(x)  (x)
+#else
+#define IF_RTCD(x)  NULL
+#endif
+
+
+void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x);
+
+
+#define RDFUNC(RM,DM,R,D,target_rd) ( ((128+(R)*(RM)) >> 8) + (DM)*(D) )
+/*int  RDFUNC( int RM,int DM, int R, int D, int target_r )
+{
+    int rd_value;
+
+    rd_value =  ( ((128+(R)*(RM)) >> 8) + (DM)*(D) );
+
+    return rd_value;
+}*/
+
+#define UVRDFUNC(RM,DM,R,D,target_r)  RDFUNC(RM,DM,R,D,target_r)
+
+#define RDCOST(RM,DM,R,D) ( ((128+(R)*(RM)) >> 8) + (DM)*(D) )
+
+#define MAXF(a,b)            (((a) > (b)) ? (a) : (b))
+
+
+extern const TOKENEXTRA vp8_dct_value_tokens[DCT_MAX_VALUE*2];
+extern const TOKENEXTRA *vp8_dct_value_tokens_ptr;
+extern int vp8_dct_value_cost[DCT_MAX_VALUE*2];
+extern int *vp8_dct_value_cost_ptr;
+
+
+const int vp8_auto_speed_thresh[17] =
+{
+    1000,
+    200,
+    150,
+    130,
+    150,
+    125,
+    120,
+    115,
+    115,
+    115,
+    115,
+    115,
+    115,
+    115,
+    115,
+    115,
+    105
+};
+
+const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES] =
+{
+    ZEROMV,
+    DC_PRED,
+
+    NEARESTMV,
+    NEARMV,
+
+    ZEROMV,
+    NEARESTMV,
+
+    ZEROMV,
+    NEARESTMV,
+
+    NEARMV,
+    NEARMV,
+
+    V_PRED,
+    H_PRED,
+    TM_PRED,
+
+    NEWMV,
+    NEWMV,
+    NEWMV,
+
+    SPLITMV,
+    SPLITMV,
+    SPLITMV,
+
+    B_PRED,
+};
+
+const MV_REFERENCE_FRAME vp8_ref_frame_order[MAX_MODES] =
+{
+    LAST_FRAME,
+    INTRA_FRAME,
+
+    LAST_FRAME,
+    LAST_FRAME,
+
+    GOLDEN_FRAME,
+    GOLDEN_FRAME,
+
+    ALTREF_FRAME,
+    ALTREF_FRAME,
+
+    GOLDEN_FRAME,
+    ALTREF_FRAME,
+
+    INTRA_FRAME,
+    INTRA_FRAME,
+    INTRA_FRAME,
+
+    LAST_FRAME,
+    GOLDEN_FRAME,
+    ALTREF_FRAME,
+
+    LAST_FRAME,
+    GOLDEN_FRAME,
+    ALTREF_FRAME,
+
+    INTRA_FRAME,
+};
+
+static void fill_token_costs(
+    unsigned int c      [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens],
+    const vp8_prob p    [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens-1]
+)
+{
+    int i, j, k;
+
+
+    for (i = 0; i < BLOCK_TYPES; i++)
+        for (j = 0; j < COEF_BANDS; j++)
+            for (k = 0; k < PREV_COEF_CONTEXTS; k++)
+
+                vp8_cost_tokens((int *)(c [i][j][k]), p [i][j][k], vp8_coef_tree);
+
+}
+
+static int rd_iifactor [ 32 ] =  {    16,  16,  16,  12,   8,   4,   2,   0,
+                                      0,   0,   0,   0,   0,   0,   0,   0,
+                                      0,   0,   0,   0,   0,   0,   0,   0,
+                                      0,   0,   0,   0,   0,   0,   0,   0,
+                                 };
+
+
+
+
+// The values in this table should be reviewed
+static int sad_per_bit16lut[128] =
+{
+    4,  4, 4, 4,  4, 4, 4, 4,   // 4
+    4,  4, 4, 4,  4, 4, 4, 4,   // 1
+    4,  4, 4, 4,  4, 4, 4, 4,   // 2
+    4,  4, 4, 4,  4, 4, 4, 4,   // 3
+    4,  4, 4, 4,  4, 4, 4, 4,   // 4
+    4,  4, 12, 12, 13, 13, 14, 14, // 5
+    14, 14, 14, 15, 15, 15, 15, 15, // 6
+    15, 15, 15, 15, 15, 15, 15, 15, // 7
+    15, 15, 15, 15, 15, 16, 16, 16, // 8
+    16, 16, 18, 18, 18, 18, 19, 19, // 9
+    19, 19, 19, 19, 19, 19, 19, 19, // 10
+    20, 20, 22, 22, 22, 22, 21, 21, // 11
+    22, 22, 22, 22, 22, 22, 22, 22, // 12
+    22, 22, 22, 22, 22, 22, 22, 22, // 13
+    22, 22, 22, 22, 22, 22, 22, 22, // 14
+    22, 22, 22, 22, 22, 22, 22, 22, // 15
+};
+
+static int sad_per_bit4lut[128] =
+{
+    4,  4, 4, 4,  4, 4, 4, 4,   // 4
+    4,  4, 4, 4,  4, 4, 4, 4,   // 1
+    4,  4, 4, 4,  4, 4, 4, 4,   // 2
+    4,  4, 4, 4,  4, 4, 4, 4,   // 3
+    4,  4, 4, 4,  4, 4, 4, 4,   // 4
+    4,  4, 15, 15, 15, 15, 16, 16, // 5
+    16, 17, 17, 17, 17, 17, 17, 17, // 6
+    17, 17, 19, 19, 22, 22, 21, 21, // 7
+    23, 23, 23, 23, 23, 24, 24, 24, // 8
+    25, 25, 27, 27, 27, 27, 28, 28, // 9
+    28, 28, 29, 29, 29, 29, 29, 29, // 10
+    30, 30, 31, 31, 31, 31, 32, 32, // 11
+    34, 34, 34, 34, 34, 34, 34, 34, // 12
+    34, 34, 34, 34, 34, 34, 34, 34, // 13
+    34, 34, 34, 34, 34, 34, 34, 34, // 14
+    34, 34, 34, 34, 34, 34, 34, 34, // 15
+};
+
+void vp8cx_initialize_me_consts(VP8_COMP *cpi, int QIndex)
+{
+    cpi->mb.sadperbit16 =  sad_per_bit16lut[QIndex];
+    cpi->mb.sadperbit4  =  sad_per_bit4lut[QIndex];
+}
+
+void vp8_initialize_rd_consts(VP8_COMP *cpi, int Qvalue)
+{
+    int q;
+    int i;
+    int *thresh;
+    int threshmult;
+
+    int capped_q = (Qvalue < 160) ? Qvalue : 160;
+
+    vp8_clear_system_state();  //__asm emms;
+
+    cpi->RDMULT = (int)((0.00007 * (capped_q * capped_q * capped_q * capped_q)) - (0.0125 * (capped_q * capped_q * capped_q)) +
+                        (2.25 * (capped_q * capped_q)) - (12.5 * capped_q) + 25.0);
+
+    if (cpi->RDMULT < 25)
+        cpi->RDMULT = 25;
+
+    if (cpi->pass == 2)
+    {
+        if (cpi->common.frame_type == KEY_FRAME)
+            cpi->RDMULT += (cpi->RDMULT * rd_iifactor[0]) / 16;
+        else if (cpi->next_iiratio > 31)
+            cpi->RDMULT += (cpi->RDMULT * rd_iifactor[31]) / 16;
+        else
+            cpi->RDMULT += (cpi->RDMULT * rd_iifactor[cpi->next_iiratio]) / 16;
+    }
+
+
+    // Extend rate multiplier along side quantizer zbin increases
+    if (cpi->zbin_over_quant  > 0)
+    {
+        // Extend rate multiplier along side quantizer zbin increases
+        if (cpi->zbin_over_quant  > 0)
+        {
+            double oq_factor = pow(1.006,  cpi->zbin_over_quant);
+
+            if (oq_factor > (1.0 + ((double)cpi->zbin_over_quant / 64.0)))
+                oq_factor = (1.0 + (double)cpi->zbin_over_quant / 64.0);
+
+            cpi->RDMULT *= (int)oq_factor;
+        }
+    }
+
+    cpi->mb.errorperbit = (cpi->RDMULT / 100);
+
+    if (cpi->mb.errorperbit < 1)
+        cpi->mb.errorperbit = 1;
+
+    vp8_set_speed_features(cpi);
+
+    if (cpi->common.simpler_lpf)
+        cpi->common.filter_type = SIMPLE_LOOPFILTER;
+
+    q = (int)pow(Qvalue, 1.25);
+
+    if (q < 8)
+        q = 8;
+
+    if (cpi->ref_frame_flags == VP8_ALT_FLAG)
+    {
+        thresh      = &cpi->rd_threshes[THR_NEWA];
+        threshmult  = cpi->sf.thresh_mult[THR_NEWA];
+    }
+    else if (cpi->ref_frame_flags == VP8_GOLD_FLAG)
+    {
+        thresh      = &cpi->rd_threshes[THR_NEWG];
+        threshmult  = cpi->sf.thresh_mult[THR_NEWG];
+    }
+    else
+    {
+        thresh      = &cpi->rd_threshes[THR_NEWMV];
+        threshmult  = cpi->sf.thresh_mult[THR_NEWMV];
+    }
+
+    if (cpi->RDMULT > 1000)
+    {
+        cpi->RDDIV = 1;
+        cpi->RDMULT /= 100;
+
+        for (i = 0; i < MAX_MODES; i++)
+        {
+            if (cpi->sf.thresh_mult[i] < INT_MAX)
+            {
+                cpi->rd_threshes[i] = cpi->sf.thresh_mult[i] * q / 100;
+            }
+            else
+            {
+                cpi->rd_threshes[i] = INT_MAX;
+            }
+
+            cpi->rd_baseline_thresh[i] = cpi->rd_threshes[i];
+        }
+    }
+    else
+    {
+        cpi->RDDIV = 100;
+
+        for (i = 0; i < MAX_MODES; i++)
+        {
+            if (cpi->sf.thresh_mult[i] < (INT_MAX / q))
+            {
+                cpi->rd_threshes[i] = cpi->sf.thresh_mult[i] * q;
+            }
+            else
+            {
+                cpi->rd_threshes[i] = INT_MAX;
+            }
+
+            cpi->rd_baseline_thresh[i] = cpi->rd_threshes[i];
+        }
+    }
+
+    fill_token_costs(
+        cpi->mb.token_costs,
+        (const vp8_prob( *)[8][3][11]) cpi->common.fc.coef_probs
+    );
+
+    vp8_init_mode_costs(cpi);
+
+}
+
+void vp8_auto_select_speed(VP8_COMP *cpi)
+{
+    int used = cpi->oxcf.cpu_used;
+
+    int milliseconds_for_compress = (int)(1000000 / cpi->oxcf.frame_rate);
+
+    milliseconds_for_compress = milliseconds_for_compress * (16 - cpi->oxcf.cpu_used) / 16;
+
+#if 0
+
+    if (0)
+    {
+        FILE *f;
+
+        f = fopen("speed.stt", "a");
+        fprintf(f, " %8ld %10ld %10ld %10ld\n",
+                cpi->common.current_video_frame, cpi->Speed, milliseconds_for_compress, cpi->avg_pick_mode_time);
+        fclose(f);
+    }
+
+#endif
+
+    /*
+    // this is done during parameter valid check
+    if( used > 16)
+        used = 16;
+    if( used < -16)
+        used = -16;
+    */
+
+    if (cpi->avg_pick_mode_time < milliseconds_for_compress && (cpi->avg_encode_time - cpi->avg_pick_mode_time) < milliseconds_for_compress)
+    {
+        if (cpi->avg_pick_mode_time == 0)
+        {
+            cpi->Speed = 4;
+        }
+        else
+        {
+            if (milliseconds_for_compress * 100 < cpi->avg_encode_time * 95)
+            {
+                cpi->Speed          += 2;
+                cpi->avg_pick_mode_time = 0;
+                cpi->avg_encode_time = 0;
+
+                if (cpi->Speed > 16)
+                {
+                    cpi->Speed = 16;
+                }
+            }
+
+            if (milliseconds_for_compress * 100 > cpi->avg_encode_time * vp8_auto_speed_thresh[cpi->Speed])
+            {
+                cpi->Speed          -= 1;
+                cpi->avg_pick_mode_time = 0;
+                cpi->avg_encode_time = 0;
+
+                // In real-time mode, cpi->speed is in [4, 16].
+                if (cpi->Speed < 4)        //if ( cpi->Speed < 0 )
+                {
+                    cpi->Speed = 4;        //cpi->Speed = 0;
+                }
+            }
+        }
+    }
+    else
+    {
+        cpi->Speed += 4;
+
+        if (cpi->Speed > 16)
+            cpi->Speed = 16;
+
+
+        cpi->avg_pick_mode_time = 0;
+        cpi->avg_encode_time = 0;
+    }
+}
+
+int vp8_block_error_c(short *coeff, short *dqcoeff)
+{
+    int i;
+    int error = 0;
+
+    for (i = 0; i < 16; i++)
+    {
+        int this_diff = coeff[i] - dqcoeff[i];
+        error += this_diff * this_diff;
+    }
+
+    return error;
+}
+
+int vp8_mbblock_error_c(MACROBLOCK *mb, int dc)
+{
+    BLOCK  *be;
+    BLOCKD *bd;
+    int i, j;
+    int berror, error = 0;
+
+    for (i = 0; i < 16; i++)
+    {
+        be = &mb->block[i];
+        bd = &mb->e_mbd.block[i];
+
+        berror = 0;
+
+        for (j = dc; j < 16; j++)
+        {
+            int this_diff = be->coeff[j] - bd->dqcoeff[j];
+            berror += this_diff * this_diff;
+        }
+
+        error += berror;
+    }
+
+    return error;
+}
+
+int vp8_mbuverror_c(MACROBLOCK *mb)
+{
+
+    BLOCK  *be;
+    BLOCKD *bd;
+
+
+    int i;
+    int error = 0;
+
+    for (i = 16; i < 24; i++)
+    {
+        be = &mb->block[i];
+        bd = &mb->e_mbd.block[i];
+
+        error += vp8_block_error_c(be->coeff, bd->dqcoeff);
+    }
+
+    return error;
+}
+
+#if !(CONFIG_REALTIME_ONLY)
+static int macro_block_max_error(MACROBLOCK *mb)
+{
+    int error = 0;
+    int dc = 0;
+    BLOCK  *be;
+    int i, j;
+    int berror;
+
+    dc = !(mb->e_mbd.mbmi.mode == B_PRED || mb->e_mbd.mbmi.mode == SPLITMV);
+
+    for (i = 0; i < 16; i++)
+    {
+        be = &mb->block[i];
+
+        berror = 0;
+
+        for (j = dc; j < 16; j++)
+        {
+            int this_diff = be->coeff[j];
+            berror += this_diff * this_diff;
+        }
+
+        error += berror;
+    }
+
+    for (i = 16; i < 24; i++)
+    {
+        be = &mb->block[i];
+        berror = 0;
+
+        for (j = 0; j < 16; j++)
+        {
+            int this_diff = be->coeff[j];
+            berror += this_diff * this_diff;
+        }
+
+        error += berror;
+    }
+
+    error <<= 2;
+
+    if (dc)
+    {
+        be = &mb->block[24];
+        berror = 0;
+
+        for (j = 0; j < 16; j++)
+        {
+            int this_diff = be->coeff[j];
+            berror += this_diff * this_diff;
+        }
+
+        error += berror;
+    }
+
+    error >>= 4;
+    return error;
+}
+#endif
+
+int VP8_UVSSE(MACROBLOCK *x, const vp8_variance_rtcd_vtable_t *rtcd)
+{
+    unsigned char *uptr, *vptr;
+    unsigned char *upred_ptr = (*(x->block[16].base_src) + x->block[16].src);
+    unsigned char *vpred_ptr = (*(x->block[20].base_src) + x->block[20].src);
+    int uv_stride = x->block[16].src_stride;
+
+    unsigned int sse1 = 0;
+    unsigned int sse2 = 0;
+    int mv_row;
+    int mv_col;
+    int offset;
+    int pre_stride = x->e_mbd.block[16].pre_stride;
+
+    vp8_build_uvmvs(&x->e_mbd, 0);
+    mv_row = x->e_mbd.block[16].bmi.mv.as_mv.row;
+    mv_col = x->e_mbd.block[16].bmi.mv.as_mv.col;
+
+    offset = (mv_row >> 3) * pre_stride + (mv_col >> 3);
+    uptr = x->e_mbd.pre.u_buffer + offset;
+    vptr = x->e_mbd.pre.v_buffer + offset;
+
+    if ((mv_row | mv_col) & 7)
+    {
+        VARIANCE_INVOKE(rtcd, subpixvar8x8)(uptr, pre_stride, mv_col & 7, mv_row & 7, upred_ptr, uv_stride, &sse2);
+        VARIANCE_INVOKE(rtcd, subpixvar8x8)(vptr, pre_stride, mv_col & 7, mv_row & 7, vpred_ptr, uv_stride, &sse1);
+        sse2 += sse1;
+    }
+    else
+    {
+        VARIANCE_INVOKE(rtcd, subpixvar8x8)(uptr, pre_stride, mv_col & 7, mv_row & 7, upred_ptr, uv_stride, &sse2);
+        VARIANCE_INVOKE(rtcd, subpixvar8x8)(vptr, pre_stride, mv_col & 7, mv_row & 7, vpred_ptr, uv_stride, &sse1);
+        sse2 += sse1;
+    }
+
+    return sse2;
+
+}
+
+#if !(CONFIG_REALTIME_ONLY)
+static int cost_coeffs(MACROBLOCK *mb, BLOCKD *b, int type, ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l)
+{
+    int c = !type;              /* start at coef 0, unless Y with Y2 */
+    int eob = b->eob;
+    int pt ;    /* surrounding block/prev coef predictor */
+    int cost = 0;
+    short *qcoeff_ptr = b->qcoeff;
+
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+# define QC( I)  ( qcoeff_ptr [vp8_default_zig_zag1d[I]] )
+
+    for (; c < eob; c++)
+    {
+        int v = QC(c);
+        int t = vp8_dct_value_tokens_ptr[v].Token;
+        cost += mb->token_costs [type] [vp8_coef_bands[c]] [pt] [t];
+        cost += vp8_dct_value_cost_ptr[v];
+        pt = vp8_prev_token_class[t];
+    }
+
+# undef QC
+
+    if (c < 16)
+        cost += mb->token_costs [type] [vp8_coef_bands[c]] [pt] [DCT_EOB_TOKEN];
+
+    pt = (c != !type); // is eob first coefficient;
+    *a = *l = pt;
+
+    return cost;
+}
+
+int vp8_rdcost_mby(MACROBLOCK *mb)
+{
+    int cost = 0;
+    int b;
+    TEMP_CONTEXT t, t2;
+    int type = 0;
+
+    MACROBLOCKD *x = &mb->e_mbd;
+
+    vp8_setup_temp_context(&t, x->above_context[Y1CONTEXT], x->left_context[Y1CONTEXT], 4);
+    vp8_setup_temp_context(&t2, x->above_context[Y2CONTEXT], x->left_context[Y2CONTEXT], 1);
+
+    if (x->mbmi.mode == SPLITMV)
+        type = 3;
+
+    for (b = 0; b < 16; b++)
+        cost += cost_coeffs(mb, x->block + b, type,
+                            t.a + vp8_block2above[b], t.l + vp8_block2left[b]);
+
+    if (x->mbmi.mode != SPLITMV)
+        cost += cost_coeffs(mb, x->block + 24, 1,
+                            t2.a + vp8_block2above[24], t2.l + vp8_block2left[24]);
+
+    return cost;
+}
+
+
+static void rd_pick_intra4x4block(
+    VP8_COMP *cpi,
+    MACROBLOCK *x,
+    BLOCK *be,
+    BLOCKD *b,
+    B_PREDICTION_MODE *best_mode,
+    B_PREDICTION_MODE above,
+    B_PREDICTION_MODE left,
+    ENTROPY_CONTEXT *a,
+    ENTROPY_CONTEXT *l,
+
+    int *bestrate,
+    int *bestratey,
+    int *bestdistortion)
+{
+    B_PREDICTION_MODE mode;
+    int best_rd = INT_MAX;       // 1<<30
+    int rate = 0;
+    int distortion;
+    unsigned int *mode_costs;
+
+    ENTROPY_CONTEXT ta = *a, tempa = *a;
+    ENTROPY_CONTEXT tl = *l, templ = *l;
+
+
+    if (x->e_mbd.frame_type == KEY_FRAME)
+    {
+        mode_costs  = x->bmode_costs[above][left];
+    }
+    else
+    {
+        mode_costs = x->inter_bmode_costs;
+    }
+
+    for (mode = B_DC_PRED; mode <= B_HU_PRED; mode++)
+    {
+        int this_rd;
+        int ratey;
+
+        rate = mode_costs[mode];
+        vp8_encode_intra4x4block_rd(IF_RTCD(&cpi->rtcd), x, be, b, mode);
+
+        tempa = ta;
+        templ = tl;
+
+        ratey = cost_coeffs(x, b, 3, &tempa, &templ);
+        rate += ratey;
+        distortion = ENCODEMB_INVOKE(IF_RTCD(&cpi->rtcd.encodemb), berr)(be->coeff, b->dqcoeff) >> 2;
+
+        this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
+
+        if (this_rd < best_rd)
+        {
+            *bestrate = rate;
+            *bestratey = ratey;
+            *bestdistortion = distortion;
+            best_rd = this_rd;
+            *best_mode = mode;
+            *a = tempa;
+            *l = templ;
+        }
+    }
+
+    b->bmi.mode = (B_PREDICTION_MODE)(*best_mode);
+    vp8_encode_intra4x4block_rd(IF_RTCD(&cpi->rtcd), x, be, b, b->bmi.mode);
+
+}
+
+
+int vp8_rd_pick_intra4x4mby_modes(VP8_COMP *cpi, MACROBLOCK *mb, int *Rate, int *rate_y, int *Distortion)
+{
+    MACROBLOCKD *const xd = &mb->e_mbd;
+    int i;
+    TEMP_CONTEXT t;
+    int cost = mb->mbmode_cost [xd->frame_type] [B_PRED];
+    int distortion = 0;
+    int tot_rate_y = 0;
+
+    vp8_intra_prediction_down_copy(xd);
+    vp8_setup_temp_context(&t, xd->above_context[Y1CONTEXT], xd->left_context[Y1CONTEXT], 4);
+
+    for (i = 0; i < 16; i++)
+    {
+        MODE_INFO *const mic = xd->mode_info_context;
+        const int mis = xd->mode_info_stride;
+        const B_PREDICTION_MODE A = vp8_above_bmi(mic, i, mis)->mode;
+        const B_PREDICTION_MODE L = vp8_left_bmi(mic, i)->mode;
+        B_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode);
+        int UNINITIALIZED_IS_SAFE(r), UNINITIALIZED_IS_SAFE(ry), UNINITIALIZED_IS_SAFE(d);
+
+        rd_pick_intra4x4block(
+            cpi, mb, mb->block + i, xd->block + i, &best_mode, A, L,
+            t.a + vp8_block2above[i],
+            t.l + vp8_block2left[i], &r, &ry, &d);
+
+        cost += r;
+        distortion += d;
+        tot_rate_y += ry;
+        mic->bmi[i].mode = xd->block[i].bmi.mode = best_mode;
+    }
+
+    *Rate = cost;
+    *rate_y += tot_rate_y;
+    *Distortion = distortion;
+
+    return RDCOST(mb->rdmult, mb->rddiv, cost, distortion);
+}
+
+int vp8_rd_pick_intra16x16mby_mode(VP8_COMP *cpi, MACROBLOCK *x, int *Rate, int *rate_y, int *Distortion)
+{
+
+    MB_PREDICTION_MODE mode;
+    MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
+    int rate, ratey;
+    unsigned int distortion;
+    int best_rd = INT_MAX;
+
+    //Y Search for 16x16 intra prediction mode
+    for (mode = DC_PRED; mode <= TM_PRED; mode++)
+    {
+        int this_rd;
+        int dummy;
+        rate = 0;
+
+        x->e_mbd.mbmi.mode = mode;
+
+        rate += x->mbmode_cost[x->e_mbd.frame_type][x->e_mbd.mbmi.mode];
+
+        vp8_encode_intra16x16mbyrd(IF_RTCD(&cpi->rtcd), x);
+
+        ratey = vp8_rdcost_mby(x);
+
+        rate += ratey;
+
+        VARIANCE_INVOKE(&cpi->rtcd.variance, get16x16var)(x->src.y_buffer, x->src.y_stride, x->e_mbd.dst.y_buffer, x->e_mbd.dst.y_stride, &distortion, &dummy);
+
+        this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
+
+        if (this_rd < best_rd)
+        {
+            mode_selected = mode;
+            best_rd = this_rd;
+            *Rate = rate;
+            *rate_y = ratey;
+            *Distortion = (int)distortion;
+        }
+    }
+
+    x->e_mbd.mbmi.mode = mode_selected;
+    return best_rd;
+}
+
+
+static int rd_cost_mbuv(MACROBLOCK *mb)
+{
+    TEMP_CONTEXT t, t2;
+    int b;
+    int cost = 0;
+    MACROBLOCKD *x = &mb->e_mbd;
+
+    vp8_setup_temp_context(&t, x->above_context[UCONTEXT], x->left_context[UCONTEXT], 2);
+    vp8_setup_temp_context(&t2, x->above_context[VCONTEXT], x->left_context[VCONTEXT], 2);
+
+    for (b = 16; b < 20; b++)
+        cost += cost_coeffs(mb, x->block + b, vp8_block2type[b],
+                            t.a + vp8_block2above[b], t.l + vp8_block2left[b]);
+
+    for (b = 20; b < 24; b++)
+        cost += cost_coeffs(mb, x->block + b, vp8_block2type[b],
+                            t2.a + vp8_block2above[b], t2.l + vp8_block2left[b]);
+
+    return cost;
+}
+
+
+unsigned int vp8_get_mbuvrecon_error(const vp8_variance_rtcd_vtable_t *rtcd, const MACROBLOCK *x) // sum of squares
+{
+    unsigned int sse0, sse1;
+    int sum0, sum1;
+    VARIANCE_INVOKE(rtcd, get8x8var)(x->src.u_buffer, x->src.uv_stride, x->e_mbd.dst.u_buffer, x->e_mbd.dst.uv_stride, &sse0, &sum0);
+    VARIANCE_INVOKE(rtcd, get8x8var)(x->src.v_buffer, x->src.uv_stride, x->e_mbd.dst.v_buffer, x->e_mbd.dst.uv_stride, &sse1, &sum1);
+    return (sse0 + sse1);
+}
+
+static int vp8_rd_inter_uv(VP8_COMP *cpi, MACROBLOCK *x, int *rate, int *distortion, int fullpixel)
+{
+    vp8_build_uvmvs(&x->e_mbd, fullpixel);
+    vp8_encode_inter16x16uvrd(IF_RTCD(&cpi->rtcd), x);
+
+
+    *rate       = rd_cost_mbuv(x);
+    *distortion = ENCODEMB_INVOKE(&cpi->rtcd.encodemb, mbuverr)(x) / 4;
+
+    return UVRDFUNC(x->rdmult, x->rddiv, *rate, *distortion, cpi->target_bits_per_mb);
+}
+
+int vp8_rd_pick_intra_mbuv_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate, int *rate_tokenonly, int *distortion)
+{
+    MB_PREDICTION_MODE mode;
+    MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(mode_selected);
+    int best_rd = INT_MAX;
+    int UNINITIALIZED_IS_SAFE(d), UNINITIALIZED_IS_SAFE(r);
+    int rate_to;
+
+    for (mode = DC_PRED; mode <= TM_PRED; mode++)
+    {
+        int rate;
+        int distortion;
+        int this_rd;
+
+        x->e_mbd.mbmi.uv_mode = mode;
+        vp8_encode_intra16x16mbuvrd(IF_RTCD(&cpi->rtcd), x);
+
+        rate_to = rd_cost_mbuv(x);
+        rate = rate_to + x->intra_uv_mode_cost[x->e_mbd.frame_type][x->e_mbd.mbmi.uv_mode];
+
+        distortion = vp8_get_mbuvrecon_error(IF_RTCD(&cpi->rtcd.variance), x);
+
+        this_rd = UVRDFUNC(x->rdmult, x->rddiv, rate, distortion, cpi->target_bits_per_mb);
+
+        if (this_rd < best_rd)
+        {
+            best_rd = this_rd;
+            d = distortion;
+            r = rate;
+            *rate_tokenonly = rate_to;
+            mode_selected = mode;
+        }
+    }
+
+    *rate = r;
+    *distortion = d;
+
+    x->e_mbd.mbmi.uv_mode = mode_selected;
+    return best_rd;
+}
+#endif
+
+int vp8_cost_mv_ref(MB_PREDICTION_MODE m, const int near_mv_ref_ct[4])
+{
+    vp8_prob p [VP8_MVREFS-1];
+    assert(NEARESTMV <= m  &&  m <= SPLITMV);
+    vp8_mv_ref_probs(p, near_mv_ref_ct);
+    return vp8_cost_token(vp8_mv_ref_tree, p, VP8_MVREFENCODINGS + m);
+}
+
+void vp8_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, MV *mv)
+{
+    int i;
+
+    x->e_mbd.mbmi.mode = mb;
+    x->e_mbd.mbmi.mv.as_mv.row = mv->row;
+    x->e_mbd.mbmi.mv.as_mv.col = mv->col;
+
+    for (i = 0; i < 16; i++)
+    {
+        B_MODE_INFO *bmi = &x->e_mbd.block[i].bmi;
+        bmi->mode = (B_PREDICTION_MODE) mb;
+        bmi->mv.as_mv.row = mv->row;
+        bmi->mv.as_mv.col = mv->col;
+    }
+}
+
+#if !(CONFIG_REALTIME_ONLY)
+int vp8_count_labels(int const *labelings)
+{
+    int i;
+    int count = 0;
+
+    for (i = 0; i < 16; i++)
+    {
+        if (labelings[i] > count)
+            count = labelings[i];
+    }
+
+    return count + 1;
+}
+
+
+static int labels2mode(
+    MACROBLOCK *x,
+    int const *labelings, int which_label,
+    B_PREDICTION_MODE this_mode,
+    MV *this_mv, MV *best_ref_mv,
+    int *mvcost[2]
+)
+{
+    MACROBLOCKD *const xd = & x->e_mbd;
+    MODE_INFO *const mic = xd->mode_info_context;
+    const int mis = xd->mode_info_stride;
+
+    int cost = 0;
+    int thismvcost = 0;
+
+    /* We have to be careful retrieving previously-encoded motion vectors.
+       Ones from this macroblock have to be pulled from the BLOCKD array
+       as they have not yet made it to the bmi array in our MB_MODE_INFO. */
+
+    int i = 0;
+
+    do
+    {
+        BLOCKD *const d = xd->block + i;
+        const int row = i >> 2,  col = i & 3;
+
+        B_PREDICTION_MODE m;
+
+        if (labelings[i] != which_label)
+            continue;
+
+        if (col  &&  labelings[i] == labelings[i-1])
+            m = LEFT4X4;
+        else if (row  &&  labelings[i] == labelings[i-4])
+            m = ABOVE4X4;
+        else
+        {
+            // the only time we should do costing for new motion vector or mode
+            // is when we are on a new label  (jbb May 08, 2007)
+            switch (m = this_mode)
+            {
+            case NEW4X4 :
+                thismvcost  = vp8_mv_bit_cost(this_mv, best_ref_mv, mvcost, 102);
+                break;
+            case LEFT4X4:
+                *this_mv = col ? d[-1].bmi.mv.as_mv : vp8_left_bmi(mic, i)->mv.as_mv;
+                break;
+            case ABOVE4X4:
+                *this_mv = row ? d[-4].bmi.mv.as_mv : vp8_above_bmi(mic, i, mis)->mv.as_mv;
+                break;
+            case ZERO4X4:
+                this_mv->row = this_mv->col = 0;
+                break;
+            default:
+                break;
+            }
+
+            if (m == ABOVE4X4)  // replace above with left if same
+            {
+                const MV mv = col ? d[-1].bmi.mv.as_mv : vp8_left_bmi(mic, i)->mv.as_mv;
+
+                if (mv.row == this_mv->row  &&  mv.col == this_mv->col)
+                    m = LEFT4X4;
+            }
+
+            cost = x->inter_bmode_costs[ m];
+        }
+
+        d->bmi.mode = m;
+        d->bmi.mv.as_mv = *this_mv;
+
+    }
+    while (++i < 16);
+
+    cost += thismvcost ;
+    return cost;
+}
+
+static int rdcost_mbsegment_y(MACROBLOCK *mb, const int *labels, int which_label, TEMP_CONTEXT *t)
+{
+    int cost = 0;
+    int b;
+    MACROBLOCKD *x = &mb->e_mbd;
+
+
+    for (b = 0; b < 16; b++)
+        if (labels[ b] == which_label)
+            cost += cost_coeffs(mb, x->block + b, 3,
+                                t->a + vp8_block2above[b],
+                                t->l + vp8_block2left[b]);
+
+    return cost;
+
+}
+static unsigned int vp8_encode_inter_mb_segment(MACROBLOCK *x, int const *labels, int which_label, const vp8_encodemb_rtcd_vtable_t *rtcd)
+{
+    int i;
+    unsigned int distortion = 0;
+
+    for (i = 0; i < 16; i++)
+    {
+        if (labels[i] == which_label)
+        {
+            BLOCKD *bd = &x->e_mbd.block[i];
+            BLOCK *be = &x->block[i];
+
+
+            vp8_build_inter_predictors_b(bd, 16, x->e_mbd.subpixel_predict);
+            ENCODEMB_INVOKE(rtcd, subb)(be, bd, 16);
+            x->short_fdct4x4rd(be->src_diff, be->coeff, 32);
+
+            // set to 0 no way to account for 2nd order DC so discount
+            //be->coeff[0] = 0;
+            x->quantize_brd(be, bd);
+
+            distortion += ENCODEMB_INVOKE(rtcd, berr)(be->coeff, bd->dqcoeff);
+        }
+    }
+
+    return distortion;
+}
+
+static void macro_block_yrd(MACROBLOCK *mb, int *Rate, int *Distortion, const vp8_encodemb_rtcd_vtable_t *rtcd)
+{
+    int b;
+    MACROBLOCKD *const x = &mb->e_mbd;
+    BLOCK   *const mb_y2 = mb->block + 24;
+    BLOCKD *const x_y2  = x->block + 24;
+    short *Y2DCPtr = mb_y2->src_diff;
+    BLOCK *beptr;
+    int d;
+
+    ENCODEMB_INVOKE(rtcd, submby)(mb->src_diff, mb->src.y_buffer, mb->e_mbd.predictor, mb->src.y_stride);
+
+    // Fdct and building the 2nd order block
+    for (beptr = mb->block; beptr < mb->block + 16; beptr += 2)
+    {
+        mb->short_fdct8x4rd(beptr->src_diff, beptr->coeff, 32);
+        *Y2DCPtr++ = beptr->coeff[0];
+        *Y2DCPtr++ = beptr->coeff[16];
+    }
+
+    // 2nd order fdct
+    if (x->mbmi.mode != SPLITMV)
+    {
+        mb->short_walsh4x4(mb_y2->src_diff, mb_y2->coeff, 8);
+    }
+
+    // Quantization
+    for (b = 0; b < 16; b++)
+    {
+        mb->quantize_brd(&mb->block[b], &mb->e_mbd.block[b]);
+    }
+
+    // DC predication and Quantization of 2nd Order block
+    if (x->mbmi.mode != SPLITMV)
+    {
+
+        {
+            mb->quantize_brd(mb_y2, x_y2);
+        }
+    }
+
+    // Distortion
+    if (x->mbmi.mode == SPLITMV)
+        d = ENCODEMB_INVOKE(rtcd, mberr)(mb, 0) << 2;
+    else
+    {
+        d = ENCODEMB_INVOKE(rtcd, mberr)(mb, 1) << 2;
+        d += ENCODEMB_INVOKE(rtcd, berr)(mb_y2->coeff, x_y2->dqcoeff);
+    }
+
+    *Distortion = (d >> 4);
+
+    // rate
+    *Rate = vp8_rdcost_mby(mb);
+}
+
+static int vp8_rd_pick_best_mbsegmentation(VP8_COMP *cpi, MACROBLOCK *x, MV *best_ref_mv, int best_rd, int *mdcounts, int *returntotrate, int *returnyrate, int *returndistortion, int compressor_speed, int *mvcost[2], int mvthresh, int fullpixel)
+{
+    int i, segmentation;
+    B_PREDICTION_MODE this_mode;
+    MACROBLOCKD *xc = &x->e_mbd;
+    BLOCK *b = &x->block[0];
+    BLOCKD *d = &x->e_mbd.block[0];
+    BLOCK *c = &x->block[0];
+    BLOCKD *e = &x->e_mbd.block[0];
+    int const *labels;
+    int best_segment_rd = INT_MAX;
+    int best_seg = 0;
+    int br = 0;
+    int bd = 0;
+    int bsr = 0;
+    int bsd = 0;
+    int bestsegmentyrate = 0;
+
+    // FIX TO Rd error outrange bug PGW 9 june 2004
+    B_PREDICTION_MODE bmodes[16] = {ZERO4X4, ZERO4X4, ZERO4X4, ZERO4X4,
+                                    ZERO4X4, ZERO4X4, ZERO4X4, ZERO4X4,
+                                    ZERO4X4, ZERO4X4, ZERO4X4, ZERO4X4,
+                                    ZERO4X4, ZERO4X4, ZERO4X4, ZERO4X4
+                                   };
+
+    MV bmvs[16];
+    int beobs[16];
+
+    for (segmentation = 0; segmentation < VP8_NUMMBSPLITS; segmentation++)
+    {
+        int label_count;
+        int this_segment_rd = 0;
+        int label_mv_thresh;
+        int rate = 0;
+        int sbr = 0;
+        int sbd = 0;
+        int UNINITIALIZED_IS_SAFE(sseshift);
+        int segmentyrate = 0;
+
+        vp8_variance_fn_ptr_t v_fn_ptr;
+
+        TEMP_CONTEXT t;
+        TEMP_CONTEXT tb;
+        vp8_setup_temp_context(&t, xc->above_context[Y1CONTEXT], xc->left_context[Y1CONTEXT], 4);
+
+        br = 0;
+        bd = 0;
+
+        switch (segmentation)
+        {
+        case 0:
+            v_fn_ptr.vf    = VARIANCE_INVOKE(&cpi->rtcd.variance, var16x8);
+            v_fn_ptr.svf   = VARIANCE_INVOKE(&cpi->rtcd.variance, subpixvar16x8);
+            v_fn_ptr.sdf   = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x8);
+            v_fn_ptr.sdx3f = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x8x3);
+            v_fn_ptr.sdx4df = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x8x4d);
+            sseshift = 3;
+            break;
+        case 1:
+            v_fn_ptr.vf    = VARIANCE_INVOKE(&cpi->rtcd.variance, var8x16);
+            v_fn_ptr.svf   = VARIANCE_INVOKE(&cpi->rtcd.variance, subpixvar8x16);
+            v_fn_ptr.sdf   = VARIANCE_INVOKE(&cpi->rtcd.variance, sad8x16);
+            v_fn_ptr.sdx3f = VARIANCE_INVOKE(&cpi->rtcd.variance, sad8x16x3);
+            v_fn_ptr.sdx4df = VARIANCE_INVOKE(&cpi->rtcd.variance, sad8x16x4d);
+            sseshift = 3;
+            break;
+        case 2:
+            v_fn_ptr.vf    = VARIANCE_INVOKE(&cpi->rtcd.variance, var8x8);
+            v_fn_ptr.svf   = VARIANCE_INVOKE(&cpi->rtcd.variance, subpixvar8x8);
+            v_fn_ptr.sdf   = VARIANCE_INVOKE(&cpi->rtcd.variance, sad8x8);
+            v_fn_ptr.sdx3f = VARIANCE_INVOKE(&cpi->rtcd.variance, sad8x8x3);
+            v_fn_ptr.sdx4df = VARIANCE_INVOKE(&cpi->rtcd.variance, sad8x8x4d);
+            sseshift = 2;
+            break;
+        case 3:
+            v_fn_ptr.vf    = VARIANCE_INVOKE(&cpi->rtcd.variance, var4x4);
+            v_fn_ptr.svf   = VARIANCE_INVOKE(&cpi->rtcd.variance, subpixvar4x4);
+            v_fn_ptr.sdf   = VARIANCE_INVOKE(&cpi->rtcd.variance, sad4x4);
+            v_fn_ptr.sdx3f = VARIANCE_INVOKE(&cpi->rtcd.variance, sad4x4x3);
+            v_fn_ptr.sdx4df = VARIANCE_INVOKE(&cpi->rtcd.variance, sad4x4x4d);
+            sseshift = 0;
+            break;
+        }
+
+        labels = vp8_mbsplits[segmentation];
+        label_count = vp8_count_labels(labels);
+
+        // 64 makes this threshold really big effectively
+        // making it so that we very rarely check mvs on
+        // segments.   setting this to 1 would make mv thresh
+        // roughly equal to what it is for macroblocks
+        label_mv_thresh = 1 * mvthresh / label_count ;
+
+        // Segmentation method overheads
+        rate = vp8_cost_token(vp8_mbsplit_tree, vp8_mbsplit_probs, vp8_mbsplit_encodings + segmentation);
+
+        rate += vp8_cost_mv_ref(SPLITMV, mdcounts);
+
+        this_segment_rd += RDFUNC(x->rdmult, x->rddiv, rate, 0, cpi->target_bits_per_mb);
+        br += rate;
+
+        for (i = 0; i < label_count; i++)
+        {
+            MV mode_mv[B_MODE_COUNT];
+            int best_label_rd = INT_MAX;
+            B_PREDICTION_MODE mode_selected = ZERO4X4;
+            int j;
+            int bestlabelyrate = 0;
+
+            b = &x->block[0];
+            d = &x->e_mbd.block[0];
+
+
+            // find first label
+            for (j = 0; j < 16; j++)
+                if (labels[j] == i)
+                    break;
+
+            c = &x->block[j];
+            e = &x->e_mbd.block[j];
+
+            // search for the best motion vector on this segment
+            for (this_mode = LEFT4X4; this_mode <= NEW4X4 ; this_mode ++)
+            {
+                int distortion;
+                int this_rd;
+                int num00;
+                int labelyrate;
+
+                TEMP_CONTEXT ts;
+                vp8_setup_temp_context(&ts, &t.a[0], &t.l[0], 4);
+
+                if (this_mode == NEW4X4)
+                {
+                    int step_param = 0;
+                    int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;
+                    int n;
+                    int thissme;
+                    int bestsme = INT_MAX;
+                    MV  temp_mv;
+
+                    // Is the best so far sufficiently good that we cant justify doing and new motion search.
+                    if (best_label_rd < label_mv_thresh)
+                        break;
+
+                    {
+                        int sadpb = x->sadperbit4;
+
+                        if (cpi->sf.search_method == HEX)
+                            bestsme = vp8_hex_search(x, c, e, best_ref_mv, &mode_mv[NEW4X4], step_param, sadpb/*x->errorperbit*/, &num00, v_fn_ptr.vf, v_fn_ptr.sdf, x->mvsadcost, mvcost);
+                        else
+                        {
+                            bestsme = cpi->diamond_search_sad(x, c, e, best_ref_mv, &mode_mv[NEW4X4], step_param, sadpb / 2/*x->errorperbit*/, &num00, &v_fn_ptr, x->mvsadcost, mvcost);
+
+                            n = num00;
+                            num00 = 0;
+
+                            while (n < further_steps)
+                            {
+                                n++;
+
+                                if (num00)
+                                    num00--;
+                                else
+                                {
+                                    thissme = cpi->diamond_search_sad(x, c, e, best_ref_mv, &temp_mv, step_param + n, sadpb / 2/*x->errorperbit*/, &num00, &v_fn_ptr, x->mvsadcost, mvcost);
+
+                                    if (thissme < bestsme)
+                                    {
+                                        bestsme = thissme;
+                                        mode_mv[NEW4X4].row = temp_mv.row;
+                                        mode_mv[NEW4X4].col = temp_mv.col;
+                                    }
+                                }
+                            }
+                        }
+
+                        // Should we do a full search (best quality only)
+                        if ((compressor_speed == 0) && (bestsme >> sseshift) > 4000)
+                        {
+                            thissme = cpi->full_search_sad(x, c, e, best_ref_mv, sadpb / 4, 16, &v_fn_ptr, x->mvcost, x->mvsadcost);
+
+                            if (thissme < bestsme)
+                            {
+                                bestsme = thissme;
+                                mode_mv[NEW4X4] = e->bmi.mv.as_mv;
+                            }
+                            else
+                            {
+                                // The full search result is actually worse so re-instate the previous best vector
+                                e->bmi.mv.as_mv = mode_mv[NEW4X4];
+                            }
+                        }
+                    }
+
+                    if (bestsme < INT_MAX)
+                    {
+                        if (!fullpixel)
+                            cpi->find_fractional_mv_step(x, c, e, &mode_mv[NEW4X4], best_ref_mv, x->errorperbit / 2, v_fn_ptr.svf, v_fn_ptr.vf, mvcost);
+                        else
+                            vp8_skip_fractional_mv_step(x, c, e, &mode_mv[NEW4X4], best_ref_mv, x->errorperbit, v_fn_ptr.svf, v_fn_ptr.vf, mvcost);
+                    }
+                }
+
+                rate = labels2mode(x, labels, i, this_mode, &mode_mv[this_mode], best_ref_mv, mvcost);
+
+                // Trap vectors that reach beyond the UMV borders
+                if (((mode_mv[this_mode].row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].row >> 3) > x->mv_row_max) ||
+                    ((mode_mv[this_mode].col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].col >> 3) > x->mv_col_max))
+                {
+                    continue;
+                }
+
+                distortion = vp8_encode_inter_mb_segment(x, labels, i, IF_RTCD(&cpi->rtcd.encodemb)) / 4;
+
+                labelyrate = rdcost_mbsegment_y(x, labels, i, &ts);
+                rate += labelyrate;
+
+                this_rd = RDFUNC(x->rdmult, x->rddiv, rate, distortion, cpi->target_bits_per_mb);
+
+                if (this_rd < best_label_rd)
+                {
+                    sbr = rate;
+                    sbd = distortion;
+                    bestlabelyrate = labelyrate;
+                    mode_selected = this_mode;
+                    best_label_rd = this_rd;
+                    vp8_setup_temp_context(&tb, &ts.a[0], &ts.l[0], 4);
+
+                }
+            }
+
+            vp8_setup_temp_context(&t, &tb.a[0], &tb.l[0], 4);
+
+            labels2mode(x, labels, i, mode_selected, &mode_mv[mode_selected], best_ref_mv, mvcost);
+
+            br += sbr;
+            bd += sbd;
+            segmentyrate += bestlabelyrate;
+            this_segment_rd += best_label_rd;
+
+            if ((this_segment_rd > best_rd) || (this_segment_rd > best_segment_rd))
+                break;
+        }
+
+        if ((this_segment_rd <= best_rd) && (this_segment_rd < best_segment_rd))
+        {
+            bsr = br;
+            bsd = bd;
+            bestsegmentyrate = segmentyrate;
+            best_segment_rd = this_segment_rd;
+            best_seg = segmentation;
+
+            // store everything needed to come back to this!!
+            for (i = 0; i < 16; i++)
+            {
+                BLOCKD *bd = &x->e_mbd.block[i];
+
+                bmvs[i] = bd->bmi.mv.as_mv;
+                bmodes[i] = bd->bmi.mode;
+                beobs[i] = bd->eob;
+            }
+        }
+    }
+
+    // set it to the best
+    for (i = 0; i < 16; i++)
+    {
+        BLOCKD *bd = &x->e_mbd.block[i];
+
+        bd->bmi.mv.as_mv = bmvs[i];
+        bd->bmi.mode = bmodes[i];
+        bd->eob = beobs[i];
+    }
+
+    // Trap cases where the best split mode has all vectors coded 0,0 (or all the same)
+    if (FALSE)
+    {
+        int allsame = 1;
+
+        for (i = 1; i < 16; i++)
+        {
+            if ((bmvs[i].col != bmvs[i-1].col) || (bmvs[i].row != bmvs[i-1].row))
+            {
+                allsame = 0;
+                break;
+            }
+        }
+
+        if (allsame)
+        {
+            best_segment_rd = INT_MAX;
+        }
+    }
+
+    *returntotrate = bsr;
+    *returndistortion = bsd;
+    *returnyrate = bestsegmentyrate;
+
+
+
+    // save partitions
+    labels = vp8_mbsplits[best_seg];
+    x->e_mbd.mbmi.partitioning = best_seg;
+    x->e_mbd.mbmi.partition_count = vp8_count_labels(labels);
+
+    for (i = 0; i < x->e_mbd.mbmi.partition_count; i++)
+    {
+        int j;
+
+        for (j = 0; j < 16; j++)
+        {
+            if (labels[j] == i)
+                break;
+        }
+
+        x->e_mbd.mbmi.partition_bmi[i].mode = x->e_mbd.block[j].bmi.mode;
+        x->e_mbd.mbmi.partition_bmi[i].mv.as_mv = x->e_mbd.block[j].bmi.mv.as_mv;
+    }
+
+    return best_segment_rd;
+}
+
+
+int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int *returnintra)
+{
+    BLOCK *b = &x->block[0];
+    BLOCKD *d = &x->e_mbd.block[0];
+    MACROBLOCKD *xd = &x->e_mbd;
+    B_MODE_INFO best_bmodes[16];
+    MB_MODE_INFO best_mbmode;
+    MV best_ref_mv;
+    MV mode_mv[MB_MODE_COUNT];
+    MB_PREDICTION_MODE this_mode;
+    int num00;
+    int best_mode_index = 0;
+
+    int i;
+    int mode_index;
+    int mdcounts[4];
+    int rate;
+    int distortion;
+    int best_rd = INT_MAX; // 1 << 30;
+    int ref_frame_cost[MAX_REF_FRAMES];
+    int rate2, distortion2;
+    int uv_intra_rate, uv_intra_distortion, uv_intra_rate_tokenonly;
+    int rate_y, UNINITIALIZED_IS_SAFE(rate_uv);
+
+    //int all_rds[MAX_MODES];        // Experimental debug code.
+    //int all_rates[MAX_MODES];
+    //int all_dist[MAX_MODES];
+    //int intermodecost[MAX_MODES];
+
+    MB_PREDICTION_MODE uv_intra_mode;
+    int sse;
+    int sum;
+    int uvintra_eob = 0;
+    int tteob = 0;
+    int force_no_skip = 0;
+
+    *returnintra = INT_MAX;
+
+    cpi->mbs_tested_so_far++;          // Count of the number of MBs tested so far this frame
+
+    x->skip = 0;
+
+    ref_frame_cost[INTRA_FRAME]   = vp8_cost_zero(cpi->prob_intra_coded);
+
+    // Experimental code
+    // Adjust the RD multiplier based on the best case distortion we saw in the most recently coded mb
+    //if ( (cpi->last_mb_distortion) > 0 && (cpi->target_bits_per_mb > 0) )
+    /*{
+        int tmprdmult;
+
+        //tmprdmult = (cpi->last_mb_distortion * 256) / ((cpi->av_per_frame_bandwidth*256)/cpi->common.MBs);
+        tmprdmult = (cpi->last_mb_distortion * 256) / cpi->target_bits_per_mb;
+        //tmprdmult = tmprdmult;
+
+        //if ( tmprdmult > cpi->RDMULT * 2 )
+        //  tmprdmult = cpi->RDMULT * 2;
+        //else if ( tmprdmult < cpi->RDMULT / 2 )
+        //  tmprdmult = cpi->RDMULT / 2;
+
+        //tmprdmult = (tmprdmult < 25) ? 25 : tmprdmult;
+
+        //x->rdmult = tmprdmult;
+
+    }*/
+
+    // Special case treatment when GF and ARF are not sensible options for reference
+    if (cpi->ref_frame_flags == VP8_LAST_FLAG)
+    {
+        ref_frame_cost[LAST_FRAME]    = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_zero(255);
+        ref_frame_cost[GOLDEN_FRAME]  = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_one(255)
+                                        + vp8_cost_zero(128);
+        ref_frame_cost[ALTREF_FRAME]  = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_one(255)
+                                        + vp8_cost_one(128);
+    }
+    else
+    {
+        ref_frame_cost[LAST_FRAME]    = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_zero(cpi->prob_last_coded);
+        ref_frame_cost[GOLDEN_FRAME]  = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_one(cpi->prob_last_coded)
+                                        + vp8_cost_zero(cpi->prob_gf_coded);
+        ref_frame_cost[ALTREF_FRAME]  = vp8_cost_one(cpi->prob_intra_coded)
+                                        + vp8_cost_one(cpi->prob_last_coded)
+                                        + vp8_cost_one(cpi->prob_gf_coded);
+    }
+
+    vpx_memset(mode_mv, 0, sizeof(mode_mv));
+
+    x->e_mbd.mbmi.ref_frame = INTRA_FRAME;
+    vp8_rd_pick_intra_mbuv_mode(cpi, x, &uv_intra_rate, &uv_intra_rate_tokenonly, &uv_intra_distortion);
+    uv_intra_mode = x->e_mbd.mbmi.uv_mode;
+    {
+        uvintra_eob = 0;
+
+        for (i = 16; i < 24; i++)
+            uvintra_eob += x->e_mbd.block[i].eob;
+    }
+
+    for (mode_index = 0; mode_index < MAX_MODES; mode_index++)
+    {
+        int frame_cost;
+        int this_rd = INT_MAX;
+        int lf_or_gf = 0;           // Lat Frame (01) or gf/arf (1)
+        int disable_skip = 0;
+
+        force_no_skip = 0;
+
+        // Experimental debug code.
+        // Record of rd values recorded for this MB. -1 indicates not measured
+        //all_rds[mode_index] = -1;
+        //all_rates[mode_index] = -1;
+        //all_dist[mode_index] = -1;
+        //intermodecost[mode_index] = -1;  
+
+        // Test best rd so far against threshold for trying this mode.
+        if (best_rd <= cpi->rd_threshes[mode_index])
+            continue;
+
+
+
+        // These variables hold are rolling total cost and distortion for this mode
+        rate2 = 0;
+        distortion2 = 0;
+
+        // Where skip is allowable add in the default per mb cost for the no skip case.
+        // where we then decide to skip we have to delete this and replace it with the
+        // cost of signallying a skip
+        if (cpi->common.mb_no_coeff_skip)
+        {
+            rate2 += vp8_cost_bit(cpi->prob_skip_false, 0);
+        }
+
+        this_mode = vp8_mode_order[mode_index];
+
+        x->e_mbd.mbmi.mode = this_mode;
+        x->e_mbd.mbmi.uv_mode = DC_PRED;
+        x->e_mbd.mbmi.ref_frame = vp8_ref_frame_order[mode_index];
+
+        //Only consider ZEROMV/ALTREF_FRAME for alt ref frame.
+        if (cpi->is_src_frame_alt_ref)
+        {
+            if (this_mode != ZEROMV || x->e_mbd.mbmi.ref_frame != ALTREF_FRAME)
+                continue;
+        }
+
+        if (x->e_mbd.mbmi.ref_frame == LAST_FRAME)
+        {
+            if (!(cpi->ref_frame_flags & VP8_LAST_FLAG))
+                continue;
+
+            lf_or_gf = 0;  // Local last frame vs Golden frame flag
+
+            // Set up pointers for this macro block into the previous frame recon buffer
+            x->e_mbd.pre.y_buffer = cpi->common.last_frame.y_buffer + recon_yoffset;
+            x->e_mbd.pre.u_buffer = cpi->common.last_frame.u_buffer + recon_uvoffset;
+            x->e_mbd.pre.v_buffer = cpi->common.last_frame.v_buffer + recon_uvoffset;
+        }
+        else if (x->e_mbd.mbmi.ref_frame == GOLDEN_FRAME)
+        {
+
+            // not supposed to reference gold frame
+            if (!(cpi->ref_frame_flags & VP8_GOLD_FLAG))
+                continue;
+
+            lf_or_gf = 1;  // Local last frame vs Golden frame flag
+
+            // Set up pointers for this macro block into the previous frame recon buffer
+            x->e_mbd.pre.y_buffer = cpi->common.golden_frame.y_buffer + recon_yoffset;
+            x->e_mbd.pre.u_buffer = cpi->common.golden_frame.u_buffer + recon_uvoffset;
+            x->e_mbd.pre.v_buffer = cpi->common.golden_frame.v_buffer + recon_uvoffset;
+        }
+        else if (x->e_mbd.mbmi.ref_frame == ALTREF_FRAME)
+        {
+            // not supposed to reference alt ref frame
+            if (!(cpi->ref_frame_flags & VP8_ALT_FLAG))
+                continue;
+
+            //if ( !cpi->source_alt_ref_active )
+            //  continue;
+
+            lf_or_gf = 1;  // Local last frame vs Golden frame flag
+
+            // Set up pointers for this macro block into the previous frame recon buffer
+            x->e_mbd.pre.y_buffer = cpi->common.alt_ref_frame.y_buffer + recon_yoffset;
+            x->e_mbd.pre.u_buffer = cpi->common.alt_ref_frame.u_buffer + recon_uvoffset;
+            x->e_mbd.pre.v_buffer = cpi->common.alt_ref_frame.v_buffer + recon_uvoffset;
+        }
+
+        vp8_find_near_mvs(&x->e_mbd,
+                          x->e_mbd.mode_info_context,
+                          &mode_mv[NEARESTMV], &mode_mv[NEARMV], &best_ref_mv,
+                          mdcounts, x->e_mbd.mbmi.ref_frame, cpi->common.ref_frame_sign_bias);
+
+
+        // Estimate the reference frame signaling cost and add it to the rolling cost variable.
+        frame_cost = ref_frame_cost[x->e_mbd.mbmi.ref_frame];
+        rate2 += frame_cost;
+
+        if (this_mode <= B_PRED)
+        {
+            for (i = 0; i < 16; i++)
+            {
+                vpx_memset(&x->e_mbd.block[i].bmi, 0, sizeof(B_MODE_INFO));
+            }
+        }
+
+        // Check to see if the testing frequency for this mode is at its max
+        // If so then prevent it from being tested and increase the threshold for its testing
+        if (cpi->mode_test_hit_counts[mode_index] && (cpi->mode_check_freq[mode_index] > 1))
+        {
+            if (cpi->mbs_tested_so_far  <= cpi->mode_check_freq[mode_index] * cpi->mode_test_hit_counts[mode_index])
+            {
+                // Increase the threshold for coding this mode to make it less likely to be chosen
+                cpi->rd_thresh_mult[mode_index] += 4;
+
+                if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
+                    cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
+
+                cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+
+                continue;
+            }
+        }
+
+        // We have now reached the point where we are going to test the current mode so increment the counter for the number of times it has been tested
+        cpi->mode_test_hit_counts[mode_index] ++;
+
+        // Experimental code. Special case for gf and arf zeromv modes. Increase zbin size to supress noise
+        if (cpi->zbin_mode_boost_enabled)
+        {
+            if ((vp8_mode_order[mode_index] == ZEROMV) && (vp8_ref_frame_order[mode_index] != LAST_FRAME))
+                cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
+            else
+                cpi->zbin_mode_boost = 0;
+
+            vp8cx_mb_init_quantizer(cpi, x);
+        }
+
+        switch (this_mode)
+        {
+        case B_PRED:
+
+            // Note the rate value returned here includes the cost of coding the BPRED mode : x->mbmode_cost[x->e_mbd.frame_type][BPRED];
+            vp8_rd_pick_intra4x4mby_modes(cpi, x, &rate, &rate_y, &distortion);
+            rate2 += rate;
+            //rate_y = rate;
+            distortion2 += distortion;
+            rate2 += uv_intra_rate;
+            rate_uv = uv_intra_rate_tokenonly;
+            distortion2 += uv_intra_distortion;
+            break;
+
+        case SPLITMV:
+        {
+            int frame_cost_rd = RDFUNC(x->rdmult, x->rddiv, frame_cost, 0, cpi->target_bits_per_mb);
+            int saved_rate = rate2;
+
+            // vp8_rd_pick_best_mbsegmentation looks only at Y and does not account for frame_cost.
+            // (best_rd - frame_cost_rd) is thus a conservative breakout number.
+            int breakout_rd = best_rd - frame_cost_rd;
+            int tmp_rd;
+
+            if (x->e_mbd.mbmi.ref_frame == LAST_FRAME)
+                tmp_rd = vp8_rd_pick_best_mbsegmentation(cpi, x, &best_ref_mv, breakout_rd, mdcounts, &rate, &rate_y, &distortion, cpi->compressor_speed, x->mvcost, cpi->rd_threshes[THR_NEWMV], cpi->common.full_pixel) ;
+            else if (x->e_mbd.mbmi.ref_frame == GOLDEN_FRAME)
+                tmp_rd = vp8_rd_pick_best_mbsegmentation(cpi, x, &best_ref_mv, breakout_rd, mdcounts, &rate, &rate_y, &distortion, cpi->compressor_speed, x->mvcost, cpi->rd_threshes[THR_NEWG], cpi->common.full_pixel) ;
+            else
+                tmp_rd = vp8_rd_pick_best_mbsegmentation(cpi, x, &best_ref_mv, breakout_rd, mdcounts, &rate, &rate_y, &distortion, cpi->compressor_speed, x->mvcost, cpi->rd_threshes[THR_NEWA], cpi->common.full_pixel) ;
+
+            rate2 += rate;
+            distortion2 += distortion;
+
+            // If even the 'Y' rd value of split is higher than best so far then dont bother looking at UV
+            if (tmp_rd < breakout_rd)
+            {
+                // Now work out UV cost and add it in
+                vp8_rd_inter_uv(cpi, x, &rate, &distortion, cpi->common.full_pixel);
+                rate2 += rate;
+                rate_uv = rate;
+                distortion2 += distortion;
+
+            }
+            else
+            {
+                this_rd = INT_MAX;
+                disable_skip = 1;
+            }
+
+            // Trap cases where the best split mode has all vectors coded 0,0 (or all the same)
+            if (0)
+            {
+                int allsame = 1;
+
+                for (i = 1; i < 16; i++)
+                {
+                    BLOCKD *bd = &x->e_mbd.block[i];
+
+                    if (bd->bmi.mv.as_int != x->e_mbd.block[0].bmi.mv.as_int)   //(bmvs[i].col != bmvs[i-1].col) || (bmvs[i].row != bmvs[i-1].row ) )
+                    {
+                        allsame = 0;
+                        break;
+                    }
+                }
+
+                if (allsame)
+                {
+                    // reset mode and mv and jump to newmv
+                    this_mode = NEWMV;
+                    distortion2 = 0;
+                    rate2 = saved_rate;
+                    mode_mv[NEWMV].row = x->e_mbd.block[0].bmi.mv.as_mv.row;
+                    mode_mv[NEWMV].col = x->e_mbd.block[0].bmi.mv.as_mv.col;
+                    rate2 += vp8_mv_bit_cost(&mode_mv[NEWMV], &best_ref_mv, x->mvcost, 96);
+                    goto mv_selected;
+                }
+            }
+
+            // trap cases where the 8x8s can be promoted to 8x16s or 16x8s
+            if (0)//x->e_mbd.mbmi.partition_count == 4)
+            {
+
+                if (x->e_mbd.mbmi.partition_bmi[0].mv.as_int == x->e_mbd.mbmi.partition_bmi[1].mv.as_int
+                    && x->e_mbd.mbmi.partition_bmi[2].mv.as_int == x->e_mbd.mbmi.partition_bmi[3].mv.as_int)
+                {
+                    const int *labels = vp8_mbsplits[2];
+                    x->e_mbd.mbmi.partitioning = 0;
+                    rate -= vp8_cost_token(vp8_mbsplit_tree, vp8_mbsplit_probs, vp8_mbsplit_encodings + 2);
+                    rate += vp8_cost_token(vp8_mbsplit_tree, vp8_mbsplit_probs, vp8_mbsplit_encodings);
+                    //rate -=  x->inter_bmode_costs[  x->e_mbd.mbmi.partition_bmi[1]];
+                    //rate -=  x->inter_bmode_costs[  x->e_mbd.mbmi.partition_bmi[3]];
+                    x->e_mbd.mbmi.partition_bmi[1] = x->e_mbd.mbmi.partition_bmi[2];
+                }
+            }
+
+        }
+        break;
+        case DC_PRED:
+        case V_PRED:
+        case H_PRED:
+        case TM_PRED:
+            x->e_mbd.mbmi.ref_frame = INTRA_FRAME;
+            vp8_build_intra_predictors_mby_ptr(&x->e_mbd);
+            {
+                macro_block_yrd(x, &rate, &distortion, IF_RTCD(&cpi->rtcd.encodemb)) ;
+                rate2 += rate;
+                rate_y = rate;
+                distortion2 += distortion;
+                rate2 += x->mbmode_cost[x->e_mbd.frame_type][x->e_mbd.mbmi.mode];
+                rate2 += uv_intra_rate;
+                rate_uv = uv_intra_rate_tokenonly;
+                distortion2 += uv_intra_distortion;
+            }
+            break;
+
+        case NEWMV:
+
+            // Decrement full search counter
+            if (cpi->check_freq[lf_or_gf] > 0)
+                cpi->check_freq[lf_or_gf] --;
+
+            {
+                int thissme;
+                int bestsme = INT_MAX;
+                int step_param = cpi->sf.first_step;
+                int search_range;
+                int further_steps;
+                int n;
+
+                // Work out how long a search we should do
+                search_range = MAXF(abs(best_ref_mv.col), abs(best_ref_mv.row)) >> 3;
+
+                if (search_range >= x->vector_range)
+                    x->vector_range = search_range;
+                else if (x->vector_range > cpi->sf.min_fs_radius)
+                    x->vector_range--;
+
+                // Initial step/diamond search
+                {
+                    int sadpb = x->sadperbit16;
+
+                    if (cpi->sf.search_method == HEX)
+                    {
+                        bestsme = vp8_hex_search(x, b, d, &best_ref_mv, &d->bmi.mv.as_mv, step_param, sadpb/*x->errorperbit*/, &num00, cpi->fn_ptr.vf, cpi->fn_ptr.sdf, x->mvsadcost, x->mvcost);
+                        mode_mv[NEWMV].row = d->bmi.mv.as_mv.row;
+                        mode_mv[NEWMV].col = d->bmi.mv.as_mv.col;
+                    }
+                    else
+                    {
+                        bestsme = cpi->diamond_search_sad(x, b, d, &best_ref_mv, &d->bmi.mv.as_mv, step_param, sadpb / 2/*x->errorperbit*/, &num00, &cpi->fn_ptr, x->mvsadcost, x->mvcost); //sadpb < 9
+                        mode_mv[NEWMV].row = d->bmi.mv.as_mv.row;
+                        mode_mv[NEWMV].col = d->bmi.mv.as_mv.col;
+
+                        // Further step/diamond searches as necessary
+                        n = 0;
+                        further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
+
+                        n = num00;
+                        num00 = 0;
+
+                        while (n < further_steps)
+                        {
+                            n++;
+
+                            if (num00)
+                                num00--;
+                            else
+                            {
+                                thissme = cpi->diamond_search_sad(x, b, d, &best_ref_mv, &d->bmi.mv.as_mv, step_param + n, sadpb / 4/*x->errorperbit*/, &num00, &cpi->fn_ptr, x->mvsadcost, x->mvcost); //sadpb = 9
+
+                                if (thissme < bestsme)
+                                {
+                                    bestsme = thissme;
+                                    mode_mv[NEWMV].row = d->bmi.mv.as_mv.row;
+                                    mode_mv[NEWMV].col = d->bmi.mv.as_mv.col;
+                                }
+                                else
+                                {
+                                    d->bmi.mv.as_mv.row = mode_mv[NEWMV].row;
+                                    d->bmi.mv.as_mv.col = mode_mv[NEWMV].col;
+                                }
+                            }
+                        }
+                    }
+
+                }
+
+                // Should we do a full search
+                if (!cpi->check_freq[lf_or_gf] || cpi->do_full[lf_or_gf])
+                {
+                    int thissme;
+                    int full_flag_thresh = 0;
+
+                    // Update x->vector_range based on best vector found in step search
+                    search_range = MAXF(abs(d->bmi.mv.as_mv.row), abs(d->bmi.mv.as_mv.col));
+
+                    if (search_range > x->vector_range)
+                        x->vector_range = search_range;
+                    else
+                        search_range = x->vector_range;
+
+                    // Apply limits
+                    search_range = (search_range > cpi->sf.max_fs_radius) ? cpi->sf.max_fs_radius : search_range;
+                    {
+                        int sadpb = x->sadperbit16 >> 2;
+                        thissme = cpi->full_search_sad(x, b, d, &best_ref_mv, sadpb, search_range, &cpi->fn_ptr, x->mvcost, x->mvsadcost);
+                    }
+
+                    // Barrier threshold to initiating full search
+                    // full_flag_thresh = 10 + (thissme >> 7);
+                    if ((thissme + full_flag_thresh) < bestsme)
+                    {
+                        cpi->do_full[lf_or_gf] ++;
+                        bestsme = thissme;
+                    }
+                    else if (thissme < bestsme)
+                        bestsme = thissme;
+                    else
+                    {
+                        cpi->do_full[lf_or_gf] = cpi->do_full[lf_or_gf] >> 1;
+                        cpi->check_freq[lf_or_gf] = cpi->sf.full_freq[lf_or_gf];
+
+                        // The full search result is actually worse so re-instate the previous best vector
+                        d->bmi.mv.as_mv.row = mode_mv[NEWMV].row;
+                        d->bmi.mv.as_mv.col = mode_mv[NEWMV].col;
+                    }
+                }
+
+                if (bestsme < INT_MAX)
+                    // cpi->find_fractional_mv_step(x,b,d,&d->bmi.mv.as_mv,&best_ref_mv,x->errorperbit/2,cpi->fn_ptr.svf,cpi->fn_ptr.vf,x->mvcost);  // normal mvc=11
+                    cpi->find_fractional_mv_step(x, b, d, &d->bmi.mv.as_mv, &best_ref_mv, x->errorperbit / 4, cpi->fn_ptr.svf, cpi->fn_ptr.vf, x->mvcost);
+
+                mode_mv[NEWMV].row = d->bmi.mv.as_mv.row;
+                mode_mv[NEWMV].col = d->bmi.mv.as_mv.col;
+
+                // Add the new motion vector cost to our rolling cost variable
+                rate2 += vp8_mv_bit_cost(&mode_mv[NEWMV], &best_ref_mv, x->mvcost, 96);
+
+            }
+
+        case NEARESTMV:
+        case NEARMV:
+
+            // Clip "next_nearest" so that it does not extend to far out of image
+            if (mode_mv[this_mode].col < (xd->mb_to_left_edge - LEFT_TOP_MARGIN))
+                mode_mv[this_mode].col = xd->mb_to_left_edge - LEFT_TOP_MARGIN;
+            else if (mode_mv[this_mode].col > xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN)
+                mode_mv[this_mode].col = xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN;
+
+            if (mode_mv[this_mode].row < (xd->mb_to_top_edge - LEFT_TOP_MARGIN))
+                mode_mv[this_mode].row = xd->mb_to_top_edge - LEFT_TOP_MARGIN;
+            else if (mode_mv[this_mode].row > xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN)
+                mode_mv[this_mode].row = xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN;
+
+            // Do not bother proceeding if the vector (from newmv,nearest or near) is 0,0 as this should then be coded using the zeromv mode.
+            if (((this_mode == NEARMV) || (this_mode == NEARESTMV)) &&
+                ((mode_mv[this_mode].row == 0) && (mode_mv[this_mode].col == 0)))
+                continue;
+
+        case ZEROMV:
+
+        mv_selected:
+
+            // Trap vectors that reach beyond the UMV borders
+            // Note that ALL New MV, Nearest MV Near MV and Zero MV code drops through to this point
+            // because of the lack of break statements in the previous two cases.
+            if (((mode_mv[this_mode].row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].row >> 3) > x->mv_row_max) ||
+                ((mode_mv[this_mode].col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].col >> 3) > x->mv_col_max))
+                continue;
+
+            vp8_set_mbmode_and_mvs(x, this_mode, &mode_mv[this_mode]);
+            vp8_build_inter_predictors_mby(&x->e_mbd);
+            VARIANCE_INVOKE(&cpi->rtcd.variance, get16x16var)(x->src.y_buffer, x->src.y_stride, x->e_mbd.predictor, 16, (unsigned int *)(&sse), &sum);
+
+            if (cpi->active_map_enabled && x->active_ptr[0] == 0)
+            {
+                x->skip = 1;
+            }
+            else if (sse < x->encode_breakout)
+            {
+                // Check u and v to make sure skip is ok
+                int sse2 = 0;
+
+                sse2 = VP8_UVSSE(x, IF_RTCD(&cpi->rtcd.variance));
+
+                if (sse2 * 2 < x->encode_breakout)
+                {
+                    x->skip = 1;
+                    distortion2 = sse;
+                    rate2 = 500;
+
+                    disable_skip = 1;    // We have no real rate data so trying to adjust for rate_y and rate_uv below will cause problems.
+                    this_rd = RDFUNC(x->rdmult, x->rddiv, rate2, distortion2, cpi->target_bits_per_mb);
+
+                    break;              // (PGW) Move break here from below - for now at least
+                }
+                else
+                    x->skip = 0;
+            }
+
+            //intermodecost[mode_index] = vp8_cost_mv_ref(this_mode, mdcounts);   // Experimental debug code
+
+            // Add in the Mv/mode cost
+            rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
+
+            // Y cost and distortion
+            macro_block_yrd(x, &rate, &distortion, IF_RTCD(&cpi->rtcd.encodemb));
+            rate2 += rate;
+            rate_y = rate;
+            distortion2 += distortion;
+
+            // UV cost and distortion
+            vp8_rd_inter_uv(cpi, x, &rate, &distortion, cpi->common.full_pixel);
+            rate2 += rate;
+            rate_uv = rate;
+            distortion2 += distortion;
+            break;
+
+        default:
+            break;
+        }
+
+        if (!disable_skip)
+        {
+            // Test for the condition where skip block will be activated because there are no non zero coefficients and make any necessary adjustment for rate
+            if (cpi->common.mb_no_coeff_skip)
+            {
+                tteob = 0;
+
+                for (i = 0; i <= 24; i++)
+                {
+                    tteob += x->e_mbd.block[i].eob;
+                }
+
+                if (tteob == 0)
+                {
+#if 1
+                    rate2 -= (rate_y + rate_uv);
+
+                    // Back out no skip flag costing and add in skip flag costing
+                    if (cpi->prob_skip_false)
+                    {
+                        rate2 += vp8_cost_bit(cpi->prob_skip_false, 1);
+                        rate2 -= vp8_cost_bit(cpi->prob_skip_false, 0);
+                    }
+
+#else
+                    int rateuseskip;
+                    int ratenotuseskip;
+
+
+
+                    ratenotuseskip = rate_y + rate_uv + vp8_cost_bit(cpi->prob_skip_false, 0);
+                    rateuseskip    = vp8_cost_bit(cpi->prob_skip_false, 1);
+
+                    if (1) // rateuseskip<ratenotuseskip)
+                    {
+                        rate2 -= ratenotuseskip;
+                        rate2 += rateuseskip;
+                        force_no_skip = 0;
+                    }
+                    else
+                    {
+                        force_no_skip = 1;
+                    }
+
+#endif
+                }
+
+#if             0
+                else
+                {
+                    int rateuseskip;
+                    int ratenotuseskip;
+                    int maxdistortion;
+                    int minrate;
+                    int skip_rd;
+
+                    // distortion when no coeff is encoded
+                    maxdistortion = macro_block_max_error(x);
+
+                    ratenotuseskip = rate_y + rate_uv + vp8_cost_bit(cpi->prob_skip_false, 0);
+                    rateuseskip    = vp8_cost_bit(cpi->prob_skip_false, 1);
+
+                    minrate         = rateuseskip - ratenotuseskip;
+
+                    skip_rd = RDFUNC(x->rdmult, x->rddiv, minrate, maxdistortion - distortion2, cpi->target_bits_per_mb);
+
+                    if (skip_rd + 50 < 0 && x->e_mbd.mbmi.ref_frame != INTRA_FRAME && rate_y + rate_uv < 4000)
+                    {
+                        force_no_skip = 1;
+                        rate2       = rate2 + rateuseskip - ratenotuseskip;
+                        distortion2 =  maxdistortion;
+                    }
+                    else
+                    {
+                        force_no_skip = 0;
+                    }
+
+                }
+
+#endif
+
+            }
+
+            // Calculate the final RD estimate for this mode
+            this_rd = RDFUNC(x->rdmult, x->rddiv, rate2, distortion2, cpi->target_bits_per_mb);
+        }
+
+        // Experimental debug code.
+        //all_rds[mode_index] = this_rd;
+        //all_rates[mode_index] = rate2;
+        //all_dist[mode_index] = distortion2;
+
+        if ((x->e_mbd.mbmi.ref_frame == INTRA_FRAME)  && (this_rd < *returnintra))
+        {
+            *returnintra = this_rd ;
+        }
+
+        // Did this mode help.. i.i is it the new best mode
+        if (this_rd < best_rd || x->skip)
+        {
+            // Note index of best mode so far
+            best_mode_index = mode_index;
+            x->e_mbd.mbmi.force_no_skip = force_no_skip;
+
+            if (this_mode <= B_PRED)
+            {
+                x->e_mbd.mbmi.uv_mode = uv_intra_mode;
+            }
+
+            *returnrate = rate2;
+            *returndistortion = distortion2;
+            best_rd = this_rd;
+            vpx_memcpy(&best_mbmode, &x->e_mbd.mbmi, sizeof(MB_MODE_INFO));
+
+            for (i = 0; i < 16; i++)
+            {
+                vpx_memcpy(&best_bmodes[i], &x->e_mbd.block[i].bmi, sizeof(B_MODE_INFO));
+            }
+
+            // Testing this mode gave rise to an improvement in best error score. Lower threshold a bit for next time
+            cpi->rd_thresh_mult[mode_index] = (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ? cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT;
+            cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+        }
+
+        // If the mode did not help improve the best error case then raise the threshold for testing that mode next time around.
+        else
+        {
+            cpi->rd_thresh_mult[mode_index] += 4;
+
+            if (cpi->rd_thresh_mult[mode_index] > MAX_THRESHMULT)
+                cpi->rd_thresh_mult[mode_index] = MAX_THRESHMULT;
+
+            cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index];
+        }
+
+        if (x->skip)
+            break;
+    }
+
+    // Reduce the activation RD thresholds for the best choice mode
+    if ((cpi->rd_baseline_thresh[best_mode_index] > 0) && (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2)))
+    {
+        int best_adjustment = (cpi->rd_thresh_mult[best_mode_index] >> 2);
+
+        cpi->rd_thresh_mult[best_mode_index] = (cpi->rd_thresh_mult[best_mode_index] >= (MIN_THRESHMULT + best_adjustment)) ? cpi->rd_thresh_mult[best_mode_index] - best_adjustment : MIN_THRESHMULT;
+        cpi->rd_threshes[best_mode_index] = (cpi->rd_baseline_thresh[best_mode_index] >> 7) * cpi->rd_thresh_mult[best_mode_index];
+
+        // If we chose a split mode then reset the new MV thresholds as well
+        /*if ( vp8_mode_order[best_mode_index] == SPLITMV )
+        {
+            best_adjustment = 4; //(cpi->rd_thresh_mult[THR_NEWMV] >> 4);
+            cpi->rd_thresh_mult[THR_NEWMV] = (cpi->rd_thresh_mult[THR_NEWMV] >= (MIN_THRESHMULT+best_adjustment)) ? cpi->rd_thresh_mult[THR_NEWMV]-best_adjustment: MIN_THRESHMULT;
+            cpi->rd_threshes[THR_NEWMV] = (cpi->rd_baseline_thresh[THR_NEWMV] >> 7) * cpi->rd_thresh_mult[THR_NEWMV];
+
+            best_adjustment = 4; //(cpi->rd_thresh_mult[THR_NEWG] >> 4);
+            cpi->rd_thresh_mult[THR_NEWG] = (cpi->rd_thresh_mult[THR_NEWG] >= (MIN_THRESHMULT+best_adjustment)) ? cpi->rd_thresh_mult[THR_NEWG]-best_adjustment: MIN_THRESHMULT;
+            cpi->rd_threshes[THR_NEWG] = (cpi->rd_baseline_thresh[THR_NEWG] >> 7) * cpi->rd_thresh_mult[THR_NEWG];
+
+            best_adjustment = 4; //(cpi->rd_thresh_mult[THR_NEWA] >> 4);
+            cpi->rd_thresh_mult[THR_NEWA] = (cpi->rd_thresh_mult[THR_NEWA] >= (MIN_THRESHMULT+best_adjustment)) ? cpi->rd_thresh_mult[THR_NEWA]-best_adjustment: MIN_THRESHMULT;
+            cpi->rd_threshes[THR_NEWA] = (cpi->rd_baseline_thresh[THR_NEWA] >> 7) * cpi->rd_thresh_mult[THR_NEWA];
+        }*/
+
+    }
+
+    // If we have chosen new mv or split then decay the full search check count more quickly.
+    if ((vp8_mode_order[best_mode_index] == NEWMV) || (vp8_mode_order[best_mode_index] == SPLITMV))
+    {
+        int lf_or_gf = (vp8_ref_frame_order[best_mode_index] == LAST_FRAME) ? 0 : 1;
+
+        if (cpi->check_freq[lf_or_gf] && !cpi->do_full[lf_or_gf])
+        {
+            cpi->check_freq[lf_or_gf] --;
+        }
+    }
+
+    // Keep a record of best mode index that we chose
+    cpi->last_best_mode_index = best_mode_index;
+
+    // Note how often each mode chosen as best
+    cpi->mode_chosen_counts[best_mode_index] ++;
+
+
+    if (cpi->is_src_frame_alt_ref && (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME))
+    {
+        best_mbmode.mode = ZEROMV;
+        best_mbmode.ref_frame = ALTREF_FRAME;
+        best_mbmode.mv.as_int = 0;
+        best_mbmode.uv_mode = 0;
+        best_mbmode.mb_skip_coeff = (cpi->common.mb_no_coeff_skip) ? 1 : 0;
+        best_mbmode.partitioning = 0;
+        best_mbmode.dc_diff = 0;
+
+        vpx_memcpy(&x->e_mbd.mbmi, &best_mbmode, sizeof(MB_MODE_INFO));
+
+        for (i = 0; i < 16; i++)
+        {
+            vpx_memset(&x->e_mbd.block[i].bmi, 0, sizeof(B_MODE_INFO));
+        }
+
+        x->e_mbd.mbmi.mv.as_int = 0;
+
+        return best_rd;
+    }
+
+
+    // macroblock modes
+    vpx_memcpy(&x->e_mbd.mbmi, &best_mbmode, sizeof(MB_MODE_INFO));
+
+    for (i = 0; i < 16; i++)
+    {
+        vpx_memcpy(&x->e_mbd.block[i].bmi, &best_bmodes[i], sizeof(B_MODE_INFO));
+    }
+
+    x->e_mbd.mbmi.mv.as_mv = x->e_mbd.block[15].bmi.mv.as_mv;
+
+    return best_rd;
+}
+#endif
+
diff --git a/vp8/encoder/rdopt.h b/vp8/encoder/rdopt.h
new file mode 100644
index 0000000..c6eae4b
--- /dev/null
+++ b/vp8/encoder/rdopt.h
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_RDOPT_H
+#define __INC_RDOPT_H
+void vp8_initialize_rd_consts(VP8_COMP *cpi, int Qvalue);
+int vp8_rd_pick_intra4x4mby_modes(VP8_COMP *cpi, MACROBLOCK *mb, int *rate, int *rate_to, int *distortion);
+int vp8_rd_pick_intra16x16mby_mode(VP8_COMP *cpi, MACROBLOCK *x, int *returnrate, int *rate_to, int *returndistortion);
+int vp8_rd_pick_intra_mbuv_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate, int *rate_to, int *distortion);
+extern int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int *returnintra);
+
+
+#endif
diff --git a/vp8/encoder/sad_c.c b/vp8/encoder/sad_c.c
new file mode 100644
index 0000000..74c6bd7
--- /dev/null
+++ b/vp8/encoder/sad_c.c
@@ -0,0 +1,248 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <stdlib.h>
+
+unsigned int vp8_sad16x16_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr,
+    int  ref_stride,
+    int max_sad)
+{
+
+    int r, c;
+    unsigned int sad = 0;
+
+    for (r = 0; r < 16; r++)
+    {
+        for (c = 0; c < 16; c++)
+        {
+            sad += abs(src_ptr[c] - ref_ptr[c]);
+        }
+
+        src_ptr += src_stride;
+        ref_ptr += ref_stride;
+    }
+
+    return sad;
+}
+
+
+static __inline
+unsigned int sad_mx_n_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr,
+    int  ref_stride,
+    int m,
+    int n)
+{
+
+    int r, c;
+    unsigned int sad = 0;
+
+    for (r = 0; r < n; r++)
+    {
+        for (c = 0; c < m; c++)
+        {
+            sad += abs(src_ptr[c] - ref_ptr[c]);
+        }
+
+        src_ptr += src_stride;
+        ref_ptr += ref_stride;
+    }
+
+    return sad;
+}
+
+
+unsigned int vp8_sad8x8_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr,
+    int  ref_stride,
+    int max_sad)
+{
+
+    return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, 8, 8);
+}
+
+
+unsigned int vp8_sad16x8_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr,
+    int  ref_stride,
+    int max_sad)
+{
+
+    return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, 16, 8);
+
+}
+
+
+unsigned int vp8_sad8x16_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr,
+    int  ref_stride,
+    int max_sad)
+{
+
+    return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, 8, 16);
+}
+
+
+unsigned int vp8_sad4x4_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr,
+    int  ref_stride,
+    int max_sad)
+{
+
+    return sad_mx_n_c(src_ptr, src_stride, ref_ptr, ref_stride, 4, 4);
+}
+
+void vp8_sad16x16x3_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad16x8x3_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad8x8x3_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad8x16x3_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad4x4x3_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr,
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr  , ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr + 1, ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr + 2, ref_stride, 0x7fffffff);
+}
+
+void vp8_sad16x16x4d_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr[],
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr[0], ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr[1], ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr[2], ref_stride, 0x7fffffff);
+    sad_array[3] = vp8_sad16x16_c(src_ptr, src_stride, ref_ptr[3], ref_stride, 0x7fffffff);
+}
+
+void vp8_sad16x8x4d_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr[],
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr[0], ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr[1], ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr[2], ref_stride, 0x7fffffff);
+    sad_array[3] = vp8_sad16x8_c(src_ptr, src_stride, ref_ptr[3], ref_stride, 0x7fffffff);
+}
+
+void vp8_sad8x8x4d_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr[],
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr[0], ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr[1], ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr[2], ref_stride, 0x7fffffff);
+    sad_array[3] = vp8_sad8x8_c(src_ptr, src_stride, ref_ptr[3], ref_stride, 0x7fffffff);
+}
+
+void vp8_sad8x16x4d_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr[],
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr[0], ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr[1], ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr[2], ref_stride, 0x7fffffff);
+    sad_array[3] = vp8_sad8x16_c(src_ptr, src_stride, ref_ptr[3], ref_stride, 0x7fffffff);
+}
+
+void vp8_sad4x4x4d_c(
+    unsigned char *src_ptr,
+    int  src_stride,
+    unsigned char *ref_ptr[],
+    int  ref_stride,
+    unsigned int *sad_array
+)
+{
+    sad_array[0] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr[0], ref_stride, 0x7fffffff);
+    sad_array[1] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr[1], ref_stride, 0x7fffffff);
+    sad_array[2] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr[2], ref_stride, 0x7fffffff);
+    sad_array[3] = vp8_sad4x4_c(src_ptr, src_stride, ref_ptr[3], ref_stride, 0x7fffffff);
+}
diff --git a/vp8/encoder/ssim.c b/vp8/encoder/ssim.c
new file mode 100644
index 0000000..df214a8
--- /dev/null
+++ b/vp8/encoder/ssim.c
@@ -0,0 +1,521 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_scale/yv12config.h"
+#include "math.h"
+
+#define C1 (float)(64 * 64 * 0.01*255*0.01*255)
+#define C2 (float)(64 * 64 * 0.03*255*0.03*255)
+
+static int width_y;
+static int height_y;
+static int height_uv;
+static int width_uv;
+static int stride_uv;
+static int stride;
+static int lumimask;
+static int luminance;
+static double plane_summed_weights = 0;
+
+static short img12_sum_block[8*4096*4096*2] ;
+
+static short img1_sum[8*4096*2];
+static short img2_sum[8*4096*2];
+static int   img1_sq_sum[8*4096*2];
+static int   img2_sq_sum[8*4096*2];
+static int   img12_mul_sum[8*4096*2];
+
+
+double vp8_similarity
+(
+    int mu_x,
+    int mu_y,
+    int pre_mu_x2,
+    int pre_mu_y2,
+    int pre_mu_xy2
+)
+{
+    int mu_x2, mu_y2, mu_xy, theta_x2, theta_y2, theta_xy;
+
+    mu_x2 = mu_x * mu_x;
+    mu_y2 = mu_y * mu_y;
+    mu_xy = mu_x * mu_y;
+
+    theta_x2 = 64 * pre_mu_x2 - mu_x2;
+    theta_y2 = 64 * pre_mu_y2 - mu_y2;
+    theta_xy = 64 * pre_mu_xy2 - mu_xy;
+
+    return (2 * mu_xy + C1) * (2 * theta_xy + C2) / ((mu_x2 + mu_y2 + C1) * (theta_x2 + theta_y2 + C2));
+}
+
+double vp8_ssim
+(
+    const unsigned char *img1,
+    const unsigned char *img2,
+    int stride_img1,
+    int stride_img2,
+    int width,
+    int height
+)
+{
+    int x, y, x2, y2, img1_block, img2_block, img1_sq_block, img2_sq_block, img12_mul_block, temp;
+
+    double plane_quality, weight, mean;
+
+    short *img1_sum_ptr1, *img1_sum_ptr2;
+    short *img2_sum_ptr1, *img2_sum_ptr2;
+    int *img1_sq_sum_ptr1, *img1_sq_sum_ptr2;
+    int *img2_sq_sum_ptr1, *img2_sq_sum_ptr2;
+    int *img12_mul_sum_ptr1, *img12_mul_sum_ptr2;
+
+    plane_quality = 0;
+
+    if (lumimask)
+        plane_summed_weights = 0.0f;
+    else
+        plane_summed_weights = (height - 7) * (width - 7);
+
+    //some prologue for the main loop
+    temp = 8 * width;
+
+    img1_sum_ptr1      = img1_sum + temp;
+    img2_sum_ptr1      = img2_sum + temp;
+    img1_sq_sum_ptr1   = img1_sq_sum + temp;
+    img2_sq_sum_ptr1   = img2_sq_sum + temp;
+    img12_mul_sum_ptr1 = img12_mul_sum + temp;
+
+    for (x = 0; x < width; x++)
+    {
+        img1_sum[x]      = img1[x];
+        img2_sum[x]      = img2[x];
+        img1_sq_sum[x]   = img1[x] * img1[x];
+        img2_sq_sum[x]   = img2[x] * img2[x];
+        img12_mul_sum[x] = img1[x] * img2[x];
+
+        img1_sum_ptr1[x]      = 0;
+        img2_sum_ptr1[x]      = 0;
+        img1_sq_sum_ptr1[x]   = 0;
+        img2_sq_sum_ptr1[x]   = 0;
+        img12_mul_sum_ptr1[x] = 0;
+    }
+
+    //the main loop
+    for (y = 1; y < height; y++)
+    {
+        img1 += stride_img1;
+        img2 += stride_img2;
+
+        temp = (y - 1) % 9 * width;
+
+        img1_sum_ptr1      = img1_sum + temp;
+        img2_sum_ptr1      = img2_sum + temp;
+        img1_sq_sum_ptr1   = img1_sq_sum + temp;
+        img2_sq_sum_ptr1   = img2_sq_sum + temp;
+        img12_mul_sum_ptr1 = img12_mul_sum + temp;
+
+        temp = y % 9 * width;
+
+        img1_sum_ptr2      = img1_sum + temp;
+        img2_sum_ptr2      = img2_sum + temp;
+        img1_sq_sum_ptr2   = img1_sq_sum + temp;
+        img2_sq_sum_ptr2   = img2_sq_sum + temp;
+        img12_mul_sum_ptr2 = img12_mul_sum + temp;
+
+        for (x = 0; x < width; x++)
+        {
+            img1_sum_ptr2[x]      = img1_sum_ptr1[x] + img1[x];
+            img2_sum_ptr2[x]      = img2_sum_ptr1[x] + img2[x];
+            img1_sq_sum_ptr2[x]   = img1_sq_sum_ptr1[x] + img1[x] * img1[x];
+            img2_sq_sum_ptr2[x]   = img2_sq_sum_ptr1[x] + img2[x] * img2[x];
+            img12_mul_sum_ptr2[x] = img12_mul_sum_ptr1[x] + img1[x] * img2[x];
+        }
+
+        if (y > 6)
+        {
+            //calculate the sum of the last 8 lines by subtracting the total sum of 8 lines back from the present sum
+            temp = (y + 1) % 9 * width;
+
+            img1_sum_ptr1      = img1_sum + temp;
+            img2_sum_ptr1      = img2_sum + temp;
+            img1_sq_sum_ptr1   = img1_sq_sum + temp;
+            img2_sq_sum_ptr1   = img2_sq_sum + temp;
+            img12_mul_sum_ptr1 = img12_mul_sum + temp;
+
+            for (x = 0; x < width; x++)
+            {
+                img1_sum_ptr1[x]      = img1_sum_ptr2[x] - img1_sum_ptr1[x];
+                img2_sum_ptr1[x]      = img2_sum_ptr2[x] - img2_sum_ptr1[x];
+                img1_sq_sum_ptr1[x]   = img1_sq_sum_ptr2[x] - img1_sq_sum_ptr1[x];
+                img2_sq_sum_ptr1[x]   = img2_sq_sum_ptr2[x] - img2_sq_sum_ptr1[x];
+                img12_mul_sum_ptr1[x] = img12_mul_sum_ptr2[x] - img12_mul_sum_ptr1[x];
+            }
+
+            //here we calculate the sum over the 8x8 block of pixels
+            //this is done by sliding a window across the column sums for the last 8 lines
+            //each time adding the new column sum, and subtracting the one which fell out of the window
+            img1_block      = 0;
+            img2_block      = 0;
+            img1_sq_block   = 0;
+            img2_sq_block   = 0;
+            img12_mul_block = 0;
+
+            //prologue, and calculation of simularity measure from the first 8 column sums
+            for (x = 0; x < 8; x++)
+            {
+                img1_block      += img1_sum_ptr1[x];
+                img2_block      += img2_sum_ptr1[x];
+                img1_sq_block   += img1_sq_sum_ptr1[x];
+                img2_sq_block   += img2_sq_sum_ptr1[x];
+                img12_mul_block += img12_mul_sum_ptr1[x];
+            }
+
+            if (lumimask)
+            {
+                y2 = y - 7;
+                x2 = 0;
+
+                if (luminance)
+                {
+                    mean = (img2_block + img1_block) / 128.0f;
+
+                    if (!(y2 % 2 || x2 % 2))
+                        *(img12_sum_block + y2 / 2 * width_uv + x2 / 2) = img2_block + img1_block;
+                }
+                else
+                {
+                    mean = *(img12_sum_block + y2 * width_uv + x2);
+                    mean += *(img12_sum_block + y2 * width_uv + x2 + 4);
+                    mean += *(img12_sum_block + (y2 + 4) * width_uv + x2);
+                    mean += *(img12_sum_block + (y2 + 4) * width_uv + x2 + 4);
+
+                    mean /= 512.0f;
+                }
+
+                weight = mean < 40 ? 0.0f :
+                         (mean < 50 ? (mean - 40.0f) / 10.0f : 1.0f);
+                plane_summed_weights += weight;
+
+                plane_quality += weight * vp8_similarity(img1_block, img2_block, img1_sq_block, img2_sq_block, img12_mul_block);
+            }
+            else
+                plane_quality += vp8_similarity(img1_block, img2_block, img1_sq_block, img2_sq_block, img12_mul_block);
+
+            //and for the rest
+            for (x = 8; x < width; x++)
+            {
+                img1_block      = img1_block + img1_sum_ptr1[x] - img1_sum_ptr1[x - 8];
+                img2_block      = img2_block + img2_sum_ptr1[x] - img2_sum_ptr1[x - 8];
+                img1_sq_block   = img1_sq_block + img1_sq_sum_ptr1[x] - img1_sq_sum_ptr1[x - 8];
+                img2_sq_block   = img2_sq_block + img2_sq_sum_ptr1[x] - img2_sq_sum_ptr1[x - 8];
+                img12_mul_block = img12_mul_block + img12_mul_sum_ptr1[x] - img12_mul_sum_ptr1[x - 8];
+
+                if (lumimask)
+                {
+                    y2 = y - 7;
+                    x2 = x - 7;
+
+                    if (luminance)
+                    {
+                        mean = (img2_block + img1_block) / 128.0f;
+
+                        if (!(y2 % 2 || x2 % 2))
+                            *(img12_sum_block + y2 / 2 * width_uv + x2 / 2) = img2_block + img1_block;
+                    }
+                    else
+                    {
+                        mean = *(img12_sum_block + y2 * width_uv + x2);
+                        mean += *(img12_sum_block + y2 * width_uv + x2 + 4);
+                        mean += *(img12_sum_block + (y2 + 4) * width_uv + x2);
+                        mean += *(img12_sum_block + (y2 + 4) * width_uv + x2 + 4);
+
+                        mean /= 512.0f;
+                    }
+
+                    weight = mean < 40 ? 0.0f :
+                             (mean < 50 ? (mean - 40.0f) / 10.0f : 1.0f);
+                    plane_summed_weights += weight;
+
+                    plane_quality += weight * vp8_similarity(img1_block, img2_block, img1_sq_block, img2_sq_block, img12_mul_block);
+                }
+                else
+                    plane_quality += vp8_similarity(img1_block, img2_block, img1_sq_block, img2_sq_block, img12_mul_block);
+            }
+        }
+    }
+
+    if (plane_summed_weights == 0)
+        return 1.0f;
+    else
+        return plane_quality / plane_summed_weights;
+}
+
+double vp8_calc_ssim
+(
+    YV12_BUFFER_CONFIG *source,
+    YV12_BUFFER_CONFIG *dest,
+    int lumamask,
+    double *weight
+)
+{
+    double a, b, c;
+    double frame_weight;
+    double ssimv;
+
+    width_y = source->y_width;
+    height_y = source->y_height;
+    height_uv = source->uv_height;
+    width_uv = source->uv_width;
+    stride_uv = dest->uv_stride;
+    stride = dest->y_stride;
+
+    lumimask = lumamask;
+
+    luminance = 1;
+    a = vp8_ssim(source->y_buffer, dest->y_buffer,
+                 source->y_stride, dest->y_stride, source->y_width, source->y_height);
+    luminance = 0;
+
+    frame_weight = plane_summed_weights / ((width_y - 7) * (height_y - 7));
+
+    if (frame_weight == 0)
+        a = b = c = 1.0f;
+    else
+    {
+        b = vp8_ssim(source->u_buffer, dest->u_buffer,
+                     source->uv_stride, dest->uv_stride, source->uv_width, source->uv_height);
+
+        c = vp8_ssim(source->v_buffer, dest->v_buffer,
+                     source->uv_stride, dest->uv_stride, source->uv_width, source->uv_height);
+    }
+
+    ssimv = a * .8 + .1 * (b + c);
+
+    *weight = frame_weight;
+
+    return ssimv;
+}
+
+// Google version of SSIM
+// SSIM
+#define KERNEL 3
+#define KERNEL_SIZE  (2 * KERNEL + 1)
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+static const int K[KERNEL_SIZE] =
+{
+    1, 4, 11, 16, 11, 4, 1    // 16 * exp(-0.3 * i * i)
+};
+static const double ki_w = 1. / 2304.;  // 1 / sum(i:0..6, j..6) K[i]*K[j]
+double get_ssimg(const uint8 *org, const uint8 *rec,
+                 int xo, int yo, int W, int H,
+                 const int stride1, const int stride2
+                )
+{
+    // TODO(skal): use summed tables
+    int y, x;
+
+    const int ymin = (yo - KERNEL < 0) ? 0 : yo - KERNEL;
+    const int ymax = (yo + KERNEL > H - 1) ? H - 1 : yo + KERNEL;
+    const int xmin = (xo - KERNEL < 0) ? 0 : xo - KERNEL;
+    const int xmax = (xo + KERNEL > W - 1) ? W - 1 : xo + KERNEL;
+    // worst case of accumulation is a weight of 48 = 16 + 2 * (11 + 4 + 1)
+    // with a diff of 255, squares. That would a max error of 0x8ee0900,
+    // which fits into 32 bits integers.
+    uint32 w = 0, xm = 0, ym = 0, xxm = 0, xym = 0, yym = 0;
+    org += ymin * stride1;
+    rec += ymin * stride2;
+
+    for (y = ymin; y <= ymax; ++y, org += stride1, rec += stride2)
+    {
+        const int Wy = K[KERNEL + y - yo];
+
+        for (x = xmin; x <= xmax; ++x)
+        {
+            const  int Wxy = Wy * K[KERNEL + x - xo];
+            // TODO(skal): inlined assembly
+            w   += Wxy;
+            xm  += Wxy * org[x];
+            ym  += Wxy * rec[x];
+            xxm += Wxy * org[x] * org[x];
+            xym += Wxy * org[x] * rec[x];
+            yym += Wxy * rec[x] * rec[x];
+        }
+    }
+
+    {
+        const double iw = 1. / w;
+        const double iwx = xm * iw;
+        const double iwy = ym * iw;
+        double sxx = xxm * iw - iwx * iwx;
+        double syy = yym * iw - iwy * iwy;
+
+        // small errors are possible, due to rounding. Clamp to zero.
+        if (sxx < 0.) sxx = 0.;
+
+        if (syy < 0.) syy = 0.;
+
+        {
+            const double sxsy = sqrt(sxx * syy);
+            const double sxy = xym * iw - iwx * iwy;
+            static const double C11 = (0.01 * 0.01) * (255 * 255);
+            static const double C22 = (0.03 * 0.03) * (255 * 255);
+            static const double C33 = (0.015 * 0.015) * (255 * 255);
+            const double l = (2. * iwx * iwy + C11) / (iwx * iwx + iwy * iwy + C11);
+            const double c = (2. * sxsy      + C22) / (sxx + syy + C22);
+
+            const double s = (sxy + C33) / (sxsy + C33);
+            return l * c * s;
+
+        }
+    }
+
+}
+
+double get_ssimfull_kernelg(const uint8 *org, const uint8 *rec,
+                            int xo, int yo, int W, int H,
+                            const int stride1, const int stride2)
+{
+    // TODO(skal): use summed tables
+    // worst case of accumulation is a weight of 48 = 16 + 2 * (11 + 4 + 1)
+    // with a diff of 255, squares. That would a max error of 0x8ee0900,
+    // which fits into 32 bits integers.
+    int y_, x_;
+    uint32 xm = 0, ym = 0, xxm = 0, xym = 0, yym = 0;
+    org += (yo - KERNEL) * stride1;
+    org += (xo - KERNEL);
+    rec += (yo - KERNEL) * stride2;
+    rec += (xo - KERNEL);
+
+    for (y_ = 0; y_ < KERNEL_SIZE; ++y_, org += stride1, rec += stride2)
+    {
+        const int Wy = K[y_];
+
+        for (x_ = 0; x_ < KERNEL_SIZE; ++x_)
+        {
+            const int Wxy = Wy * K[x_];
+            // TODO(skal): inlined assembly
+            const int org_x = org[x_];
+            const int rec_x = rec[x_];
+            xm  += Wxy * org_x;
+            ym  += Wxy * rec_x;
+            xxm += Wxy * org_x * org_x;
+            xym += Wxy * org_x * rec_x;
+            yym += Wxy * rec_x * rec_x;
+        }
+    }
+
+    {
+        const double iw = ki_w;
+        const double iwx = xm * iw;
+        const double iwy = ym * iw;
+        double sxx = xxm * iw - iwx * iwx;
+        double syy = yym * iw - iwy * iwy;
+
+        // small errors are possible, due to rounding. Clamp to zero.
+        if (sxx < 0.) sxx = 0.;
+
+        if (syy < 0.) syy = 0.;
+
+        {
+            const double sxsy = sqrt(sxx * syy);
+            const double sxy = xym * iw - iwx * iwy;
+            static const double C11 = (0.01 * 0.01) * (255 * 255);
+            static const double C22 = (0.03 * 0.03) * (255 * 255);
+            static const double C33 = (0.015 * 0.015) * (255 * 255);
+            const double l = (2. * iwx * iwy + C11) / (iwx * iwx + iwy * iwy + C11);
+            const double c = (2. * sxsy      + C22) / (sxx + syy + C22);
+            const double s = (sxy + C33) / (sxsy + C33);
+            return l * c * s;
+        }
+    }
+}
+
+double calc_ssimg(const uint8 *org, const uint8 *rec,
+                  const int image_width, const int image_height,
+                  const int stride1, const int stride2
+                 )
+{
+    int j, i;
+    double SSIM = 0.;
+
+    for (j = 0; j < KERNEL; ++j)
+    {
+        for (i = 0; i < image_width; ++i)
+        {
+            SSIM += get_ssimg(org, rec, i, j, image_width, image_height, stride1, stride2);
+        }
+    }
+
+    for (j = KERNEL; j < image_height - KERNEL; ++j)
+    {
+        for (i = 0; i < KERNEL; ++i)
+        {
+            SSIM += get_ssimg(org, rec, i, j, image_width, image_height, stride1, stride2);
+        }
+
+        for (i = KERNEL; i < image_width - KERNEL; ++i)
+        {
+            SSIM += get_ssimfull_kernelg(org, rec, i, j,
+                                         image_width, image_height, stride1, stride2);
+        }
+
+        for (i = image_width - KERNEL; i < image_width; ++i)
+        {
+            SSIM += get_ssimg(org, rec, i, j, image_width, image_height, stride1, stride2);
+        }
+    }
+
+    for (j = image_height - KERNEL; j < image_height; ++j)
+    {
+        for (i = 0; i < image_width; ++i)
+        {
+            SSIM += get_ssimg(org, rec, i, j, image_width, image_height, stride1, stride2);
+        }
+    }
+
+    return SSIM;
+}
+
+
+double vp8_calc_ssimg
+(
+    YV12_BUFFER_CONFIG *source,
+    YV12_BUFFER_CONFIG *dest,
+    double *ssim_y,
+    double *ssim_u,
+    double *ssim_v
+)
+{
+    double ssim_all = 0;
+    int ysize  = source->y_width * source->y_height;
+    int uvsize = ysize / 4;
+
+    *ssim_y = calc_ssimg(source->y_buffer, dest->y_buffer,
+                         source->y_width, source->y_height,
+                         source->y_stride, dest->y_stride);
+
+
+    *ssim_u = calc_ssimg(source->u_buffer, dest->u_buffer,
+                         source->uv_width, source->uv_height,
+                         source->uv_stride, dest->uv_stride);
+
+
+    *ssim_v = calc_ssimg(source->v_buffer, dest->v_buffer,
+                         source->uv_width, source->uv_height,
+                         source->uv_stride, dest->uv_stride);
+
+    ssim_all = (*ssim_y + *ssim_u + *ssim_v) / (ysize + uvsize + uvsize);
+    *ssim_y /= ysize;
+    *ssim_u /= uvsize;
+    *ssim_v /= uvsize;
+    return ssim_all;
+}
diff --git a/vp8/encoder/tokenize.c b/vp8/encoder/tokenize.c
new file mode 100644
index 0000000..33ddd64
--- /dev/null
+++ b/vp8/encoder/tokenize.c
@@ -0,0 +1,636 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "onyx_int.h"
+#include "tokenize.h"
+#include "vpx_mem/vpx_mem.h"
+
+/* Global event counters used for accumulating statistics across several
+   compressions, then generating context.c = initial stats. */
+
+#ifdef ENTROPY_STATS
+_int64 context_counters[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens];
+#endif
+void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) ;
+void vp8_fix_contexts(VP8_COMP *cpi, MACROBLOCKD *x);
+
+TOKENEXTRA vp8_dct_value_tokens[DCT_MAX_VALUE*2];
+TOKENEXTRA *vp8_dct_value_tokens_ptr;
+int vp8_dct_value_cost[DCT_MAX_VALUE*2];
+int *vp8_dct_value_cost_ptr;
+#if 0
+int skip_true_count = 0;
+int skip_false_count = 0;
+#endif
+static void fill_value_tokens()
+{
+
+    TOKENEXTRA *const t = vp8_dct_value_tokens + DCT_MAX_VALUE;
+    vp8_extra_bit_struct *const e = vp8_extra_bits;
+
+    int i = -DCT_MAX_VALUE;
+    int sign = 1;
+
+    do
+    {
+        if (!i)
+            sign = 0;
+
+        {
+            const int a = sign ? -i : i;
+            int eb = sign;
+
+            if (a > 4)
+            {
+                int j = 4;
+
+                while (++j < 11  &&  e[j].base_val <= a) {}
+
+                t[i].Token = --j;
+                eb |= (a - e[j].base_val) << 1;
+            }
+            else
+                t[i].Token = a;
+
+            t[i].Extra = eb;
+        }
+
+        // initialize the cost for extra bits for all possible coefficient value.
+        {
+            int cost = 0;
+            vp8_extra_bit_struct *p = vp8_extra_bits + t[i].Token;
+
+            if (p->base_val)
+            {
+                const int extra = t[i].Extra;
+                const int Length = p->Len;
+
+                if (Length)
+                    cost += vp8_treed_cost(p->tree, p->prob, extra >> 1, Length);
+
+                cost += vp8_cost_bit(vp8_prob_half, extra & 1); /* sign */
+                vp8_dct_value_cost[i + DCT_MAX_VALUE] = cost;
+            }
+
+        }
+
+    }
+    while (++i < DCT_MAX_VALUE);
+
+    vp8_dct_value_tokens_ptr = vp8_dct_value_tokens + DCT_MAX_VALUE;
+    vp8_dct_value_cost_ptr   = vp8_dct_value_cost + DCT_MAX_VALUE;
+}
+
+static void tokenize2nd_order_b
+(
+    const BLOCKD *const b,
+    TOKENEXTRA **tp,
+    const int type,     /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
+    const FRAME_TYPE frametype,
+    ENTROPY_CONTEXT *a,
+    ENTROPY_CONTEXT *l,
+    VP8_COMP *cpi
+)
+{
+    int pt; /* near block/prev token context index */
+    int c = 0;          /* start at DC */
+    const int eob = b->eob;     /* one beyond last nonzero coeff */
+    TOKENEXTRA *t = *tp;        /* store tokens starting here */
+    int x;
+    const short *qcoeff_ptr = b->qcoeff;
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+    do
+    {
+        const int band = vp8_coef_bands[c];
+
+        if (c < eob)
+        {
+            int rc = vp8_default_zig_zag1d[c];
+            const int v = qcoeff_ptr[rc];
+
+            assert(-DCT_MAX_VALUE <= v  &&  v < (DCT_MAX_VALUE));
+
+            t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
+            x        = vp8_dct_value_tokens_ptr[v].Token;
+        }
+        else
+            x = DCT_EOB_TOKEN;
+
+        t->Token = x;
+        t->context_tree = cpi->common.fc.coef_probs [type] [band] [pt];
+
+        t->section = frametype * BLOCK_TYPES * 2 + 2 * type + (c == 0);
+
+        t->skip_eob_node = pt == 0 && ((band > 0 && type > 0) || (band > 1 && type == 0));
+
+        ++cpi->coef_counts       [type] [band] [pt] [x];
+    }
+    while (pt = vp8_prev_token_class[x], ++t, c < eob  &&  ++c < 16);
+
+    *tp = t;
+    pt = (c != !type); /* 0 <-> all coeff data is zero */
+    *a = *l = pt;
+
+}
+
+static void tokenize1st_order_b
+(
+    const BLOCKD *const b,
+    TOKENEXTRA **tp,
+    const int type,     /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
+    const FRAME_TYPE frametype,
+    ENTROPY_CONTEXT *a,
+    ENTROPY_CONTEXT *l,
+    VP8_COMP *cpi
+)
+{
+    int pt; /* near block/prev token context index */
+    int c = type ? 0 : 1;       /* start at DC unless type 0 */
+    const int eob = b->eob;     /* one beyond last nonzero coeff */
+    TOKENEXTRA *t = *tp;        /* store tokens starting here */
+    int x;
+    const short *qcoeff_ptr = b->qcoeff;
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+
+    do
+    {
+        const int band = vp8_coef_bands[c];
+
+        x = DCT_EOB_TOKEN;
+
+        if (c < eob)
+        {
+            int rc = vp8_default_zig_zag1d[c];
+            const int v = qcoeff_ptr[rc];
+
+            assert(-DCT_MAX_VALUE <= v  &&  v < (DCT_MAX_VALUE));
+
+            t->Extra = vp8_dct_value_tokens_ptr[v].Extra;
+            x        = vp8_dct_value_tokens_ptr[v].Token;
+        }
+
+        t->Token = x;
+        t->context_tree = cpi->common.fc.coef_probs [type] [band] [pt];
+
+        t->section = frametype * BLOCK_TYPES * 2 + 2 * type + (c == 0);
+        t->skip_eob_node = pt == 0 && ((band > 0 && type > 0) || (band > 1 && type == 0));
+
+        ++cpi->coef_counts       [type] [band] [pt] [x];
+    }
+    while (pt = vp8_prev_token_class[x], ++t, c < eob  &&  ++c < 16);
+
+    *tp = t;
+    pt = (c != !type); /* 0 <-> all coeff data is zero */
+    *a = *l = pt;
+
+}
+#if 0
+void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t)
+{
+    //int i;
+    ENTROPY_CONTEXT **const A = x->above_context;
+    ENTROPY_CONTEXT(* const L)[4] = x->left_context;
+    int plane_type;
+    int b;
+
+    TOKENEXTRA *start = *t;
+    TOKENEXTRA *tp = *t;
+
+    x->mbmi.dc_diff = 1;
+
+    vpx_memcpy(cpi->coef_counts_backup, cpi->coef_counts, sizeof(cpi->coef_counts));
+
+    if (x->mbmi.mode == B_PRED || x->mbmi.mode == SPLITMV)
+    {
+        plane_type = 3;
+    }
+    else
+    {
+        tokenize2nd_order_b(x->block + 24, t, 1, x->frame_type,
+                            A[Y2CONTEXT] + vp8_block2above[24], L[Y2CONTEXT] + vp8_block2left[24], cpi);
+        plane_type = 0;
+
+    }
+
+    for (b = 0; b < 16; b++)
+        tokenize1st_order_b(x->block + b, t, plane_type, x->frame_type,
+                            A[vp8_block2context[b]] + vp8_block2above[b],
+                            L[vp8_block2context[b]] + vp8_block2left[b], cpi);
+
+    for (b = 16; b < 24; b++)
+        tokenize1st_order_b(x->block + b, t, 2, x->frame_type,
+                            A[vp8_block2context[b]] + vp8_block2above[b],
+                            L[vp8_block2context[b]] + vp8_block2left[b], cpi);
+
+    if (cpi->common.mb_no_coeff_skip)
+    {
+        x->mbmi.mb_skip_coeff = 1;
+
+        while ((tp != *t) && x->mbmi.mb_skip_coeff)
+        {
+            x->mbmi.mb_skip_coeff = (x->mbmi.mb_skip_coeff && (tp->Token == DCT_EOB_TOKEN));
+            tp ++;
+        }
+
+        if (x->mbmi.mb_skip_coeff == 1)
+        {
+            x->mbmi.dc_diff = 0;
+            //redo the coutnts
+            vpx_memcpy(cpi->coef_counts, cpi->coef_counts_backup, sizeof(cpi->coef_counts));
+
+            *t = start;
+            cpi->skip_true_count++;
+
+            //skip_true_count++;
+        }
+        else
+        {
+
+            cpi->skip_false_count++;
+            //skip_false_count++;
+        }
+    }
+}
+#else
+void vp8_tokenize_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t)
+{
+    //int i;
+    ENTROPY_CONTEXT **const A = x->above_context;
+    ENTROPY_CONTEXT(* const L)[4] = x->left_context;
+    int plane_type;
+    int b;
+
+    TOKENEXTRA *start = *t;
+    TOKENEXTRA *tp = *t;
+
+    x->mbmi.dc_diff = 1;
+
+#if 0
+
+    if (x->mbmi.force_no_skip)
+    {
+        x->mbmi.mb_skip_coeff = 1;
+        //reset for next_mb.
+        x->mbmi.force_no_skip = 0;
+    }
+
+#endif
+
+#if 1
+
+    if (x->mbmi.mb_skip_coeff)
+    {
+
+        cpi->skip_true_count++;
+
+        if (!cpi->common.mb_no_coeff_skip)
+            vp8_stuff_mb(cpi, x, t) ;
+        else
+        {
+            vp8_fix_contexts(cpi, x);
+        }
+
+        if (x->mbmi.mode != B_PRED && x->mbmi.mode != SPLITMV)
+            x->mbmi.dc_diff = 0;
+        else
+            x->mbmi.dc_diff = 1;
+
+
+        return;
+    }
+
+    cpi->skip_false_count++;
+#endif
+#if 0
+
+    if (x->mbmi.mode == B_PRED || x->mbmi.mode == SPLITMV)
+    {
+        int i, skip = 1;
+
+        for (i = 0; i < 24; i++)
+            skip &= (!x->block[i].eob);
+
+        if (skip != x->mbmi.mb_skip_coeff)
+            skip += 0;
+
+        x->mbmi.mb_skip_coeff = skip;
+    }
+    else
+    {
+        int i, skip = 1;
+
+        for (i = 0; i < 16; i++)
+            skip &= (x->block[i].eob < 2);
+
+        for (i = 16; i < 25; i++)
+            skip &= (!x->block[i].eob);
+
+        if (skip != x->mbmi.mb_skip_coeff)
+            skip += 0;
+
+        x->mbmi.mb_skip_coeff = skip;
+    }
+
+    vpx_memcpy(cpi->coef_counts_backup, cpi->coef_counts, sizeof(cpi->coef_counts));
+#endif
+
+    if (x->mbmi.mode == B_PRED || x->mbmi.mode == SPLITMV)
+    {
+        plane_type = 3;
+    }
+    else
+    {
+        tokenize2nd_order_b(x->block + 24, t, 1, x->frame_type,
+                            A[Y2CONTEXT] + vp8_block2above[24], L[Y2CONTEXT] + vp8_block2left[24], cpi);
+        plane_type = 0;
+
+    }
+
+    for (b = 0; b < 16; b++)
+        tokenize1st_order_b(x->block + b, t, plane_type, x->frame_type,
+                            A[vp8_block2context[b]] + vp8_block2above[b],
+                            L[vp8_block2context[b]] + vp8_block2left[b], cpi);
+
+    for (b = 16; b < 24; b++)
+        tokenize1st_order_b(x->block + b, t, 2, x->frame_type,
+                            A[vp8_block2context[b]] + vp8_block2above[b],
+                            L[vp8_block2context[b]] + vp8_block2left[b], cpi);
+
+#if 0
+
+    if (cpi->common.mb_no_coeff_skip)
+    {
+        int skip = 1;
+
+        while ((tp != *t) && skip)
+        {
+            skip = (skip && (tp->Token == DCT_EOB_TOKEN));
+            tp ++;
+        }
+
+        if (skip != x->mbmi.mb_skip_coeff)
+            skip += 0;
+
+        x->mbmi.mb_skip_coeff = skip;
+
+        if (x->mbmi.mb_skip_coeff == 1)
+        {
+            x->mbmi.dc_diff = 0;
+            //redo the coutnts
+            vpx_memcpy(cpi->coef_counts, cpi->coef_counts_backup, sizeof(cpi->coef_counts));
+
+            *t = start;
+            cpi->skip_true_count++;
+            //skip_true_count++;
+        }
+        else
+        {
+
+            cpi->skip_false_count++;
+            //skip_false_count++;
+        }
+    }
+
+#endif
+}
+#endif
+
+#ifdef ENTROPY_STATS
+
+void init_context_counters(void)
+{
+    vpx_memset(context_counters, 0, sizeof(context_counters));
+}
+
+void print_context_counters()
+{
+
+    int type, band, pt, t;
+
+    FILE *const f = fopen("context.c", "w");
+
+    fprintf(f, "#include \"entropy.h\"\n");
+
+    fprintf(f, "\n/* *** GENERATED FILE: DO NOT EDIT *** */\n\n");
+
+    fprintf(f, "int Contexts[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens];\n\n");
+
+    fprintf(f, "const int default_contexts[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens] = {");
+
+# define Comma( X) (X? ",":"")
+
+    type = 0;
+
+    do
+    {
+        fprintf(f, "%s\n  { /* block Type %d */", Comma(type), type);
+
+        band = 0;
+
+        do
+        {
+            fprintf(f, "%s\n    { /* Coeff Band %d */", Comma(band), band);
+
+            pt = 0;
+
+            do
+            {
+                fprintf(f, "%s\n      {", Comma(pt));
+
+                t = 0;
+
+                do
+                {
+                    const _int64 x = context_counters [type] [band] [pt] [t];
+                    const int y = (int) x;
+
+                    assert(x == (_int64) y);  /* no overflow handling yet */
+                    fprintf(f, "%s %d", Comma(t), y);
+
+                }
+                while (++t < vp8_coef_tokens);
+
+                fprintf(f, "}");
+            }
+            while (++pt < PREV_COEF_CONTEXTS);
+
+            fprintf(f, "\n    }");
+
+        }
+        while (++band < COEF_BANDS);
+
+        fprintf(f, "\n  }");
+    }
+    while (++type < BLOCK_TYPES);
+
+    fprintf(f, "\n};\n");
+    fclose(f);
+}
+#endif
+
+
+void vp8_tokenize_initialize()
+{
+    fill_value_tokens();
+}
+
+
+static __inline void stuff2nd_order_b
+(
+    const BLOCKD *const b,
+    TOKENEXTRA **tp,
+    const int type,     /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
+    const FRAME_TYPE frametype,
+    ENTROPY_CONTEXT *a,
+    ENTROPY_CONTEXT *l,
+    VP8_COMP *cpi
+)
+{
+    int pt; /* near block/prev token context index */
+    TOKENEXTRA *t = *tp;        /* store tokens starting here */
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+    (void) frametype;
+    (void) type;
+    (void) b;
+
+    t->Token = DCT_EOB_TOKEN;
+    t->context_tree = cpi->common.fc.coef_probs [1] [0] [pt];
+    t->section = 11;
+    t->skip_eob_node = 0;
+    ++cpi->coef_counts       [1] [0] [pt] [DCT_EOB_TOKEN];
+    ++t;
+
+    *tp = t;
+    pt = 0;
+    *a = *l = pt;
+
+}
+
+static __inline void stuff1st_order_b
+(
+    const BLOCKD *const b,
+    TOKENEXTRA **tp,
+    const int type,     /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
+    const FRAME_TYPE frametype,
+    ENTROPY_CONTEXT *a,
+    ENTROPY_CONTEXT *l,
+    VP8_COMP *cpi
+)
+{
+    int pt; /* near block/prev token context index */
+    TOKENEXTRA *t = *tp;        /* store tokens starting here */
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+    (void) frametype;
+    (void) type;
+    (void) b;
+
+    t->Token = DCT_EOB_TOKEN;
+    t->context_tree = cpi->common.fc.coef_probs [0] [1] [pt];
+    t->section = 8;
+    t->skip_eob_node = 0;
+    ++cpi->coef_counts       [0] [1] [pt] [DCT_EOB_TOKEN];
+    ++t;
+    *tp = t;
+    pt = 0; /* 0 <-> all coeff data is zero */
+    *a = *l = pt;
+
+}
+static __inline
+void stuff1st_order_buv
+(
+    const BLOCKD *const b,
+    TOKENEXTRA **tp,
+    const int type,     /* which plane: 0=Y no DC, 1=Y2, 2=UV, 3=Y with DC */
+    const FRAME_TYPE frametype,
+    ENTROPY_CONTEXT *a,
+    ENTROPY_CONTEXT *l,
+    VP8_COMP *cpi
+)
+{
+    int pt; /* near block/prev token context index */
+    TOKENEXTRA *t = *tp;        /* store tokens starting here */
+    VP8_COMBINEENTROPYCONTEXTS(pt, *a, *l);
+    (void) frametype;
+    (void) type;
+    (void) b;
+
+    t->Token = DCT_EOB_TOKEN;
+    t->context_tree = cpi->common.fc.coef_probs [2] [0] [pt];
+    t->section = 13;
+    t->skip_eob_node = 0;
+    ++cpi->coef_counts[2] [0] [pt] [DCT_EOB_TOKEN];
+    ++t;
+    *tp = t;
+    pt = 0; /* 0 <-> all coeff data is zero */
+    *a = *l = pt;
+
+}
+
+void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t)
+{
+    //int i;
+    ENTROPY_CONTEXT **const A = x->above_context;
+    ENTROPY_CONTEXT(* const L)[4] = x->left_context;
+    int plane_type;
+    int b;
+
+    stuff2nd_order_b(x->block + 24, t, 1, x->frame_type,
+                     A[Y2CONTEXT] + vp8_block2above[24], L[Y2CONTEXT] + vp8_block2left[24], cpi);
+    plane_type = 0;
+
+
+    if (x->mbmi.mode != B_PRED && x->mbmi.mode != SPLITMV)
+        x->mbmi.dc_diff = 0;
+    else
+        x->mbmi.dc_diff = 1;
+
+
+    for (b = 0; b < 16; b++)
+        stuff1st_order_b(x->block + b, t, plane_type, x->frame_type,
+                         A[vp8_block2context[b]] + vp8_block2above[b],
+                         L[vp8_block2context[b]] + vp8_block2left[b], cpi);
+
+    for (b = 16; b < 24; b++)
+        stuff1st_order_buv(x->block + b, t, 2, x->frame_type,
+                           A[vp8_block2context[b]] + vp8_block2above[b],
+                           L[vp8_block2context[b]] + vp8_block2left[b], cpi);
+
+}
+void vp8_fix_contexts(VP8_COMP *cpi, MACROBLOCKD *x)
+{
+    x->left_context[Y1CONTEXT][0] = 0;
+    x->left_context[Y1CONTEXT][1] = 0;
+    x->left_context[Y1CONTEXT][2] = 0;
+    x->left_context[Y1CONTEXT][3] = 0;
+    x->left_context[UCONTEXT][0]  = 0;
+    x->left_context[VCONTEXT][0]  = 0;
+    x->left_context[UCONTEXT][1]  = 0;
+    x->left_context[VCONTEXT][1]  = 0;
+
+    x->above_context[Y1CONTEXT][0] = 0;
+    x->above_context[Y1CONTEXT][1] = 0;
+    x->above_context[Y1CONTEXT][2] = 0;
+    x->above_context[Y1CONTEXT][3] = 0;
+    x->above_context[UCONTEXT][0]  = 0;
+    x->above_context[VCONTEXT][0]  = 0;
+    x->above_context[UCONTEXT][1]  = 0;
+    x->above_context[VCONTEXT][1]  = 0;
+
+    if (x->mbmi.mode != B_PRED && x->mbmi.mode != SPLITMV)
+    {
+        x->left_context[Y2CONTEXT][0] = 0;
+        x->above_context[Y2CONTEXT][0] = 0;
+    }
+}
diff --git a/vp8/encoder/tokenize.h b/vp8/encoder/tokenize.h
new file mode 100644
index 0000000..02aacc2
--- /dev/null
+++ b/vp8/encoder/tokenize.h
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef tokenize_h
+#define tokenize_h
+
+#include "entropy.h"
+#include "block.h"
+
+void vp8_tokenize_initialize();
+
+typedef struct
+{
+    int Token;
+    int Extra;
+    const vp8_prob *context_tree;
+    int skip_eob_node;
+    int section;
+} TOKENEXTRA;
+
+int rd_cost_mby(MACROBLOCKD *);
+
+#ifdef ENTROPY_STATS
+void init_context_counters();
+void print_context_counters();
+
+extern _int64 context_counters[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [vp8_coef_tokens];
+#endif
+
+
+#endif  /* tokenize_h */
diff --git a/vp8/encoder/treewriter.c b/vp8/encoder/treewriter.c
new file mode 100644
index 0000000..e398044
--- /dev/null
+++ b/vp8/encoder/treewriter.c
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "treewriter.h"
+
+static void cost(
+    int *const C,
+    vp8_tree T,
+    const vp8_prob *const P,
+    int i,
+    int c
+)
+{
+    const vp8_prob p = P [i>>1];
+
+    do
+    {
+        const vp8_tree_index j = T[i];
+        const int d = c + vp8_cost_bit(p, i & 1);
+
+        if (j <= 0)
+            C[-j] = d;
+        else
+            cost(C, T, P, j, d);
+    }
+    while (++i & 1);
+}
+void vp8_cost_tokens(int *c, const vp8_prob *p, vp8_tree t)
+{
+    cost(c, t, p, 0, 0);
+}
diff --git a/vp8/encoder/treewriter.h b/vp8/encoder/treewriter.h
new file mode 100644
index 0000000..05ac74c
--- /dev/null
+++ b/vp8/encoder/treewriter.h
@@ -0,0 +1,121 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef __INC_TREEWRITER_H
+#define __INC_TREEWRITER_H
+
+/* Trees map alphabets into huffman-like codes suitable for an arithmetic
+   bit coder.  Timothy S Murphy  11 October 2004 */
+
+#include "treecoder.h"
+
+#include "boolhuff.h"       /* for now */
+
+typedef BOOL_CODER vp8_writer;
+
+#define vp8_write vp8_encode_bool
+#define vp8_write_literal vp8_encode_value
+#define vp8_write_bit( W, V) vp8_write( W, V, vp8_prob_half)
+
+#define vp8bc_write vp8bc_write_bool
+#define vp8bc_write_literal vp8bc_write_bits
+#define vp8bc_write_bit( W, V) vp8bc_write_bits( W, V, 1)
+
+
+/* Approximate length of an encoded bool in 256ths of a bit at given prob */
+
+#define vp8_cost_zero( x) ( vp8_prob_cost[x])
+#define vp8_cost_one( x)  vp8_cost_zero( vp8_complement(x))
+
+#define vp8_cost_bit( x, b) vp8_cost_zero( (b)?  vp8_complement(x) : (x) )
+
+/* VP8BC version is scaled by 2^20 rather than 2^8; see bool_coder.h */
+
+
+/* Both of these return bits, not scaled bits. */
+
+static __inline unsigned int vp8_cost_branch(const unsigned int ct[2], vp8_prob p)
+{
+    /* Imitate existing calculation */
+
+    return ((ct[0] * vp8_cost_zero(p))
+            + (ct[1] * vp8_cost_one(p))) >> 8;
+}
+
+/* Small functions to write explicit values and tokens, as well as
+   estimate their lengths. */
+
+static __inline void vp8_treed_write
+(
+    vp8_writer *const w,
+    vp8_tree t,
+    const vp8_prob *const p,
+    int v,
+    int n               /* number of bits in v, assumed nonzero */
+)
+{
+    vp8_tree_index i = 0;
+
+    do
+    {
+        const int b = (v >> --n) & 1;
+        vp8_write(w, b, p[i>>1]);
+        i = t[i+b];
+    }
+    while (n);
+}
+static __inline void vp8_write_token
+(
+    vp8_writer *const w,
+    vp8_tree t,
+    const vp8_prob *const p,
+    vp8_token *const x
+)
+{
+    vp8_treed_write(w, t, p, x->value, x->Len);
+}
+
+static __inline int vp8_treed_cost(
+    vp8_tree t,
+    const vp8_prob *const p,
+    int v,
+    int n               /* number of bits in v, assumed nonzero */
+)
+{
+    int c = 0;
+    vp8_tree_index i = 0;
+
+    do
+    {
+        const int b = (v >> --n) & 1;
+        c += vp8_cost_bit(p[i>>1], b);
+        i = t[i+b];
+    }
+    while (n);
+
+    return c;
+}
+static __inline int vp8_cost_token
+(
+    vp8_tree t,
+    const vp8_prob *const p,
+    vp8_token *const x
+)
+{
+    return vp8_treed_cost(t, p, x->value, x->Len);
+}
+
+/* Fill array of costs for all possible token values. */
+
+void vp8_cost_tokens(
+    int *Costs, const vp8_prob *, vp8_tree
+);
+
+#endif
diff --git a/vp8/encoder/variance.h b/vp8/encoder/variance.h
new file mode 100644
index 0000000..b3b55c3
--- /dev/null
+++ b/vp8/encoder/variance.h
@@ -0,0 +1,327 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef VARIANCE_H
+#define VARIANCE_H
+
+#define prototype_sad(sym)\
+    unsigned int (sym)\
+    (\
+     unsigned char *src_ptr, \
+     int source_stride, \
+     unsigned char *ref_ptr, \
+     int  ref_stride, \
+     int max_sad\
+    )
+
+#define prototype_sad_multi_same_address(sym)\
+    void (sym)\
+    (\
+     unsigned char *src_ptr, \
+     int source_stride, \
+     unsigned char *ref_ptr, \
+     int  ref_stride, \
+     unsigned int *sad_array\
+    )
+
+#define prototype_sad_multi_dif_address(sym)\
+    void (sym)\
+    (\
+     unsigned char *src_ptr, \
+     int source_stride, \
+     unsigned char *ref_ptr[4], \
+     int  ref_stride, \
+     unsigned int *sad_array\
+    )
+
+#define prototype_variance(sym) \
+    unsigned int (sym) \
+    (\
+     unsigned char *src_ptr, \
+     int source_stride, \
+     unsigned char *ref_ptr, \
+     int  ref_stride, \
+     unsigned int *sse\
+    )
+
+#define prototype_variance2(sym) \
+    unsigned int (sym) \
+    (\
+     unsigned char *src_ptr, \
+     int source_stride, \
+     unsigned char *ref_ptr, \
+     int  ref_stride, \
+     unsigned int *sse,\
+     int *sum\
+    )
+
+#define prototype_subpixvariance(sym) \
+    unsigned int (sym) \
+    ( \
+      unsigned char  *src_ptr, \
+      int  source_stride, \
+      int  xoffset, \
+      int  yoffset, \
+      unsigned char *ref_ptr, \
+      int Refstride, \
+      unsigned int *sse \
+    );
+
+
+#define prototype_getmbss(sym) unsigned int (sym)(short *)
+
+#if ARCH_X86 || ARCH_X86_64
+#include "x86/variance_x86.h"
+#endif
+
+#if ARCH_ARM
+#include "arm/variance_arm.h"
+#endif
+
+#ifndef vp8_variance_sad4x4
+#define vp8_variance_sad4x4 vp8_sad4x4_c
+#endif
+extern prototype_sad(vp8_variance_sad4x4);
+
+#ifndef vp8_variance_sad8x8
+#define vp8_variance_sad8x8 vp8_sad8x8_c
+#endif
+extern prototype_sad(vp8_variance_sad8x8);
+
+#ifndef vp8_variance_sad8x16
+#define vp8_variance_sad8x16 vp8_sad8x16_c
+#endif
+extern prototype_sad(vp8_variance_sad8x16);
+
+#ifndef vp8_variance_sad16x8
+#define vp8_variance_sad16x8 vp8_sad16x8_c
+#endif
+extern prototype_sad(vp8_variance_sad16x8);
+
+#ifndef vp8_variance_sad16x16
+#define vp8_variance_sad16x16 vp8_sad16x16_c
+#endif
+extern prototype_sad(vp8_variance_sad16x16);
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+#ifndef vp8_variance_sad16x16x3
+#define vp8_variance_sad16x16x3 vp8_sad16x16x3_c
+#endif
+extern prototype_sad_multi_same_address(vp8_variance_sad16x16x3);
+
+#ifndef vp8_variance_sad16x8x3
+#define vp8_variance_sad16x8x3 vp8_sad16x8x3_c
+#endif
+extern prototype_sad_multi_same_address(vp8_variance_sad16x8x3);
+
+#ifndef vp8_variance_sad8x8x3
+#define vp8_variance_sad8x8x3 vp8_sad8x8x3_c
+#endif
+extern prototype_sad_multi_same_address(vp8_variance_sad8x8x3);
+
+#ifndef vp8_variance_sad8x16x3
+#define vp8_variance_sad8x16x3 vp8_sad8x16x3_c
+#endif
+extern prototype_sad_multi_same_address(vp8_variance_sad8x16x3);
+
+#ifndef vp8_variance_sad4x4x3
+#define vp8_variance_sad4x4x3 vp8_sad4x4x3_c
+#endif
+extern prototype_sad_multi_same_address(vp8_variance_sad4x4x3);
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+#ifndef vp8_variance_sad16x16x4d
+#define vp8_variance_sad16x16x4d vp8_sad16x16x4d_c
+#endif
+extern prototype_sad_multi_dif_address(vp8_variance_sad16x16x4d);
+
+#ifndef vp8_variance_sad16x8x4d
+#define vp8_variance_sad16x8x4d vp8_sad16x8x4d_c
+#endif
+extern prototype_sad_multi_dif_address(vp8_variance_sad16x8x4d);
+
+#ifndef vp8_variance_sad8x8x4d
+#define vp8_variance_sad8x8x4d vp8_sad8x8x4d_c
+#endif
+extern prototype_sad_multi_dif_address(vp8_variance_sad8x8x4d);
+
+#ifndef vp8_variance_sad8x16x4d
+#define vp8_variance_sad8x16x4d vp8_sad8x16x4d_c
+#endif
+extern prototype_sad_multi_dif_address(vp8_variance_sad8x16x4d);
+
+#ifndef vp8_variance_sad4x4x4d
+#define vp8_variance_sad4x4x4d vp8_sad4x4x4d_c
+#endif
+extern prototype_sad_multi_dif_address(vp8_variance_sad4x4x4d);
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+#ifndef vp8_variance_var4x4
+#define vp8_variance_var4x4 vp8_variance4x4_c
+#endif
+extern prototype_variance(vp8_variance_var4x4);
+
+#ifndef vp8_variance_var8x8
+#define vp8_variance_var8x8 vp8_variance8x8_c
+#endif
+extern prototype_variance(vp8_variance_var8x8);
+
+#ifndef vp8_variance_var8x16
+#define vp8_variance_var8x16 vp8_variance8x16_c
+#endif
+extern prototype_variance(vp8_variance_var8x16);
+
+#ifndef vp8_variance_var16x8
+#define vp8_variance_var16x8 vp8_variance16x8_c
+#endif
+extern prototype_variance(vp8_variance_var16x8);
+
+#ifndef vp8_variance_var16x16
+#define vp8_variance_var16x16 vp8_variance16x16_c
+#endif
+extern prototype_variance(vp8_variance_var16x16);
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+#ifndef vp8_variance_subpixvar4x4
+#define vp8_variance_subpixvar4x4 vp8_sub_pixel_variance4x4_c
+#endif
+extern prototype_subpixvariance(vp8_variance_subpixvar4x4);
+
+#ifndef vp8_variance_subpixvar8x8
+#define vp8_variance_subpixvar8x8 vp8_sub_pixel_variance8x8_c
+#endif
+extern prototype_subpixvariance(vp8_variance_subpixvar8x8);
+
+#ifndef vp8_variance_subpixvar8x16
+#define vp8_variance_subpixvar8x16 vp8_sub_pixel_variance8x16_c
+#endif
+extern prototype_subpixvariance(vp8_variance_subpixvar8x16);
+
+#ifndef vp8_variance_subpixvar16x8
+#define vp8_variance_subpixvar16x8 vp8_sub_pixel_variance16x8_c
+#endif
+extern prototype_subpixvariance(vp8_variance_subpixvar16x8);
+
+#ifndef vp8_variance_subpixvar16x16
+#define vp8_variance_subpixvar16x16 vp8_sub_pixel_variance16x16_c
+#endif
+extern prototype_subpixvariance(vp8_variance_subpixvar16x16);
+
+#ifndef vp8_variance_subpixmse16x16
+#define vp8_variance_subpixmse16x16 vp8_sub_pixel_mse16x16_c
+#endif
+extern prototype_subpixvariance(vp8_variance_subpixmse16x16);
+
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+#ifndef vp8_variance_getmbss
+#define vp8_variance_getmbss vp8_get_mb_ss_c
+#endif
+extern prototype_getmbss(vp8_variance_getmbss);
+
+#ifndef vp8_variance_mse16x16
+#define vp8_variance_mse16x16 vp8_mse16x16_c
+#endif
+extern prototype_variance(vp8_variance_mse16x16);
+
+#ifndef vp8_variance_get16x16prederror
+#define vp8_variance_get16x16prederror vp8_get16x16pred_error_c
+#endif
+extern prototype_sad(vp8_variance_get16x16prederror);
+
+#ifndef vp8_variance_get8x8var
+#define vp8_variance_get8x8var vp8_get8x8var_c
+#endif
+extern prototype_variance2(vp8_variance_get8x8var);
+
+#ifndef vp8_variance_get16x16var
+#define vp8_variance_get16x16var vp8_get16x16var_c
+#endif
+extern prototype_variance2(vp8_variance_get16x16var);
+
+#ifndef vp8_variance_get4x4sse_cs
+#define vp8_variance_get4x4sse_cs vp8_get4x4sse_cs_c
+#endif
+extern prototype_sad(vp8_variance_get4x4sse_cs);
+
+
+typedef prototype_sad(*vp8_sad_fn_t);
+typedef prototype_sad_multi_same_address(*vp8_sad_multi_fn_t);
+typedef prototype_sad_multi_dif_address(*vp8_sad_multi_d_fn_t);
+typedef prototype_variance(*vp8_variance_fn_t);
+typedef prototype_variance2(*vp8_variance2_fn_t);
+typedef prototype_subpixvariance(*vp8_subpixvariance_fn_t);
+typedef prototype_getmbss(*vp8_getmbss_fn_t);
+typedef struct
+{
+    vp8_sad_fn_t             sad4x4;
+    vp8_sad_fn_t             sad8x8;
+    vp8_sad_fn_t             sad8x16;
+    vp8_sad_fn_t             sad16x8;
+    vp8_sad_fn_t             sad16x16;
+
+    vp8_variance_fn_t        var4x4;
+    vp8_variance_fn_t        var8x8;
+    vp8_variance_fn_t        var8x16;
+    vp8_variance_fn_t        var16x8;
+    vp8_variance_fn_t        var16x16;
+
+    vp8_subpixvariance_fn_t  subpixvar4x4;
+    vp8_subpixvariance_fn_t  subpixvar8x8;
+    vp8_subpixvariance_fn_t  subpixvar8x16;
+    vp8_subpixvariance_fn_t  subpixvar16x8;
+    vp8_subpixvariance_fn_t  subpixvar16x16;
+    vp8_subpixvariance_fn_t  subpixmse16x16;
+
+    vp8_getmbss_fn_t         getmbss;
+    vp8_variance_fn_t        mse16x16;
+
+    vp8_sad_fn_t             get16x16prederror;
+    vp8_variance2_fn_t       get8x8var;
+    vp8_variance2_fn_t       get16x16var;
+    vp8_sad_fn_t             get4x4sse_cs;
+
+    vp8_sad_multi_fn_t       sad16x16x3;
+    vp8_sad_multi_fn_t       sad16x8x3;
+    vp8_sad_multi_fn_t       sad8x16x3;
+    vp8_sad_multi_fn_t       sad8x8x3;
+    vp8_sad_multi_fn_t       sad4x4x3;
+
+    vp8_sad_multi_d_fn_t     sad16x16x4d;
+    vp8_sad_multi_d_fn_t     sad16x8x4d;
+    vp8_sad_multi_d_fn_t     sad8x16x4d;
+    vp8_sad_multi_d_fn_t     sad8x8x4d;
+    vp8_sad_multi_d_fn_t     sad4x4x4d;
+
+} vp8_variance_rtcd_vtable_t;
+
+typedef struct
+{
+    vp8_sad_fn_t  sdf;
+    vp8_sad_multi_fn_t sdx3f;
+    vp8_sad_multi_d_fn_t sdx4df;
+    vp8_variance_fn_t vf;
+    vp8_subpixvariance_fn_t svf;
+} vp8_variance_fn_ptr_t;
+
+#if CONFIG_RUNTIME_CPU_DETECT
+#define VARIANCE_INVOKE(ctx,fn) (ctx)->fn
+#else
+#define VARIANCE_INVOKE(ctx,fn) vp8_variance_##fn
+#endif
+
+/* TODO: Determine if this USEBILINEAR flag is necessary. */
+#define USEBILINEAR
+
+#endif
diff --git a/vp8/encoder/variance_c.c b/vp8/encoder/variance_c.c
new file mode 100644
index 0000000..85269b9
--- /dev/null
+++ b/vp8/encoder/variance_c.c
@@ -0,0 +1,527 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "variance.h"
+
+const int vp8_six_tap[8][6] =
+{
+    { 0,  0,  128,    0,   0,  0 },         // note that 1/8 pel positions are just as per alpha -0.5 bicubic
+    { 0, -6,  123,   12,  -1,  0 },
+    { 2, -11, 108,   36,  -8,  1 },         // New 1/4 pel 6 tap filter
+    { 0, -9,   93,   50,  -6,  0 },
+    { 3, -16,  77,   77, -16,  3 },         // New 1/2 pel 6 tap filter
+    { 0, -6,   50,   93,  -9,  0 },
+    { 1, -8,   36,  108, -11,  2 },         // New 1/4 pel 6 tap filter
+    { 0, -1,   12,  123,  -6,  0 }
+};
+
+
+#ifdef USEBILINEAR
+const int VP8_FILTER_WEIGHT = 128;
+const int VP8_FILTER_SHIFT  =   7;
+const int vp8_bilinear_taps[8][2] =
+{
+    { 128,   0 },
+    { 112,  16 },
+    {  96,  32 },
+    {  80,  48 },
+    {  64,  64 },
+    {  48,  80 },
+    {  32,  96 },
+    {  16, 112 }
+};
+
+unsigned int vp8_get_mb_ss_c
+(
+    short *src_ptr
+)
+{
+    unsigned int i = 0, sum = 0;
+
+    do
+    {
+        sum += (src_ptr[i] * src_ptr[i]);
+        i++;
+    }
+    while (i < 256);
+
+    return sum;
+}
+
+
+void  vp8_variance(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    int  w,
+    int  h,
+    unsigned int *sse,
+    int *sum)
+{
+    int i, j;
+    int diff;
+
+    *sum = 0;
+    *sse = 0;
+
+    for (i = 0; i < h; i++)
+    {
+        for (j = 0; j < w; j++)
+        {
+            diff = src_ptr[j] - ref_ptr[j];
+            *sum += diff;
+            *sse += diff * diff;
+        }
+
+        src_ptr += source_stride;
+        ref_ptr += recon_stride;
+    }
+}
+
+unsigned int
+vp8_get8x8var_c
+(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *SSE,
+    int *Sum
+)
+{
+
+    vp8_variance(src_ptr, source_stride, ref_ptr, recon_stride, 8, 8, SSE, Sum);
+    return (*SSE - (((*Sum) * (*Sum)) >> 6));
+}
+
+unsigned int
+vp8_get16x16var_c
+(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *SSE,
+    int *Sum
+)
+{
+
+    vp8_variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 16, SSE, Sum);
+    return (*SSE - (((*Sum) * (*Sum)) >> 8));
+
+}
+
+
+
+unsigned int vp8_variance16x16_c(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+
+    vp8_variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 16, &var, &avg);
+    *sse = var;
+    return (var - ((avg * avg) >> 8));
+}
+
+unsigned int vp8_variance8x16_c(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+
+    vp8_variance(src_ptr, source_stride, ref_ptr, recon_stride, 8, 16, &var, &avg);
+    *sse = var;
+    return (var - ((avg * avg) >> 7));
+}
+
+unsigned int vp8_variance16x8_c(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+
+    vp8_variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 8, &var, &avg);
+    *sse = var;
+    return (var - ((avg * avg) >> 7));
+}
+
+
+unsigned int vp8_variance8x8_c(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+
+    vp8_variance(src_ptr, source_stride, ref_ptr, recon_stride, 8, 8, &var, &avg);
+    *sse = var;
+    return (var - ((avg * avg) >> 6));
+}
+
+unsigned int vp8_variance4x4_c(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+
+    vp8_variance(src_ptr, source_stride, ref_ptr, recon_stride, 4, 4, &var, &avg);
+    *sse = var;
+    return (var - ((avg * avg) >> 4));
+}
+
+
+unsigned int vp8_mse16x16_c(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+    vp8_variance(src_ptr, source_stride, ref_ptr, recon_stride, 16, 16, &var, &avg);
+    *sse = var;
+    return var;
+}
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : filter_block2d_bil_first_pass
+ *
+ *  INPUTS        : UINT8  *src_ptr          : Pointer to source block.
+ *                  UINT32 src_pixels_per_line : Stride of input block.
+ *                  UINT32 pixel_step        : Offset between filter input samples (see notes).
+ *                  UINT32 output_height     : Input block height.
+ *                  UINT32 output_width      : Input block width.
+ *                  INT32  *vp8_filter          : Array of 2 bi-linear filter taps.
+ *
+ *  OUTPUTS       : INT32 *output_ptr        : Pointer to filtered block.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block in
+ *                  either horizontal or vertical direction to produce the
+ *                  filtered output block. Used to implement first-pass
+ *                  of 2-D separable filter.
+ *
+ *  SPECIAL NOTES : Produces INT32 output to retain precision for next pass.
+ *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
+ *                  pixel_step defines whether the filter is applied
+ *                  horizontally (pixel_step=1) or vertically (pixel_step=stride).
+ *                  It defines the offset required to move from one input
+ *                  to the next.
+ *
+ ****************************************************************************/
+void vp8e_filter_block2d_bil_first_pass
+(
+    unsigned char *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int src_pixels_per_line,
+    int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    const int *vp8_filter
+)
+{
+    unsigned int i, j;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+            // Apply bilinear filter
+            output_ptr[j] = (((int)src_ptr[0]          * vp8_filter[0]) +
+                             ((int)src_ptr[pixel_step] * vp8_filter[1]) +
+                             (VP8_FILTER_WEIGHT / 2)) >> VP8_FILTER_SHIFT;
+            src_ptr++;
+        }
+
+        // Next row...
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_width;
+    }
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : filter_block2d_bil_second_pass
+ *
+ *  INPUTS        : INT32  *src_ptr          : Pointer to source block.
+ *                  UINT32 src_pixels_per_line : Stride of input block.
+ *                  UINT32 pixel_step        : Offset between filter input samples (see notes).
+ *                  UINT32 output_height     : Input block height.
+ *                  UINT32 output_width      : Input block width.
+ *                  INT32  *vp8_filter          : Array of 2 bi-linear filter taps.
+ *
+ *  OUTPUTS       : UINT16 *output_ptr       : Pointer to filtered block.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Applies a 1-D 2-tap bi-linear filter to the source block in
+ *                  either horizontal or vertical direction to produce the
+ *                  filtered output block. Used to implement second-pass
+ *                  of 2-D separable filter.
+ *
+ *  SPECIAL NOTES : Requires 32-bit input as produced by filter_block2d_bil_first_pass.
+ *                  Two filter taps should sum to VP8_FILTER_WEIGHT.
+ *                  pixel_step defines whether the filter is applied
+ *                  horizontally (pixel_step=1) or vertically (pixel_step=stride).
+ *                  It defines the offset required to move from one input
+ *                  to the next.
+ *
+ ****************************************************************************/
+void vp8e_filter_block2d_bil_second_pass
+(
+    unsigned short *src_ptr,
+    unsigned char  *output_ptr,
+    unsigned int  src_pixels_per_line,
+    unsigned int  pixel_step,
+    unsigned int  output_height,
+    unsigned int  output_width,
+    const int *vp8_filter
+)
+{
+    unsigned int  i, j;
+    int  Temp;
+
+    for (i = 0; i < output_height; i++)
+    {
+        for (j = 0; j < output_width; j++)
+        {
+            // Apply filter
+            Temp = ((int)src_ptr[0]         * vp8_filter[0]) +
+                   ((int)src_ptr[pixel_step] * vp8_filter[1]) +
+                   (VP8_FILTER_WEIGHT / 2);
+            output_ptr[j] = (unsigned int)(Temp >> VP8_FILTER_SHIFT);
+            src_ptr++;
+        }
+
+        // Next row...
+        src_ptr    += src_pixels_per_line - output_width;
+        output_ptr += output_width;
+    }
+}
+
+
+/****************************************************************************
+ *
+ *  ROUTINE       : filter_block2d_bil
+ *
+ *  INPUTS        : UINT8  *src_ptr          : Pointer to source block.
+ *                  UINT32 src_pixels_per_line : Stride of input block.
+ *                  INT32  *HFilter         : Array of 2 horizontal filter taps.
+ *                  INT32  *VFilter         : Array of 2 vertical filter taps.
+ *
+ *  OUTPUTS       : UINT16 *output_ptr       : Pointer to filtered block.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : 2-D filters an 8x8 input block by applying a 2-tap
+ *                  bi-linear filter horizontally followed by a 2-tap
+ *                  bi-linear filter vertically on the result.
+ *
+ *  SPECIAL NOTES : The intermediate horizontally filtered block must produce
+ *                  1 more point than the input block in each column. This
+ *                  is to ensure that the 2-tap filter has one extra data-point
+ *                  at the top of each column so filter taps do not extend
+ *                  beyond data. Thus the output of the first stage filter
+ *                  is an 8x9 (hx_v) block.
+ *
+ ****************************************************************************/
+void vp8e_filter_block2d_bil
+(
+    unsigned char  *src_ptr,
+    unsigned char *output_ptr,
+    unsigned int src_pixels_per_line,
+    int  *HFilter,
+    int  *VFilter
+)
+{
+
+    unsigned short FData[20*16];    // Temp data bufffer used in filtering
+
+    // First filter 1-D horizontally...
+    vp8e_filter_block2d_bil_first_pass(src_ptr, FData, src_pixels_per_line, 1, 9, 8, HFilter);
+
+    // then 1-D vertically...
+    vp8e_filter_block2d_bil_second_pass(FData, output_ptr, 8, 8, 8, 8, VFilter);
+}
+
+
+
+unsigned int vp8_sub_pixel_variance4x4_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    unsigned char  temp2[20*16];
+    const int *HFilter, *VFilter;
+    unsigned short FData3[5*4]; // Temp data bufffer used in filtering
+
+    HFilter = vp8_bilinear_taps[xoffset];
+    VFilter = vp8_bilinear_taps[yoffset];
+
+    // First filter 1d Horizontal
+    vp8e_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 5, 4, HFilter);
+
+    // Now filter Verticaly
+    vp8e_filter_block2d_bil_second_pass(FData3, temp2, 4,  4,  4,  4, VFilter);
+
+    return vp8_variance4x4_c(temp2, 4, dst_ptr, dst_pixels_per_line, sse);
+}
+
+
+unsigned int vp8_sub_pixel_variance8x8_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    unsigned short FData3[9*8]; // Temp data bufffer used in filtering
+    unsigned char  temp2[20*16];
+    const int *HFilter, *VFilter;
+
+    HFilter = vp8_bilinear_taps[xoffset];
+    VFilter = vp8_bilinear_taps[yoffset];
+
+    vp8e_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 9, 8, HFilter);
+    vp8e_filter_block2d_bil_second_pass(FData3, temp2, 8, 8, 8, 8, VFilter);
+
+    return vp8_variance8x8_c(temp2, 8, dst_ptr, dst_pixels_per_line, sse);
+}
+
+unsigned int vp8_sub_pixel_variance16x16_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    unsigned short FData3[17*16];   // Temp data bufffer used in filtering
+    unsigned char  temp2[20*16];
+    const int *HFilter, *VFilter;
+
+    HFilter = vp8_bilinear_taps[xoffset];
+    VFilter = vp8_bilinear_taps[yoffset];
+
+    vp8e_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 17, 16, HFilter);
+    vp8e_filter_block2d_bil_second_pass(FData3, temp2, 16, 16, 16, 16, VFilter);
+
+    return vp8_variance16x16_c(temp2, 16, dst_ptr, dst_pixels_per_line, sse);
+}
+
+unsigned int vp8_sub_pixel_mse16x16_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    vp8_sub_pixel_variance16x16_c(src_ptr, src_pixels_per_line, xoffset, yoffset, dst_ptr, dst_pixels_per_line, sse);
+    return *sse;
+}
+
+unsigned int vp8_sub_pixel_variance16x8_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    unsigned short FData3[16*9];    // Temp data bufffer used in filtering
+    unsigned char  temp2[20*16];
+    const int *HFilter, *VFilter;
+
+    HFilter = vp8_bilinear_taps[xoffset];
+    VFilter = vp8_bilinear_taps[yoffset];
+
+    vp8e_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 9, 16, HFilter);
+    vp8e_filter_block2d_bil_second_pass(FData3, temp2, 16, 16, 8, 16, VFilter);
+
+    return vp8_variance16x8_c(temp2, 16, dst_ptr, dst_pixels_per_line, sse);
+}
+
+unsigned int vp8_sub_pixel_variance8x16_c
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    unsigned short FData3[9*16];    // Temp data bufffer used in filtering
+    unsigned char  temp2[20*16];
+    const int *HFilter, *VFilter;
+
+
+    HFilter = vp8_bilinear_taps[xoffset];
+    VFilter = vp8_bilinear_taps[yoffset];
+
+
+    vp8e_filter_block2d_bil_first_pass(src_ptr, FData3, src_pixels_per_line, 1, 17, 8, HFilter);
+    vp8e_filter_block2d_bil_second_pass(FData3, temp2, 8, 8, 16, 8, VFilter);
+
+    return vp8_variance8x16_c(temp2, 8, dst_ptr, dst_pixels_per_line, sse);
+}
+#endif
diff --git a/vp8/encoder/x86/csystemdependent.c b/vp8/encoder/x86/csystemdependent.c
new file mode 100644
index 0000000..186ee68
--- /dev/null
+++ b/vp8/encoder/x86/csystemdependent.c
@@ -0,0 +1,289 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "variance.h"
+#include "onyx_int.h"
+
+SADFunction *vp8_sad16x16;
+SADFunction *vp8_sad16x8;
+SADFunction *vp8_sad8x16;
+SADFunction *vp8_sad8x8;
+SADFunction *vp8_sad4x4;
+
+variance_function *vp8_variance4x4;
+variance_function *vp8_variance8x8;
+variance_function *vp8_variance8x16;
+variance_function *vp8_variance16x8;
+variance_function *vp8_variance16x16;
+
+
+variance_function *vp8_mse16x16;
+
+sub_pixel_variance_function *vp8_sub_pixel_variance4x4;
+sub_pixel_variance_function *vp8_sub_pixel_variance8x8;
+sub_pixel_variance_function *vp8_sub_pixel_variance8x16;
+sub_pixel_variance_function *vp8_sub_pixel_variance16x8;
+sub_pixel_variance_function *vp8_sub_pixel_variance16x16;
+
+int (*vp8_block_error)(short *, short *);
+int (*vp8_mbblock_error)(MACROBLOCK *mb, int dc);
+void (*vp8_subtract_mby)(short *diff, unsigned char *src, unsigned char *pred, int stride);
+
+extern void vp8_subtract_mby_c(short *diff, unsigned char *src, unsigned char *pred, int stride);
+extern void vp8_subtract_mby_mmx(short *diff, unsigned char *src, unsigned char *pred, int stride);
+
+extern int vp8_block_error_c(short *, short *);
+extern int vp8_mbblock_error_c(MACROBLOCK *x, int dc);
+
+extern int vp8_block_error_mmx(short *, short *);
+extern int vp8_mbblock_error_mmx(MACROBLOCK *x, int dc);
+
+extern int vp8_block_error_xmm(short *, short *);
+extern int vp8_mbblock_error_xmm(MACROBLOCK *x, int dc);
+
+
+
+int (*vp8_mbuverror)(MACROBLOCK *mb);
+unsigned int (*vp8_get_mb_ss)(short *);
+void (*vp8_short_fdct4x4)(short *input, short *output, int pitch);
+void (*vp8_short_fdct8x4)(short *input, short *output, int pitch);
+void (*vp8_fast_fdct4x4)(short *input, short *output, int pitch);
+void (*vp8_fast_fdct8x4)(short *input, short *output, int pitch);
+
+void (*vp8_subtract_b)(BLOCK *be, BLOCKD *bd, int pitch);
+void (*vp8_subtract_mbuv)(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride);
+void (*vp8_fast_quantize_b)(BLOCK *b, BLOCKD *d);
+unsigned int (*vp8_get16x16pred_error)(unsigned char *src_ptr, int src_stride, unsigned char *ref_ptr, int ref_stride);
+unsigned int (*vp8_get8x8var)(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+unsigned int (*vp8_get16x16var)(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+unsigned int (*vp8_get4x4sse_cs)(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride);
+
+// c imports
+extern int vp8_mbuverror_c(MACROBLOCK *mb);
+extern unsigned int vp8_get8x8var_c(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+extern void vp8_short_fdct4x4_c(short *input, short *output, int pitch);
+extern void vp8_short_fdct8x4_c(short *input, short *output, int pitch);
+extern void vp8_fast_fdct4x4_c(short *input, short *output, int pitch);
+extern void vp8_fast_fdct8x4_c(short *input, short *output, int pitch);
+
+
+extern void vp8_subtract_b_c(BLOCK *be, BLOCKD *bd, int pitch);
+extern void vp8_subtract_mbuv_c(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride);
+extern void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d);
+
+extern SADFunction vp8_sad16x16_c;
+extern SADFunction vp8_sad16x8_c;
+extern SADFunction vp8_sad8x16_c;
+extern SADFunction vp8_sad8x8_c;
+extern SADFunction vp8_sad4x4_c;
+
+extern SADFunction vp8_sad16x16_wmt;
+extern SADFunction vp8_sad16x8_wmt;
+extern SADFunction vp8_sad8x16_wmt;
+extern SADFunction vp8_sad8x8_wmt;
+extern SADFunction vp8_sad4x4_wmt;
+
+extern SADFunction vp8_sad16x16_mmx;
+extern SADFunction vp8_sad16x8_mmx;
+extern SADFunction vp8_sad8x16_mmx;
+extern SADFunction vp8_sad8x8_mmx;
+extern SADFunction vp8_sad4x4_mmx;
+
+extern variance_function vp8_variance16x16_c;
+extern variance_function vp8_variance8x16_c;
+extern variance_function vp8_variance16x8_c;
+extern variance_function vp8_variance8x8_c;
+extern variance_function vp8_variance4x4_c;
+extern variance_function vp8_mse16x16_c;
+
+extern sub_pixel_variance_function vp8_sub_pixel_variance4x4_c;
+extern sub_pixel_variance_function vp8_sub_pixel_variance8x8_c;
+extern sub_pixel_variance_function vp8_sub_pixel_variance8x16_c;
+extern sub_pixel_variance_function vp8_sub_pixel_variance16x8_c;
+extern sub_pixel_variance_function vp8_sub_pixel_variance16x16_c;
+
+extern unsigned int vp8_get_mb_ss_c(short *);
+extern unsigned int vp8_get16x16pred_error_c(unsigned char *src_ptr, int src_stride, unsigned char *ref_ptr, int ref_stride);
+extern unsigned int vp8_get8x8var_c(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+extern unsigned int vp8_get16x16var_c(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+extern unsigned int vp8_get4x4sse_cs_c(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride);
+
+// mmx imports
+extern int vp8_mbuverror_mmx(MACROBLOCK *mb);
+extern void vp8_fast_quantize_b_mmx(BLOCK *b, BLOCKD *d);
+extern void vp8_subtract_b_mmx(BLOCK *be, BLOCKD *bd, int pitch);
+extern void vp8_subtract_mbuv_mmx(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride);
+extern void vp8_short_fdct4x4_mmx(short *input, short *output, int pitch);
+extern void vp8_short_fdct8x4_mmx(short *input, short *output, int pitch);
+extern void vp8_fast_fdct8x4_mmx(short *input, short *output, int pitch);
+extern void vp8_fast_fdct4x4_mmx(short *input, short *output, int pitch);
+extern variance_function vp8_variance4x4_mmx;
+extern variance_function vp8_variance8x8_mmx;
+extern variance_function vp8_variance8x16_mmx;
+extern variance_function vp8_variance16x8_mmx;
+extern variance_function vp8_variance16x16_mmx;
+
+extern variance_function vp8_mse16x16_mmx;
+extern sub_pixel_variance_function vp8_sub_pixel_variance4x4_mmx;
+extern sub_pixel_variance_function vp8_sub_pixel_variance8x8_mmx;
+extern sub_pixel_variance_function vp8_sub_pixel_variance8x16_mmx;
+extern sub_pixel_variance_function vp8_sub_pixel_variance16x8_mmx;
+extern sub_pixel_variance_function vp8_sub_pixel_variance16x16_mmx;
+
+extern unsigned int vp8_get16x16pred_error_mmx(unsigned char *src_ptr, int src_stride, unsigned char *ref_ptr, int ref_stride);
+extern unsigned int vp8_get_mb_ss_mmx(short *);
+extern unsigned int vp8_get8x8var_mmx(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+extern unsigned int vp8_get16x16var_mmx(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+extern unsigned int vp8_get4x4sse_cs_mmx(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride);
+
+
+// wmt imports
+extern int vp8_mbuverror_xmm(MACROBLOCK *mb);
+extern void vp8_fast_quantize_b_sse(BLOCK *b, BLOCKD *d);
+extern void vp8_fast_fdct8x4_wmt(short *input, short *output, int pitch);
+extern variance_function vp8_variance4x4_wmt;
+extern variance_function vp8_variance8x8_wmt;
+extern variance_function vp8_variance8x16_wmt;
+extern variance_function vp8_variance16x8_wmt;
+extern variance_function vp8_variance16x16_wmt;
+
+extern variance_function vp8_mse16x16_wmt;
+extern sub_pixel_variance_function vp8_sub_pixel_variance4x4_wmt;
+extern sub_pixel_variance_function vp8_sub_pixel_variance8x8_wmt;
+extern sub_pixel_variance_function vp8_sub_pixel_variance8x16_wmt;
+extern sub_pixel_variance_function vp8_sub_pixel_variance16x8_wmt;
+extern sub_pixel_variance_function vp8_sub_pixel_variance16x16_wmt;
+extern unsigned int vp8_get16x16pred_error_sse2(unsigned char *src_ptr, int src_stride, unsigned char *ref_ptr, int ref_stride);
+extern unsigned int vp8_get_mb_ss_sse2(short *src_ptr);
+extern unsigned int vp8_get8x8var_sse2(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+extern unsigned int vp8_get16x16var_sse2(unsigned char *src_ptr, int  source_stride, unsigned char *ref_ptr, int  recon_stride, unsigned int *SSE, int *Sum);
+
+extern void vpx_get_processor_flags(int *mmx_enabled, int *xmm_enabled, int *wmt_enabled);
+
+void vp8_cmachine_specific_config(void)
+{
+    int mmx_enabled;
+    int xmm_enabled;
+    int wmt_enabled;
+
+    vpx_get_processor_flags(&mmx_enabled, &xmm_enabled, &wmt_enabled);
+
+    if (wmt_enabled)         // Willamette
+    {
+        // Willamette instruction set available:
+        vp8_mbuverror                = vp8_mbuverror_xmm;
+        vp8_fast_quantize_b            = vp8_fast_quantize_b_sse;
+        vp8_short_fdct4x4             = vp8_short_fdct4x4_mmx;
+        vp8_short_fdct8x4             = vp8_short_fdct8x4_mmx;
+        vp8_fast_fdct4x4              = vp8_fast_fdct4x4_mmx;
+        vp8_fast_fdct8x4              = vp8_fast_fdct8x4_wmt;
+        vp8_subtract_b                = vp8_subtract_b_mmx;
+        vp8_subtract_mbuv             = vp8_subtract_mbuv_mmx;
+        vp8_variance4x4              = vp8_variance4x4_mmx;
+        vp8_variance8x8              = vp8_variance8x8_mmx;
+        vp8_variance8x16             = vp8_variance8x16_wmt;
+        vp8_variance16x8             = vp8_variance16x8_wmt;
+        vp8_variance16x16            = vp8_variance16x16_wmt;
+        vp8_mse16x16                 = vp8_mse16x16_wmt;
+        vp8_sub_pixel_variance4x4      = vp8_sub_pixel_variance4x4_wmt;
+        vp8_sub_pixel_variance8x8      = vp8_sub_pixel_variance8x8_wmt;
+        vp8_sub_pixel_variance8x16     = vp8_sub_pixel_variance8x16_wmt;
+        vp8_sub_pixel_variance16x8     = vp8_sub_pixel_variance16x8_wmt;
+        vp8_sub_pixel_variance16x16    = vp8_sub_pixel_variance16x16_wmt;
+        vp8_get_mb_ss                  = vp8_get_mb_ss_sse2;
+        vp8_get16x16pred_error        = vp8_get16x16pred_error_sse2;
+        vp8_get8x8var                = vp8_get8x8var_sse2;
+        vp8_get16x16var              = vp8_get16x16var_sse2;
+        vp8_get4x4sse_cs             = vp8_get4x4sse_cs_mmx;
+        vp8_sad16x16                 = vp8_sad16x16_wmt;
+        vp8_sad16x8                  = vp8_sad16x8_wmt;
+        vp8_sad8x16                  = vp8_sad8x16_wmt;
+        vp8_sad8x8                   = vp8_sad8x8_wmt;
+        vp8_sad4x4                   = vp8_sad4x4_wmt;
+        vp8_block_error               = vp8_block_error_xmm;
+        vp8_mbblock_error             = vp8_mbblock_error_xmm;
+        vp8_subtract_mby              = vp8_subtract_mby_mmx;
+
+    }
+    else if (mmx_enabled)
+    {
+        // MMX instruction set available:
+        vp8_mbuverror                = vp8_mbuverror_mmx;
+        vp8_fast_quantize_b            = vp8_fast_quantize_b_mmx;
+        vp8_short_fdct4x4             = vp8_short_fdct4x4_mmx;
+        vp8_short_fdct8x4             = vp8_short_fdct8x4_mmx;
+        vp8_fast_fdct4x4              = vp8_fast_fdct4x4_mmx;
+        vp8_fast_fdct8x4              = vp8_fast_fdct8x4_mmx;
+        vp8_subtract_b                = vp8_subtract_b_mmx;
+        vp8_subtract_mbuv             = vp8_subtract_mbuv_mmx;
+        vp8_variance4x4              = vp8_variance4x4_mmx;
+        vp8_variance8x8              = vp8_variance8x8_mmx;
+        vp8_variance8x16             = vp8_variance8x16_mmx;
+        vp8_variance16x8             = vp8_variance16x8_mmx;
+        vp8_variance16x16            = vp8_variance16x16_mmx;
+        vp8_mse16x16                 = vp8_mse16x16_mmx;
+        vp8_sub_pixel_variance4x4      = vp8_sub_pixel_variance4x4_mmx;
+        vp8_sub_pixel_variance8x8      = vp8_sub_pixel_variance8x8_mmx;
+        vp8_sub_pixel_variance8x16     = vp8_sub_pixel_variance8x16_mmx;
+        vp8_sub_pixel_variance16x8     = vp8_sub_pixel_variance16x8_mmx;
+        vp8_sub_pixel_variance16x16    = vp8_sub_pixel_variance16x16_mmx;
+        vp8_get_mb_ss                  = vp8_get_mb_ss_mmx;
+        vp8_get16x16pred_error        = vp8_get16x16pred_error_mmx;
+        vp8_get8x8var                = vp8_get8x8var_mmx;
+        vp8_get16x16var              = vp8_get16x16var_mmx;
+        vp8_get4x4sse_cs             = vp8_get4x4sse_cs_mmx;
+        vp8_sad16x16                 = vp8_sad16x16_mmx;
+        vp8_sad16x8                  = vp8_sad16x8_mmx;
+        vp8_sad8x16                  = vp8_sad8x16_mmx;
+        vp8_sad8x8                   = vp8_sad8x8_mmx;
+        vp8_sad4x4                   = vp8_sad4x4_mmx;
+        vp8_block_error               = vp8_block_error_mmx;
+        vp8_mbblock_error             = vp8_mbblock_error_mmx;
+        vp8_subtract_mby              = vp8_subtract_mby_mmx;
+
+    }
+    else
+    {
+        // Pure C:
+        vp8_mbuverror                = vp8_mbuverror_c;
+        vp8_fast_quantize_b            = vp8_fast_quantize_b_c;
+        vp8_short_fdct4x4             = vp8_short_fdct4x4_c;
+        vp8_short_fdct8x4             = vp8_short_fdct8x4_c;
+        vp8_fast_fdct4x4              = vp8_fast_fdct4x4_c;
+        vp8_fast_fdct8x4              = vp8_fast_fdct8x4_c;
+        vp8_subtract_b                = vp8_subtract_b_c;
+        vp8_subtract_mbuv             = vp8_subtract_mbuv_c;
+        vp8_variance4x4              = vp8_variance4x4_c;
+        vp8_variance8x8              = vp8_variance8x8_c;
+        vp8_variance8x16             = vp8_variance8x16_c;
+        vp8_variance16x8             = vp8_variance16x8_c;
+        vp8_variance16x16            = vp8_variance16x16_c;
+        vp8_mse16x16                 = vp8_mse16x16_c;
+        vp8_sub_pixel_variance4x4      = vp8_sub_pixel_variance4x4_c;
+        vp8_sub_pixel_variance8x8      = vp8_sub_pixel_variance8x8_c;
+        vp8_sub_pixel_variance8x16     = vp8_sub_pixel_variance8x16_c;
+        vp8_sub_pixel_variance16x8     = vp8_sub_pixel_variance16x8_c;
+        vp8_sub_pixel_variance16x16    = vp8_sub_pixel_variance16x16_c;
+        vp8_get_mb_ss                  = vp8_get_mb_ss_c;
+        vp8_get16x16pred_error        = vp8_get16x16pred_error_c;
+        vp8_get8x8var                = vp8_get8x8var_c;
+        vp8_get16x16var              = vp8_get16x16var_c;
+        vp8_get4x4sse_cs             = vp8_get4x4sse_cs_c;
+        vp8_sad16x16                 = vp8_sad16x16_c;
+        vp8_sad16x8                  = vp8_sad16x8_c;
+        vp8_sad8x16                  = vp8_sad8x16_c;
+        vp8_sad8x8                   = vp8_sad8x8_c;
+        vp8_sad4x4                   = vp8_sad4x4_c;
+        vp8_block_error               = vp8_block_error_c;
+        vp8_mbblock_error             = vp8_mbblock_error_c;
+        vp8_subtract_mby              = vp8_subtract_mby_c;
+    }
+
+}
diff --git a/vp8/encoder/x86/dct_mmx.asm b/vp8/encoder/x86/dct_mmx.asm
new file mode 100644
index 0000000..e134237
--- /dev/null
+++ b/vp8/encoder/x86/dct_mmx.asm
@@ -0,0 +1,846 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+section .text
+    global sym(vp8_short_fdct4x4_mmx)
+    global sym(vp8_fast_fdct4x4_mmx)
+    global sym(vp8_fast_fdct8x4_wmt)
+
+
+%define         DCTCONSTANTSBITS         (16)
+%define         DCTROUNDINGVALUE         (1<< (DCTCONSTANTSBITS-1))
+%define         x_c1                      (60547)          ; cos(pi  /8) * (1<<15)
+%define         x_c2                      (46341)          ; cos(pi*2/8) * (1<<15)
+%define         x_c3                      (25080)          ; cos(pi*3/8) * (1<<15)
+
+
+%define _1STSTAGESHIFT           14
+%define _2NDSTAGESHIFT           16
+
+; using matrix multiply with source and destbuffer has a pitch
+;void vp8_short_fdct4x4_mmx(short *input, short *output, int pitch)
+sym(vp8_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         rdx,    [dct_matrix GLOBAL]
+
+        movq        mm0,    [rsi   ]
+        movq        mm1,    [rsi + rax]
+
+        movq        mm2,    [rsi + rax*2]
+        lea         rsi,    [rsi + rax*2]
+
+        movq        mm3,    [rsi + rax]
+
+        ; first column
+        movq        mm4,    mm0
+        movq        mm7,    [rdx]
+
+        pmaddwd     mm4,    mm7
+        movq        mm5,    mm1
+
+        pmaddwd     mm5,    mm7
+        movq        mm6,    mm4
+
+        punpckldq   mm4,    mm5
+        punpckhdq   mm6,    mm5
+
+        paddd       mm4,    mm6
+        movq        mm5,    mm2
+
+
+        pmaddwd     mm5,    mm7
+        movq        mm6,    mm3
+
+        pmaddwd     mm6,    mm7
+        movq        mm7,    mm5
+
+        punpckldq   mm5,    mm6
+        punpckhdq   mm7,    mm6
+
+        paddd       mm5,    mm7
+        movq        mm6,    [dct1st_stage_rounding_mmx GLOBAL]
+
+        paddd       mm4,    mm6
+        paddd       mm5,    mm6
+
+        psrad       mm4,    _1STSTAGESHIFT
+        psrad       mm5,    _1STSTAGESHIFT
+
+        packssdw    mm4,    mm5
+        movq        [rdi],  mm4
+
+        ;second column
+        movq        mm4,    mm0
+
+        pmaddwd     mm4,    [rdx+8]
+        movq        mm5,    mm1
+
+        pmaddwd     mm5,    [rdx+8]
+        movq        mm6,    mm4
+
+        punpckldq   mm4,    mm5
+        punpckhdq   mm6,    mm5
+
+        paddd       mm4,    mm6
+        movq        mm5,    mm2
+
+        pmaddwd     mm5,    [rdx+8]
+        movq        mm6,    mm3
+
+        pmaddwd     mm6,    [rdx+8]
+        movq        mm7,    mm5
+
+        punpckldq   mm5,    mm6
+        punpckhdq   mm7,    mm6
+
+        paddd       mm5,    mm7
+        movq        mm6,    [dct1st_stage_rounding_mmx GLOBAL]
+
+        paddd       mm4,    mm6
+        paddd       mm5,    mm6
+
+        psrad       mm4,    _1STSTAGESHIFT
+        psrad       mm5,    _1STSTAGESHIFT
+
+        packssdw    mm4,    mm5
+        movq        [rdi+8],  mm4
+
+
+        ;third column
+        movq        mm4,    mm0
+
+        pmaddwd     mm4,    [rdx+16]
+        movq        mm5,    mm1
+
+        pmaddwd     mm5,    [rdx+16]
+        movq        mm6,    mm4
+
+        punpckldq   mm4,    mm5
+        punpckhdq   mm6,    mm5
+
+        paddd       mm4,    mm6
+        movq        mm5,    mm2
+
+        pmaddwd     mm5,    [rdx+16]
+        movq        mm6,    mm3
+
+        pmaddwd     mm6,    [rdx+16]
+        movq        mm7,    mm5
+
+        punpckldq   mm5,    mm6
+        punpckhdq   mm7,    mm6
+
+        paddd       mm5,    mm7
+        movq        mm6,    [dct1st_stage_rounding_mmx GLOBAL]
+
+        paddd       mm4,    mm6
+        paddd       mm5,    mm6
+
+        psrad       mm4,    _1STSTAGESHIFT
+        psrad       mm5,    _1STSTAGESHIFT
+
+        packssdw    mm4,    mm5
+        movq        [rdi+16],  mm4
+
+        ;fourth column (this is the last column, so we do not have save the source any more)
+
+        pmaddwd     mm0,    [rdx+24]
+
+        pmaddwd     mm1,    [rdx+24]
+        movq        mm6,    mm0
+
+        punpckldq   mm0,    mm1
+        punpckhdq   mm6,    mm1
+
+        paddd       mm0,    mm6
+
+        pmaddwd     mm2,    [rdx+24]
+
+        pmaddwd     mm3,    [rdx+24]
+        movq        mm7,    mm2
+
+        punpckldq   mm2,    mm3
+        punpckhdq   mm7,    mm3
+
+        paddd       mm2,    mm7
+        movq        mm6,    [dct1st_stage_rounding_mmx GLOBAL]
+
+        paddd       mm0,    mm6
+        paddd       mm2,    mm6
+
+        psrad       mm0,    _1STSTAGESHIFT
+        psrad       mm2,    _1STSTAGESHIFT
+
+        packssdw    mm0,    mm2
+
+        movq        mm3,    mm0
+
+        ; done with one pass
+        ; now start second pass
+        movq        mm0,    [rdi   ]
+        movq        mm1,    [rdi+ 8]
+        movq        mm2,    [rdi+ 16]
+
+        movq        mm4,    mm0
+
+        pmaddwd     mm4,    [rdx]
+        movq        mm5,    mm1
+
+        pmaddwd     mm5,    [rdx]
+        movq        mm6,    mm4
+
+        punpckldq   mm4,    mm5
+        punpckhdq   mm6,    mm5
+
+        paddd       mm4,    mm6
+        movq        mm5,    mm2
+
+        pmaddwd     mm5,    [rdx]
+        movq        mm6,    mm3
+
+        pmaddwd     mm6,    [rdx]
+        movq        mm7,    mm5
+
+        punpckldq   mm5,    mm6
+        punpckhdq   mm7,    mm6
+
+        paddd       mm5,    mm7
+        movq        mm6,    [dct2nd_stage_rounding_mmx GLOBAL]
+
+        paddd       mm4,    mm6
+        paddd       mm5,    mm6
+
+        psrad       mm4,    _2NDSTAGESHIFT
+        psrad       mm5,    _2NDSTAGESHIFT
+
+        packssdw    mm4,    mm5
+        movq        [rdi],  mm4
+
+        ;second column
+        movq        mm4,    mm0
+
+        pmaddwd     mm4,    [rdx+8]
+        movq        mm5,    mm1
+
+        pmaddwd     mm5,    [rdx+8]
+        movq        mm6,    mm4
+
+        punpckldq   mm4,    mm5
+        punpckhdq   mm6,    mm5
+
+        paddd       mm4,    mm6
+        movq        mm5,    mm2
+
+        pmaddwd     mm5,    [rdx+8]
+        movq        mm6,    mm3
+
+        pmaddwd     mm6,    [rdx+8]
+        movq        mm7,    mm5
+
+        punpckldq   mm5,    mm6
+        punpckhdq   mm7,    mm6
+
+        paddd       mm5,    mm7
+        movq        mm6,    [dct2nd_stage_rounding_mmx GLOBAL]
+
+        paddd       mm4,    mm6
+        paddd       mm5,    mm6
+
+        psrad       mm4,    _2NDSTAGESHIFT
+        psrad       mm5,    _2NDSTAGESHIFT
+
+        packssdw    mm4,    mm5
+        movq        [rdi+8],  mm4
+
+
+        ;third column
+        movq        mm4,    mm0
+
+        pmaddwd     mm4,    [rdx+16]
+        movq        mm5,    mm1
+
+        pmaddwd     mm5,    [rdx+16]
+        movq        mm6,    mm4
+
+        punpckldq   mm4,    mm5
+        punpckhdq   mm6,    mm5
+
+        paddd       mm4,    mm6
+        movq        mm5,    mm2
+
+        pmaddwd     mm5,    [rdx+16]
+        movq        mm6,    mm3
+
+        pmaddwd     mm6,    [rdx+16]
+        movq        mm7,    mm5
+
+        punpckldq   mm5,    mm6
+        punpckhdq   mm7,    mm6
+
+        paddd       mm5,    mm7
+        movq        mm6,    [dct2nd_stage_rounding_mmx GLOBAL]
+
+        paddd       mm4,    mm6
+        paddd       mm5,    mm6
+
+        psrad       mm4,    _2NDSTAGESHIFT
+        psrad       mm5,    _2NDSTAGESHIFT
+
+        packssdw    mm4,    mm5
+        movq        [rdi+16],  mm4
+
+        ;fourth column
+        movq        mm4,    mm0
+
+        pmaddwd     mm4,    [rdx+24]
+        movq        mm5,    mm1
+
+        pmaddwd     mm5,    [rdx+24]
+        movq        mm6,    mm4
+
+        punpckldq   mm4,    mm5
+        punpckhdq   mm6,    mm5
+
+        paddd       mm4,    mm6
+        movq        mm5,    mm2
+
+        pmaddwd     mm5,    [rdx+24]
+        movq        mm6,    mm3
+
+        pmaddwd     mm6,    [rdx+24]
+        movq        mm7,    mm5
+
+        punpckldq   mm5,    mm6
+        punpckhdq   mm7,    mm6
+
+        paddd       mm5,    mm7
+        movq        mm6,    [dct2nd_stage_rounding_mmx GLOBAL]
+
+        paddd       mm4,    mm6
+        paddd       mm5,    mm6
+
+        psrad       mm4,    _2NDSTAGESHIFT
+        psrad       mm5,    _2NDSTAGESHIFT
+
+        packssdw    mm4,    mm5
+        movq        [rdi+24],  mm4
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_fast_fdct4x4_mmx(short *input, short *output, int pitch)
+sym(vp8_fast_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
+
+        lea     rdx,    [dct_const_mmx GLOBAL]
+        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    mm3,    [rcx + rax]
+        ; get the constants
+        ;shift to left by 1 for prescision
+        paddw   mm0,    mm0
+        paddw   mm1,    mm1
+
+        psllw   mm2,    1
+        psllw   mm3,    1
+
+        ; transpose for the second stage
+        movq    mm4,    mm0         ; 00 01 02 03
+        movq    mm5,    mm2         ; 10 11 12 03
+
+        punpcklwd   mm0,    mm1     ; 00 10 01 11
+        punpckhwd   mm4,    mm1     ; 02 12 03 13
+
+        punpcklwd   mm2,    mm3     ; 20 30 21 31
+        punpckhwd   mm5,    mm3     ; 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,    mm4     ; 02 12 03 13
+        punpckldq   mm2,    mm5     ; 02 12 22 32
+
+        punpckhdq   mm4,    mm5     ; 03 13 23 33
+        movq        mm3,    mm4
+
+
+        ; first stage
+        movq    mm5,    mm0
+        movq    mm4,    mm1
+
+        paddw   mm0,    mm3         ; a = 0 + 3
+        paddw   mm1,    mm2         ; b = 1 + 2
+
+        psubw   mm4,    mm2         ; c = 1 - 2
+        psubw   mm5,    mm3         ; d = 0 - 3
+
+
+        ; output 0 and 2
+        movq    mm6,    [rdx +  16] ; c2
+        movq    mm2,    mm0         ; a
+
+        paddw   mm0,    mm1         ; a + b
+        psubw   mm2,    mm1         ; a - b
+
+        movq    mm1,    mm0         ; a + b
+        pmulhw  mm0,    mm6         ; 00 01 02 03
+
+        paddw   mm0,    mm1         ; output 00 01 02 03
+        pmulhw  mm6,    mm2         ; 20 21 22 23
+
+        paddw   mm2,    mm6         ; output 20 21 22 23
+
+        ; output 1 and 3
+        movq    mm6,    [rdx +  8]  ; c1
+        movq    mm7,    [rdx + 24]  ; c3
+
+        movq    mm1,    mm4         ; c
+        movq    mm3,    mm5         ; d
+
+        pmulhw  mm1,    mm7         ; c * c3
+        pmulhw  mm3,    mm6         ; d * c1
+
+        paddw   mm3,    mm5         ; d * c1 rounded
+        paddw   mm1,    mm3         ; output 10 11 12 13
+
+        movq    mm3,    mm4         ; c
+        pmulhw  mm5,    mm7         ; d * c3
+
+        pmulhw  mm4,    mm6         ; c * c1
+        paddw   mm3,    mm4         ; round c* c1
+
+        psubw   mm5,    mm3         ; output 30 31 32 33
+        movq    mm3,    mm5
+
+
+        ; done with vertical
+        ; transpose for the second stage
+        movq    mm4,    mm0         ; 00 01 02 03
+        movq    mm5,    mm2         ; 10 11 12 03
+
+        punpcklwd   mm0,    mm1     ; 00 10 01 11
+        punpckhwd   mm4,    mm1     ; 02 12 03 13
+
+        punpcklwd   mm2,    mm3     ; 20 30 21 31
+        punpckhwd   mm5,    mm3     ; 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,    mm4     ; 02 12 03 13
+        punpckldq   mm2,    mm5     ; 02 12 22 32
+
+        punpckhdq   mm4,    mm5     ; 03 13 23 33
+        movq        mm3,    mm4
+
+
+        ; first stage
+        movq    mm5,    mm0
+        movq    mm4,    mm1
+
+        paddw   mm0,    mm3         ; a = 0 + 3
+        paddw   mm1,    mm2         ; b = 1 + 2
+
+        psubw   mm4,    mm2         ; c = 1 - 2
+        psubw   mm5,    mm3         ; d = 0 - 3
+
+
+        ; output 0 and 2
+        movq    mm6,    [rdx +  16] ; c2
+        movq    mm2,    mm0         ; a
+        paddw   mm0,    mm1         ; a + b
+
+        psubw   mm2,    mm1         ; a - b
+
+        movq    mm1,    mm0         ; a + b
+        pmulhw  mm0,    mm6         ; 00 01 02 03
+
+        paddw   mm0,    mm1         ; output 00 01 02 03
+        pmulhw  mm6,    mm2         ; 20 21 22 23
+
+        paddw   mm2,    mm6         ; output 20 21 22 23
+
+
+        ; output 1 and 3
+        movq    mm6,    [rdx +  8]  ; c1
+        movq    mm7,    [rdx + 24]  ; c3
+
+        movq    mm1,    mm4         ; c
+        movq    mm3,    mm5         ; d
+
+        pmulhw  mm1,    mm7         ; c * c3
+        pmulhw  mm3,    mm6         ; d * c1
+
+        paddw   mm3,    mm5         ; d * c1 rounded
+        paddw   mm1,    mm3         ; output 10 11 12 13
+
+        movq    mm3,    mm4         ; c
+        pmulhw  mm5,    mm7         ; d * c3
+
+        pmulhw  mm4,    mm6         ; c * c1
+        paddw   mm3,    mm4         ; round c* c1
+
+        psubw   mm5,    mm3         ; output 30 31 32 33
+        movq    mm3,    mm5
+        ; done with vertical
+
+		pcmpeqw	mm4,	mm4
+		pcmpeqw	mm5,	mm5
+		psrlw	mm4,	15
+		psrlw	mm5,	15
+
+        paddw   mm0,    mm4
+        paddw   mm1,    mm5
+        paddw   mm2,    mm4
+        paddw   mm3,    mm5
+
+        psraw   mm0, 1
+        psraw   mm1, 1
+        psraw   mm2, 1
+        psraw   mm3, 1
+
+        movq        [rdi   ],   mm0
+        movq        [rdi+ 8],   mm1
+        movq        [rdi+16],   mm2
+        movq        [rdi+24],   mm3
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_fast_fdct8x4_wmt(short *input, short *output, int pitch)
+sym(vp8_fast_fdct8x4_wmt):
+    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
+
+        lea         rdx,    [dct_const_xmm GLOBAL]
+        movsxd      rax,    dword ptr arg(2) ;pitch
+
+        lea         rcx,    [rsi + rax*2]
+        ; read the input data
+        movdqa      xmm0,       [rsi]
+        movdqa      xmm2,       [rsi + rax]
+
+        movdqa      xmm4,       [rcx]
+        movdqa      xmm3,       [rcx + rax]
+        ; get the constants
+        ;shift to left by 1 for prescision
+        psllw       xmm0,        1
+        psllw       xmm2,        1
+
+        psllw       xmm4,        1
+        psllw       xmm3,        1
+
+        ; transpose for the second stage
+        movdqa      xmm1,       xmm0         ; 00 01 02 03 04 05 06 07
+        movdqa      xmm5,       xmm4         ; 20 21 22 23 24 25 26 27
+
+        punpcklwd   xmm0,       xmm2         ; 00 10 01 11 02 12 03 13
+        punpckhwd   xmm1,       xmm2         ; 04 14 05 15 06 16 07 17
+
+        punpcklwd   xmm4,       xmm3         ; 20 30 21 31 22 32 23 33
+        punpckhwd   xmm5,       xmm3         ; 24 34 25 35 26 36 27 37
+
+        movdqa      xmm2,       xmm0         ; 00 10 01 11 02 12 03 13
+        punpckldq   xmm0,       xmm4         ; 00 10 20 30 01 11 21 31
+
+        punpckhdq   xmm2,       xmm4         ; 02 12 22 32 03 13 23 33
+
+
+        movdqa      xmm4,       xmm1         ; 04 14 05 15 06 16 07 17
+        punpckldq   xmm4,       xmm5         ; 04 14 24 34 05 15 25 35
+
+        punpckhdq   xmm1,       xmm5         ; 06 16 26 36 07 17 27 37
+        movdqa      xmm3,       xmm2         ; 02 12 22 32 03 13 23 33
+
+        punpckhqdq  xmm3,       xmm1         ; 03 13 23 33 07 17 27 37
+        punpcklqdq  xmm2,       xmm1         ; 02 12 22 32 06 16 26 36
+
+        movdqa      xmm1,       xmm0         ; 00 10 20 30 01 11 21 31
+        punpcklqdq  xmm0,       xmm4         ; 00 10 20 30 04 14 24 34
+
+        punpckhqdq  xmm1,       xmm4         ; 01 11 21 32 05 15 25 35
+
+        ; xmm0 0
+        ; xmm1 1
+        ; xmm2 2
+        ; xmm3 3
+
+        ; first stage
+        movdqa      xmm5,       xmm0
+        movdqa      xmm4,       xmm1
+
+        paddw       xmm0,       xmm3         ; a = 0 + 3
+        paddw       xmm1,       xmm2         ; b = 1 + 2
+
+        psubw       xmm4,       xmm2         ; c = 1 - 2
+        psubw       xmm5,       xmm3         ; d = 0 - 3
+
+
+        ; output 0 and 2
+        movdqa      xmm6,       [rdx +  32] ; c2
+        movdqa      xmm2,       xmm0         ; a
+
+        paddw       xmm0,       xmm1         ; a + b
+        psubw       xmm2,       xmm1         ; a - b
+
+        movdqa      xmm1,       xmm0         ; a + b
+        pmulhw      xmm0,       xmm6         ; 00 01 02 03
+
+        paddw       xmm0,       xmm1         ; output 00 01 02 03
+        pmulhw      xmm6,       xmm2         ; 20 21 22 23
+
+        paddw       xmm2,       xmm6         ; output 20 21 22 23
+
+        ; output 1 and 3
+        movdqa      xmm6,       [rdx + 16]  ; c1
+        movdqa      xmm7,       [rdx + 48]  ; c3
+
+        movdqa      xmm1,       xmm4         ; c
+        movdqa      xmm3,       xmm5         ; d
+
+        pmulhw      xmm1,       xmm7         ; c * c3
+        pmulhw      xmm3,       xmm6         ; d * c1
+
+        paddw       xmm3,       xmm5         ; d * c1 rounded
+        paddw       xmm1,       xmm3         ; output 10 11 12 13
+
+        movdqa      xmm3,       xmm4         ; c
+        pmulhw      xmm5,       xmm7         ; d * c3
+
+        pmulhw      xmm4,       xmm6         ; c * c1
+        paddw       xmm3,       xmm4         ; round c* c1
+
+        psubw       xmm5,       xmm3         ; output 30 31 32 33
+        movdqa      xmm3,       xmm5
+
+
+        ; done with vertical
+        ; transpose for the second stage
+        movdqa      xmm4,       xmm2         ; 02 12 22 32 06 16 26 36
+        movdqa      xmm2,       xmm1         ; 01 11 21 31 05 15 25 35
+
+        movdqa      xmm1,       xmm0         ; 00 10 20 30 04 14 24 34
+        movdqa      xmm5,       xmm4         ; 02 12 22 32 06 16 26 36
+
+        punpcklwd   xmm0,       xmm2         ; 00 01 10 11 20 21 30 31
+        punpckhwd   xmm1,       xmm2         ; 04 05 14 15 24 25 34 35
+
+        punpcklwd   xmm4,       xmm3         ; 02 03 12 13 22 23 32 33
+        punpckhwd   xmm5,       xmm3         ; 06 07 16 17 26 27 36 37
+
+        movdqa      xmm2,       xmm0         ; 00 01 10 11 20 21 30 31
+        punpckldq   xmm0,       xmm4         ; 00 01 02 03 10 11 12 13
+
+        punpckhdq   xmm2,       xmm4         ; 20 21 22 23 30 31 32 33
+
+
+        movdqa      xmm4,       xmm1         ; 04 05 14 15 24 25 34 35
+        punpckldq   xmm4,       xmm5         ; 04 05 06 07 14 15 16 17
+
+        punpckhdq   xmm1,       xmm5         ; 24 25 26 27 34 35 36 37
+        movdqa      xmm3,       xmm2         ; 20 21 22 23 30 31 32 33
+
+        punpckhqdq  xmm3,       xmm1         ; 30 31 32 33 34 35 36 37
+        punpcklqdq  xmm2,       xmm1         ; 20 21 22 23 24 25 26 27
+
+        movdqa      xmm1,       xmm0         ; 00 01 02 03 10 11 12 13
+        punpcklqdq  xmm0,       xmm4         ; 00 01 02 03 04 05 06 07
+
+        punpckhqdq  xmm1,       xmm4         ; 10 11 12 13 14 15 16 17
+
+        ; first stage
+        movdqa      xmm5,       xmm0
+        movdqa      xmm4,       xmm1
+
+        paddw       xmm0,       xmm3         ; a = 0 + 3
+        paddw       xmm1,       xmm2         ; b = 1 + 2
+
+        psubw       xmm4,       xmm2         ; c = 1 - 2
+        psubw       xmm5,       xmm3         ; d = 0 - 3
+
+
+        ; output 0 and 2
+        movdqa      xmm6,       [rdx +  32] ; c2
+        movdqa      xmm2,       xmm0         ; a
+
+        paddw       xmm0,       xmm1         ; a + b
+        psubw       xmm2,       xmm1         ; a - b
+
+        movdqa      xmm1,       xmm0         ; a + b
+        pmulhw      xmm0,       xmm6         ; 00 01 02 03
+
+        paddw       xmm0,       xmm1         ; output 00 01 02 03
+        pmulhw      xmm6,       xmm2         ; 20 21 22 23
+
+        paddw       xmm2,       xmm6         ; output 20 21 22 23
+
+        ; output 1 and 3
+        movdqa      xmm6,       [rdx + 16]  ; c1
+        movdqa      xmm7,       [rdx + 48]  ; c3
+
+        movdqa      xmm1,       xmm4         ; c
+        movdqa      xmm3,       xmm5         ; d
+
+        pmulhw      xmm1,       xmm7         ; c * c3
+        pmulhw      xmm3,       xmm6         ; d * c1
+
+        paddw       xmm3,       xmm5         ; d * c1 rounded
+        paddw       xmm1,       xmm3         ; output 10 11 12 13
+
+        movdqa      xmm3,       xmm4         ; c
+        pmulhw      xmm5,       xmm7         ; d * c3
+
+        pmulhw      xmm4,       xmm6         ; c * c1
+        paddw       xmm3,       xmm4         ; round c* c1
+
+        psubw       xmm5,       xmm3         ; output 30 31 32 33
+        movdqa      xmm3,       xmm5
+        ; done with vertical
+
+
+        pcmpeqw		xmm4,		xmm4
+        pcmpeqw		xmm5,		xmm5;
+        psrlw		xmm4,		15
+        psrlw		xmm5,		15
+
+        paddw       xmm0,       xmm4
+        paddw       xmm1,       xmm5
+        paddw       xmm2,       xmm4
+        paddw       xmm3,       xmm5
+
+        psraw       xmm0,       1
+        psraw       xmm1,       1
+        psraw       xmm2,       1
+        psraw       xmm3,       1
+
+        movq        QWORD PTR[rdi   ],   xmm0
+        movq        QWORD PTR[rdi+ 8],   xmm1
+        movq        QWORD PTR[rdi+16],   xmm2
+        movq        QWORD PTR[rdi+24],   xmm3
+
+        psrldq      xmm0,       8
+        psrldq      xmm1,       8
+        psrldq      xmm2,       8
+        psrldq      xmm3,       8
+
+        movq        QWORD PTR[rdi+32],   xmm0
+        movq        QWORD PTR[rdi+40],   xmm1
+        movq        QWORD PTR[rdi+48],   xmm2
+        movq        QWORD PTR[rdi+56],   xmm3
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+SECTION_RODATA
+;static const unsigned int dct1st_stage_rounding_mmx[2] =
+align 16
+dct1st_stage_rounding_mmx:
+    times 2 dd 8192
+
+
+;static const unsigned int dct2nd_stage_rounding_mmx[2] =
+align 16
+dct2nd_stage_rounding_mmx:
+    times 2 dd 32768
+
+
+;static const short dct_matrix[4][4]=
+align 16
+dct_matrix:
+    times 4 dw 23170
+
+    dw  30274
+    dw  12540
+    dw -12540
+    dw -30274
+
+    dw 23170
+    times 2 dw -23170
+    dw 23170
+
+    dw  12540
+    dw -30274
+    dw  30274
+    dw -12540
+
+
+;static const unsigned short dct_const_mmx[4 * 4]=
+align 16
+dct_const_mmx:
+    times 4 dw 0
+    times 4 dw 60547
+    times 4 dw 46341
+    times 4 dw 25080
+
+
+;static const unsigned short dct_const_xmm[8 * 4]=
+align 16
+dct_const_xmm:
+    times 8 dw 0
+    times 8 dw 60547
+    times 8 dw 46341
+    times 8 dw 25080
diff --git a/vp8/encoder/x86/dct_sse2.asm b/vp8/encoder/x86/dct_sse2.asm
new file mode 100644
index 0000000..3e5e9a7
--- /dev/null
+++ b/vp8/encoder/x86/dct_sse2.asm
@@ -0,0 +1,260 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+global sym(vp8_short_fdct4x4_wmt)
+
+%define         DCTCONSTANTSBITS         (16)
+%define         DCTROUNDINGVALUE         (1<< (DCTCONSTANTSBITS-1))
+%define         x_c1                      (60547)          ; cos(pi  /8) * (1<<15)
+%define         x_c2                      (46341)          ; cos(pi*2/8) * (1<<15)
+%define         x_c3                      (25080)          ; cos(pi*3/8) * (1<<15)
+
+%define _1STSTAGESHIFT           14
+%define _2NDSTAGESHIFT           16
+
+
+;; using matrix multiply
+;void vp8_short_fdct4x4_wmt(short *input, short *output)
+sym(vp8_short_fdct4x4_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    GET_GOT     rbx
+    ; end prolog
+
+        mov         rax,        arg(0) ;input
+        mov         rcx,        arg(1) ;output
+
+        lea         rdx,        [dct_matrix_sse2 GLOBAL]
+
+        movdqu      xmm0,       [rax   ]
+        movdqu      xmm1,       [rax+16]
+
+        ; first column
+        movdqa      xmm2,       xmm0
+        movdqa      xmm7,       [rdx]
+
+        pmaddwd     xmm2,       xmm7
+        movdqa      xmm3,       xmm1
+
+        pmaddwd     xmm3,       xmm7
+        movdqa      xmm4,       xmm2
+
+        punpckldq   xmm2,       xmm3
+        punpckhdq   xmm4,       xmm3
+
+        movdqa      xmm3,       xmm2
+        punpckldq   xmm2,       xmm4
+
+        punpckhdq   xmm3,       xmm4
+        paddd       xmm2,       xmm3
+
+
+        paddd       xmm2,       XMMWORD PTR [dct1st_stage_rounding_sse2 GLOBAL]
+        psrad       xmm2,       _1STSTAGESHIFT
+        ;second column
+        movdqa      xmm3,       xmm0
+        pmaddwd     xmm3,       [rdx+16]
+
+        movdqa      xmm4,       xmm1
+        pmaddwd     xmm4,       [rdx+16]
+
+        movdqa      xmm5,       xmm3
+        punpckldq   xmm3,       xmm4
+
+        punpckhdq   xmm5,       xmm4
+        movdqa      xmm4,       xmm3
+
+        punpckldq   xmm3,       xmm5
+        punpckhdq   xmm4,       xmm5
+
+        paddd       xmm3,       xmm4
+        paddd       xmm3,       XMMWORD PTR [dct1st_stage_rounding_sse2 GLOBAL]
+
+
+        psrad       xmm3,       _1STSTAGESHIFT
+        packssdw    xmm2,       xmm3
+
+        ;third column
+        movdqa      xmm3,       xmm0
+        pmaddwd     xmm3,       [rdx+32]
+
+        movdqa      xmm4,       xmm1
+        pmaddwd     xmm4,       [rdx+32]
+
+        movdqa      xmm5,       xmm3
+        punpckldq   xmm3,       xmm4
+
+        punpckhdq   xmm5,       xmm4
+        movdqa      xmm4,       xmm3
+
+        punpckldq   xmm3,       xmm5
+        punpckhdq   xmm4,       xmm5
+
+        paddd       xmm3,       xmm4
+        paddd       xmm3,       XMMWORD PTR [dct1st_stage_rounding_sse2 GLOBAL]
+
+        psrad       xmm3,       _1STSTAGESHIFT
+
+        ;fourth column (this is the last column, so we do not have save the source any more)
+        pmaddwd     xmm0,       [rdx+48]
+        pmaddwd     xmm1,       [rdx+48]
+
+        movdqa      xmm4,       xmm0
+        punpckldq   xmm0,       xmm1
+
+        punpckhdq   xmm4,       xmm1
+        movdqa      xmm1,       xmm0
+
+        punpckldq   xmm0,       xmm4
+        punpckhdq   xmm1,       xmm4
+
+        paddd       xmm0,       xmm1
+        paddd       xmm0,       XMMWORD PTR [dct1st_stage_rounding_sse2 GLOBAL]
+
+
+        psrad       xmm0,       _1STSTAGESHIFT
+        packssdw    xmm3,       xmm0
+        ; done with one pass
+        ; now start second pass
+        movdqa      xmm0,       xmm2
+        movdqa      xmm1,       xmm3
+
+        pmaddwd     xmm2,       xmm7
+        pmaddwd     xmm3,       xmm7
+
+        movdqa      xmm4,       xmm2
+        punpckldq   xmm2,       xmm3
+
+        punpckhdq   xmm4,       xmm3
+        movdqa      xmm3,       xmm2
+
+        punpckldq   xmm2,       xmm4
+        punpckhdq   xmm3,       xmm4
+
+        paddd       xmm2,       xmm3
+        paddd       xmm2,       XMMWORD PTR [dct2nd_stage_rounding_sse2 GLOBAL]
+
+        psrad       xmm2,       _2NDSTAGESHIFT
+
+        ;second column
+        movdqa      xmm3,       xmm0
+        pmaddwd     xmm3,       [rdx+16]
+
+        movdqa      xmm4,       xmm1
+        pmaddwd     xmm4,       [rdx+16]
+
+        movdqa      xmm5,       xmm3
+        punpckldq   xmm3,       xmm4
+
+        punpckhdq   xmm5,       xmm4
+        movdqa      xmm4,       xmm3
+
+        punpckldq   xmm3,       xmm5
+        punpckhdq   xmm4,       xmm5
+
+        paddd       xmm3,       xmm4
+        paddd       xmm3,       XMMWORD PTR [dct2nd_stage_rounding_sse2 GLOBAL]
+
+        psrad       xmm3,       _2NDSTAGESHIFT
+        packssdw    xmm2,       xmm3
+
+        movdqu      [rcx],      xmm2
+        ;third column
+        movdqa      xmm3,       xmm0
+        pmaddwd     xmm3,       [rdx+32]
+
+        movdqa      xmm4,       xmm1
+        pmaddwd     xmm4,       [rdx+32]
+
+        movdqa      xmm5,       xmm3
+        punpckldq   xmm3,       xmm4
+
+        punpckhdq   xmm5,       xmm4
+        movdqa      xmm4,       xmm3
+
+        punpckldq   xmm3,       xmm5
+        punpckhdq   xmm4,       xmm5
+
+        paddd       xmm3,       xmm4
+        paddd       xmm3,       XMMWORD PTR [dct2nd_stage_rounding_sse2 GLOBAL]
+
+        psrad       xmm3,       _2NDSTAGESHIFT
+        ;fourth column
+        pmaddwd     xmm0,       [rdx+48]
+        pmaddwd     xmm1,       [rdx+48]
+
+        movdqa      xmm4,       xmm0
+        punpckldq   xmm0,       xmm1
+
+        punpckhdq   xmm4,       xmm1
+        movdqa      xmm1,       xmm0
+
+        punpckldq   xmm0,       xmm4
+        punpckhdq   xmm1,       xmm4
+
+        paddd       xmm0,       xmm1
+        paddd       xmm0,       XMMWORD PTR [dct2nd_stage_rounding_sse2 GLOBAL]
+
+        psrad       xmm0,       _2NDSTAGESHIFT
+        packssdw    xmm3,       xmm0
+
+        movdqu     [rcx+16],   xmm3
+
+    mov rsp, rbp
+    ; begin epilog
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+SECTION_RODATA
+;static unsigned int dct1st_stage_rounding_sse2[4] =
+align 16
+dct1st_stage_rounding_sse2:
+    times 4 dd 8192
+
+
+;static unsigned int dct2nd_stage_rounding_sse2[4] =
+align 16
+dct2nd_stage_rounding_sse2:
+    times 4 dd 32768
+
+;static short dct_matrix_sse2[4][8]=
+align 16
+dct_matrix_sse2:
+    times 8 dw 23170
+
+    dw  30274
+    dw  12540
+    dw -12540
+    dw -30274
+    dw  30274
+    dw  12540
+    dw -12540
+    dw -30274
+
+    dw  23170
+    times 2 dw -23170
+    times 2 dw  23170
+    times 2 dw -23170
+    dw  23170
+
+    dw  12540
+    dw -30274
+    dw  30274
+    dw -12540
+    dw  12540
+    dw -30274
+    dw  30274
+    dw -12540
diff --git a/vp8/encoder/x86/dct_x86.h b/vp8/encoder/x86/dct_x86.h
new file mode 100644
index 0000000..bc80e64
--- /dev/null
+++ b/vp8/encoder/x86/dct_x86.h
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef DCT_X86_H
+#define DCT_X86_H
+
+
+/* Note:
+ *
+ * This platform is commonly built for runtime CPU detection. If you modify
+ * any of the function mappings present in this file, be sure to also update
+ * them in the function pointer initialization code
+ */
+#if HAVE_MMX
+extern prototype_fdct(vp8_short_fdct4x4_mmx);
+extern prototype_fdct(vp8_short_fdct8x4_mmx);
+extern prototype_fdct(vp8_fast_fdct4x4_mmx);
+extern prototype_fdct(vp8_fast_fdct8x4_mmx);
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_fdct_short4x4
+#define vp8_fdct_short4x4 vp8_short_fdct4x4_mmx
+
+#undef  vp8_fdct_short8x4
+#define vp8_fdct_short8x4 vp8_short_fdct8x4_mmx
+
+#undef  vp8_fdct_fast4x4
+#define vp8_fdct_fast4x4 vp8_fast_fdct4x4_mmx
+
+#undef  vp8_fdct_fast8x4
+#define vp8_fdct_fast8x4 vp8_fast_fdct8x4_mmx
+
+#endif
+#endif
+
+
+#if HAVE_SSE2
+extern prototype_fdct(vp8_short_fdct4x4_wmt);
+extern prototype_fdct(vp8_short_fdct8x4_wmt);
+extern prototype_fdct(vp8_fast_fdct8x4_wmt);
+
+extern prototype_fdct(vp8_short_walsh4x4_sse2);
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+
+#if 0
+/* short SSE2 DCT currently disabled, does not match the MMX version */
+#undef  vp8_fdct_short4x4
+#define vp8_fdct_short4x4 vp8_short_fdct4x4_wmt
+
+#undef  vp8_fdct_short8x4
+#define vp8_fdct_short8x4 vp8_short_fdct8x4_wmt
+#endif
+
+#undef  vp8_fdct_fast8x4
+#define vp8_fdct_fast8x4 vp8_fast_fdct8x4_wmt
+
+#undef vp8_fdct_walsh_short4x4
+#define vp8_fdct_walsh_short4x4  vp8_short_walsh4x4_sse2
+
+#endif
+
+
+#endif
+
+#endif
diff --git a/vp8/encoder/x86/encodemb_x86.h b/vp8/encoder/x86/encodemb_x86.h
new file mode 100644
index 0000000..9397a6c
--- /dev/null
+++ b/vp8/encoder/x86/encodemb_x86.h
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef ENCODEMB_X86_H
+#define ENCODEMB_X86_H
+
+
+/* Note:
+ *
+ * This platform is commonly built for runtime CPU detection. If you modify
+ * any of the function mappings present in this file, be sure to also update
+ * them in the function pointer initialization code
+ */
+#if HAVE_MMX
+extern prototype_berr(vp8_block_error_mmx);
+extern prototype_mberr(vp8_mbblock_error_mmx);
+extern prototype_mbuverr(vp8_mbuverror_mmx);
+extern prototype_subb(vp8_subtract_b_mmx);
+extern prototype_submby(vp8_subtract_mby_mmx);
+extern prototype_submbuv(vp8_subtract_mbuv_mmx);
+
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_encodemb_berr
+#define vp8_encodemb_berr vp8_block_error_mmx
+
+#undef  vp8_encodemb_mberr
+#define vp8_encodemb_mberr vp8_mbblock_error_mmx
+
+#undef  vp8_encodemb_mbuverr
+#define vp8_encodemb_mbuverr vp8_mbuverror_mmx
+
+#undef  vp8_encodemb_subb
+#define vp8_encodemb_subb vp8_subtract_b_mmx
+
+#undef  vp8_encodemb_submby
+#define vp8_encodemb_submby vp8_subtract_mby_mmx
+
+#undef  vp8_encodemb_submbuv
+#define vp8_encodemb_submbuv vp8_subtract_mbuv_mmx
+
+#endif
+#endif
+
+
+#if HAVE_SSE2
+extern prototype_berr(vp8_block_error_xmm);
+extern prototype_mberr(vp8_mbblock_error_xmm);
+extern prototype_mbuverr(vp8_mbuverror_xmm);
+
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_encodemb_berr
+#define vp8_encodemb_berr vp8_block_error_xmm
+
+#undef  vp8_encodemb_mberr
+#define vp8_encodemb_mberr vp8_mbblock_error_xmm
+
+#undef  vp8_encodemb_mbuverr
+#define vp8_encodemb_mbuverr vp8_mbuverror_xmm
+
+#endif
+#endif
+
+
+#endif
diff --git a/vp8/encoder/x86/encodeopt.asm b/vp8/encoder/x86/encodeopt.asm
new file mode 100644
index 0000000..1940471
--- /dev/null
+++ b/vp8/encoder/x86/encodeopt.asm
@@ -0,0 +1,393 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+
+;int vp8_block_error_xmm(short *coeff_ptr,  short *dcoef_ptr)
+global sym(vp8_block_error_xmm)
+sym(vp8_block_error_xmm):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov         rsi,        arg(0) ;coeff_ptr
+        pxor        xmm7,       xmm7
+
+        mov         rdi,        arg(1) ;dcoef_ptr
+        movdqa      xmm3,       [rsi]
+
+        movdqa      xmm4,       [rdi]
+        movdqa      xmm5,       [rsi+16]
+
+        movdqa      xmm6,       [rdi+16]
+        pxor        xmm1,       xmm1    ; from movd xmm1, dc; dc=0
+
+        movdqa      xmm2,       xmm7
+        psubw       xmm5,       xmm6
+
+        por         xmm1,       xmm2
+        pmaddwd     xmm5,       xmm5
+
+        pcmpeqw     xmm1,       xmm7
+        psubw       xmm3,       xmm4
+
+        pand        xmm1,       xmm3
+        pmaddwd     xmm1,       xmm1
+
+        paddd       xmm1,       xmm5
+        movdqa      xmm0,       xmm1
+
+        punpckldq   xmm0,       xmm7
+        punpckhdq   xmm1,       xmm7
+
+        paddd       xmm0,       xmm1
+        movdqa      xmm1,       xmm0
+
+        psrldq      xmm0,       8
+        paddd       xmm0,       xmm1
+
+        movd        rax,        xmm0
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;int vp8_block_error_mmx(short *coeff_ptr,  short *dcoef_ptr)
+global sym(vp8_block_error_mmx)
+sym(vp8_block_error_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov         rsi,        arg(0) ;coeff_ptr
+        pxor        mm7,        mm7
+
+        mov         rdi,        arg(1) ;dcoef_ptr
+        movq        mm3,        [rsi]
+
+        movq        mm4,        [rdi]
+        movq        mm5,        [rsi+8]
+
+        movq        mm6,        [rdi+8]
+        pxor        mm1,        mm1 ; from movd mm1, dc ; dc =0
+
+        movq        mm2,        mm7
+        psubw       mm5,        mm6
+
+        por         mm1,        mm2
+        pmaddwd     mm5,        mm5
+
+        pcmpeqw     mm1,        mm7
+        psubw       mm3,        mm4
+
+        pand        mm1,        mm3
+        pmaddwd     mm1,        mm1
+
+        paddd       mm1,        mm5
+        movq        mm3,        [rsi+16]
+
+        movq        mm4,        [rdi+16]
+        movq        mm5,        [rsi+24]
+
+        movq        mm6,        [rdi+24]
+        psubw       mm5,        mm6
+
+        pmaddwd     mm5,        mm5
+        psubw       mm3,        mm4
+
+        pmaddwd     mm3,        mm3
+        paddd       mm3,        mm5
+
+        paddd       mm1,        mm3
+        movq        mm0,        mm1
+
+        psrlq       mm1,        32
+        paddd       mm0,        mm1
+
+        movd        rax,        mm0
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;int vp8_mbblock_error_mmx_impl(short *coeff_ptr, short *dcoef_ptr, int dc);
+global sym(vp8_mbblock_error_mmx_impl)
+sym(vp8_mbblock_error_mmx_impl):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov         rsi,        arg(0) ;coeff_ptr
+        pxor        mm7,        mm7
+
+        mov         rdi,        arg(1) ;dcoef_ptr
+        pxor        mm2,        mm2
+
+        movd        mm1,        dword ptr arg(2) ;dc
+        por         mm1,        mm2
+
+        pcmpeqw     mm1,        mm7
+        mov         rcx,        16
+
+mberror_loop_mmx:
+        movq        mm3,       [rsi]
+        movq        mm4,       [rdi]
+
+        movq        mm5,       [rsi+8]
+        movq        mm6,       [rdi+8]
+
+
+        psubw       mm5,        mm6
+        pmaddwd     mm5,        mm5
+
+        psubw       mm3,        mm4
+        pand        mm3,        mm1
+
+        pmaddwd     mm3,        mm3
+        paddd       mm2,        mm5
+
+        paddd       mm2,        mm3
+        movq        mm3,       [rsi+16]
+
+        movq        mm4,       [rdi+16]
+        movq        mm5,       [rsi+24]
+
+        movq        mm6,       [rdi+24]
+        psubw       mm5,        mm6
+
+        pmaddwd     mm5,        mm5
+        psubw       mm3,        mm4
+
+        pmaddwd     mm3,        mm3
+        paddd       mm2,        mm5
+
+        paddd       mm2,        mm3
+        add         rsi,        32
+
+        add         rdi,        32
+        sub         rcx,        1
+
+        jnz         mberror_loop_mmx
+
+        movq        mm0,        mm2
+        psrlq       mm2,        32
+
+        paddd       mm0,        mm2
+        movd        rax,        mm0
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;int vp8_mbblock_error_xmm_impl(short *coeff_ptr, short *dcoef_ptr, int dc);
+global sym(vp8_mbblock_error_xmm_impl)
+sym(vp8_mbblock_error_xmm_impl):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov         rsi,        arg(0) ;coeff_ptr
+        pxor        xmm7,       xmm7
+
+        mov         rdi,        arg(1) ;dcoef_ptr
+        pxor        xmm2,       xmm2
+
+        movd        xmm1,       dword ptr arg(2) ;dc
+        por         xmm1,       xmm2
+
+        pcmpeqw     xmm1,       xmm7
+        mov         rcx,        16
+
+mberror_loop:
+        movdqa      xmm3,       [rsi]
+        movdqa      xmm4,       [rdi]
+
+        movdqa      xmm5,       [rsi+16]
+        movdqa      xmm6,       [rdi+16]
+
+
+        psubw       xmm5,       xmm6
+        pmaddwd     xmm5,       xmm5
+
+        psubw       xmm3,       xmm4
+        pand        xmm3,       xmm1
+
+        pmaddwd     xmm3,       xmm3
+        add         rsi,        32
+
+        add         rdi,        32
+
+        sub         rcx,        1
+        paddd       xmm2,       xmm5
+
+        paddd       xmm2,       xmm3
+        jnz         mberror_loop
+
+        movdqa      xmm0,       xmm2
+        punpckldq   xmm0,       xmm7
+
+        punpckhdq   xmm2,       xmm7
+        paddd       xmm0,       xmm2
+
+        movdqa      xmm1,       xmm0
+        psrldq      xmm0,       8
+
+        paddd       xmm0,       xmm1
+        movd        rax,        xmm0
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;int vp8_mbuverror_mmx_impl(short *s_ptr, short *d_ptr);
+global sym(vp8_mbuverror_mmx_impl)
+sym(vp8_mbuverror_mmx_impl):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov             rsi,        arg(0) ;s_ptr
+        mov             rdi,        arg(1) ;d_ptr
+
+        mov             rcx,        16
+        pxor            mm7,        mm7
+
+mbuverror_loop_mmx:
+
+        movq            mm1,        [rsi]
+        movq            mm2,        [rdi]
+
+        psubw           mm1,        mm2
+        pmaddwd         mm1,        mm1
+
+
+        movq            mm3,        [rsi+8]
+        movq            mm4,        [rdi+8]
+
+        psubw           mm3,        mm4
+        pmaddwd         mm3,        mm3
+
+
+        paddd           mm7,        mm1
+        paddd           mm7,        mm3
+
+
+        add             rsi,        16
+        add             rdi,        16
+
+        dec             rcx
+        jnz             mbuverror_loop_mmx
+
+        movq            mm0,        mm7
+        psrlq           mm7,        32
+
+        paddd           mm0,        mm7
+        movd            rax,        mm0
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;int vp8_mbuverror_xmm_impl(short *s_ptr, short *d_ptr);
+global sym(vp8_mbuverror_xmm_impl)
+sym(vp8_mbuverror_xmm_impl):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 2
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov             rsi,        arg(0) ;s_ptr
+        mov             rdi,        arg(1) ;d_ptr
+
+        mov             rcx,        16
+        pxor            xmm7,       xmm7
+
+mbuverror_loop:
+
+        movdqa          xmm1,       [rsi]
+        movdqa          xmm2,       [rdi]
+
+        psubw           xmm1,       xmm2
+        pmaddwd         xmm1,       xmm1
+
+        paddd           xmm7,       xmm1
+
+        add             rsi,        16
+        add             rdi,        16
+
+        dec             rcx
+        jnz             mbuverror_loop
+
+        pxor        xmm0,           xmm0
+        movdqa      xmm1,           xmm7
+
+        movdqa      xmm2,           xmm1
+        punpckldq   xmm1,           xmm0
+
+        punpckhdq   xmm2,           xmm0
+        paddd       xmm1,           xmm2
+
+        movdqa      xmm2,           xmm1
+
+        psrldq      xmm1,           8
+        paddd       xmm1,           xmm2
+
+        movd            rax,            xmm1
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/encoder/x86/fwalsh_sse2.asm b/vp8/encoder/x86/fwalsh_sse2.asm
new file mode 100644
index 0000000..7d86201
--- /dev/null
+++ b/vp8/encoder/x86/fwalsh_sse2.asm
@@ -0,0 +1,117 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_short_walsh4x4_sse2(short *input, short *output, int pitch)
+global sym(vp8_short_walsh4x4_sse2)
+sym(vp8_short_walsh4x4_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 3
+    push        rsi
+    push        rdi
+    ; end prolog
+
+    mov     rsi, arg(0)
+    mov     rdi, arg(1)
+
+    movdqu    xmm4, [rsi + 0]       ;ip[4] ip[0]
+    movdqu    xmm0, [rsi + 16]      ;ip[12] ip[8]
+
+    pxor  xmm7, xmm7
+    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    ; 13 12 11 10 03 02 01 00
+    ;
+    ; 33 32 31 30 23 22 21 20
+    ;
+    movdqa    xmm3, xmm4          ; 13 12 11 10 03 02 01 00
+    punpcklwd xmm4, xmm0          ; 23 03 22 02 21 01 20 00
+    punpckhwd xmm3, xmm0          ; 33 13 32 12 31 11 30 10
+    movdqa    xmm1, xmm4          ; 23 03 22 02 21 01 20 00
+    punpcklwd xmm4, xmm3          ; 31 21 11 01 30 20 10 00
+    punpckhwd xmm1, xmm3          ; 33 23 13 03 32 22 12 02
+    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    pshufd    xmm2, xmm1, 4eh       ;ip[8] ip[12]
+    movdqa    xmm3, xmm4          ;ip[4] ip[0]
+
+    paddw   xmm4, xmm2          ;ip[4]+ip[8] ip[0]+ip[12] aka b1 a1
+    psubw   xmm3, xmm2          ;ip[4]-ip[8] ip[0]-ip[12] aka c1 d1
+
+    movdqa    xmm5, xmm4
+    punpcklqdq  xmm4, xmm3          ;d1 a1
+    punpckhqdq  xmm5, xmm3          ;c1 b1
+
+    movdqa    xmm1, xmm5          ;c1 b1
+    paddw   xmm5, xmm4          ;dl+cl a1+b1 aka op[4] op[0]
+    psubw   xmm4, xmm1          ;d1-c1 a1-b1 aka op[12] op[8]
+    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    ; 13 12 11 10 03 02 01 00
+    ;
+    ; 33 32 31 30 23 22 21 20
+    ;
+    movdqa    xmm0, xmm5          ; 13 12 11 10 03 02 01 00
+    punpcklwd xmm5, xmm4          ; 23 03 22 02 21 01 20 00
+    punpckhwd xmm0, xmm4          ; 33 13 32 12 31 11 30 10
+    movdqa    xmm1, xmm5          ; 23 03 22 02 21 01 20 00
+    punpcklwd xmm5, xmm0          ; 31 21 11 01 30 20 10 00
+    punpckhwd xmm1, xmm0          ; 33 23 13 03 32 22 12 02
+    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    pshufd    xmm2, xmm1, 4eh       ;ip[8] ip[12]
+    movdqa    xmm3, xmm5          ;ip[4] ip[0]
+
+    paddw   xmm5, xmm2          ;ip[4]+ip[8] ip[0]+ip[12] aka b1 a1
+    psubw   xmm3, xmm2          ;ip[4]-ip[8] ip[0]-ip[12] aka c1 d1
+
+    movdqa    xmm6, xmm5
+    punpcklqdq  xmm5, xmm3          ;d1 a1
+    punpckhqdq  xmm6, xmm3          ;c1 b1
+
+    movdqa    xmm1, xmm6          ;c1 b1
+    paddw   xmm6, xmm5          ;dl+cl a1+b1 aka op[4] op[0]
+    psubw   xmm5, xmm1          ;d1-c1 a1-b1 aka op[12] op[8]
+
+    movdqa    xmm0, xmm6          ;aka b2 a2
+    movdqa    xmm1, xmm5          ;aka d2 c2
+
+    pcmpgtw   xmm0, xmm7
+    pcmpgtw   xmm1, xmm7
+
+    psrlw   xmm0, 15
+    psrlw   xmm1, 15
+
+    paddw   xmm6, xmm0
+    paddw   xmm5, xmm1
+
+    psraw   xmm6, 1
+    psraw   xmm5, 1
+
+    ;   a2 = a1 + b1;
+    ;   b2 = c1 + d1;
+    ;   c2 = a1 - b1;
+    ;   d2 = d1 - c1;
+    ;        a2 += (a2>0);
+    ;        b2 += (b2>0);
+    ;        c2 += (c2>0);
+    ;        d2 += (d2>0);
+    ;   op[0] = (a2)>>1;
+    ;   op[4] = (b2)>>1;
+    ;   op[8] = (c2)>>1;
+    ;   op[12]= (d2)>>1;
+
+    movdqu  [rdi + 0], xmm6
+    movdqu  [rdi + 16], xmm5
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/encoder/x86/mcomp_x86.h b/vp8/encoder/x86/mcomp_x86.h
new file mode 100644
index 0000000..5661491
--- /dev/null
+++ b/vp8/encoder/x86/mcomp_x86.h
@@ -0,0 +1,27 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef MCOMP_X86_H
+#define MCOMP_X86_H
+
+#if HAVE_SSE3
+#if !CONFIG_RUNTIME_CPU_DETECT
+
+#undef  vp8_search_full_search
+#define vp8_search_full_search vp8_full_search_sadx3
+
+#undef  vp8_search_diamond_search
+#define vp8_search_diamond_search vp8_diamond_search_sadx4
+
+#endif
+#endif
+
+#endif
+
diff --git a/vp8/encoder/x86/preproc_mmx.c b/vp8/encoder/x86/preproc_mmx.c
new file mode 100644
index 0000000..69617ca
--- /dev/null
+++ b/vp8/encoder/x86/preproc_mmx.c
@@ -0,0 +1,297 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "memory.h"
+#include "preproc.h"
+#include "pragmas.h"
+
+/****************************************************************************
+*  Macros
+****************************************************************************/
+#define FRAMECOUNT 7
+#define ROUNDUP32(X) ( ( ( (unsigned long) X ) + 31 )&( 0xFFFFFFE0 ) )
+
+/****************************************************************************
+*  Imports
+****************************************************************************/
+extern void vpx_get_processor_flags(int *mmx_enabled, int *xmm_enabled, int *wmt_enabled);
+
+/****************************************************************************
+*  Exported Global Variables
+****************************************************************************/
+void (*temp_filter)(pre_proc_instance *ppi, unsigned char *s, unsigned char *d, int bytes, int strength);
+
+/****************************************************************************
+ *
+ *  ROUTINE       : temp_filter_wmt
+ *
+ *  INPUTS        : pre_proc_instance *ppi : Pointer to pre-processor instance.
+ *                  unsigned char *s     : Pointer to source frame.
+ *                  unsigned char *d     : Pointer to destination frame.
+ *                  int bytes            : Number of bytes to filter.
+ *                  int strength         : Strength of filter to apply.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Performs a closesness adjusted temporarl blur
+ *
+ *  SPECIAL NOTES : Destination frame can be same as source frame.
+ *
+ ****************************************************************************/
+void temp_filter_wmt
+(
+    pre_proc_instance *ppi,
+    unsigned char *s,
+    unsigned char *d,
+    int bytes,
+    int strength
+)
+{
+    int byte = 0;
+    unsigned char *frameptr = ppi->frame_buffer;
+
+    __declspec(align(16)) unsigned short threes[]  = { 3, 3, 3, 3, 3, 3, 3, 3};
+    __declspec(align(16)) unsigned short sixteens[] = {16, 16, 16, 16, 16, 16, 16, 16};
+
+    if (ppi->frame == 0)
+    {
+        do
+        {
+            int i;
+            int frame = 0;
+
+            do
+            {
+                for (i = 0; i < 8; i++)
+                {
+                    *frameptr = s[byte+i];
+                    ++frameptr;
+                }
+
+                ++frame;
+            }
+            while (frame < FRAMECOUNT);
+
+            for (i = 0; i < 8; i++)
+                d[byte+i] = s[byte+i];
+
+            byte += 8;
+
+        }
+        while (byte < bytes);
+    }
+    else
+    {
+        int i;
+        int offset2 = (ppi->frame % FRAMECOUNT);
+
+        do
+        {
+            __declspec(align(16)) unsigned short counts[8];
+            __declspec(align(16)) unsigned short sums[8];
+            __asm
+            {
+                mov         eax, offset2
+                mov         edi, s                  // source pixels
+                pxor        xmm1, xmm1              // accumulator
+
+                pxor        xmm7, xmm7
+
+                mov         esi, frameptr           // accumulator
+                pxor        xmm2, xmm2              // count
+
+                movq        xmm3, QWORD PTR [edi]
+
+                movq        QWORD PTR [esi+8*eax], xmm3
+
+                punpcklbw   xmm3, xmm2              // xmm3 source pixels
+                mov         ecx,  FRAMECOUNT
+
+                next_frame:
+                movq        xmm4, QWORD PTR [esi]   // get frame buffer values
+                punpcklbw   xmm4, xmm7              // xmm4 frame buffer pixels
+                movdqa      xmm6, xmm4              // save the pixel values
+                psubsw      xmm4, xmm3              // subtracted pixel values
+                pmullw      xmm4, xmm4              // square xmm4
+                movd        xmm5, strength
+                psrlw       xmm4, xmm5              // should be strength
+                pmullw      xmm4, threes            // 3 * modifier
+                movdqa      xmm5, sixteens          // 16s
+                psubusw     xmm5, xmm4              // 16 - modifiers
+                movdqa      xmm4, xmm5              // save the modifiers
+                pmullw      xmm4, xmm6              // multiplier values
+                paddusw     xmm1, xmm4              // accumulator
+                paddusw     xmm2, xmm5              // count
+                add         esi, 8                  // next frame
+                dec         ecx                     // next set of eight pixels
+                jnz         next_frame
+
+                movdqa      counts, xmm2
+                psrlw       xmm2, 1                 // divide count by 2 for rounding
+                paddusw     xmm1, xmm2              // rounding added in
+
+                mov         frameptr, esi
+
+                movdqa      sums, xmm1
+            }
+
+            for (i = 0; i < 8; i++)
+            {
+                int blurvalue = sums[i] * ppi->fixed_divide[counts[i]];
+                blurvalue >>= 16;
+                d[i] = blurvalue;
+            }
+
+            s += 8;
+            d += 8;
+            byte += 8;
+        }
+        while (byte < bytes);
+    }
+
+    ++ppi->frame;
+    __asm emms
+}
+
+/****************************************************************************
+ *
+ *  ROUTINE       : temp_filter_mmx
+ *
+ *  INPUTS        : pre_proc_instance *ppi : Pointer to pre-processor instance.
+ *                  unsigned char *s     : Pointer to source frame.
+ *                  unsigned char *d     : Pointer to destination frame.
+ *                  int bytes            : Number of bytes to filter.
+ *                  int strength         : Strength of filter to apply.
+ *
+ *  OUTPUTS       : None.
+ *
+ *  RETURNS       : void
+ *
+ *  FUNCTION      : Performs a closesness adjusted temporarl blur
+ *
+ *  SPECIAL NOTES : Destination frame can be same as source frame.
+ *
+ ****************************************************************************/
+void temp_filter_mmx
+(
+    pre_proc_instance *ppi,
+    unsigned char *s,
+    unsigned char *d,
+    int bytes,
+    int strength
+)
+{
+    int byte = 0;
+    unsigned char *frameptr = ppi->frame_buffer;
+
+    __declspec(align(16)) unsigned short threes[]  = { 3, 3, 3, 3};
+    __declspec(align(16)) unsigned short sixteens[] = {16, 16, 16, 16};
+
+    if (ppi->frame == 0)
+    {
+        do
+        {
+            int i;
+            int frame = 0;
+
+            do
+            {
+                for (i = 0; i < 4; i++)
+                {
+                    *frameptr = s[byte+i];
+                    ++frameptr;
+                }
+
+                ++frame;
+            }
+            while (frame < FRAMECOUNT);
+
+            for (i = 0; i < 4; i++)
+                d[byte+i] = s[byte+i];
+
+            byte += 4;
+
+        }
+        while (byte < bytes);
+    }
+    else
+    {
+        int i;
+        int offset2 = (ppi->frame % FRAMECOUNT);
+
+        do
+        {
+            __declspec(align(16)) unsigned short counts[8];
+            __declspec(align(16)) unsigned short sums[8];
+            __asm
+            {
+
+                mov         eax, offset2
+                mov         edi, s                  // source pixels
+                pxor        mm1, mm1                // accumulator
+                pxor        mm7, mm7
+
+                mov         esi, frameptr           // accumulator
+                pxor        mm2, mm2                // count
+
+                movd        mm3, DWORD PTR [edi]
+                movd        DWORD PTR [esi+4*eax], mm3
+
+                punpcklbw   mm3, mm2                // mm3 source pixels
+                mov         ecx,  FRAMECOUNT
+
+                next_frame:
+                movd        mm4, DWORD PTR [esi]    // get frame buffer values
+                punpcklbw   mm4, mm7                // mm4 frame buffer pixels
+                movq        mm6, mm4                // save the pixel values
+                psubsw      mm4, mm3                // subtracted pixel values
+                pmullw      mm4, mm4                // square mm4
+                movd        mm5, strength
+                psrlw       mm4, mm5                // should be strength
+                pmullw      mm4, threes             // 3 * modifier
+                movq        mm5, sixteens           // 16s
+                psubusw     mm5, mm4                // 16 - modifiers
+                movq        mm4, mm5                // save the modifiers
+                pmullw      mm4, mm6                // multiplier values
+                paddusw     mm1, mm4                // accumulator
+                paddusw     mm2, mm5                // count
+                add         esi, 4                  // next frame
+                dec         ecx                     // next set of eight pixels
+                jnz         next_frame
+
+                movq        counts, mm2
+                psrlw       mm2, 1                  // divide count by 2 for rounding
+                paddusw     mm1, mm2                // rounding added in
+
+                mov         frameptr, esi
+
+                movq        sums, mm1
+
+            }
+
+            for (i = 0; i < 4; i++)
+            {
+                int blurvalue = sums[i] * ppi->fixed_divide[counts[i]];
+                blurvalue >>= 16;
+                d[i] = blurvalue;
+            }
+
+            s += 4;
+            d += 4;
+            byte += 4;
+        }
+        while (byte < bytes);
+    }
+
+    ++ppi->frame;
+    __asm emms
+}
diff --git a/vp8/encoder/x86/quantize_mmx.asm b/vp8/encoder/x86/quantize_mmx.asm
new file mode 100644
index 0000000..847fc6e
--- /dev/null
+++ b/vp8/encoder/x86/quantize_mmx.asm
@@ -0,0 +1,438 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;int vp8_fast_quantize_b_impl_mmx(short *coeff_ptr, short *zbin_ptr,
+;                           short *qcoeff_ptr,short *dequant_ptr,
+;                           short *scan_mask, short *round_ptr,
+;                           short *quant_ptr, short *dqcoeff_ptr);
+global sym(vp8_fast_quantize_b_impl_mmx)
+sym(vp8_fast_quantize_b_impl_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov             rsi,        arg(0) ;coeff_ptr
+        movq            mm0,        [rsi]
+
+        mov             rax,        arg(1) ;zbin_ptr
+        movq            mm1,        [rax]
+
+        movq            mm3,        mm0
+        psraw           mm0,        15
+
+        pxor            mm3,        mm0
+        psubw           mm3,        mm0         ; abs
+
+        movq            mm2,        mm3
+        pcmpgtw         mm1,        mm2
+
+        pandn           mm1,        mm2
+        movq            mm3,        mm1
+
+        mov             rdx,        arg(6) ;quant_ptr
+        movq            mm1,        [rdx]
+
+        mov             rcx,        arg(5) ;round_ptr
+        movq            mm2,        [rcx]
+
+        paddw           mm3,        mm2
+        pmulhuw         mm3,        mm1
+
+        pxor            mm3,        mm0
+        psubw           mm3,        mm0     ;gain the sign back
+
+        mov             rdi,        arg(2) ;qcoeff_ptr
+        movq            mm0,        mm3
+
+        movq            [rdi],      mm3
+
+        mov             rax,        arg(3) ;dequant_ptr
+        movq            mm2,        [rax]
+
+        pmullw          mm3,        mm2
+        mov             rax,        arg(7) ;dqcoeff_ptr
+
+        movq            [rax],      mm3
+
+        ; next 8
+        movq            mm4,        [rsi+8]
+
+        mov             rax,        arg(1) ;zbin_ptr
+        movq            mm5,        [rax+8]
+
+        movq            mm7,        mm4
+        psraw           mm4,        15
+
+        pxor            mm7,        mm4
+        psubw           mm7,        mm4         ; abs
+
+        movq            mm6,        mm7
+        pcmpgtw         mm5,        mm6
+
+        pandn           mm5,        mm6
+        movq            mm7,        mm5
+
+        movq            mm5,        [rdx+8]
+        movq            mm6,        [rcx+8]
+
+        paddw           mm7,        mm6
+        pmulhuw         mm7,        mm5
+
+        pxor            mm7,        mm4
+        psubw           mm7,        mm4;gain the sign back
+
+        mov             rdi,        arg(2) ;qcoeff_ptr
+
+        movq            mm1,        mm7
+        movq            [rdi+8],    mm7
+
+        mov             rax,        arg(3) ;dequant_ptr
+        movq            mm6,        [rax+8]
+
+        pmullw          mm7,        mm6
+        mov             rax,        arg(7) ;dqcoeff_ptr
+
+        movq            [rax+8],    mm7
+
+
+                ; next 8
+        movq            mm4,        [rsi+16]
+
+        mov             rax,        arg(1) ;zbin_ptr
+        movq            mm5,        [rax+16]
+
+        movq            mm7,        mm4
+        psraw           mm4,        15
+
+        pxor            mm7,        mm4
+        psubw           mm7,        mm4         ; abs
+
+        movq            mm6,        mm7
+        pcmpgtw         mm5,        mm6
+
+        pandn           mm5,        mm6
+        movq            mm7,        mm5
+
+        movq            mm5,        [rdx+16]
+        movq            mm6,        [rcx+16]
+
+        paddw           mm7,        mm6
+        pmulhuw         mm7,        mm5
+
+        pxor            mm7,        mm4
+        psubw           mm7,        mm4;gain the sign back
+
+        mov             rdi,        arg(2) ;qcoeff_ptr
+
+        movq            mm1,        mm7
+        movq            [rdi+16],   mm7
+
+        mov             rax,        arg(3) ;dequant_ptr
+        movq            mm6,        [rax+16]
+
+        pmullw          mm7,        mm6
+        mov             rax,        arg(7) ;dqcoeff_ptr
+
+        movq            [rax+16],   mm7
+
+
+                ; next 8
+        movq            mm4,        [rsi+24]
+
+        mov             rax,        arg(1) ;zbin_ptr
+        movq            mm5,        [rax+24]
+
+        movq            mm7,        mm4
+        psraw           mm4,        15
+
+        pxor            mm7,        mm4
+        psubw           mm7,        mm4         ; abs
+
+        movq            mm6,        mm7
+        pcmpgtw         mm5,        mm6
+
+        pandn           mm5,        mm6
+        movq            mm7,        mm5
+
+        movq            mm5,        [rdx+24]
+        movq            mm6,        [rcx+24]
+
+        paddw           mm7,        mm6
+        pmulhuw         mm7,        mm5
+
+        pxor            mm7,        mm4
+        psubw           mm7,        mm4;gain the sign back
+
+        mov             rdi,        arg(2) ;qcoeff_ptr
+
+        movq            mm1,        mm7
+        movq            [rdi+24],   mm7
+
+        mov             rax,        arg(3) ;dequant_ptr
+        movq            mm6,        [rax+24]
+
+        pmullw          mm7,        mm6
+        mov             rax,        arg(7) ;dqcoeff_ptr
+
+        movq            [rax+24],   mm7
+
+
+
+        mov             rdi,        arg(4) ;scan_mask
+        mov             rsi,        arg(2) ;qcoeff_ptr
+
+        pxor            mm5,        mm5
+        pxor            mm7,        mm7
+
+        movq            mm0,        [rsi]
+        movq            mm1,        [rsi+8]
+
+        movq            mm2,        [rdi]
+        movq            mm3,        [rdi+8];
+
+        pcmpeqw         mm0,        mm7
+        pcmpeqw         mm1,        mm7
+
+        pcmpeqw         mm6,        mm6
+        pxor            mm0,        mm6
+
+        pxor            mm1,        mm6
+        psrlw           mm0,        15
+
+        psrlw           mm1,        15
+        pmaddwd         mm0,        mm2
+
+        pmaddwd         mm1,        mm3
+        movq            mm5,        mm0
+
+        paddd           mm5,        mm1
+
+        movq            mm0,        [rsi+16]
+        movq            mm1,        [rsi+24]
+
+        movq            mm2,        [rdi+16]
+        movq            mm3,        [rdi+24];
+
+        pcmpeqw         mm0,        mm7
+        pcmpeqw         mm1,        mm7
+
+        pcmpeqw         mm6,        mm6
+        pxor            mm0,        mm6
+
+        pxor            mm1,        mm6
+        psrlw           mm0,        15
+
+        psrlw           mm1,        15
+        pmaddwd         mm0,        mm2
+
+        pmaddwd         mm1,        mm3
+        paddd           mm5,        mm0
+
+        paddd           mm5,        mm1
+        movq            mm0,        mm5
+
+        psrlq           mm5,        32
+        paddd           mm0,        mm5
+
+        ; eob adjustment begins here
+        movd            rcx,        mm0
+        and             rcx,        0xffff
+
+        xor             rdx,        rdx
+        sub             rdx,        rcx ; rdx=-rcx
+
+        bsr             rax,        rcx
+        inc             rax
+
+        sar             rdx,        31
+        and             rax,        rdx
+        ; Substitute the sse assembly for the old mmx mixed assembly/C. The
+        ; following is kept as reference
+        ;    movd            rcx,        mm0
+        ;    bsr             rax,        rcx
+        ;
+        ;    mov             eob,        rax
+        ;    mov             eee,        rcx
+        ;
+        ;if(eee==0)
+        ;{
+        ;    eob=-1;
+        ;}
+        ;else if(eee<0)
+        ;{
+        ;    eob=15;
+        ;}
+        ;d->eob = eob+1;
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;int vp8_fast_quantize_b_impl_sse(short *coeff_ptr, short *zbin_ptr,
+;                           short *qcoeff_ptr,short *dequant_ptr,
+;                           short *scan_mask, short *round_ptr,
+;                           short *quant_ptr, short *dqcoeff_ptr);
+global sym(vp8_fast_quantize_b_impl_sse)
+sym(vp8_fast_quantize_b_impl_sse):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov             rsi,        arg(0) ;coeff_ptr
+        movdqa          xmm0,       [rsi]
+
+        mov             rax,        arg(1) ;zbin_ptr
+        movdqa          xmm1,       [rax]
+
+        movdqa          xmm3,       xmm0
+        psraw           xmm0,       15
+
+        pxor            xmm3,       xmm0
+        psubw           xmm3,       xmm0            ; abs
+
+        movdqa          xmm2,       xmm3
+        pcmpgtw         xmm1,       xmm2
+
+        pandn           xmm1,       xmm2
+        movdqa          xmm3,       xmm1
+
+        mov             rdx,        arg(6) ; quant_ptr
+        movdqa          xmm1,       [rdx]
+
+        mov             rcx,        arg(5) ; round_ptr
+        movdqa          xmm2,       [rcx]
+
+        paddw           xmm3,       xmm2
+        pmulhuw         xmm3,       xmm1
+
+        pxor            xmm3,       xmm0
+        psubw           xmm3,       xmm0        ;gain the sign back
+
+        mov             rdi,        arg(2) ;qcoeff_ptr
+        movdqa          xmm0,       xmm3
+
+        movdqa          [rdi],      xmm3
+
+        mov             rax,        arg(3) ;dequant_ptr
+        movdqa          xmm2,       [rax]
+
+        pmullw          xmm3,       xmm2
+        mov             rax,        arg(7) ;dqcoeff_ptr
+
+        movdqa          [rax],      xmm3
+
+        ; next 8
+        movdqa          xmm4,       [rsi+16]
+
+        mov             rax,        arg(1) ;zbin_ptr
+        movdqa          xmm5,       [rax+16]
+
+        movdqa          xmm7,       xmm4
+        psraw           xmm4,       15
+
+        pxor            xmm7,       xmm4
+        psubw           xmm7,       xmm4            ; abs
+
+        movdqa          xmm6,       xmm7
+        pcmpgtw         xmm5,       xmm6
+
+        pandn           xmm5,       xmm6
+        movdqa          xmm7,       xmm5
+
+        movdqa          xmm5,       [rdx+16]
+        movdqa          xmm6,       [rcx+16]
+
+
+        paddw           xmm7,       xmm6
+        pmulhuw         xmm7,       xmm5
+
+        pxor            xmm7,       xmm4
+        psubw           xmm7,       xmm4;gain the sign back
+
+        mov             rdi,        arg(2) ;qcoeff_ptr
+
+        movdqa          xmm1,       xmm7
+        movdqa          [rdi+16],   xmm7
+
+        mov             rax,        arg(3) ;dequant_ptr
+        movdqa          xmm6,       [rax+16]
+
+        pmullw          xmm7,       xmm6
+        mov             rax,        arg(7) ;dqcoeff_ptr
+
+        movdqa          [rax+16],   xmm7
+        mov             rdi,        arg(4) ;scan_mask
+
+        pxor            xmm7,       xmm7
+        movdqa          xmm2,       [rdi]
+
+        movdqa          xmm3,       [rdi+16];
+        pcmpeqw         xmm0,       xmm7
+
+        pcmpeqw         xmm1,       xmm7
+        pcmpeqw         xmm6,       xmm6
+
+        pxor            xmm0,       xmm6
+        pxor            xmm1,       xmm6
+
+        psrlw           xmm0,       15
+        psrlw           xmm1,       15
+
+        pmaddwd         xmm0,       xmm2
+        pmaddwd         xmm1,       xmm3
+
+        movq            xmm2,       xmm0
+        movq            xmm3,       xmm1
+
+        psrldq          xmm0,       8
+        psrldq          xmm1,       8
+
+        paddd           xmm0,       xmm1
+        paddd           xmm2,       xmm3
+
+        paddd           xmm0,       xmm2
+        movq            xmm1,       xmm0
+
+        psrldq          xmm0,       4
+        paddd           xmm1,       xmm0
+
+        movd            rcx,        xmm1
+        and             rcx,        0xffff
+
+        xor             rdx,        rdx
+        sub             rdx,        rcx
+
+        bsr             rax,        rcx
+        inc             rax
+
+        sar             rdx,        31
+        and             rax,        rdx
+
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/encoder/x86/sad_mmx.asm b/vp8/encoder/x86/sad_mmx.asm
new file mode 100644
index 0000000..a825698
--- /dev/null
+++ b/vp8/encoder/x86/sad_mmx.asm
@@ -0,0 +1,428 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+global sym(vp8_sad16x16_mmx)
+global sym(vp8_sad8x16_mmx)
+global sym(vp8_sad8x8_mmx)
+global sym(vp8_sad4x4_mmx)
+global sym(vp8_sad16x8_mmx)
+
+%idefine QWORD
+
+;unsigned int vp8_sad16x16_mmx(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+sym(vp8_sad16x16_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rax*8]
+
+        lea             rcx,        [rcx+rax*8]
+        pxor            mm7,        mm7
+
+        pxor            mm6,        mm6
+
+x16x16sad_mmx_loop:
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm2,        QWORD PTR [rsi+8]
+
+        movq            mm1,        QWORD PTR [rdi]
+        movq            mm3,        QWORD PTR [rdi+8]
+
+        movq            mm4,        mm0
+        movq            mm5,        mm2
+
+        psubusb         mm0,        mm1
+        psubusb         mm1,        mm4
+
+        psubusb         mm2,        mm3
+        psubusb         mm3,        mm5
+
+        por             mm0,        mm1
+        por             mm2,        mm3
+
+        movq            mm1,        mm0
+        movq            mm3,        mm2
+
+        punpcklbw       mm0,        mm6
+        punpcklbw       mm2,        mm6
+
+        punpckhbw       mm1,        mm6
+        punpckhbw       mm3,        mm6
+
+        paddw           mm0,        mm2
+        paddw           mm1,        mm3
+
+
+        lea             rsi,        [rsi+rax]
+        add             rdi,        rdx
+
+        paddw           mm7,        mm0
+        paddw           mm7,        mm1
+
+        cmp             rsi,        rcx
+        jne             x16x16sad_mmx_loop
+
+
+        movq            mm0,        mm7
+
+        punpcklwd       mm0,        mm6
+        punpckhwd       mm7,        mm6
+
+        paddw           mm0,        mm7
+        movq            mm7,        mm0
+
+
+        psrlq           mm0,        32
+        paddw           mm7,        mm0
+
+        movd            rax,        mm7
+
+    pop rdi
+    pop rsi
+    mov rsp, rbp
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_sad8x16_mmx(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+sym(vp8_sad8x16_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rax*8]
+
+        lea             rcx,        [rcx+rax*8]
+        pxor            mm7,        mm7
+
+        pxor            mm6,        mm6
+
+x8x16sad_mmx_loop:
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm1,        QWORD PTR [rdi]
+
+        movq            mm2,        mm0
+        psubusb         mm0,        mm1
+
+        psubusb         mm1,        mm2
+        por             mm0,        mm1
+
+        movq            mm2,        mm0
+        punpcklbw       mm0,        mm6
+
+        punpckhbw       mm2,        mm6
+        lea             rsi,        [rsi+rax]
+
+        add             rdi,        rdx
+        paddw           mm7,        mm0
+
+        paddw           mm7,        mm2
+        cmp             rsi,        rcx
+
+        jne             x8x16sad_mmx_loop
+
+        movq            mm0,        mm7
+        punpcklwd       mm0,        mm6
+
+        punpckhwd       mm7,        mm6
+        paddw           mm0,        mm7
+
+        movq            mm7,        mm0
+        psrlq           mm0,        32
+
+        paddw           mm7,        mm0
+        movd            rax,        mm7
+
+    pop rdi
+    pop rsi
+    mov rsp, rbp
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_sad8x8_mmx(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+sym(vp8_sad8x8_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rax*8]
+        pxor            mm7,        mm7
+
+        pxor            mm6,        mm6
+
+x8x8sad_mmx_loop:
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm1,        QWORD PTR [rdi]
+
+        movq            mm2,        mm0
+        psubusb         mm0,        mm1
+
+        psubusb         mm1,        mm2
+        por             mm0,        mm1
+
+        movq            mm2,        mm0
+        punpcklbw       mm0,        mm6
+
+        punpckhbw       mm2,        mm6
+        paddw           mm0,        mm2
+
+        lea             rsi,       [rsi+rax]
+        add             rdi,        rdx
+
+        paddw           mm7,       mm0
+        cmp             rsi,        rcx
+
+        jne             x8x8sad_mmx_loop
+
+        movq            mm0,        mm7
+        punpcklwd       mm0,        mm6
+
+        punpckhwd       mm7,        mm6
+        paddw           mm0,        mm7
+
+        movq            mm7,        mm0
+        psrlq           mm0,        32
+
+        paddw           mm7,        mm0
+        movd            rax,        mm7
+
+    pop rdi
+    pop rsi
+    mov rsp, rbp
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_sad4x4_mmx(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+sym(vp8_sad4x4_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        movd            mm0,       QWORD PTR [rsi]
+        movd            mm1,       QWORD PTR [rdi]
+
+        movd            mm2,       QWORD PTR [rsi+rax]
+        movd            mm3,       QWORD PTR [rdi+rdx]
+
+        punpcklbw       mm0,        mm2
+        punpcklbw       mm1,        mm3
+
+        movq            mm2,        mm0
+        psubusb         mm0,        mm1
+
+        psubusb         mm1,        mm2
+        por             mm0,        mm1
+
+        movq            mm2,        mm0
+        pxor            mm3,        mm3
+
+        punpcklbw       mm0,        mm3
+        punpckhbw       mm2,        mm3
+
+        paddw           mm0,        mm2
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        movd            mm4,       QWORD PTR [rsi]
+        movd            mm5,       QWORD PTR [rdi]
+
+        movd            mm6,       QWORD PTR [rsi+rax]
+        movd            mm7,       QWORD PTR [rdi+rdx]
+
+        punpcklbw       mm4,        mm6
+        punpcklbw       mm5,        mm7
+
+        movq            mm6,        mm4
+        psubusb         mm4,        mm5
+
+        psubusb         mm5,        mm6
+        por             mm4,        mm5
+
+        movq            mm5,        mm4
+        punpcklbw       mm4,        mm3
+
+        punpckhbw       mm5,        mm3
+        paddw           mm4,        mm5
+
+        paddw           mm0,        mm4
+        movq            mm1,        mm0
+
+        punpcklwd       mm0,        mm3
+        punpckhwd       mm1,        mm3
+
+        paddw           mm0,        mm1
+        movq            mm1,        mm0
+
+        psrlq           mm0,        32
+        paddw           mm0,        mm1
+
+        movd            rax,        mm0
+
+    pop rdi
+    pop rsi
+    mov rsp, rbp
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_sad16x8_mmx(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+sym(vp8_sad16x8_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rax*8]
+        pxor            mm7,        mm7
+
+        pxor            mm6,        mm6
+
+x16x8sad_mmx_loop:
+
+        movq            mm0,       [rsi]
+        movq            mm1,       [rdi]
+
+        movq            mm2,        [rsi+8]
+        movq            mm3,        [rdi+8]
+
+        movq            mm4,        mm0
+        movq            mm5,        mm2
+
+        psubusb         mm0,        mm1
+        psubusb         mm1,        mm4
+
+        psubusb         mm2,        mm3
+        psubusb         mm3,        mm5
+
+        por             mm0,        mm1
+        por             mm2,        mm3
+
+        movq            mm1,        mm0
+        movq            mm3,        mm2
+
+        punpcklbw       mm0,        mm6
+        punpckhbw       mm1,        mm6
+
+        punpcklbw       mm2,        mm6
+        punpckhbw       mm3,        mm6
+
+
+        paddw           mm0,        mm2
+        paddw           mm1,        mm3
+
+        paddw           mm0,        mm1
+        lea             rsi,        [rsi+rax]
+
+        add             rdi,        rdx
+        paddw           mm7,        mm0
+
+        cmp             rsi,        rcx
+        jne             x16x8sad_mmx_loop
+
+        movq            mm0,        mm7
+        punpcklwd       mm0,        mm6
+
+        punpckhwd       mm7,        mm6
+        paddw           mm0,        mm7
+
+        movq            mm7,        mm0
+        psrlq           mm0,        32
+
+        paddw           mm7,        mm0
+        movd            rax,        mm7
+
+    pop rdi
+    pop rsi
+    mov rsp, rbp
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/encoder/x86/sad_sse2.asm b/vp8/encoder/x86/sad_sse2.asm
new file mode 100644
index 0000000..53240bb
--- /dev/null
+++ b/vp8/encoder/x86/sad_sse2.asm
@@ -0,0 +1,329 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%idefine QWORD
+
+;unsigned int vp8_sad16x16_wmt(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+global sym(vp8_sad16x16_wmt)
+sym(vp8_sad16x16_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rax*8]
+
+        lea             rcx,        [rcx+rax*8]
+        pxor            xmm7,       xmm7
+
+x16x16sad_wmt_loop:
+
+        movq            xmm0,       QWORD PTR [rsi]
+        movq            xmm2,       QWORD PTR [rsi+8]
+
+        movq            xmm1,       QWORD PTR [rdi]
+        movq            xmm3,       QWORD PTR [rdi+8]
+
+        movq            xmm4,       QWORD PTR [rsi+rax]
+        movq            xmm5,       QWORD PTR [rdi+rdx]
+
+
+        punpcklbw       xmm0,       xmm2
+        punpcklbw       xmm1,       xmm3
+
+        psadbw          xmm0,       xmm1
+        movq            xmm6,       QWORD PTR [rsi+rax+8]
+
+        movq            xmm3,       QWORD PTR [rdi+rdx+8]
+        lea             rsi,        [rsi+rax*2]
+
+        lea             rdi,        [rdi+rdx*2]
+        punpcklbw       xmm4,       xmm6
+
+        punpcklbw       xmm5,       xmm3
+        psadbw          xmm4,       xmm5
+
+        paddw           xmm7,       xmm0
+        paddw           xmm7,       xmm4
+
+        cmp             rsi,        rcx
+        jne             x16x16sad_wmt_loop
+
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            rax,        xmm0
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;unsigned int vp8_sad8x16_wmt(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  max_err)
+global sym(vp8_sad8x16_wmt)
+sym(vp8_sad8x16_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rbx,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rbx*8]
+
+        lea             rcx,        [rcx+rbx*8]
+        pxor            mm7,        mm7
+
+x8x16sad_wmt_loop:
+
+        movd            rax,        mm7
+        cmp             rax,        arg(4)
+        jg              x8x16sad_wmt_early_exit
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm1,        QWORD PTR [rdi]
+
+        movq            mm2,        QWORD PTR [rsi+rbx]
+        movq            mm3,        QWORD PTR [rdi+rdx]
+
+        psadbw          mm0,        mm1
+        psadbw          mm2,        mm3
+
+        lea             rsi,        [rsi+rbx*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        paddw           mm7,        mm0
+        paddw           mm7,        mm2
+
+        cmp             rsi,        rcx
+        jne             x8x16sad_wmt_loop
+
+        movd            rax,        mm7
+
+x8x16sad_wmt_early_exit:
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    pop         rbx
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_sad8x8_wmt(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+global sym(vp8_sad8x8_wmt)
+sym(vp8_sad8x8_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rbx,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rbx*8]
+        pxor            mm7,        mm7
+
+x8x8sad_wmt_loop:
+
+        movd            rax,        mm7
+        cmp             rax,        arg(4)
+        jg              x8x8sad_wmt_early_exit
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm1,        QWORD PTR [rdi]
+
+        psadbw          mm0,        mm1
+        lea             rsi,        [rsi+rbx]
+
+        add             rdi,        rdx
+        paddw           mm7,        mm0
+
+        cmp             rsi,        rcx
+        jne             x8x8sad_wmt_loop
+
+        movd            rax,        mm7
+x8x8sad_wmt_early_exit:
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    pop         rbx
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;unsigned int vp8_sad4x4_wmt(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+global sym(vp8_sad4x4_wmt)
+sym(vp8_sad4x4_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        movd            mm0,       QWORD PTR [rsi]
+        movd            mm1,       QWORD PTR [rdi]
+
+        movd            mm2,       QWORD PTR [rsi+rax]
+        movd            mm3,       QWORD PTR [rdi+rdx]
+
+        punpcklbw       mm0,        mm2
+        punpcklbw       mm1,        mm3
+
+        psadbw          mm0,        mm1
+        lea             rsi,        [rsi+rax*2]
+
+        lea             rdi,        [rdi+rdx*2]
+        movd            mm4,       QWORD PTR [rsi]
+
+        movd            mm5,       QWORD PTR [rdi]
+        movd            mm6,       QWORD PTR [rsi+rax]
+
+        movd            mm7,       QWORD PTR [rdi+rdx]
+        punpcklbw       mm4,        mm6
+
+        punpcklbw       mm5,        mm7
+        psadbw          mm4,        mm5
+
+        paddw           mm0,        mm4
+        movd            rax,        mm0
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_sad16x8_wmt(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride)
+global sym(vp8_sad16x8_wmt)
+sym(vp8_sad16x8_wmt):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rbx,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rbx*8]
+        pxor            mm7,        mm7
+
+x16x8sad_wmt_loop:
+
+        movd            rax,        mm7
+        cmp             rax,        arg(4)
+        jg              x16x8sad_wmt_early_exit
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm2,        QWORD PTR [rsi+8]
+
+        movq            mm1,        QWORD PTR [rdi]
+        movq            mm3,        QWORD PTR [rdi+8]
+
+        movq            mm4,        QWORD PTR [rsi+rbx]
+        movq            mm5,        QWORD PTR [rdi+rdx]
+
+        psadbw          mm0,        mm1
+        psadbw          mm2,        mm3
+
+        movq            mm1,        QWORD PTR [rsi+rbx+8]
+        movq            mm3,        QWORD PTR [rdi+rdx+8]
+
+        psadbw          mm4,        mm5
+        psadbw          mm1,        mm3
+
+        lea             rsi,        [rsi+rbx*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        paddw           mm0,        mm2
+        paddw           mm4,        mm1
+
+        paddw           mm7,        mm0
+        paddw           mm7,        mm4
+
+        cmp             rsi,        rcx
+        jne             x16x8sad_wmt_loop
+
+        movd            rax,        mm7
+
+x16x8sad_wmt_early_exit:
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    pop         rbx
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/encoder/x86/sad_sse3.asm b/vp8/encoder/x86/sad_sse3.asm
new file mode 100644
index 0000000..38cc029
--- /dev/null
+++ b/vp8/encoder/x86/sad_sse3.asm
@@ -0,0 +1,939 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%idefine QWORD
+
+%macro PROCESS_16X2X3 1
+%if %1
+        movdqa          xmm0,       [rsi]
+        lddqu           xmm5,       [rdi]
+        lddqu           xmm6,       [rdi+1]
+        lddqu           xmm7,       [rdi+2]
+
+        psadbw          xmm5,       xmm0
+        psadbw          xmm6,       xmm0
+        psadbw          xmm7,       xmm0
+%else
+        movdqa          xmm0,       [rsi]
+        lddqu           xmm1,       [rdi]
+        lddqu           xmm2,       [rdi+1]
+        lddqu           xmm3,       [rdi+2]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm5,       xmm1
+        paddw           xmm6,       xmm2
+        paddw           xmm7,       xmm3
+%endif
+        movdqa          xmm0,       QWORD PTR [rsi+rax]
+        lddqu           xmm1,       QWORD PTR [rdi+rdx]
+        lddqu           xmm2,       QWORD PTR [rdi+rdx+1]
+        lddqu           xmm3,       QWORD PTR [rdi+rdx+2]
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm5,       xmm1
+        paddw           xmm6,       xmm2
+        paddw           xmm7,       xmm3
+%endmacro
+
+%macro PROCESS_8X2X3 1
+%if %1
+        movq            mm0,       [rsi]
+        movq            mm5,       [rdi]
+        movq            mm6,       [rdi+1]
+        movq            mm7,       [rdi+2]
+
+        psadbw          mm5,       mm0
+        psadbw          mm6,       mm0
+        psadbw          mm7,       mm0
+%else
+        movq            mm0,       [rsi]
+        movq            mm1,       [rdi]
+        movq            mm2,       [rdi+1]
+        movq            mm3,       [rdi+2]
+
+        psadbw          mm1,       mm0
+        psadbw          mm2,       mm0
+        psadbw          mm3,       mm0
+
+        paddw           mm5,       mm1
+        paddw           mm6,       mm2
+        paddw           mm7,       mm3
+%endif
+        movq            mm0,       QWORD PTR [rsi+rax]
+        movq            mm1,       QWORD PTR [rdi+rdx]
+        movq            mm2,       QWORD PTR [rdi+rdx+1]
+        movq            mm3,       QWORD PTR [rdi+rdx+2]
+
+        lea             rsi,       [rsi+rax*2]
+        lea             rdi,       [rdi+rdx*2]
+
+        psadbw          mm1,       mm0
+        psadbw          mm2,       mm0
+        psadbw          mm3,       mm0
+
+        paddw           mm5,       mm1
+        paddw           mm6,       mm2
+        paddw           mm7,       mm3
+%endmacro
+
+%macro LOAD_X4_ADDRESSES 5
+        mov             %2,         [%1+REG_SZ_BYTES*0]
+        mov             %3,         [%1+REG_SZ_BYTES*1]
+
+        mov             %4,         [%1+REG_SZ_BYTES*2]
+        mov             %5,         [%1+REG_SZ_BYTES*3]
+%endmacro
+
+%macro PROCESS_16X2X4 1
+%if %1
+        movdqa          xmm0,       [rsi]
+        lddqu           xmm4,       [rcx]
+        lddqu           xmm5,       [rdx]
+        lddqu           xmm6,       [rbx]
+        lddqu           xmm7,       [rdi]
+
+        psadbw          xmm4,       xmm0
+        psadbw          xmm5,       xmm0
+        psadbw          xmm6,       xmm0
+        psadbw          xmm7,       xmm0
+%else
+        movdqa          xmm0,       [rsi]
+        lddqu           xmm1,       [rcx]
+        lddqu           xmm2,       [rdx]
+        lddqu           xmm3,       [rbx]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm4,       xmm1
+        lddqu           xmm1,       [rdi]
+        paddw           xmm5,       xmm2
+        paddw           xmm6,       xmm3
+
+        psadbw          xmm1,       xmm0
+        paddw           xmm7,       xmm1
+%endif
+        movdqa          xmm0,       QWORD PTR [rsi+rax]
+        lddqu           xmm1,       QWORD PTR [rcx+rbp]
+        lddqu           xmm2,       QWORD PTR [rdx+rbp]
+        lddqu           xmm3,       QWORD PTR [rbx+rbp]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm4,       xmm1
+        lddqu           xmm1,       QWORD PTR [rdi+rbp]
+        paddw           xmm5,       xmm2
+        paddw           xmm6,       xmm3
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rcx,        [rcx+rbp*2]
+
+        lea             rdx,        [rdx+rbp*2]
+        lea             rbx,        [rbx+rbp*2]
+
+        lea             rdi,        [rdi+rbp*2]
+
+        psadbw          xmm1,       xmm0
+        paddw           xmm7,       xmm1
+
+%endmacro
+
+%macro PROCESS_8X2X4 1
+%if %1
+        movq            mm0,        [rsi]
+        movq            mm4,        [rcx]
+        movq            mm5,        [rdx]
+        movq            mm6,        [rbx]
+        movq            mm7,        [rdi]
+
+        psadbw          mm4,        mm0
+        psadbw          mm5,        mm0
+        psadbw          mm6,        mm0
+        psadbw          mm7,        mm0
+%else
+        movq            mm0,        [rsi]
+        movq            mm1,        [rcx]
+        movq            mm2,        [rdx]
+        movq            mm3,        [rbx]
+
+        psadbw          mm1,        mm0
+        psadbw          mm2,        mm0
+        psadbw          mm3,        mm0
+
+        paddw           mm4,        mm1
+        movq            mm1,        [rdi]
+        paddw           mm5,        mm2
+        paddw           mm6,        mm3
+
+        psadbw          mm1,        mm0
+        paddw           mm7,        mm1
+%endif
+        movq            mm0,        QWORD PTR [rsi+rax]
+        movq            mm1,        QWORD PTR [rcx+rbp]
+        movq            mm2,        QWORD PTR [rdx+rbp]
+        movq            mm3,        QWORD PTR [rbx+rbp]
+
+        psadbw          mm1,        mm0
+        psadbw          mm2,        mm0
+        psadbw          mm3,        mm0
+
+        paddw           mm4,        mm1
+        movq            mm1,        QWORD PTR [rdi+rbp]
+        paddw           mm5,        mm2
+        paddw           mm6,        mm3
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rcx,        [rcx+rbp*2]
+
+        lea             rdx,        [rdx+rbp*2]
+        lea             rbx,        [rbx+rbp*2]
+
+        lea             rdi,        [rdi+rbp*2]
+
+        psadbw          mm1,        mm0
+        paddw           mm7,        mm1
+
+%endmacro
+
+;void int vp8_sad16x16x3_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad16x16x3_sse3)
+sym(vp8_sad16x16x3_sse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        PROCESS_16X2X3 1
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+
+        mov             rdi,        arg(4) ;Results
+
+        movq            xmm0,       xmm5
+        psrldq          xmm5,       8
+
+        paddw           xmm0,       xmm5
+        movd            [rdi],      xmm0
+;-
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movd            [rdi+4],    xmm0
+;-
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            [rdi+8],    xmm0
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void int vp8_sad16x8x3_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad16x8x3_sse3)
+sym(vp8_sad16x8x3_sse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        PROCESS_16X2X3 1
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+
+        mov             rdi,        arg(4) ;Results
+
+        movq            xmm0,       xmm5
+        psrldq          xmm5,       8
+
+        paddw           xmm0,       xmm5
+        movd            [rdi],      xmm0
+;-
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movd            [rdi+4],    xmm0
+;-
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            [rdi+8],    xmm0
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void int vp8_sad8x16x3_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad8x16x3_sse3)
+sym(vp8_sad8x16x3_sse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        PROCESS_8X2X3 1
+        PROCESS_8X2X3 0
+        PROCESS_8X2X3 0
+        PROCESS_8X2X3 0
+        PROCESS_8X2X3 0
+        PROCESS_8X2X3 0
+        PROCESS_8X2X3 0
+        PROCESS_8X2X3 0
+
+        mov             rdi,        arg(4) ;Results
+
+        movd            [rdi],      mm5
+        movd            [rdi+4],    mm6
+        movd            [rdi+8],    mm7
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void int vp8_sad8x8x3_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad8x8x3_sse3)
+sym(vp8_sad8x8x3_sse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        PROCESS_8X2X3 1
+        PROCESS_8X2X3 0
+        PROCESS_8X2X3 0
+        PROCESS_8X2X3 0
+
+        mov             rdi,        arg(4) ;Results
+
+        movd            [rdi],      mm5
+        movd            [rdi+4],    mm6
+        movd            [rdi+8],    mm7
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void int vp8_sad4x4x3_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad4x4x3_sse3)
+sym(vp8_sad4x4x3_sse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        movd            mm0,        QWORD PTR [rsi]
+        movd            mm1,        QWORD PTR [rdi]
+
+        movd            mm2,        QWORD PTR [rsi+rax]
+        movd            mm3,        QWORD PTR [rdi+rdx]
+
+        punpcklbw       mm0,        mm2
+        punpcklbw       mm1,        mm3
+
+        movd            mm4,        QWORD PTR [rdi+1]
+        movd            mm5,        QWORD PTR [rdi+2]
+
+        movd            mm2,        QWORD PTR [rdi+rdx+1]
+        movd            mm3,        QWORD PTR [rdi+rdx+2]
+
+        psadbw          mm1,        mm0
+
+        punpcklbw       mm4,        mm2
+        punpcklbw       mm5,        mm3
+
+        psadbw          mm4,        mm0
+        psadbw          mm5,        mm0
+
+
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        movd            mm0,        QWORD PTR [rsi]
+        movd            mm2,        QWORD PTR [rdi]
+
+        movd            mm3,        QWORD PTR [rsi+rax]
+        movd            mm6,        QWORD PTR [rdi+rdx]
+
+        punpcklbw       mm0,        mm3
+        punpcklbw       mm2,        mm6
+
+        movd            mm3,        QWORD PTR [rdi+1]
+        movd            mm7,        QWORD PTR [rdi+2]
+
+        psadbw          mm2,        mm0
+
+        paddw           mm1,        mm2
+
+        movd            mm2,        QWORD PTR [rdi+rdx+1]
+        movd            mm6,        QWORD PTR [rdi+rdx+2]
+
+        punpcklbw       mm3,        mm2
+        punpcklbw       mm7,        mm6
+
+        psadbw          mm3,        mm0
+        psadbw          mm7,        mm0
+
+        paddw           mm3,        mm4
+        paddw           mm7,        mm5
+
+        mov             rdi,        arg(4) ;Results
+        movd            [rdi],      mm1
+
+        movd            [rdi+4],    mm3
+        movd            [rdi+8],    mm7
+
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;unsigned int vp8_sad16x16_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  max_err)
+;%define lddqu movdqu
+global sym(vp8_sad16x16_sse3)
+sym(vp8_sad16x16_sse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rbx
+    push        rsi
+    push        rdi
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        movsxd          rbx,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        lea             rcx,        [rsi+rbx*8]
+
+        lea             rcx,        [rcx+rbx*8]
+        pxor            mm7,        mm7
+
+vp8_sad16x16_sse3_loop:
+
+        movd            rax,        mm7
+        cmp             rax,        arg(4)
+        jg              vp8_sad16x16_early_exit
+
+        movq            mm0,        QWORD PTR [rsi]
+        movq            mm2,        QWORD PTR [rsi+8]
+
+        movq            mm1,        QWORD PTR [rdi]
+        movq            mm3,        QWORD PTR [rdi+8]
+
+        movq            mm4,        QWORD PTR [rsi+rbx]
+        movq            mm5,        QWORD PTR [rdi+rdx]
+
+        psadbw          mm0,        mm1
+        psadbw          mm2,        mm3
+
+        movq            mm1,        QWORD PTR [rsi+rbx+8]
+        movq            mm3,        QWORD PTR [rdi+rdx+8]
+
+        psadbw          mm4,        mm5
+        psadbw          mm1,        mm3
+
+        lea             rsi,        [rsi+rbx*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        paddw           mm0,        mm2
+        paddw           mm4,        mm1
+
+        paddw           mm7,        mm0
+        paddw           mm7,        mm4
+
+        cmp             rsi,        rcx
+        jne             vp8_sad16x16_sse3_loop
+
+        movd            rax,        mm7
+
+vp8_sad16x16_early_exit:
+
+    ; begin epilog
+    pop         rdi
+    pop         rsi
+    pop         rbx
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_sad16x16x4d_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr_base,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad16x16x4d_sse3)
+sym(vp8_sad16x16x4d_sse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    push        rbx
+    ; end prolog
+
+        push            rbp
+        mov             rdi,        arg(2) ; ref_ptr_base
+
+        LOAD_X4_ADDRESSES rdi, rcx, rdx, rax, rdi
+
+        mov             rsi,        arg(0) ;src_ptr
+
+        movsxd          rbx,        dword ptr arg(1) ;src_stride
+        movsxd          rbp,        dword ptr arg(3) ;ref_stride
+
+        xchg            rbx,        rax
+
+        PROCESS_16X2X4 1
+        PROCESS_16X2X4 0
+        PROCESS_16X2X4 0
+        PROCESS_16X2X4 0
+        PROCESS_16X2X4 0
+        PROCESS_16X2X4 0
+        PROCESS_16X2X4 0
+        PROCESS_16X2X4 0
+
+        pop             rbp
+        mov             rdi,        arg(4) ;Results
+
+        movq            xmm0,       xmm4
+        psrldq          xmm4,       8
+
+        paddw           xmm0,       xmm4
+        movd            [rdi],      xmm0
+;-
+        movq            xmm0,       xmm5
+        psrldq          xmm5,       8
+
+        paddw           xmm0,       xmm5
+        movd            [rdi+4],    xmm0
+;-
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movd            [rdi+8],    xmm0
+;-
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            [rdi+12],   xmm0
+
+    ; begin epilog
+    pop         rbx
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_sad16x8x4d_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr_base,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad16x8x4d_sse3)
+sym(vp8_sad16x8x4d_sse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    push        rbx
+    ; end prolog
+
+        push            rbp
+        mov             rdi,        arg(2) ; ref_ptr_base
+
+        LOAD_X4_ADDRESSES rdi, rcx, rdx, rax, rdi
+
+        mov             rsi,        arg(0) ;src_ptr
+
+        movsxd          rbx,        dword ptr arg(1) ;src_stride
+        movsxd          rbp,        dword ptr arg(3) ;ref_stride
+
+        xchg            rbx,        rax
+
+        PROCESS_16X2X4 1
+        PROCESS_16X2X4 0
+        PROCESS_16X2X4 0
+        PROCESS_16X2X4 0
+
+        pop             rbp
+        mov             rdi,        arg(4) ;Results
+
+        movq            xmm0,       xmm4
+        psrldq          xmm4,       8
+
+        paddw           xmm0,       xmm4
+        movd            [rdi],      xmm0
+;-
+        movq            xmm0,       xmm5
+        psrldq          xmm5,       8
+
+        paddw           xmm0,       xmm5
+        movd            [rdi+4],    xmm0
+;-
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movd            [rdi+8],    xmm0
+;-
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            [rdi+12],   xmm0
+
+    ; begin epilog
+    pop         rbx
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void int vp8_sad8x16x4d_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad8x16x4d_sse3)
+sym(vp8_sad8x16x4d_sse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    push        rbx
+    ; end prolog
+
+        push            rbp
+        mov             rdi,        arg(2) ; ref_ptr_base
+
+        LOAD_X4_ADDRESSES rdi, rcx, rdx, rax, rdi
+
+        mov             rsi,        arg(0) ;src_ptr
+
+        movsxd          rbx,        dword ptr arg(1) ;src_stride
+        movsxd          rbp,        dword ptr arg(3) ;ref_stride
+
+        xchg            rbx,        rax
+
+        PROCESS_8X2X4 1
+        PROCESS_8X2X4 0
+        PROCESS_8X2X4 0
+        PROCESS_8X2X4 0
+        PROCESS_8X2X4 0
+        PROCESS_8X2X4 0
+        PROCESS_8X2X4 0
+        PROCESS_8X2X4 0
+
+        pop             rbp
+        mov             rdi,        arg(4) ;Results
+
+        movd            [rdi],      mm4
+        movd            [rdi+4],    mm5
+        movd            [rdi+8],    mm6
+        movd            [rdi+12],   mm7
+
+    ; begin epilog
+    pop         rbx
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void int vp8_sad8x8x4d_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad8x8x4d_sse3)
+sym(vp8_sad8x8x4d_sse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    push        rbx
+    ; end prolog
+
+        push            rbp
+        mov             rdi,        arg(2) ; ref_ptr_base
+
+        LOAD_X4_ADDRESSES rdi, rcx, rdx, rax, rdi
+
+        mov             rsi,        arg(0) ;src_ptr
+
+        movsxd          rbx,        dword ptr arg(1) ;src_stride
+        movsxd          rbp,        dword ptr arg(3) ;ref_stride
+
+        xchg            rbx,        rax
+
+        PROCESS_8X2X4 1
+        PROCESS_8X2X4 0
+        PROCESS_8X2X4 0
+        PROCESS_8X2X4 0
+
+        pop             rbp
+        mov             rdi,        arg(4) ;Results
+
+        movd            [rdi],      mm4
+        movd            [rdi+4],    mm5
+        movd            [rdi+8],    mm6
+        movd            [rdi+12],   mm7
+
+    ; begin epilog
+    pop         rbx
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void int vp8_sad4x4x4d_sse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad4x4x4d_sse3)
+sym(vp8_sad4x4x4d_sse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    push        rbx
+    ; end prolog
+
+        push            rbp
+        mov             rdi,        arg(2) ; ref_ptr_base
+
+        LOAD_X4_ADDRESSES rdi, rcx, rdx, rax, rdi
+
+        mov             rsi,        arg(0) ;src_ptr
+
+        movsxd          rbx,        dword ptr arg(1) ;src_stride
+        movsxd          rbp,        dword ptr arg(3) ;ref_stride
+
+        xchg            rbx,        rax
+
+        movd            mm0,        QWORD PTR [rsi]
+        movd            mm1,        QWORD PTR [rcx]
+
+        movd            mm2,        QWORD PTR [rsi+rax]
+        movd            mm3,        QWORD PTR [rcx+rbp]
+
+        punpcklbw       mm0,        mm2
+        punpcklbw       mm1,        mm3
+
+        movd            mm4,        QWORD PTR [rdx]
+        movd            mm5,        QWORD PTR [rbx]
+
+        movd            mm6,        QWORD PTR [rdi]
+        movd            mm2,        QWORD PTR [rdx+rbp]
+
+        movd            mm3,        QWORD PTR [rbx+rbp]
+        movd            mm7,        QWORD PTR [rdi+rbp]
+
+        psadbw          mm1,        mm0
+
+        punpcklbw       mm4,        mm2
+        punpcklbw       mm5,        mm3
+
+        punpcklbw       mm6,        mm7
+        psadbw          mm4,        mm0
+
+        psadbw          mm5,        mm0
+        psadbw          mm6,        mm0
+
+
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rcx,        [rcx+rbp*2]
+
+        lea             rdx,        [rdx+rbp*2]
+        lea             rbx,        [rbx+rbp*2]
+
+        lea             rdi,        [rdi+rbp*2]
+
+        movd            mm0,        QWORD PTR [rsi]
+        movd            mm2,        QWORD PTR [rcx]
+
+        movd            mm3,        QWORD PTR [rsi+rax]
+        movd            mm7,        QWORD PTR [rcx+rbp]
+
+        punpcklbw       mm0,        mm3
+        punpcklbw       mm2,        mm7
+
+        movd            mm3,        QWORD PTR [rdx]
+        movd            mm7,        QWORD PTR [rbx]
+
+        psadbw          mm2,        mm0
+        mov             rax,        rbp
+
+        pop             rbp
+        mov             rsi,        arg(4) ;Results
+
+        paddw           mm1,        mm2
+        movd            [rsi],      mm1
+
+        movd            mm2,        QWORD PTR [rdx+rax]
+        movd            mm1,        QWORD PTR [rbx+rax]
+
+        punpcklbw       mm3,        mm2
+        punpcklbw       mm7,        mm1
+
+        psadbw          mm3,        mm0
+        psadbw          mm7,        mm0
+
+        movd            mm2,        QWORD PTR [rdi]
+        movd            mm1,        QWORD PTR [rdi+rax]
+
+        paddw           mm3,        mm4
+        paddw           mm7,        mm5
+
+        movd            [rsi+4],    mm3
+        punpcklbw       mm2,        mm1
+
+        movd            [rsi+8],    mm7
+        psadbw          mm2,        mm0
+
+        paddw           mm2,        mm6
+        movd            [rsi+12],   mm2
+
+
+    ; begin epilog
+    pop         rbx
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/encoder/x86/sad_ssse3.asm b/vp8/encoder/x86/sad_ssse3.asm
new file mode 100644
index 0000000..1bb9561
--- /dev/null
+++ b/vp8/encoder/x86/sad_ssse3.asm
@@ -0,0 +1,367 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%idefine QWORD
+
+%macro PROCESS_16X2X3 1
+%if %1
+        movdqa          xmm0,       [rsi]
+        lddqu           xmm5,       [rdi]
+        lddqu           xmm6,       [rdi+1]
+        lddqu           xmm7,       [rdi+2]
+
+        psadbw          xmm5,       xmm0
+        psadbw          xmm6,       xmm0
+        psadbw          xmm7,       xmm0
+%else
+        movdqa          xmm0,       [rsi]
+        lddqu           xmm1,       [rdi]
+        lddqu           xmm2,       [rdi+1]
+        lddqu           xmm3,       [rdi+2]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm5,       xmm1
+        paddw           xmm6,       xmm2
+        paddw           xmm7,       xmm3
+%endif
+        movdqa          xmm0,       QWORD PTR [rsi+rax]
+        lddqu           xmm1,       QWORD PTR [rdi+rdx]
+        lddqu           xmm2,       QWORD PTR [rdi+rdx+1]
+        lddqu           xmm3,       QWORD PTR [rdi+rdx+2]
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm5,       xmm1
+        paddw           xmm6,       xmm2
+        paddw           xmm7,       xmm3
+%endmacro
+
+%macro PROCESS_16X2X3_OFFSET 2
+%if %1
+        movdqa          xmm0,       [rsi]
+        movdqa          xmm4,       [rdi]
+        movdqa          xmm7,       [rdi+16]
+
+        movdqa          xmm5,       xmm7
+        palignr         xmm5,       xmm4,       %2
+
+        movdqa          xmm6,       xmm7
+        palignr         xmm6,       xmm4,       (%2+1)
+
+        palignr         xmm7,       xmm4,       (%2+2)
+
+        psadbw          xmm5,       xmm0
+        psadbw          xmm6,       xmm0
+        psadbw          xmm7,       xmm0
+%else
+        movdqa          xmm0,       [rsi]
+        movdqa          xmm4,       [rdi]
+        movdqa          xmm3,       [rdi+16]
+
+        movdqa          xmm1,       xmm3
+        palignr         xmm1,       xmm4,       %2
+
+        movdqa          xmm2,       xmm3
+        palignr         xmm2,       xmm4,       (%2+1)
+
+        palignr         xmm3,       xmm4,       (%2+2)
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm5,       xmm1
+        paddw           xmm6,       xmm2
+        paddw           xmm7,       xmm3
+%endif
+        movdqa          xmm0,       QWORD PTR [rsi+rax]
+        movdqa          xmm4,       QWORD PTR [rdi+rdx]
+        movdqa          xmm3,       QWORD PTR [rdi+rdx+16]
+
+        movdqa          xmm1,       xmm3
+        palignr         xmm1,       xmm4,       %2
+
+        movdqa          xmm2,       xmm3
+        palignr         xmm2,       xmm4,       (%2+1)
+
+        palignr         xmm3,       xmm4,       (%2+2)
+
+        lea             rsi,        [rsi+rax*2]
+        lea             rdi,        [rdi+rdx*2]
+
+        psadbw          xmm1,       xmm0
+        psadbw          xmm2,       xmm0
+        psadbw          xmm3,       xmm0
+
+        paddw           xmm5,       xmm1
+        paddw           xmm6,       xmm2
+        paddw           xmm7,       xmm3
+%endmacro
+
+%macro PROCESS_16X16X3_OFFSET 2
+%2_aligned_by_%1:
+
+        sub             rdi,        %1
+
+        PROCESS_16X2X3_OFFSET 1, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+
+        jmp             %2_store_off
+
+%endmacro
+
+%macro PROCESS_16X8X3_OFFSET 2
+%2_aligned_by_%1:
+
+        sub             rdi,        %1
+
+        PROCESS_16X2X3_OFFSET 1, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+        PROCESS_16X2X3_OFFSET 0, %1
+
+        jmp             %2_store_off
+
+%endmacro
+
+;void int vp8_sad16x16x3_ssse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad16x16x3_ssse3)
+sym(vp8_sad16x16x3_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    push        rcx
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        mov             rdx,        0xf
+        and             rdx,        rdi
+
+        jmp vp8_sad16x16x3_ssse3_skiptable
+vp8_sad16x16x3_ssse3_jumptable:
+        dd vp8_sad16x16x3_ssse3_aligned_by_0  - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_1  - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_2  - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_3  - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_4  - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_5  - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_6  - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_7  - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_8  - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_9  - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_10 - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_11 - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_12 - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_13 - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_14 - vp8_sad16x16x3_ssse3_do_jump
+        dd vp8_sad16x16x3_ssse3_aligned_by_15 - vp8_sad16x16x3_ssse3_do_jump
+vp8_sad16x16x3_ssse3_skiptable:
+
+        call vp8_sad16x16x3_ssse3_do_jump
+vp8_sad16x16x3_ssse3_do_jump:
+        pop             rcx                         ; get the address of do_jump
+        mov             rax,  vp8_sad16x16x3_ssse3_jumptable - vp8_sad16x16x3_ssse3_do_jump
+        add             rax,  rcx  ; get the absolute address of vp8_sad16x16x3_ssse3_jumptable
+
+        movsxd          rax,  dword [rax + 4*rdx]   ; get the 32 bit offset from the jumptable
+        add             rcx,        rax
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        jmp             rcx
+
+        PROCESS_16X16X3_OFFSET 0,  vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 1,  vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 2,  vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 3,  vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 4,  vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 5,  vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 6,  vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 7,  vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 8,  vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 9,  vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 10, vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 11, vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 12, vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 13, vp8_sad16x16x3_ssse3
+        PROCESS_16X16X3_OFFSET 14, vp8_sad16x16x3_ssse3
+
+vp8_sad16x16x3_ssse3_aligned_by_15:
+        PROCESS_16X2X3 1
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+
+vp8_sad16x16x3_ssse3_store_off:
+        mov             rdi,        arg(4) ;Results
+
+        movq            xmm0,       xmm5
+        psrldq          xmm5,       8
+
+        paddw           xmm0,       xmm5
+        movd            [rdi],      xmm0
+;-
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movd            [rdi+4],    xmm0
+;-
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            [rdi+8],    xmm0
+
+    ; begin epilog
+    pop         rcx
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void int vp8_sad16x8x3_ssse3(
+;    unsigned char *src_ptr,
+;    int  src_stride,
+;    unsigned char *ref_ptr,
+;    int  ref_stride,
+;    int  *results)
+global sym(vp8_sad16x8x3_ssse3)
+sym(vp8_sad16x8x3_ssse3):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push        rsi
+    push        rdi
+    push        rcx
+    ; end prolog
+
+        mov             rsi,        arg(0) ;src_ptr
+        mov             rdi,        arg(2) ;ref_ptr
+
+        mov             rdx,        0xf
+        and             rdx,        rdi
+
+        jmp vp8_sad16x8x3_ssse3_skiptable
+vp8_sad16x8x3_ssse3_jumptable:
+        dd vp8_sad16x8x3_ssse3_aligned_by_0  - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_1  - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_2  - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_3  - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_4  - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_5  - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_6  - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_7  - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_8  - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_9  - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_10 - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_11 - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_12 - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_13 - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_14 - vp8_sad16x8x3_ssse3_do_jump
+        dd vp8_sad16x8x3_ssse3_aligned_by_15 - vp8_sad16x8x3_ssse3_do_jump
+vp8_sad16x8x3_ssse3_skiptable:
+
+        call vp8_sad16x8x3_ssse3_do_jump
+vp8_sad16x8x3_ssse3_do_jump:
+        pop             rcx                         ; get the address of do_jump
+        mov             rax,  vp8_sad16x8x3_ssse3_jumptable - vp8_sad16x8x3_ssse3_do_jump
+        add             rax,  rcx  ; get the absolute address of vp8_sad16x8x3_ssse3_jumptable
+
+        movsxd          rax,  dword [rax + 4*rdx]   ; get the 32 bit offset from the jumptable
+        add             rcx,        rax
+
+        movsxd          rax,        dword ptr arg(1) ;src_stride
+        movsxd          rdx,        dword ptr arg(3) ;ref_stride
+
+        jmp             rcx
+
+        PROCESS_16X8X3_OFFSET 0,  vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 1,  vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 2,  vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 3,  vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 4,  vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 5,  vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 6,  vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 7,  vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 8,  vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 9,  vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 10, vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 11, vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 12, vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 13, vp8_sad16x8x3_ssse3
+        PROCESS_16X8X3_OFFSET 14, vp8_sad16x8x3_ssse3
+
+vp8_sad16x8x3_ssse3_aligned_by_15:
+
+        PROCESS_16X2X3 1
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+        PROCESS_16X2X3 0
+
+vp8_sad16x8x3_ssse3_store_off:
+        mov             rdi,        arg(4) ;Results
+
+        movq            xmm0,       xmm5
+        psrldq          xmm5,       8
+
+        paddw           xmm0,       xmm5
+        movd            [rdi],      xmm0
+;-
+        movq            xmm0,       xmm6
+        psrldq          xmm6,       8
+
+        paddw           xmm0,       xmm6
+        movd            [rdi+4],    xmm0
+;-
+        movq            xmm0,       xmm7
+        psrldq          xmm7,       8
+
+        paddw           xmm0,       xmm7
+        movd            [rdi+8],    xmm0
+
+    ; begin epilog
+    pop         rcx
+    pop         rdi
+    pop         rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/encoder/x86/subtract_mmx.asm b/vp8/encoder/x86/subtract_mmx.asm
new file mode 100644
index 0000000..ce3e610
--- /dev/null
+++ b/vp8/encoder/x86/subtract_mmx.asm
@@ -0,0 +1,431 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;void vp8_subtract_b_mmx_impl(unsigned char *z,  int src_stride,
+;                            unsigned short *diff, unsigned char *Predictor,
+;                            int pitch);
+global sym(vp8_subtract_b_mmx_impl)
+sym(vp8_subtract_b_mmx_impl)
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push rsi
+    push rdi
+    ; end prolog
+
+
+        mov     rdi,        arg(2) ;diff
+        mov     rax,        arg(3) ;Predictor
+        mov     rsi,        arg(0) ;z
+        movsxd  rdx,        dword ptr arg(1);src_stride;
+        movsxd  rcx,        dword ptr arg(4);pitch
+        pxor    mm7,        mm7
+
+        movd    mm0,        [rsi]
+        movd    mm1,        [rax]
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+        psubw   mm0,        mm1
+        movq    [rdi],      mm0
+
+
+        movd    mm0,        [rsi+rdx]
+        movd    mm1,        [rax+rcx]
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+        psubw   mm0,        mm1
+        movq    [rdi+rcx*2],mm0
+
+
+        movd    mm0,        [rsi+rdx*2]
+        movd    mm1,        [rax+rcx*2]
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+        psubw   mm0,        mm1
+        movq    [rdi+rcx*4],        mm0
+
+        lea     rsi,        [rsi+rdx*2]
+        lea     rcx,        [rcx+rcx*2]
+
+
+
+        movd    mm0,        [rsi+rdx]
+        movd    mm1,        [rax+rcx]
+        punpcklbw   mm0,    mm7
+        punpcklbw   mm1,    mm7
+        psubw   mm0,        mm1
+        movq    [rdi+rcx*2],        mm0
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_subtract_mby_mmx(short *diff, unsigned char *src, unsigned char *pred, int stride)
+global sym(vp8_subtract_mby_mmx)
+sym(vp8_subtract_mby_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    ; end prolog
+
+
+            mov         rsi,            arg(1) ;src
+            mov         rdi,            arg(0) ;diff
+
+            mov         rax,            arg(2) ;pred
+            movsxd      rdx,            dword ptr arg(3) ;stride
+
+            mov         rcx,            16
+            pxor        mm0,            mm0
+
+submby_loop:
+
+            movq        mm1,            [rsi]
+            movq        mm3,            [rax]
+
+            movq        mm2,            mm1
+            movq        mm4,            mm3
+
+            punpcklbw   mm1,            mm0
+            punpcklbw   mm3,            mm0
+
+            punpckhbw   mm2,            mm0
+            punpckhbw   mm4,            mm0
+
+            psubw       mm1,            mm3
+            psubw       mm2,            mm4
+
+            movq        [rdi],          mm1
+            movq        [rdi+8],        mm2
+
+
+            movq        mm1,            [rsi+8]
+            movq        mm3,            [rax+8]
+
+            movq        mm2,            mm1
+            movq        mm4,            mm3
+
+            punpcklbw   mm1,            mm0
+            punpcklbw   mm3,            mm0
+
+            punpckhbw   mm2,            mm0
+            punpckhbw   mm4,            mm0
+
+            psubw       mm1,            mm3
+            psubw       mm2,            mm4
+
+            movq        [rdi+16],       mm1
+            movq        [rdi+24],       mm2
+
+
+            add         rdi,            32
+            add         rax,            16
+
+            lea         rsi,            [rsi+rdx]
+
+            sub         rcx,            1
+            jnz         submby_loop
+
+    pop rdi
+    pop rsi
+    ; begin epilog
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_subtract_mbuv_mmx(short *diff, unsigned char *usrc, unsigned char *vsrc, unsigned char *pred, int stride)
+global sym(vp8_subtract_mbuv_mmx)
+sym(vp8_subtract_mbuv_mmx)
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 5
+    push rsi
+    push rdi
+    ; end prolog
+
+    ;short *udiff = diff + 256;
+    ;short *vdiff = diff + 320;
+    ;unsigned char *upred = pred + 256;
+    ;unsigned char *vpred = pred + 320;
+
+        ;unsigned char  *z    = usrc;
+        ;unsigned short *diff = udiff;
+        ;unsigned char  *Predictor= upred;
+
+            mov     rdi,        arg(0) ;diff
+            mov     rax,        arg(3) ;pred
+            mov     rsi,        arg(1) ;z = usrc
+            add     rdi,        256*2  ;diff = diff + 256 (shorts)
+            add     rax,        256    ;Predictor = pred + 256
+            movsxd  rdx,        dword ptr arg(4) ;stride;
+            pxor    mm7,        mm7
+
+            movq    mm0,        [rsi]
+            movq    mm1,        [rax]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+            movq    [rdi],      mm0
+            movq    [rdi+8],    mm3
+
+
+            movq    mm0,        [rsi+rdx]
+            movq    mm1,        [rax+8]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+            movq    [rdi+16],   mm0
+            movq    [rdi+24],   mm3
+
+            movq    mm0,        [rsi+rdx*2]
+            movq    mm1,        [rax+16]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+            movq    [rdi+32],   mm0
+            movq    [rdi+40],   mm3
+            lea     rsi,        [rsi+rdx*2]
+
+
+            movq    mm0,        [rsi+rdx]
+            movq    mm1,        [rax+24]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+
+            movq    [rdi+48],   mm0
+            movq    [rdi+56],   mm3
+
+
+            add     rdi,        64
+            add     rax,        32
+            lea     rsi,        [rsi+rdx*2]
+
+
+            movq    mm0,        [rsi]
+            movq    mm1,        [rax]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+            movq    [rdi],      mm0
+            movq    [rdi+8],    mm3
+
+
+            movq    mm0,        [rsi+rdx]
+            movq    mm1,        [rax+8]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+            movq    [rdi+16],   mm0
+            movq    [rdi+24],   mm3
+
+            movq    mm0,        [rsi+rdx*2]
+            movq    mm1,        [rax+16]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+            movq    [rdi+32],   mm0
+            movq    [rdi+40],   mm3
+            lea     rsi,        [rsi+rdx*2]
+
+
+            movq    mm0,        [rsi+rdx]
+            movq    mm1,        [rax+24]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+
+            movq    [rdi+48],   mm0
+            movq    [rdi+56],   mm3
+
+        ;unsigned char  *z    = vsrc;
+        ;unsigned short *diff = vdiff;
+        ;unsigned char  *Predictor= vpred;
+
+            mov     rdi,        arg(0) ;diff
+            mov     rax,        arg(3) ;pred
+            mov     rsi,        arg(2) ;z = usrc
+            add     rdi,        320*2  ;diff = diff + 320 (shorts)
+            add     rax,        320    ;Predictor = pred + 320
+            movsxd  rdx,        dword ptr arg(4) ;stride;
+            pxor    mm7,        mm7
+
+            movq    mm0,        [rsi]
+            movq    mm1,        [rax]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+            movq    [rdi],      mm0
+            movq    [rdi+8],    mm3
+
+
+            movq    mm0,        [rsi+rdx]
+            movq    mm1,        [rax+8]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+            movq    [rdi+16],   mm0
+            movq    [rdi+24],   mm3
+
+            movq    mm0,        [rsi+rdx*2]
+            movq    mm1,        [rax+16]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+            movq    [rdi+32],   mm0
+            movq    [rdi+40],   mm3
+            lea     rsi,        [rsi+rdx*2]
+
+
+            movq    mm0,        [rsi+rdx]
+            movq    mm1,        [rax+24]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+
+            movq    [rdi+48],   mm0
+            movq    [rdi+56],   mm3
+
+
+            add     rdi,        64
+            add     rax,        32
+            lea     rsi,        [rsi+rdx*2]
+
+
+            movq    mm0,        [rsi]
+            movq    mm1,        [rax]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+            movq    [rdi],      mm0
+            movq    [rdi+8],    mm3
+
+
+            movq    mm0,        [rsi+rdx]
+            movq    mm1,        [rax+8]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+            movq    [rdi+16],   mm0
+            movq    [rdi+24],   mm3
+
+            movq    mm0,        [rsi+rdx*2]
+            movq    mm1,        [rax+16]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+            movq    [rdi+32],   mm0
+            movq    [rdi+40],   mm3
+            lea     rsi,        [rsi+rdx*2]
+
+
+            movq    mm0,        [rsi+rdx]
+            movq    mm1,        [rax+24]
+            movq    mm3,        mm0
+            movq    mm4,        mm1
+            punpcklbw   mm0,    mm7
+            punpcklbw   mm1,    mm7
+            punpckhbw   mm3,    mm7
+            punpckhbw   mm4,    mm7
+            psubw   mm0,        mm1
+            psubw   mm3,        mm4
+
+            movq    [rdi+48],   mm0
+            movq    [rdi+56],   mm3
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
diff --git a/vp8/encoder/x86/variance_impl_mmx.asm b/vp8/encoder/x86/variance_impl_mmx.asm
new file mode 100644
index 0000000..d0da82a
--- /dev/null
+++ b/vp8/encoder/x86/variance_impl_mmx.asm
@@ -0,0 +1,980 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+;unsigned int vp8_get_mb_ss_mmx( short *src_ptr )
+global sym(vp8_get_mb_ss_mmx)
+sym(vp8_get_mb_ss_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 8
+    ; end prolog
+
+        mov         rax, arg(0) ;src_ptr
+        mov         rcx, 16
+        pxor        mm4, mm4
+
+NEXTROW:
+        movq        mm0, [rax]
+        movq        mm1, [rax+8]
+        movq        mm2, [rax+16]
+        movq        mm3, [rax+24]
+        pmaddwd     mm0, mm0
+        pmaddwd     mm1, mm1
+        pmaddwd     mm2, mm2
+        pmaddwd     mm3, mm3
+
+        paddd       mm4, mm0
+        paddd       mm4, mm1
+        paddd       mm4, mm2
+        paddd       mm4, mm3
+
+        add         rax, 32
+        dec         rcx
+        ja          NEXTROW
+        movq        QWORD PTR [rsp], mm4
+
+        ;return sum[0]+sum[1];
+        movsxd      rax, dword ptr [rsp]
+        movsxd      rcx, dword ptr [rsp+4]
+        add         rax, rcx
+
+
+    ; begin epilog
+    add rsp, 8
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_get8x8var_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  source_stride,
+;    unsigned char *ref_ptr,
+;    int  recon_stride,
+;    unsigned int *SSE,
+;    int *Sum
+;)
+global sym(vp8_get8x8var_mmx)
+sym(vp8_get8x8var_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    push rsi
+    push rdi
+    push rbx
+    sub         rsp, 16
+    ; end prolog
+
+
+        pxor        mm5, mm5                    ; Blank mmx6
+        pxor        mm6, mm6                    ; Blank mmx7
+        pxor        mm7, mm7                    ; Blank mmx7
+
+        mov         rax, arg(0) ;[src_ptr]  ; Load base addresses
+        mov         rbx, arg(2) ;[ref_ptr]
+        movsxd      rcx, dword ptr arg(1) ;[source_stride]
+        movsxd      rdx, dword ptr arg(3) ;[recon_stride]
+
+        ; Row 1
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+
+        ; Row 2
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Row 3
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Row 4
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Row 5
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        ;              movq        mm4, [rbx + rdx]
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Row 6
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Row 7
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Row 8
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm2, mm0                    ; Take copies
+        movq        mm3, mm1                    ; Take copies
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        punpckhbw   mm2, mm6                    ; unpack to higher prrcision
+        punpckhbw   mm3, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        psubsw      mm2, mm3                    ; A-B (high order) to MM2
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        paddw       mm5, mm2                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        pmaddwd     mm2, mm2                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        paddd       mm7, mm0                    ; accumulate in mm7
+        paddd       mm7, mm2                    ; accumulate in mm7
+
+        ; Now accumulate the final results.
+        movq        QWORD PTR [rsp+8], mm5      ; copy back accumulated results into normal memory
+        movq        QWORD PTR [rsp], mm7        ; copy back accumulated results into normal memory
+        movsx       rdx, WORD PTR [rsp+8]
+        movsx       rcx, WORD PTR [rsp+10]
+        movsx       rbx, WORD PTR [rsp+12]
+        movsx       rax, WORD PTR [rsp+14]
+        add         rdx, rcx
+        add         rbx, rax
+        add         rdx, rbx    ;XSum
+        movsxd      rax, DWORD PTR [rsp]
+        movsxd      rcx, DWORD PTR [rsp+4]
+        add         rax, rcx    ;XXSum
+        mov         rsi, arg(4) ;SSE
+        mov         rdi, arg(5) ;Sum
+        mov         dword ptr [rsi], eax
+        mov         dword ptr [rdi], edx
+        xor         rax, rax    ; return 0
+
+
+    ; begin epilog
+    add rsp, 16
+    pop rbx
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+;unsigned int
+;vp8_get4x4var_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  source_stride,
+;    unsigned char *ref_ptr,
+;    int  recon_stride,
+;    unsigned int *SSE,
+;    int *Sum
+;)
+global sym(vp8_get4x4var_mmx)
+sym(vp8_get4x4var_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    push rsi
+    push rdi
+    push rbx
+    sub         rsp, 16
+    ; end prolog
+
+
+        pxor        mm5, mm5                    ; Blank mmx6
+        pxor        mm6, mm6                    ; Blank mmx7
+        pxor        mm7, mm7                    ; Blank mmx7
+
+        mov         rax, arg(0) ;[src_ptr]  ; Load base addresses
+        mov         rbx, arg(2) ;[ref_ptr]
+        movsxd      rcx, dword ptr arg(1) ;[source_stride]
+        movsxd      rdx, dword ptr arg(3) ;[recon_stride]
+
+        ; Row 1
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+
+        ; Row 2
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+        ; Row 3
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movq        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+        ; Row 4
+        movq        mm0, [rax]                  ; Copy eight bytes to mm0
+
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+
+        paddw       mm5, mm0                    ; accumulate differences in mm5
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+
+        ; Now accumulate the final results.
+        movq        QWORD PTR [rsp+8], mm5      ; copy back accumulated results into normal memory
+        movq        QWORD PTR [rsp], mm7        ; copy back accumulated results into normal memory
+        movsx       rdx, WORD PTR [rsp+8]
+        movsx       rcx, WORD PTR [rsp+10]
+        movsx       rbx, WORD PTR [rsp+12]
+        movsx       rax, WORD PTR [rsp+14]
+        add         rdx, rcx
+        add         rbx, rax
+        add         rdx, rbx    ;XSum
+        movsxd      rax, DWORD PTR [rsp]
+        movsxd      rcx, DWORD PTR [rsp+4]
+        add         rax, rcx    ;XXSum
+        mov         rsi, arg(4) ;SSE
+        mov         rdi, arg(5) ;Sum
+        mov         dword ptr [rsi], eax
+        mov         dword ptr [rdi], edx
+        xor         rax, rax    ; return 0
+
+
+    ; begin epilog
+    add rsp, 16
+    pop rbx
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+;unsigned int
+;vp8_get4x4sse_cs_mmx
+;(
+;    unsigned char *src_ptr,
+;    int  source_stride,
+;    unsigned char *ref_ptr,
+;    int  recon_stride
+;)
+global sym(vp8_get4x4sse_cs_mmx)
+sym(vp8_get4x4sse_cs_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    push rsi
+    push rdi
+    push rbx
+    ; end prolog
+
+
+        pxor        mm6, mm6                    ; Blank mmx7
+        pxor        mm7, mm7                    ; Blank mmx7
+
+        mov         rax, arg(0) ;[src_ptr]  ; Load base addresses
+        mov         rbx, arg(2) ;[ref_ptr]
+        movsxd      rcx, dword ptr arg(1) ;[source_stride]
+        movsxd      rdx, dword ptr arg(3) ;[recon_stride]
+        ; Row 1
+        movd        mm0, [rax]                  ; Copy eight bytes to mm0
+        movd        mm1, [rbx]                  ; Copy eight bytes to mm1
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movd        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+        ; Row 2
+        movd        mm0, [rax]                  ; Copy eight bytes to mm0
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movd        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+        ; Row 3
+        movd        mm0, [rax]                  ; Copy eight bytes to mm0
+        punpcklbw   mm1, mm6
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        add         rbx,rdx                     ; Inc pointer into ref data
+        add         rax,rcx                     ; Inc pointer into the new data
+        movd        mm1, [rbx]                  ; Copy eight bytes to mm1
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+        ; Row 4
+        movd        mm0, [rax]                  ; Copy eight bytes to mm0
+        punpcklbw   mm0, mm6                    ; unpack to higher prrcision
+        punpcklbw   mm1, mm6
+        psubsw      mm0, mm1                    ; A-B (low order) to MM0
+        pmaddwd     mm0, mm0                    ; square and accumulate
+        paddd       mm7, mm0                    ; accumulate in mm7
+
+        movq        mm0,    mm7                 ;
+        psrlq       mm7,    32
+
+        paddd       mm0,    mm7
+        movd        rax,    mm0
+
+
+    ; begin epilog
+    pop rbx
+    pop rdi
+    pop rsi
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+%define mmx_filter_shift            7
+
+;void vp8_filter_block2d_bil4x4_var_mmx
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned short *HFilter,
+;    unsigned short *VFilter,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_filter_block2d_bil4x4_var_mmx)
+sym(vp8_filter_block2d_bil4x4_var_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 8
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 16
+    ; end prolog
+
+
+        pxor            mm6,            mm6                 ;
+        pxor            mm7,            mm7                 ;
+
+        mov             rax,            arg(4) ;HFilter             ;
+        mov             rdx,            arg(5) ;VFilter             ;
+
+        mov             rsi,            arg(0) ;ref_ptr              ;
+        mov             rdi,            arg(2) ;src_ptr              ;
+
+        mov             rcx,            4                   ;
+        pxor            mm0,            mm0                 ;
+
+        movd            mm1,            [rsi]               ;
+        movd            mm3,            [rsi+1]             ;
+
+        punpcklbw       mm1,            mm0                 ;
+        pmullw          mm1,            [rax]               ;
+
+        punpcklbw       mm3,            mm0                 ;
+        pmullw          mm3,            [rax+8]             ;
+
+        paddw           mm1,            mm3                 ;
+        paddw           mm1,            [mmx_bi_rd GLOBAL]  ;
+
+        psraw           mm1,            mmx_filter_shift    ;
+        movq            mm5,            mm1
+
+%if ABI_IS_32BIT
+        add             rsi, dword ptr  arg(1) ;ref_pixels_per_line    ;
+%else
+        movsxd          r8, dword ptr  arg(1) ;ref_pixels_per_line    ;
+        add             rsi, r8
+%endif
+
+filter_block2d_bil4x4_var_mmx_loop:
+
+        movd            mm1,            [rsi]               ;
+        movd            mm3,            [rsi+1]             ;
+
+        punpcklbw       mm1,            mm0                 ;
+        pmullw          mm1,            [rax]               ;
+
+        punpcklbw       mm3,            mm0                 ;
+        pmullw          mm3,            [rax+8]             ;
+
+        paddw           mm1,            mm3                 ;
+        paddw           mm1,            [mmx_bi_rd GLOBAL]  ;
+
+        psraw           mm1,            mmx_filter_shift    ;
+        movq            mm3,            mm5                 ;
+
+        movq            mm5,            mm1                 ;
+        pmullw          mm3,            [rdx]               ;
+
+        pmullw          mm1,            [rdx+8]             ;
+        paddw           mm1,            mm3                 ;
+
+
+        paddw           mm1,            [mmx_bi_rd GLOBAL]  ;
+        psraw           mm1,            mmx_filter_shift    ;
+
+        movd            mm3,            [rdi]               ;
+        punpcklbw       mm3,            mm0                 ;
+
+        psubw           mm1,            mm3                 ;
+        paddw           mm6,            mm1                 ;
+
+        pmaddwd         mm1,            mm1                 ;
+        paddd           mm7,            mm1                 ;
+
+%if ABI_IS_32BIT
+        add             rsi,            dword ptr arg(1) ;ref_pixels_per_line    ;
+        add             rdi,            dword ptr arg(3) ;src_pixels_per_line    ;
+%else
+        movsxd          r8,             dword ptr arg(1) ;ref_pixels_per_line
+        movsxd          r9,             dword ptr arg(3) ;src_pixels_per_line
+        add             rsi,            r8
+        add             rdi,            r9
+%endif
+        sub             rcx,            1                   ;
+        jnz             filter_block2d_bil4x4_var_mmx_loop       ;
+
+
+        pxor            mm3,            mm3                 ;
+        pxor            mm2,            mm2                 ;
+
+        punpcklwd       mm2,            mm6                 ;
+        punpckhwd       mm3,            mm6                 ;
+
+        paddd           mm2,            mm3                 ;
+        movq            mm6,            mm2                 ;
+
+        psrlq           mm6,            32                  ;
+        paddd           mm2,            mm6                 ;
+
+        psrad           mm2,            16                  ;
+        movq            mm4,            mm7                 ;
+
+        psrlq           mm4,            32                  ;
+        paddd           mm4,            mm7                 ;
+
+        mov             rdi,            arg(6) ;sum
+        mov             rsi,            arg(7) ;sumsquared
+
+        movd            dword ptr [rdi],          mm2                 ;
+        movd            dword ptr [rsi],          mm4                 ;
+
+
+
+    ; begin epilog
+    add rsp, 16
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+
+;void vp8_filter_block2d_bil_var_mmx
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    unsigned short *HFilter,
+;    unsigned short *VFilter,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_filter_block2d_bil_var_mmx)
+sym(vp8_filter_block2d_bil_var_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 9
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 16
+    ; end prolog
+
+        pxor            mm6,            mm6                 ;
+        pxor            mm7,            mm7                 ;
+        mov             rax,            arg(5) ;HFilter             ;
+
+        mov             rdx,            arg(6) ;VFilter             ;
+        mov             rsi,            arg(0) ;ref_ptr              ;
+
+        mov             rdi,            arg(2) ;src_ptr              ;
+        movsxd          rcx,            dword ptr arg(4) ;Height              ;
+
+        pxor            mm0,            mm0                 ;
+        movq            mm1,            [rsi]               ;
+
+        movq            mm3,            [rsi+1]             ;
+        movq            mm2,            mm1                 ;
+
+        movq            mm4,            mm3                 ;
+        punpcklbw       mm1,            mm0                 ;
+
+        punpckhbw       mm2,            mm0                 ;
+        pmullw          mm1,            [rax]               ;
+
+        pmullw          mm2,            [rax]               ;
+        punpcklbw       mm3,            mm0                 ;
+
+        punpckhbw       mm4,            mm0                 ;
+        pmullw          mm3,            [rax+8]             ;
+
+        pmullw          mm4,            [rax+8]             ;
+        paddw           mm1,            mm3                 ;
+
+        paddw           mm2,            mm4                 ;
+        paddw           mm1,            [mmx_bi_rd GLOBAL]  ;
+
+        psraw           mm1,            mmx_filter_shift    ;
+        paddw           mm2,            [mmx_bi_rd GLOBAL]  ;
+
+        psraw           mm2,            mmx_filter_shift    ;
+        movq            mm5,            mm1
+
+        packuswb        mm5,            mm2                 ;
+%if ABI_IS_32BIT
+        add             rsi,            dword ptr arg(1) ;ref_pixels_per_line
+%else
+        movsxd          r8,             dword ptr arg(1) ;ref_pixels_per_line
+        add             rsi,            r8
+%endif
+
+filter_block2d_bil_var_mmx_loop:
+
+        movq            mm1,            [rsi]               ;
+        movq            mm3,            [rsi+1]             ;
+
+        movq            mm2,            mm1                 ;
+        movq            mm4,            mm3                 ;
+
+        punpcklbw       mm1,            mm0                 ;
+        punpckhbw       mm2,            mm0                 ;
+
+        pmullw          mm1,            [rax]               ;
+        pmullw          mm2,            [rax]               ;
+
+        punpcklbw       mm3,            mm0                 ;
+        punpckhbw       mm4,            mm0                 ;
+
+        pmullw          mm3,            [rax+8]             ;
+        pmullw          mm4,            [rax+8]             ;
+
+        paddw           mm1,            mm3                 ;
+        paddw           mm2,            mm4                 ;
+
+        paddw           mm1,            [mmx_bi_rd GLOBAL]  ;
+        psraw           mm1,            mmx_filter_shift    ;
+
+        paddw           mm2,            [mmx_bi_rd GLOBAL]  ;
+        psraw           mm2,            mmx_filter_shift    ;
+
+        movq            mm3,            mm5                 ;
+        movq            mm4,            mm5                 ;
+
+        punpcklbw       mm3,            mm0                 ;
+        punpckhbw       mm4,            mm0                 ;
+
+        movq            mm5,            mm1                 ;
+        packuswb        mm5,            mm2                 ;
+
+        pmullw          mm3,            [rdx]               ;
+        pmullw          mm4,            [rdx]               ;
+
+        pmullw          mm1,            [rdx+8]             ;
+        pmullw          mm2,            [rdx+8]             ;
+
+        paddw           mm1,            mm3                 ;
+        paddw           mm2,            mm4                 ;
+
+        paddw           mm1,            [mmx_bi_rd GLOBAL]  ;
+        paddw           mm2,            [mmx_bi_rd GLOBAL]  ;
+
+        psraw           mm1,            mmx_filter_shift    ;
+        psraw           mm2,            mmx_filter_shift    ;
+
+        movq            mm3,            [rdi]               ;
+        movq            mm4,            mm3                 ;
+
+        punpcklbw       mm3,            mm0                 ;
+        punpckhbw       mm4,            mm0                 ;
+
+        psubw           mm1,            mm3                 ;
+        psubw           mm2,            mm4                 ;
+
+        paddw           mm6,            mm1                 ;
+        pmaddwd         mm1,            mm1                 ;
+
+        paddw           mm6,            mm2                 ;
+        pmaddwd         mm2,            mm2                 ;
+
+        paddd           mm7,            mm1                 ;
+        paddd           mm7,            mm2                 ;
+
+%if ABI_IS_32BIT
+        add             rsi,            dword ptr arg(1) ;ref_pixels_per_line    ;
+        add             rdi,            dword ptr arg(3) ;src_pixels_per_line    ;
+%else
+        movsxd          r8,             dword ptr arg(1) ;ref_pixels_per_line    ;
+        movsxd          r9,             dword ptr arg(3) ;src_pixels_per_line    ;
+        add             rsi,            r8
+        add             rdi,            r9
+%endif
+        sub             rcx,            1                   ;
+        jnz             filter_block2d_bil_var_mmx_loop       ;
+
+
+        pxor            mm3,            mm3                 ;
+        pxor            mm2,            mm2                 ;
+
+        punpcklwd       mm2,            mm6                 ;
+        punpckhwd       mm3,            mm6                 ;
+
+        paddd           mm2,            mm3                 ;
+        movq            mm6,            mm2                 ;
+
+        psrlq           mm6,            32                  ;
+        paddd           mm2,            mm6                 ;
+
+        psrad           mm2,            16                  ;
+        movq            mm4,            mm7                 ;
+
+        psrlq           mm4,            32                  ;
+        paddd           mm4,            mm7                 ;
+
+        mov             rdi,            arg(7) ;sum
+        mov             rsi,            arg(8) ;sumsquared
+
+        movd            dword ptr [rdi],          mm2                 ;
+        movd            dword ptr [rsi],          mm4                 ;
+
+    ; begin epilog
+    add rsp, 16
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;unsigned int vp8_get16x16pred_error_mmx
+;(
+;    unsigned char *src_ptr,
+;    int src_stride,
+;    unsigned char *ref_ptr,
+;    int ref_stride
+;)
+global sym(vp8_get16x16pred_error_mmx)
+sym(vp8_get16x16pred_error_mmx):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 16
+    ; end prolog
+
+        mov         rsi,            arg(0) ;DWORD PTR [src_ptr]
+        mov         rdi,            arg(2) ;DWORD PTR [ref_ptr]
+
+        movsxd      rax,            DWORD PTR arg(1) ;[src_stride]
+        movsxd      rdx,            DWORD PTR arg(3) ;[ref_stride]
+
+        pxor        mm0,            mm0                     ; clear xmm0 for unpack
+        pxor        mm7,            mm7                     ; clear xmm7 for accumulating diffs
+
+        pxor        mm6,            mm6                     ; clear xmm6 for accumulating sse
+        mov         rcx,            16
+
+var16loop:
+
+        movq        mm1,            [rsi]
+        movq        mm2,            [rdi]
+
+        movq        mm3,            mm1
+        movq        mm4,            mm2
+
+        punpcklbw   mm1,            mm0
+        punpckhbw   mm3,            mm0
+
+        punpcklbw   mm2,            mm0
+        punpckhbw   mm4,            mm0
+
+        psubw       mm1,            mm2
+        psubw       mm3,            mm4
+
+        paddw       mm7,            mm1
+        pmaddwd     mm1,            mm1
+
+        paddw       mm7,            mm3
+        pmaddwd     mm3,            mm3
+
+        paddd       mm6,            mm1
+        paddd       mm6,            mm3
+
+
+        movq        mm1,            [rsi+8]
+        movq        mm2,            [rdi+8]
+
+        movq        mm3,            mm1
+        movq        mm4,            mm2
+
+        punpcklbw   mm1,            mm0
+        punpckhbw   mm3,            mm0
+
+        punpcklbw   mm2,            mm0
+        punpckhbw   mm4,            mm0
+
+        psubw       mm1,            mm2
+        psubw       mm3,            mm4
+
+        paddw       mm7,            mm1
+        pmaddwd     mm1,            mm1
+
+        paddw       mm7,            mm3
+        pmaddwd     mm3,            mm3
+
+        paddd       mm6,            mm1
+        paddd       mm6,            mm3
+
+        add         rsi,            rax
+        add         rdi,            rdx
+
+        sub         rcx,            1
+        jnz         var16loop
+
+
+        movq        mm1,            mm6
+        pxor        mm6,            mm6
+
+        pxor        mm5,            mm5
+        punpcklwd   mm6,            mm7
+
+        punpckhwd   mm5,            mm7
+        psrad       mm5,            16
+
+        psrad       mm6,            16
+        paddd       mm6,            mm5
+
+        movq        mm2,            mm1
+        psrlq       mm1,            32
+
+        paddd       mm2,            mm1
+        movq        mm7,            mm6
+
+        psrlq       mm6,            32
+        paddd       mm6,            mm7
+
+        movd DWORD PTR [rsp],       mm6  ;Sum
+        movd DWORD PTR [rsp+4],     mm2  ;SSE
+
+        ; return (SSE-((Sum*Sum)>>8));
+        movsxd      rdx, dword ptr [rsp]
+        imul        rdx, rdx
+        sar         rdx, 8
+        movsxd      rax, dword ptr [rsp + 4]
+        sub         rax, rdx
+
+
+    ; begin epilog
+    add rsp, 16
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+SECTION_RODATA
+;short mmx_bi_rd[4] = { 64, 64, 64, 64};
+align 16
+mmx_bi_rd:
+    times 4 dw 64
diff --git a/vp8/encoder/x86/variance_impl_sse2.asm b/vp8/encoder/x86/variance_impl_sse2.asm
new file mode 100644
index 0000000..7e5ee28
--- /dev/null
+++ b/vp8/encoder/x86/variance_impl_sse2.asm
@@ -0,0 +1,975 @@
+;
+;  Copyright (c) 2010 The VP8 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.
+;
+
+
+%include "vpx_ports/x86_abi_support.asm"
+
+%define xmm_filter_shift            7
+
+;unsigned int vp8_get_mb_ss_sse2
+;(
+;    short *src_ptr
+;)
+global sym(vp8_get_mb_ss_sse2)
+sym(vp8_get_mb_ss_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 1
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 16
+    ; end prolog
+
+
+        mov         rax, arg(0) ;[src_ptr]
+        mov         rcx, 8
+        pxor        xmm4, xmm4
+
+NEXTROW:
+        movdqa      xmm0, [rax]
+        movdqa      xmm1, [rax+16]
+        movdqa      xmm2, [rax+32]
+        movdqa      xmm3, [rax+48]
+        pmaddwd     xmm0, xmm0
+        pmaddwd     xmm1, xmm1
+        pmaddwd     xmm2, xmm2
+        pmaddwd     xmm3, xmm3
+
+        paddd       xmm0, xmm1
+        paddd       xmm2, xmm3
+        paddd       xmm4, xmm0
+        paddd       xmm4, xmm2
+
+        add         rax, 0x40
+        dec         rcx
+        ja          NEXTROW
+
+        movdqa      xmm3,xmm4
+        psrldq      xmm4,8
+        paddd       xmm4,xmm3
+        movdqa      xmm3,xmm4
+        psrldq      xmm4,4
+        paddd       xmm4,xmm3
+        movd        rax,xmm4
+
+
+    ; begin epilog
+    add rsp, 16
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_get16x16var_sse2
+;(
+;    unsigned char   *  src_ptr,
+;    int             source_stride,
+;    unsigned char   *  ref_ptr,
+;    int             recon_stride,
+;    unsigned int    *  SSE,
+;    int             *  Sum
+;)
+global sym(vp8_get16x16var_sse2)
+sym(vp8_get16x16var_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 16
+    ; end prolog
+
+        mov         rsi,            arg(0) ;[src_ptr]
+        mov         rdi,            arg(2) ;[ref_ptr]
+
+        movsxd      rax,            DWORD PTR arg(1) ;[source_stride]
+        movsxd      rdx,            DWORD PTR arg(3) ;[recon_stride]
+
+        pxor        xmm0,           xmm0                        ; clear xmm0 for unpack
+        pxor        xmm7,           xmm7                        ; clear xmm7 for accumulating diffs
+
+        pxor        xmm6,           xmm6                        ; clear xmm6 for accumulating sse
+        mov         rcx,            16
+
+var16loop:
+        movdqu      xmm1,           XMMWORD PTR [rsi]
+        movdqu      xmm2,           XMMWORD PTR [rdi]
+
+        movdqa      xmm3,           xmm1
+        movdqa      xmm4,           xmm2
+
+
+        punpcklbw   xmm1,           xmm0
+        punpckhbw   xmm3,           xmm0
+
+        punpcklbw   xmm2,           xmm0
+        punpckhbw   xmm4,           xmm0
+
+
+        psubw       xmm1,           xmm2
+        psubw       xmm3,           xmm4
+
+        paddw       xmm7,           xmm1
+        pmaddwd     xmm1,           xmm1
+
+        paddw       xmm7,           xmm3
+        pmaddwd     xmm3,           xmm3
+
+        paddd       xmm6,           xmm1
+        paddd       xmm6,           xmm3
+
+        add         rsi,            rax
+        add         rdi,            rdx
+
+        sub         rcx,            1
+        jnz         var16loop
+
+
+        movdqa      xmm1,           xmm6
+        pxor        xmm6,           xmm6
+
+        pxor        xmm5,           xmm5
+        punpcklwd   xmm6,           xmm7
+
+        punpckhwd   xmm5,           xmm7
+        psrad       xmm5,           16
+
+        psrad       xmm6,           16
+        paddd       xmm6,           xmm5
+
+        movdqa      xmm2,           xmm1
+        punpckldq   xmm1,           xmm0
+
+        punpckhdq   xmm2,           xmm0
+        movdqa      xmm7,           xmm6
+
+        paddd       xmm1,           xmm2
+        punpckldq   xmm6,           xmm0
+
+        punpckhdq   xmm7,           xmm0
+        paddd       xmm6,           xmm7
+
+        movdqa      xmm2,           xmm1
+        movdqa      xmm7,           xmm6
+
+        psrldq      xmm1,           8
+        psrldq      xmm6,           8
+
+        paddd       xmm7,           xmm6
+        paddd       xmm1,           xmm2
+
+        mov         rax,            arg(5) ;[Sum]
+        mov         rdi,            arg(4) ;[SSE]
+
+        movd DWORD PTR [rax],       xmm7
+        movd DWORD PTR [rdi],       xmm1
+
+
+    ; begin epilog
+    add rsp, 16
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;unsigned int vp8_get16x16pred_error_sse2
+;(
+;   unsigned char *src_ptr,
+;    int src_stride,
+;    unsigned char *ref_ptr,
+;    int ref_stride
+;)
+global sym(vp8_get16x16pred_error_sse2)
+sym(vp8_get16x16pred_error_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 4
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 16
+    ; end prolog
+
+        mov         rsi,            arg(0) ;[src_ptr]
+        mov         rdi,            arg(2) ;[ref_ptr]
+
+        movsxd      rax,            DWORD PTR arg(1) ;[src_stride]
+        movsxd      rdx,            DWORD PTR arg(3) ;[ref_stride]
+
+        pxor        xmm0,           xmm0                        ; clear xmm0 for unpack
+        pxor        xmm7,           xmm7                        ; clear xmm7 for accumulating diffs
+
+        pxor        xmm6,           xmm6                        ; clear xmm6 for accumulating sse
+        mov         rcx,            16
+
+var16peloop:
+        movdqu      xmm1,           XMMWORD PTR [rsi]
+        movdqu      xmm2,           XMMWORD PTR [rdi]
+
+        movdqa      xmm3,           xmm1
+        movdqa      xmm4,           xmm2
+
+        punpcklbw   xmm1,           xmm0
+        punpckhbw   xmm3,           xmm0
+
+        punpcklbw   xmm2,           xmm0
+        punpckhbw   xmm4,           xmm0
+
+        psubw       xmm1,           xmm2
+        psubw       xmm3,           xmm4
+
+        paddw       xmm7,           xmm1
+        pmaddwd     xmm1,           xmm1
+
+        paddw       xmm7,           xmm3
+        pmaddwd     xmm3,           xmm3
+
+        paddd       xmm6,           xmm1
+        paddd       xmm6,           xmm3
+
+        add         rsi,            rax
+        add         rdi,            rdx
+
+        sub         rcx,            1
+        jnz         var16peloop
+
+
+        movdqa      xmm1,           xmm6
+        pxor        xmm6,           xmm6
+
+        pxor        xmm5,           xmm5
+        punpcklwd   xmm6,           xmm7
+
+        punpckhwd   xmm5,           xmm7
+        psrad       xmm5,           16
+
+        psrad       xmm6,           16
+        paddd       xmm6,           xmm5
+
+        movdqa      xmm2,           xmm1
+        punpckldq   xmm1,           xmm0
+
+        punpckhdq   xmm2,           xmm0
+        movdqa      xmm7,           xmm6
+
+        paddd       xmm1,           xmm2
+        punpckldq   xmm6,           xmm0
+
+        punpckhdq   xmm7,           xmm0
+        paddd       xmm6,           xmm7
+
+        movdqa      xmm2,           xmm1
+        movdqa      xmm7,           xmm6
+
+        psrldq      xmm1,           8
+        psrldq      xmm6,           8
+
+        paddd       xmm7,           xmm6
+        paddd       xmm1,           xmm2
+
+        movd DWORD PTR [rsp],       xmm7  ;Sum
+        movd DWORD PTR [rsp+4],     xmm1  ;SSE
+
+        ; return (SSE-((Sum*Sum)>>8));
+        movsxd      rdx, dword ptr [rsp]
+        imul        rdx, rdx
+        sar         rdx, 8
+        movsxd      rax, dword ptr [rsp + 4]
+        sub         rax, rdx
+
+    ; begin epilog
+    add rsp, 16
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+
+;unsigned int vp8_get8x8var_sse2
+;(
+;    unsigned char   *  src_ptr,
+;    int             source_stride,
+;    unsigned char   *  ref_ptr,
+;    int             recon_stride,
+;    unsigned int    *  SSE,
+;    int             *  Sum
+;)
+global sym(vp8_get8x8var_sse2)
+sym(vp8_get8x8var_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 6
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 16
+    ; end prolog
+
+        mov         rsi,            arg(0) ;[src_ptr]
+        mov         rdi,            arg(2) ;[ref_ptr]
+
+        movsxd      rax,            DWORD PTR arg(1) ;[source_stride]
+        movsxd      rdx,            DWORD PTR arg(3) ;[recon_stride]
+
+        pxor        xmm0,           xmm0                        ; clear xmm0 for unpack
+        pxor        xmm7,           xmm7                        ; clear xmm7 for accumulating diffs
+
+        movq        xmm1,           QWORD PTR [rsi]
+        movq        xmm2,           QWORD PTR [rdi]
+
+        punpcklbw   xmm1,           xmm0
+        punpcklbw   xmm2,           xmm0
+
+        psubsw      xmm1,           xmm2
+        paddw       xmm7,           xmm1
+
+        pmaddwd     xmm1,           xmm1
+
+        movq        xmm2,           QWORD PTR[rsi + rax]
+        movq        xmm3,           QWORD PTR[rdi + rdx]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+
+        movq        xmm2,           QWORD PTR[rsi + rax * 2]
+        movq        xmm3,           QWORD PTR[rdi + rdx * 2]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+
+        lea         rsi,            [rsi + rax * 2]
+        lea         rdi,            [rdi + rdx * 2]
+        movq        xmm2,           QWORD PTR[rsi + rax]
+        movq        xmm3,           QWORD PTR[rdi + rdx]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+        movq        xmm2,           QWORD PTR[rsi + rax *2]
+        movq        xmm3,           QWORD PTR[rdi + rdx *2]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+
+        lea         rsi,            [rsi + rax * 2]
+        lea         rdi,            [rdi + rdx * 2]
+
+
+        movq        xmm2,           QWORD PTR[rsi + rax]
+        movq        xmm3,           QWORD PTR[rdi + rdx]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+        movq        xmm2,           QWORD PTR[rsi + rax *2]
+        movq        xmm3,           QWORD PTR[rdi + rdx *2]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+
+        lea         rsi,            [rsi + rax * 2]
+        lea         rdi,            [rdi + rdx * 2]
+
+        movq        xmm2,           QWORD PTR[rsi + rax]
+        movq        xmm3,           QWORD PTR[rdi + rdx]
+
+        punpcklbw   xmm2,           xmm0
+        punpcklbw   xmm3,           xmm0
+
+        psubsw      xmm2,           xmm3
+        paddw       xmm7,           xmm2
+
+        pmaddwd     xmm2,           xmm2
+        paddd       xmm1,           xmm2
+
+
+        movdqa      xmm6,           xmm7
+        punpcklwd   xmm6,           xmm0
+
+        punpckhwd   xmm7,           xmm0
+        movdqa      xmm2,           xmm1
+
+        paddw       xmm6,           xmm7
+        punpckldq   xmm1,           xmm0
+
+        punpckhdq   xmm2,           xmm0
+        movdqa      xmm7,           xmm6
+
+        paddd       xmm1,           xmm2
+        punpckldq   xmm6,           xmm0
+
+        punpckhdq   xmm7,           xmm0
+        paddw       xmm6,           xmm7
+
+        movdqa      xmm2,           xmm1
+        movdqa      xmm7,           xmm6
+
+        psrldq      xmm1,           8
+        psrldq      xmm6,           8
+
+        paddw       xmm7,           xmm6
+        paddd       xmm1,           xmm2
+
+        mov         rax,            arg(5) ;[Sum]
+        mov         rdi,            arg(4) ;[SSE]
+
+        movd        rdx,            xmm7
+        movsx       rcx,            dx
+
+        mov  dword ptr [rax],       ecx
+        movd DWORD PTR [rdi],       xmm1
+
+    ; begin epilog
+    add rsp, 16
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+;void vp8_filter_block2d_bil_var_sse2
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    unsigned short *HFilter,
+;    unsigned short *VFilter,
+;    int *sum,
+;    unsigned int *sumsquared;;
+;
+;)
+global sym(vp8_filter_block2d_bil_var_sse2)
+sym(vp8_filter_block2d_bil_var_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 9
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    sub         rsp, 16
+    ; end prolog
+
+        pxor            xmm6,           xmm6                 ;
+        pxor            xmm7,           xmm7                 ;
+        mov             rax,            arg(5) ;HFilter             ;
+
+        mov             rdx,            arg(6) ;VFilter             ;
+        mov             rsi,            arg(0) ;ref_ptr              ;
+
+        mov             rdi,            arg(2) ;src_ptr              ;
+        movsxd          rcx,            dword ptr arg(4) ;Height              ;
+
+        pxor            xmm0,           xmm0                 ;
+        movq            xmm1,           QWORD PTR [rsi]               ;
+
+        movq            xmm3,           QWORD PTR [rsi+1]        ;
+        punpcklbw       xmm1,           xmm0                 ;
+
+        pmullw          xmm1,           [rax]               ;
+        punpcklbw       xmm3,           xmm0
+            ;
+        pmullw          xmm3,           [rax+16]             ;
+        paddw           xmm1,           xmm3                 ;
+
+        paddw           xmm1,           [xmm_bi_rd GLOBAL]   ;
+        psraw           xmm1,           xmm_filter_shift    ;
+
+        movdqa          xmm5,           xmm1
+%if ABI_IS_32BIT
+        add             rsi,            dword ptr arg(1) ;ref_pixels_per_line    ;
+%else
+        movsxd          r8,             dword ptr arg(1) ;ref_pixels_per_line    ;
+        add             rsi,            r8
+%endif
+filter_block2d_bil_var_sse2_loop:
+
+        movq            xmm1,           QWORD PTR [rsi]               ;
+        movq            xmm3,           QWORD PTR [rsi+1]             ;
+
+        punpcklbw       xmm1,           xmm0                 ;
+        pmullw          xmm1,           [rax]               ;
+
+        punpcklbw       xmm3,           xmm0                 ;
+        pmullw          xmm3,           [rax+16]             ;
+
+        paddw           xmm1,           xmm3                 ;
+        paddw           xmm1,           [xmm_bi_rd GLOBAL]   ;
+
+        psraw           xmm1,           xmm_filter_shift    ;
+        movdqa          xmm3,           xmm5                 ;
+
+        movdqa          xmm5,           xmm1                 ;
+        pmullw          xmm3,           [rdx]               ;
+
+        pmullw          xmm1,           [rdx+16]             ;
+        paddw           xmm1,           xmm3                 ;
+
+        paddw           xmm1,           [xmm_bi_rd GLOBAL]   ;
+        psraw           xmm1,           xmm_filter_shift    ;
+
+        movq            xmm3,           QWORD PTR [rdi]               ;
+        punpcklbw       xmm3,           xmm0                 ;
+
+        psubw           xmm1,           xmm3                 ;
+        paddw           xmm6,           xmm1                 ;
+
+        pmaddwd         xmm1,           xmm1                 ;
+        paddd           xmm7,           xmm1                 ;
+
+%if ABI_IS_32BIT
+        add             rsi,            dword ptr arg(1) ;ref_pixels_per_line    ;
+        add             rdi,            dword ptr arg(3) ;src_pixels_per_line    ;
+%else
+        movsxd          r8,             dword ptr arg(1) ;ref_pixels_per_line    ;
+        movsxd          r9,             dword ptr arg(3) ;src_pixels_per_line    ;
+        add             rsi,            r8
+        add             rdi,            r9
+%endif
+
+        sub             rcx,            1                   ;
+        jnz             filter_block2d_bil_var_sse2_loop       ;
+
+
+        movdq2q         mm6,            xmm6                ;
+        movdq2q         mm7,            xmm7                ;
+
+        psrldq          xmm6,           8
+        psrldq          xmm7,           8
+
+        movdq2q         mm2,            xmm6
+        movdq2q         mm3,            xmm7
+
+        paddw           mm6,            mm2
+        paddd           mm7,            mm3
+
+        pxor            mm3,            mm3                 ;
+        pxor            mm2,            mm2                 ;
+
+        punpcklwd       mm2,            mm6                 ;
+        punpckhwd       mm3,            mm6                 ;
+
+        paddd           mm2,            mm3                 ;
+        movq            mm6,            mm2                 ;
+
+        psrlq           mm6,            32                  ;
+        paddd           mm2,            mm6                 ;
+
+        psrad           mm2,            16                  ;
+        movq            mm4,            mm7                 ;
+
+        psrlq           mm4,            32                  ;
+        paddd           mm4,            mm7                 ;
+
+        mov             rsi,            arg(7) ; sum
+        mov             rdi,            arg(8) ; sumsquared
+
+        movd            [rsi],          mm2    ; xsum
+        movd            [rdi],          mm4    ; xxsum
+
+
+    ; begin epilog
+    add rsp, 16
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_half_horiz_vert_variance16x_h_sse2
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_half_horiz_vert_variance16x_h_sse2)
+sym(vp8_half_horiz_vert_variance16x_h_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+%if ABI_IS_32BIT=0
+    movsxd          r8, dword ptr arg(1) ;ref_pixels_per_line
+    movsxd          r9, dword ptr arg(3) ;src_pixels_per_line
+%endif
+
+        pxor            xmm6,           xmm6                ;  error accumulator
+        pxor            xmm7,           xmm7                ;  sse eaccumulator
+        mov             rsi,            arg(0) ;ref_ptr              ;
+
+        mov             rdi,            arg(2) ;src_ptr              ;
+        movsxd          rcx,            dword ptr arg(4) ;Height              ;
+        movsxd          rax,            dword ptr arg(1) ;ref_pixels_per_line
+
+        pxor            xmm0,           xmm0                ;
+
+        movq            xmm5,           QWORD PTR [rsi]     ;  xmm5 = s0,s1,s2..s8
+        movq            xmm3,           QWORD PTR [rsi+1]   ;  xmm3 = s1,s2,s3..s9
+        pavgb           xmm5,           xmm3                ;  xmm5 = avg(xmm1,xmm3) horizontal line 1
+
+%if ABI_IS_32BIT
+        add             rsi,            dword ptr arg(1) ;ref_pixels_per_line    ;  next source
+%else
+        add             rsi, r8
+%endif
+
+vp8_half_horiz_vert_variance16x_h_1:
+
+        movq            xmm1,           QWORD PTR [rsi]     ;
+        movq            xmm2,           QWORD PTR [rsi+1]   ;
+        pavgb           xmm1,           xmm2                ;  xmm1 = avg(xmm1,xmm3) horizontal line i+1
+
+        pavgb           xmm5,           xmm1                ;  xmm = vertical average of the above
+        punpcklbw       xmm5,           xmm0                ;  xmm5 = words of above
+
+        movq            xmm3,           QWORD PTR [rdi]     ;  xmm3 = d0,d1,d2..d8
+        punpcklbw       xmm3,           xmm0                ;  xmm3 = words of above
+
+        psubw           xmm5,           xmm3                ;  xmm5 -= xmm3
+        paddw           xmm6,           xmm5                ;  xmm6 += accumulated column differences
+        pmaddwd         xmm5,           xmm5                ;  xmm5 *= xmm5
+        paddd           xmm7,           xmm5                ;  xmm7 += accumulated square column differences
+
+        movdqa          xmm5,           xmm1                ;  save xmm1 for use on the next row
+
+%if ABI_IS_32BIT
+        add             esi,            dword ptr arg(1) ;ref_pixels_per_line    ;  next source
+        add             edi,            dword ptr arg(3) ;src_pixels_per_line    ;  next destination
+%else
+        add             rsi, r8
+        add             rdi, r9
+%endif
+
+        sub             rcx,            1                   ;
+        jnz             vp8_half_horiz_vert_variance16x_h_1     ;
+
+        movdq2q         mm6,            xmm6                ;
+        movdq2q         mm7,            xmm7                ;
+
+        psrldq          xmm6,           8
+        psrldq          xmm7,           8
+
+        movdq2q         mm2,            xmm6
+        movdq2q         mm3,            xmm7
+
+        paddw           mm6,            mm2
+        paddd           mm7,            mm3
+
+        pxor            mm3,            mm3                 ;
+        pxor            mm2,            mm2                 ;
+
+        punpcklwd       mm2,            mm6                 ;
+        punpckhwd       mm3,            mm6                 ;
+
+        paddd           mm2,            mm3                 ;
+        movq            mm6,            mm2                 ;
+
+        psrlq           mm6,            32                  ;
+        paddd           mm2,            mm6                 ;
+
+        psrad           mm2,            16                  ;
+        movq            mm4,            mm7                 ;
+
+        psrlq           mm4,            32                  ;
+        paddd           mm4,            mm7                 ;
+
+        mov             rsi,            arg(5) ; sum
+        mov             rdi,            arg(6) ; sumsquared
+
+        movd            [rsi],          mm2                 ;
+        movd            [rdi],          mm4                 ;
+
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_half_vert_variance16x_h_sse2
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_half_vert_variance16x_h_sse2)
+sym(vp8_half_vert_variance16x_h_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+%if ABI_IS_32BIT=0
+    movsxd          r8, dword ptr arg(1) ;ref_pixels_per_line
+    movsxd          r9, dword ptr arg(3) ;src_pixels_per_line
+%endif
+
+        pxor            xmm6,           xmm6                ;  error accumulator
+        pxor            xmm7,           xmm7                ;  sse eaccumulator
+        mov             rsi,            arg(0) ;ref_ptr              ;
+
+        mov             rdi,            arg(2) ;src_ptr              ;
+        movsxd          rcx,            dword ptr arg(4) ;Height              ;
+        movsxd          rax,            dword ptr arg(1) ;ref_pixels_per_line
+
+        pxor            xmm0,           xmm0                ;
+vp8_half_vert_variance16x_h_1:
+        movq            xmm5,           QWORD PTR [rsi]     ;  xmm5 = s0,s1,s2..s8
+        movq            xmm3,           QWORD PTR [rsi+rax] ;  xmm3 = s1,s2,s3..s9
+
+        pavgb           xmm5,           xmm3                ;  xmm5 = avg(xmm1,xmm3)
+        punpcklbw       xmm5,           xmm0                ;  xmm5 = words of above
+
+        movq            xmm3,           QWORD PTR [rdi]     ;  xmm3 = d0,d1,d2..d8
+        punpcklbw       xmm3,           xmm0                ;  xmm3 = words of above
+
+        psubw           xmm5,           xmm3                ;  xmm5 -= xmm3
+        paddw           xmm6,           xmm5                ;  xmm6 += accumulated column differences
+        pmaddwd         xmm5,           xmm5                ;  xmm5 *= xmm5
+        paddd           xmm7,           xmm5                ;  xmm7 += accumulated square column differences
+
+%if ABI_IS_32BIT
+        add             esi,            dword ptr arg(1) ;ref_pixels_per_line    ;  next source
+        add             edi,            dword ptr arg(3) ;src_pixels_per_line    ;  next destination
+%else
+        add             rsi, r8
+        add             rdi, r9
+%endif
+
+        sub             rcx,            1                   ;
+        jnz             vp8_half_vert_variance16x_h_1          ;
+
+        movdq2q         mm6,            xmm6                ;
+        movdq2q         mm7,            xmm7                ;
+
+        psrldq          xmm6,           8
+        psrldq          xmm7,           8
+
+        movdq2q         mm2,            xmm6
+        movdq2q         mm3,            xmm7
+
+        paddw           mm6,            mm2
+        paddd           mm7,            mm3
+
+        pxor            mm3,            mm3                 ;
+        pxor            mm2,            mm2                 ;
+
+        punpcklwd       mm2,            mm6                 ;
+        punpckhwd       mm3,            mm6                 ;
+
+        paddd           mm2,            mm3                 ;
+        movq            mm6,            mm2                 ;
+
+        psrlq           mm6,            32                  ;
+        paddd           mm2,            mm6                 ;
+
+        psrad           mm2,            16                  ;
+        movq            mm4,            mm7                 ;
+
+        psrlq           mm4,            32                  ;
+        paddd           mm4,            mm7                 ;
+
+        mov             rsi,            arg(5) ; sum
+        mov             rdi,            arg(6) ; sumsquared
+
+        movd            [rsi],          mm2                 ;
+        movd            [rdi],          mm4                 ;
+
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+;void vp8_half_horiz_variance16x_h_sse2
+;(
+;    unsigned char *ref_ptr,
+;    int ref_pixels_per_line,
+;    unsigned char *src_ptr,
+;    int src_pixels_per_line,
+;    unsigned int Height,
+;    int *sum,
+;    unsigned int *sumsquared
+;)
+global sym(vp8_half_horiz_variance16x_h_sse2)
+sym(vp8_half_horiz_variance16x_h_sse2):
+    push        rbp
+    mov         rbp, rsp
+    SHADOW_ARGS_TO_STACK 7
+    GET_GOT     rbx
+    push rsi
+    push rdi
+    ; end prolog
+
+%if ABI_IS_32BIT=0
+    movsxd          r8, dword ptr arg(1) ;ref_pixels_per_line
+    movsxd          r9, dword ptr arg(3) ;src_pixels_per_line
+%endif
+
+        pxor            xmm6,           xmm6                ;  error accumulator
+        pxor            xmm7,           xmm7                ;  sse eaccumulator
+        mov             rsi,            arg(0) ;ref_ptr              ;
+
+        mov             rdi,            arg(2) ;src_ptr              ;
+        movsxd          rcx,            dword ptr arg(4) ;Height              ;
+
+        pxor            xmm0,           xmm0                ;
+vp8_half_horiz_variance16x16_1:
+        movq            xmm5,           QWORD PTR [rsi]     ;  xmm5 = s0,s1,s2..s8
+        movq            xmm3,           QWORD PTR [rsi+1]   ;  xmm3 = s1,s2,s3..s9
+
+        pavgb           xmm5,           xmm3                ;  xmm5 = avg(xmm1,xmm3)
+        punpcklbw       xmm5,           xmm0                ;  xmm5 = words of above
+
+        movq            xmm3,           QWORD PTR [rdi]     ;  xmm3 = d0,d1,d2..d8
+        punpcklbw       xmm3,           xmm0                ;  xmm3 = words of above
+
+        psubw           xmm5,           xmm3                ;  xmm5 -= xmm3
+        paddw           xmm6,           xmm5                ;  xmm6 += accumulated column differences
+        pmaddwd         xmm5,           xmm5                ;  xmm5 *= xmm5
+        paddd           xmm7,           xmm5                ;  xmm7 += accumulated square column differences
+
+%if ABI_IS_32BIT
+        add             esi,            dword ptr arg(1) ;ref_pixels_per_line    ;  next source
+        add             edi,            dword ptr arg(3) ;src_pixels_per_line    ;  next destination
+%else
+        add             rsi, r8
+        add             rdi, r9
+%endif
+        sub             rcx,            1                   ;
+        jnz             vp8_half_horiz_variance16x16_1        ;
+
+        movdq2q         mm6,            xmm6                ;
+        movdq2q         mm7,            xmm7                ;
+
+        psrldq          xmm6,           8
+        psrldq          xmm7,           8
+
+        movdq2q         mm2,            xmm6
+        movdq2q         mm3,            xmm7
+
+        paddw           mm6,            mm2
+        paddd           mm7,            mm3
+
+        pxor            mm3,            mm3                 ;
+        pxor            mm2,            mm2                 ;
+
+        punpcklwd       mm2,            mm6                 ;
+        punpckhwd       mm3,            mm6                 ;
+
+        paddd           mm2,            mm3                 ;
+        movq            mm6,            mm2                 ;
+
+        psrlq           mm6,            32                  ;
+        paddd           mm2,            mm6                 ;
+
+        psrad           mm2,            16                  ;
+        movq            mm4,            mm7                 ;
+
+        psrlq           mm4,            32                  ;
+        paddd           mm4,            mm7                 ;
+
+        mov             rsi,            arg(5) ; sum
+        mov             rdi,            arg(6) ; sumsquared
+
+        movd            [rsi],          mm2                 ;
+        movd            [rdi],          mm4                 ;
+
+
+    ; begin epilog
+    pop rdi
+    pop rsi
+    RESTORE_GOT
+    UNSHADOW_ARGS
+    pop         rbp
+    ret
+
+
+SECTION_RODATA
+;    short xmm_bi_rd[8] = { 64, 64, 64, 64,64, 64, 64, 64};
+align 16
+xmm_bi_rd:
+    times 8 dw 64
diff --git a/vp8/encoder/x86/variance_mmx.c b/vp8/encoder/x86/variance_mmx.c
new file mode 100644
index 0000000..4a5b25b
--- /dev/null
+++ b/vp8/encoder/x86/variance_mmx.c
@@ -0,0 +1,596 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "variance.h"
+#include "pragmas.h"
+#include "vpx_ports/mem.h"
+
+extern void filter_block1d_h6_mmx
+(
+    unsigned char *src_ptr,
+    unsigned short *output_ptr,
+    unsigned int src_pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    short *vp7_filter
+);
+extern void filter_block1d_v6_mmx
+(
+    short *src_ptr,
+    unsigned char *output_ptr,
+    unsigned int pixels_per_line,
+    unsigned int pixel_step,
+    unsigned int output_height,
+    unsigned int output_width,
+    short *vp7_filter
+);
+
+extern unsigned int vp8_get_mb_ss_mmx(short *src_ptr);
+extern unsigned int vp8_get8x8var_mmx
+(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *SSE,
+    int *Sum
+);
+extern unsigned int vp8_get4x4var_mmx
+(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *SSE,
+    int *Sum
+);
+extern unsigned int vp8_get4x4sse_cs_mmx
+(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride
+);
+extern void vp8_filter_block2d_bil4x4_var_mmx
+(
+    unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    unsigned char *src_ptr,
+    int src_pixels_per_line,
+    const short *HFilter,
+    const short *VFilter,
+    int *sum,
+    unsigned int *sumsquared
+);
+extern void vp8_filter_block2d_bil_var_mmx
+(
+    unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    const short *HFilter,
+    const short *VFilter,
+    int *sum,
+    unsigned int *sumsquared
+);
+extern unsigned int vp8_get16x16pred_error_mmx
+(
+    unsigned char *src_ptr,
+    int src_stride,
+    unsigned char *ref_ptr,
+    int ref_stride
+);
+
+
+void vp8_test_get_mb_ss(void)
+{
+    short zz[] =
+    {
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -2, -2, -2, -2, 2, 2, 2, 2, -2, -2, -2, -2, 2, 2, 2, 2,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -3, -3, -3, -3, 3, 3, 3, 3, -3, -3, -3, -3, 3, 3, 3, 3,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+        -4, -4, -4, -4, 4, 4, 4, 4, -4, -4, -4, -4, 4, 4, 4, 4,
+    };
+    int s = 0, x = vp8_get_mb_ss_mmx(zz);
+    {
+        int y;
+
+        for (y = 0; y < 256; y++)
+            s += (zz[y] * zz[y]);
+    }
+
+    x += 0;
+}
+
+
+unsigned int vp8_get16x16var_mmx(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned *SSE,
+    unsigned *SUM
+)
+{
+    unsigned int sse0, sse1, sse2, sse3, var;
+    int sum0, sum1, sum2, sum3, avg;
+
+
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_mmx(src_ptr + 8, source_stride, ref_ptr + 8, recon_stride, &sse1, &sum1);
+    vp8_get8x8var_mmx(src_ptr + 8 * source_stride, source_stride, ref_ptr + 8 * recon_stride, recon_stride, &sse2, &sum2) ;
+    vp8_get8x8var_mmx(src_ptr + 8 * source_stride + 8, source_stride, ref_ptr + 8 * recon_stride + 8, recon_stride, &sse3, &sum3);
+
+    var = sse0 + sse1 + sse2 + sse3;
+    avg = sum0 + sum1 + sum2 + sum3;
+
+    *SSE = var;
+    *SUM = avg;
+    return (var - ((avg * avg) >> 8));
+
+}
+
+
+
+
+
+unsigned int vp8_variance4x4_mmx(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+    vp8_get4x4var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &var, &avg) ;
+    *sse = var;
+    return (var - ((avg * avg) >> 4));
+
+}
+
+unsigned int vp8_variance8x8_mmx(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int var;
+    int avg;
+
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &var, &avg) ;
+    *sse = var;
+
+    return (var - ((avg * avg) >> 6));
+
+}
+
+unsigned int vp8_mse16x16_mmx(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, sse2, sse3, var;
+    int sum0, sum1, sum2, sum3;
+
+
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_mmx(src_ptr + 8, source_stride, ref_ptr + 8, recon_stride, &sse1, &sum1);
+    vp8_get8x8var_mmx(src_ptr + 8 * source_stride, source_stride, ref_ptr + 8 * recon_stride, recon_stride, &sse2, &sum2) ;
+    vp8_get8x8var_mmx(src_ptr + 8 * source_stride + 8, source_stride, ref_ptr + 8 * recon_stride + 8, recon_stride, &sse3, &sum3);
+
+    var = sse0 + sse1 + sse2 + sse3;
+    *sse = var;
+    return var;
+}
+
+
+unsigned int vp8_variance16x16_mmx(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    int *sse)
+{
+    unsigned int sse0, sse1, sse2, sse3, var;
+    int sum0, sum1, sum2, sum3, avg;
+
+
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_mmx(src_ptr + 8, source_stride, ref_ptr + 8, recon_stride, &sse1, &sum1);
+    vp8_get8x8var_mmx(src_ptr + 8 * source_stride, source_stride, ref_ptr + 8 * recon_stride, recon_stride, &sse2, &sum2) ;
+    vp8_get8x8var_mmx(src_ptr + 8 * source_stride + 8, source_stride, ref_ptr + 8 * recon_stride + 8, recon_stride, &sse3, &sum3);
+
+    var = sse0 + sse1 + sse2 + sse3;
+    avg = sum0 + sum1 + sum2 + sum3;
+    *sse = var;
+    return (var - ((avg * avg) >> 8));
+}
+
+unsigned int vp8_variance16x8_mmx(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, var;
+    int sum0, sum1, avg;
+
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_mmx(src_ptr + 8, source_stride, ref_ptr + 8, recon_stride, &sse1, &sum1);
+
+    var = sse0 + sse1;
+    avg = sum0 + sum1;
+    *sse = var;
+    return (var - ((avg * avg) >> 7));
+
+}
+
+
+unsigned int vp8_variance8x16_mmx(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, var;
+    int sum0, sum1, avg;
+
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_mmx(src_ptr + 8 * source_stride, source_stride, ref_ptr + 8 * recon_stride, recon_stride, &sse1, &sum1) ;
+
+    var = sse0 + sse1;
+    avg = sum0 + sum1;
+    *sse = var;
+
+    return (var - ((avg * avg) >> 7));
+
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+// the mmx function that does the bilinear filtering and var calculation //
+// int one pass                                                          //
+///////////////////////////////////////////////////////////////////////////
+DECLARE_ALIGNED(16, const short, vp8_vp7_bilinear_filters_mmx[8][8]) =
+{
+    { 128, 128, 128, 128,  0,  0,  0,  0 },
+    { 112, 112, 112, 112, 16, 16, 16, 16 },
+    {  96, 96, 96, 96, 32, 32, 32, 32 },
+    {  80, 80, 80, 80, 48, 48, 48, 48 },
+    {  64, 64, 64, 64, 64, 64, 64, 64 },
+    {  48, 48, 48, 48, 80, 80, 80, 80 },
+    {  32, 32, 32, 32, 96, 96, 96, 96 },
+    {  16, 16, 16, 16, 112, 112, 112, 112 }
+};
+
+unsigned int vp8_sub_pixel_variance4x4_mmx
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse)
+
+{
+    int xsum;
+    unsigned int xxsum;
+    vp8_filter_block2d_bil4x4_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum, &xxsum
+    );
+    *sse = xxsum;
+    return (xxsum - ((xsum * xsum) >> 4));
+}
+
+
+unsigned int vp8_sub_pixel_variance8x8_mmx
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+
+    int xsum;
+    unsigned int xxsum;
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 8,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum, &xxsum
+    );
+    *sse = xxsum;
+    return (xxsum - ((xsum * xsum) >> 6));
+}
+
+unsigned int vp8_sub_pixel_variance16x16_mmx
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+
+    int xsum0, xsum1;
+    unsigned int xxsum0, xxsum1;
+
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 16,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum0, &xxsum0
+    );
+
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr + 8, src_pixels_per_line,
+        dst_ptr + 8, dst_pixels_per_line, 16,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum1, &xxsum1
+    );
+
+    xsum0 += xsum1;
+    xxsum0 += xxsum1;
+
+    *sse = xxsum0;
+    return (xxsum0 - ((xsum0 * xsum0) >> 8));
+
+
+}
+
+unsigned int vp8_sub_pixel_mse16x16_mmx(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    vp8_sub_pixel_variance16x16_mmx(src_ptr, src_pixels_per_line, xoffset, yoffset, dst_ptr, dst_pixels_per_line, sse);
+    return *sse;
+}
+
+unsigned int vp8_sub_pixel_variance16x8_mmx
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum0, xsum1;
+    unsigned int xxsum0, xxsum1;
+
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 8,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum0, &xxsum0
+    );
+
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr + 8, src_pixels_per_line,
+        dst_ptr + 8, dst_pixels_per_line, 8,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum1, &xxsum1
+    );
+
+    xsum0 += xsum1;
+    xxsum0 += xxsum1;
+
+    *sse = xxsum0;
+    return (xxsum0 - ((xsum0 * xsum0) >> 7));
+}
+
+unsigned int vp8_sub_pixel_variance8x16_mmx
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    int *sse
+)
+{
+    int xsum;
+    unsigned int xxsum;
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 16,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum, &xxsum
+    );
+    *sse = xxsum;
+    return (xxsum - ((xsum * xsum) >> 7));
+}
+
+unsigned int vp8_i_variance16x16_mmx(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, sse2, sse3, var;
+    int sum0, sum1, sum2, sum3, avg;
+
+
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_mmx(src_ptr + 8, source_stride, ref_ptr + 8, recon_stride, &sse1, &sum1);
+    vp8_get8x8var_mmx(src_ptr + (source_stride >> 1), source_stride, ref_ptr + (recon_stride >> 1), recon_stride, &sse2, &sum2) ;
+    vp8_get8x8var_mmx(src_ptr + (source_stride >> 1) + 8, source_stride, ref_ptr + (recon_stride >> 1) + 8, recon_stride, &sse3, &sum3);
+
+    var = sse0 + sse1 + sse2 + sse3;
+    avg = sum0 + sum1 + sum2 + sum3;
+    *sse = var;
+    return (var - ((avg * avg) >> 8));
+
+}
+
+unsigned int vp8_i_variance8x16_mmx(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, var;
+    int sum0, sum1, avg;
+    vp8_get8x8var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_mmx(src_ptr + (source_stride >> 1), source_stride, ref_ptr + (recon_stride >> 1), recon_stride, &sse1, &sum1) ;
+
+    var = sse0 + sse1;
+    avg = sum0 + sum1;
+
+    *sse = var;
+    return (var - ((avg * avg) >> 7));
+
+}
+
+unsigned int vp8_i_sub_pixel_variance16x16_mmx
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum0, xsum1;
+    unsigned int xxsum0, xxsum1;
+    int f2soffset = (src_pixels_per_line >> 1);
+    int f2doffset = (dst_pixels_per_line >> 1);
+
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 8,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum0, &xxsum0
+    );
+
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr + 8, src_pixels_per_line,
+        dst_ptr + 8, dst_pixels_per_line, 8,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum1, &xxsum1
+    );
+
+    xsum0 += xsum1;
+    xxsum0 += xxsum1;
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr + f2soffset, src_pixels_per_line,
+        dst_ptr + f2doffset, dst_pixels_per_line, 8,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum1, &xxsum1
+    );
+
+    xsum0 += xsum1;
+    xxsum0 += xxsum1;
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr + f2soffset + 8, src_pixels_per_line,
+        dst_ptr + f2doffset + 8, dst_pixels_per_line, 8,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum1, &xxsum1
+    );
+
+    xsum0 += xsum1;
+    xxsum0 += xxsum1;
+    *sse = xxsum0;
+    return (xxsum0 - ((xsum0 * xsum0) >> 8));
+}
+
+
+unsigned int vp8_i_sub_pixel_variance8x16_mmx
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum0, xsum1;
+    unsigned int xxsum0, xxsum1;
+    int f2soffset = (src_pixels_per_line >> 1);
+    int f2doffset = (dst_pixels_per_line >> 1);
+
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 8,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum0, &xxsum0
+    );
+
+
+    vp8_filter_block2d_bil_var_mmx(
+        src_ptr + f2soffset, src_pixels_per_line,
+        dst_ptr + f2doffset, dst_pixels_per_line, 8,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum1, &xxsum1
+    );
+
+    xsum0 += xsum1;
+    xxsum0 += xxsum1;
+    *sse = xxsum0;
+    return (xxsum0 - ((xsum0 * xsum0) >> 7));
+}
diff --git a/vp8/encoder/x86/variance_sse2.c b/vp8/encoder/x86/variance_sse2.c
new file mode 100644
index 0000000..ea80753
--- /dev/null
+++ b/vp8/encoder/x86/variance_sse2.c
@@ -0,0 +1,514 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "variance.h"
+#include "pragmas.h"
+#include "vpx_ports/mem.h"
+
+extern void filter_block1d_h6_mmx(unsigned char *src_ptr, unsigned short *output_ptr, unsigned int src_pixels_per_line, unsigned int pixel_step, unsigned int output_height, unsigned int output_width, short *vp7_filter);
+extern void filter_block1d_v6_mmx(short *src_ptr, unsigned char *output_ptr, unsigned int pixels_per_line, unsigned int pixel_step, unsigned int output_height, unsigned int output_width, short *vp7_filter);
+extern void filter_block1d8_h6_sse2(unsigned char *src_ptr, unsigned short *output_ptr, unsigned int src_pixels_per_line, unsigned int pixel_step, unsigned int output_height, unsigned int output_width, short *vp7_filter);
+extern void filter_block1d8_v6_sse2(short *src_ptr, unsigned char *output_ptr, unsigned int pixels_per_line, unsigned int pixel_step, unsigned int output_height, unsigned int output_width, short *vp7_filter);
+
+extern void vp8_filter_block2d_bil4x4_var_mmx
+(
+    unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    unsigned char *src_ptr,
+    int src_pixels_per_line,
+    const short *HFilter,
+    const short *VFilter,
+    int *sum,
+    unsigned int *sumsquared
+);
+
+extern unsigned int vp8_get4x4var_mmx
+(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *SSE,
+    int *Sum
+);
+
+unsigned int vp8_get_mb_ss_sse2
+(
+    short *src_ptr
+);
+unsigned int vp8_get16x16var_sse2
+(
+    unsigned char     *src_ptr,
+    int             source_stride,
+    unsigned char     *ref_ptr,
+    int             recon_stride,
+    unsigned int      *SSE,
+    int               *Sum
+);
+unsigned int vp8_get16x16pred_error_sse2
+(
+    unsigned char *src_ptr,
+    int src_stride,
+    unsigned char *ref_ptr,
+    int ref_stride
+);
+unsigned int vp8_get8x8var_sse2
+(
+    unsigned char     *src_ptr,
+    int             source_stride,
+    unsigned char     *ref_ptr,
+    int             recon_stride,
+    unsigned int      *SSE,
+    int               *Sum
+);
+void vp8_filter_block2d_bil_var_sse2
+(
+    unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    const short *HFilter,
+    const short *VFilter,
+    int *sum,
+    unsigned int *sumsquared
+);
+void vp8_half_horiz_vert_variance16x_h_sse2
+(
+    unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int *sum,
+    unsigned int *sumsquared
+);
+void vp8_half_horiz_variance16x_h_sse2
+(
+    unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int *sum,
+    unsigned int *sumsquared
+);
+void vp8_half_vert_variance16x_h_sse2
+(
+    unsigned char *ref_ptr,
+    int ref_pixels_per_line,
+    unsigned char *src_ptr,
+    int src_pixels_per_line,
+    unsigned int Height,
+    int *sum,
+    unsigned int *sumsquared
+);
+
+DECLARE_ALIGNED(16, extern short, vp8_vp7_bilinear_filters_mmx[8][8]);
+
+unsigned int vp8_variance4x4_wmt(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride)
+{
+    unsigned int var;
+    int avg;
+
+    vp8_get4x4var_mmx(src_ptr, source_stride, ref_ptr, recon_stride, &var, &avg) ;
+    return (var - ((avg * avg) >> 4));
+
+}
+
+
+
+unsigned int vp8_variance8x8_wmt
+(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride)
+{
+    unsigned int var;
+    int avg;
+
+    vp8_get8x8var_sse2(src_ptr, source_stride, ref_ptr, recon_stride, &var, &avg) ;
+
+    return (var - ((avg * avg) >> 6));
+
+}
+
+
+unsigned int vp8_variance16x16_wmt
+(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0;
+    int sum0;
+
+
+    vp8_get16x16var_sse2(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    *sse = sse0;
+    return (sse0 - ((sum0 * sum0) >> 8));
+}
+unsigned int vp8_mse16x16_wmt(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+
+    unsigned int sse0;
+    int sum0;
+    vp8_get16x16var_sse2(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    *sse = sse0;
+    return sse0;
+
+}
+
+
+unsigned int vp8_variance16x8_wmt
+(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, var;
+    int sum0, sum1, avg;
+
+    vp8_get8x8var_sse2(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_sse2(src_ptr + 8, source_stride, ref_ptr + 8, recon_stride, &sse1, &sum1);
+
+    var = sse0 + sse1;
+    avg = sum0 + sum1;
+    *sse = var;
+    return (var - ((avg * avg) >> 7));
+
+}
+
+unsigned int vp8_variance8x16_wmt
+(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, var;
+    int sum0, sum1, avg;
+
+    vp8_get8x8var_sse2(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_sse2(src_ptr + 8 * source_stride, source_stride, ref_ptr + 8 * recon_stride, recon_stride, &sse1, &sum1) ;
+
+    var = sse0 + sse1;
+    avg = sum0 + sum1;
+    *sse = var;
+    return (var - ((avg * avg) >> 7));
+
+}
+
+///////////////////////////////////////////////////////////////////////////
+// the mmx function that does the bilinear filtering and var calculation //
+// int one pass                                                          //
+///////////////////////////////////////////////////////////////////////////
+DECLARE_ALIGNED(16, const short, vp8_bilinear_filters_xmm[8][16]) =
+{
+    { 128, 128, 128, 128, 128, 128, 128, 128,  0,  0,  0,  0,  0,  0,  0,  0 },
+    { 112, 112, 112, 112, 112, 112, 112, 112, 16, 16, 16, 16, 16, 16, 16, 16 },
+    {  96, 96, 96, 96, 96, 96, 96, 96, 32, 32, 32, 32, 32, 32, 32, 32 },
+    {  80, 80, 80, 80, 80, 80, 80, 80, 48, 48, 48, 48, 48, 48, 48, 48 },
+    {  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 },
+    {  48, 48, 48, 48, 48, 48, 48, 48, 80, 80, 80, 80, 80, 80, 80, 80 },
+    {  32, 32, 32, 32, 32, 32, 32, 32, 96, 96, 96, 96, 96, 96, 96, 96 },
+    {  16, 16, 16, 16, 16, 16, 16, 16, 112, 112, 112, 112, 112, 112, 112, 112 }
+};
+unsigned int vp8_sub_pixel_variance4x4_wmt
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum;
+    unsigned int xxsum;
+    vp8_filter_block2d_bil4x4_var_mmx(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line,
+        vp8_vp7_bilinear_filters_mmx[xoffset], vp8_vp7_bilinear_filters_mmx[yoffset],
+        &xsum, &xxsum
+    );
+    *sse = xxsum;
+    return (xxsum - ((xsum * xsum) >> 4));
+}
+
+
+unsigned int vp8_sub_pixel_variance8x8_wmt
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+
+    int xsum;
+    unsigned int xxsum;
+    vp8_filter_block2d_bil_var_sse2(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 8,
+        vp8_bilinear_filters_xmm[xoffset], vp8_bilinear_filters_xmm[yoffset],
+        &xsum, &xxsum
+    );
+
+    *sse = xxsum;
+    return (xxsum - ((xsum * xsum) >> 6));
+}
+
+unsigned int vp8_sub_pixel_variance16x16_wmt
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum0, xsum1;
+    unsigned int xxsum0, xxsum1;
+
+
+    // note we could avoid these if statements if the calling function
+    // just called the appropriate functions inside.
+    if (xoffset == 4 && yoffset == 0)
+    {
+        vp8_half_horiz_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            &xsum0, &xxsum0);
+
+        vp8_half_horiz_variance16x_h_sse2(
+            src_ptr + 8, src_pixels_per_line,
+            dst_ptr + 8, dst_pixels_per_line, 16,
+            &xsum1, &xxsum1);
+    }
+    else if (xoffset == 0 && yoffset == 4)
+    {
+        vp8_half_vert_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            &xsum0, &xxsum0);
+
+        vp8_half_vert_variance16x_h_sse2(
+            src_ptr + 8, src_pixels_per_line,
+            dst_ptr + 8, dst_pixels_per_line, 16,
+            &xsum1, &xxsum1);
+    }
+    else if (xoffset == 4 && yoffset == 4)
+    {
+        vp8_half_horiz_vert_variance16x_h_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            &xsum0, &xxsum0);
+
+        vp8_half_horiz_vert_variance16x_h_sse2(
+            src_ptr + 8, src_pixels_per_line,
+            dst_ptr + 8, dst_pixels_per_line, 16,
+            &xsum1, &xxsum1);
+    }
+    else
+    {
+        vp8_filter_block2d_bil_var_sse2(
+            src_ptr, src_pixels_per_line,
+            dst_ptr, dst_pixels_per_line, 16,
+            vp8_bilinear_filters_xmm[xoffset], vp8_bilinear_filters_xmm[yoffset],
+            &xsum0, &xxsum0
+        );
+
+
+        vp8_filter_block2d_bil_var_sse2(
+            src_ptr + 8, src_pixels_per_line,
+            dst_ptr + 8, dst_pixels_per_line, 16,
+            vp8_bilinear_filters_xmm[xoffset], vp8_bilinear_filters_xmm[yoffset],
+            &xsum1, &xxsum1
+        );
+    }
+
+    xsum0 += xsum1;
+    xxsum0 += xxsum1;
+    *sse = xxsum0;
+    return (xxsum0 - ((xsum0 * xsum0) >> 8));
+}
+
+unsigned int vp8_sub_pixel_mse16x16_wmt(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    vp8_sub_pixel_variance16x16_wmt(src_ptr, src_pixels_per_line, xoffset, yoffset, dst_ptr, dst_pixels_per_line, sse);
+    return *sse;
+}
+
+unsigned int vp8_sub_pixel_variance16x8_wmt
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+
+)
+{
+    int xsum0, xsum1;
+    unsigned int xxsum0, xxsum1;
+
+
+    vp8_filter_block2d_bil_var_sse2(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 8,
+        vp8_bilinear_filters_xmm[xoffset], vp8_bilinear_filters_xmm[yoffset],
+        &xsum0, &xxsum0
+    );
+
+
+    vp8_filter_block2d_bil_var_sse2(
+        src_ptr + 8, src_pixels_per_line,
+        dst_ptr + 8, dst_pixels_per_line, 8,
+        vp8_bilinear_filters_xmm[xoffset], vp8_bilinear_filters_xmm[yoffset],
+        &xsum1, &xxsum1
+    );
+
+    xsum0 += xsum1;
+    xxsum0 += xxsum1;
+
+    *sse = xxsum0;
+    return (xxsum0 - ((xsum0 * xsum0) >> 7));
+}
+
+unsigned int vp8_sub_pixel_variance8x16_wmt
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    int xsum;
+    unsigned int xxsum;
+    vp8_filter_block2d_bil_var_sse2(
+        src_ptr, src_pixels_per_line,
+        dst_ptr, dst_pixels_per_line, 16,
+        vp8_bilinear_filters_xmm[xoffset], vp8_bilinear_filters_xmm[yoffset],
+        &xsum, &xxsum
+    );
+
+    *sse = xxsum;
+    return (xxsum - ((xsum * xsum) >> 7));
+}
+
+unsigned int vp8_i_variance16x16_wmt(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, sse2, sse3, var;
+    int sum0, sum1, sum2, sum3, avg;
+
+
+    vp8_get8x8var_sse2(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_sse2(src_ptr + 8, source_stride, ref_ptr + 8, recon_stride, &sse1, &sum1);
+    vp8_get8x8var_sse2(src_ptr + (source_stride >> 1), source_stride, ref_ptr + (recon_stride >> 1), recon_stride, &sse2, &sum2) ;
+    vp8_get8x8var_sse2(src_ptr + (source_stride >> 1) + 8, source_stride, ref_ptr + (recon_stride >> 1) + 8, recon_stride, &sse3, &sum3);
+
+    var = sse0 + sse1 + sse2 + sse3;
+    avg = sum0 + sum1 + sum2 + sum3;
+
+    *sse = var;
+    return (var - ((avg * avg) >> 8));
+
+}
+
+unsigned int vp8_i_variance8x16_wmt(
+    unsigned char *src_ptr,
+    int  source_stride,
+    unsigned char *ref_ptr,
+    int  recon_stride,
+    unsigned int *sse)
+{
+    unsigned int sse0, sse1, var;
+    int sum0, sum1, avg;
+    vp8_get8x8var_sse2(src_ptr, source_stride, ref_ptr, recon_stride, &sse0, &sum0) ;
+    vp8_get8x8var_sse2(src_ptr + (source_stride >> 1), source_stride, ref_ptr + (recon_stride >> 1), recon_stride, &sse1, &sum1) ;
+
+    var = sse0 + sse1;
+    avg = sum0 + sum1;
+
+    *sse = var;
+    return (var - ((avg * avg) >> 7));
+
+}
+
+
+unsigned int vp8_i_sub_pixel_variance16x16_wmt
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+    return vp8_sub_pixel_variance16x16_wmt(src_ptr, (src_pixels_per_line >> 1), xoffset, yoffset, dst_ptr, (dst_pixels_per_line >> 1), sse);
+}
+
+
+unsigned int vp8_i_sub_pixel_variance8x16_wmt
+(
+    unsigned char  *src_ptr,
+    int  src_pixels_per_line,
+    int  xoffset,
+    int  yoffset,
+    unsigned char *dst_ptr,
+    int dst_pixels_per_line,
+    unsigned int *sse
+)
+{
+
+    return vp8_sub_pixel_variance8x16_wmt(src_ptr, (src_pixels_per_line >> 1), xoffset, yoffset, dst_ptr, (dst_pixels_per_line >> 1), sse);
+}
diff --git a/vp8/encoder/x86/variance_x86.h b/vp8/encoder/x86/variance_x86.h
new file mode 100644
index 0000000..35fc90c
--- /dev/null
+++ b/vp8/encoder/x86/variance_x86.h
@@ -0,0 +1,275 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#ifndef VARIANCE_X86_H
+#define VARIANCE_X86_H
+
+
+/* Note:
+ *
+ * This platform is commonly built for runtime CPU detection. If you modify
+ * any of the function mappings present in this file, be sure to also update
+ * them in the function pointer initialization code
+ */
+#if HAVE_MMX
+extern prototype_sad(vp8_sad4x4_mmx);
+extern prototype_sad(vp8_sad8x8_mmx);
+extern prototype_sad(vp8_sad8x16_mmx);
+extern prototype_sad(vp8_sad16x8_mmx);
+extern prototype_sad(vp8_sad16x16_mmx);
+extern prototype_variance(vp8_variance4x4_mmx);
+extern prototype_variance(vp8_variance8x8_mmx);
+extern prototype_variance(vp8_variance8x16_mmx);
+extern prototype_variance(vp8_variance16x8_mmx);
+extern prototype_variance(vp8_variance16x16_mmx);
+extern prototype_subpixvariance(vp8_sub_pixel_variance4x4_mmx);
+extern prototype_subpixvariance(vp8_sub_pixel_variance8x8_mmx);
+extern prototype_subpixvariance(vp8_sub_pixel_variance8x16_mmx);
+extern prototype_subpixvariance(vp8_sub_pixel_variance16x8_mmx);
+extern prototype_subpixvariance(vp8_sub_pixel_variance16x16_mmx);
+extern prototype_subpixvariance(vp8_sub_pixel_mse16x16_mmx);
+extern prototype_getmbss(vp8_get_mb_ss_mmx);
+extern prototype_variance(vp8_mse16x16_mmx);
+extern prototype_sad(vp8_get16x16pred_error_mmx);
+extern prototype_variance2(vp8_get8x8var_mmx);
+extern prototype_variance2(vp8_get16x16var_mmx);
+extern prototype_sad(vp8_get4x4sse_cs_mmx);
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_variance_sad4x4
+#define vp8_variance_sad4x4 vp8_sad4x4_mmx
+
+#undef  vp8_variance_sad8x8
+#define vp8_variance_sad8x8 vp8_sad8x8_mmx
+
+#undef  vp8_variance_sad8x16
+#define vp8_variance_sad8x16 vp8_sad8x16_mmx
+
+#undef  vp8_variance_sad16x8
+#define vp8_variance_sad16x8 vp8_sad16x8_mmx
+
+#undef  vp8_variance_sad16x16
+#define vp8_variance_sad16x16 vp8_sad16x16_mmx
+
+#undef  vp8_variance_var4x4
+#define vp8_variance_var4x4 vp8_variance4x4_mmx
+
+#undef  vp8_variance_var8x8
+#define vp8_variance_var8x8 vp8_variance8x8_mmx
+
+#undef  vp8_variance_var8x16
+#define vp8_variance_var8x16 vp8_variance8x16_mmx
+
+#undef  vp8_variance_var16x8
+#define vp8_variance_var16x8 vp8_variance16x8_mmx
+
+#undef  vp8_variance_var16x16
+#define vp8_variance_var16x16 vp8_variance16x16_mmx
+
+#undef  vp8_variance_subpixvar4x4
+#define vp8_variance_subpixvar4x4 vp8_sub_pixel_variance4x4_mmx
+
+#undef  vp8_variance_subpixvar8x8
+#define vp8_variance_subpixvar8x8 vp8_sub_pixel_variance8x8_mmx
+
+#undef  vp8_variance_subpixvar8x16
+#define vp8_variance_subpixvar8x16 vp8_sub_pixel_variance8x16_mmx
+
+#undef  vp8_variance_subpixvar16x8
+#define vp8_variance_subpixvar16x8 vp8_sub_pixel_variance16x8_mmx
+
+#undef  vp8_variance_subpixvar16x16
+#define vp8_variance_subpixvar16x16 vp8_sub_pixel_variance16x16_mmx
+
+#undef  vp8_variance_subpixmse16x16
+#define vp8_variance_subpixmse16x16 vp8_sub_pixel_mse16x16_mmx
+
+#undef  vp8_variance_getmbss
+#define vp8_variance_getmbss vp8_get_mb_ss_mmx
+
+#undef  vp8_variance_mse16x16
+#define vp8_variance_mse16x16 vp8_mse16x16_mmx
+
+#undef  vp8_variance_get16x16prederror
+#define vp8_variance_get16x16prederror vp8_get16x16pred_error_mmx
+
+#undef  vp8_variance_get8x8var
+#define vp8_variance_get8x8var vp8_get8x8var_mmx
+
+#undef  vp8_variance_get16x16var
+#define vp8_variance_get16x16var vp8_get16x16var_mmx
+
+#undef  vp8_variance_get4x4sse_cs
+#define vp8_variance_get4x4sse_cs vp8_get4x4sse_cs_mmx
+
+#endif
+#endif
+
+
+#if HAVE_SSE2
+extern prototype_sad(vp8_sad4x4_wmt);
+extern prototype_sad(vp8_sad8x8_wmt);
+extern prototype_sad(vp8_sad8x16_wmt);
+extern prototype_sad(vp8_sad16x8_wmt);
+extern prototype_sad(vp8_sad16x16_wmt);
+extern prototype_variance(vp8_variance4x4_wmt);
+extern prototype_variance(vp8_variance8x8_wmt);
+extern prototype_variance(vp8_variance8x16_wmt);
+extern prototype_variance(vp8_variance16x8_wmt);
+extern prototype_variance(vp8_variance16x16_wmt);
+extern prototype_subpixvariance(vp8_sub_pixel_variance4x4_wmt);
+extern prototype_subpixvariance(vp8_sub_pixel_variance8x8_wmt);
+extern prototype_subpixvariance(vp8_sub_pixel_variance8x16_wmt);
+extern prototype_subpixvariance(vp8_sub_pixel_variance16x8_wmt);
+extern prototype_subpixvariance(vp8_sub_pixel_variance16x16_wmt);
+extern prototype_subpixvariance(vp8_sub_pixel_mse16x16_wmt);
+extern prototype_getmbss(vp8_get_mb_ss_sse2);
+extern prototype_variance(vp8_mse16x16_wmt);
+extern prototype_sad(vp8_get16x16pred_error_sse2);
+extern prototype_variance2(vp8_get8x8var_sse2);
+extern prototype_variance2(vp8_get16x16var_sse2);
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_variance_sad4x4
+#define vp8_variance_sad4x4 vp8_sad4x4_wmt
+
+#undef  vp8_variance_sad8x8
+#define vp8_variance_sad8x8 vp8_sad8x8_wmt
+
+#undef  vp8_variance_sad8x16
+#define vp8_variance_sad8x16 vp8_sad8x16_wmt
+
+#undef  vp8_variance_sad16x8
+#define vp8_variance_sad16x8 vp8_sad16x8_wmt
+
+#undef  vp8_variance_sad16x16
+#define vp8_variance_sad16x16 vp8_sad16x16_wmt
+
+#undef  vp8_variance_var4x4
+#define vp8_variance_var4x4 vp8_variance4x4_wmt
+
+#undef  vp8_variance_var8x8
+#define vp8_variance_var8x8 vp8_variance8x8_wmt
+
+#undef  vp8_variance_var8x16
+#define vp8_variance_var8x16 vp8_variance8x16_wmt
+
+#undef  vp8_variance_var16x8
+#define vp8_variance_var16x8 vp8_variance16x8_wmt
+
+#undef  vp8_variance_var16x16
+#define vp8_variance_var16x16 vp8_variance16x16_wmt
+
+#undef  vp8_variance_subpixvar4x4
+#define vp8_variance_subpixvar4x4 vp8_sub_pixel_variance4x4_wmt
+
+#undef  vp8_variance_subpixvar8x8
+#define vp8_variance_subpixvar8x8 vp8_sub_pixel_variance8x8_wmt
+
+#undef  vp8_variance_subpixvar8x16
+#define vp8_variance_subpixvar8x16 vp8_sub_pixel_variance8x16_wmt
+
+#undef  vp8_variance_subpixvar16x8
+#define vp8_variance_subpixvar16x8 vp8_sub_pixel_variance16x8_wmt
+
+#undef  vp8_variance_subpixvar16x16
+#define vp8_variance_subpixvar16x16 vp8_sub_pixel_variance16x16_wmt
+
+#undef  vp8_variance_subpixmse16x16
+#define vp8_variance_subpixmse16x16 vp8_sub_pixel_mse16x16_wmt
+
+#undef  vp8_variance_getmbss
+#define vp8_variance_getmbss vp8_get_mb_ss_sse2
+
+#undef  vp8_variance_mse16x16
+#define vp8_variance_mse16x16 vp8_mse16x16_wmt
+
+#undef  vp8_variance_get16x16prederror
+#define vp8_variance_get16x16prederror vp8_get16x16pred_error_sse2
+
+#undef  vp8_variance_get8x8var
+#define vp8_variance_get8x8var vp8_get8x8var_sse2
+
+#undef  vp8_variance_get16x16var
+#define vp8_variance_get16x16var vp8_get16x16var_sse2
+
+#endif
+#endif
+
+
+#if HAVE_SSE3
+extern prototype_sad(vp8_sad16x16_sse3);
+extern prototype_sad(vp8_sad16x8_sse3);
+extern prototype_sad_multi_same_address(vp8_sad16x16x3_sse3);
+extern prototype_sad_multi_same_address(vp8_sad16x8x3_sse3);
+extern prototype_sad_multi_same_address(vp8_sad8x16x3_sse3);
+extern prototype_sad_multi_same_address(vp8_sad8x8x3_sse3);
+extern prototype_sad_multi_same_address(vp8_sad4x4x3_sse3);
+
+extern prototype_sad_multi_dif_address(vp8_sad16x16x4d_sse3);
+extern prototype_sad_multi_dif_address(vp8_sad16x8x4d_sse3);
+extern prototype_sad_multi_dif_address(vp8_sad8x16x4d_sse3);
+extern prototype_sad_multi_dif_address(vp8_sad8x8x4d_sse3);
+extern prototype_sad_multi_dif_address(vp8_sad4x4x4d_sse3);
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+
+#undef  vp8_variance_sad16x16
+#define vp8_variance_sad16x16 vp8_sad16x16_sse3
+
+#undef  vp8_variance_sad16x16x3
+#define vp8_variance_sad16x16x3 vp8_sad16x16x3_sse3
+
+#undef  vp8_variance_sad16x8x3
+#define vp8_variance_sad16x8x3 vp8_sad16x8x3_sse3
+
+#undef  vp8_variance_sad8x16x3
+#define vp8_variance_sad8x16x3 vp8_sad8x16x3_sse3
+
+#undef  vp8_variance_sad8x8x3
+#define vp8_variance_sad8x8x3 vp8_sad8x8x3_sse3
+
+#undef  vp8_variance_sad4x4x3
+#define vp8_variance_sad4x4x3 vp8_sad4x4x3_sse3
+
+#undef  vp8_variance_sad16x16x4d
+#define vp8_variance_sad16x16x4 vp8_sad16x16x4d_sse3
+
+#undef  vp8_variance_sad16x8x4d
+#define vp8_variance_sad16x8x4d vp8_sad16x8x4d_sse3
+
+#undef  vp8_variance_sad8x16x4d
+#define vp8_variance_sad8x16x4d vp8_sad8x16x4d_sse3
+
+#undef  vp8_variance_sad8x8x4d
+#define vp8_variance_sad8x8x4d vp8_sad8x8x4d_sse3
+
+#undef  vp8_variance_sad4x4x4d
+#define vp8_variance_sad4x4x4d vp8_sad4x4x4d_sse3
+
+#endif
+#endif
+
+
+#if HAVE_SSSE3
+extern prototype_sad_multi_same_address(vp8_sad16x16x3_ssse3);
+extern prototype_sad_multi_same_address(vp8_sad16x8x3_ssse3);
+
+#if !CONFIG_RUNTIME_CPU_DETECT
+#undef  vp8_variance_sad16x16x3
+#define vp8_variance_sad16x16x3 vp8_sad16x16x3_ssse3
+
+#undef  vp8_variance_sad16x8x3
+#define vp8_variance_sad16x8x3 vp8_sad16x8x3_ssse3
+
+#endif
+#endif
+
+#endif
diff --git a/vp8/encoder/x86/x86_csystemdependent.c b/vp8/encoder/x86/x86_csystemdependent.c
new file mode 100644
index 0000000..f1391ba
--- /dev/null
+++ b/vp8/encoder/x86/x86_csystemdependent.c
@@ -0,0 +1,287 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_ports/config.h"
+#include "vpx_ports/x86.h"
+#include "variance.h"
+#include "onyx_int.h"
+
+
+#if HAVE_MMX
+void vp8_short_fdct8x4_mmx(short *input, short *output, int pitch)
+{
+    vp8_short_fdct4x4_mmx(input,   output,    pitch);
+    vp8_short_fdct4x4_mmx(input + 4, output + 16, pitch);
+}
+
+void vp8_fast_fdct8x4_mmx(short *input, short *output, int pitch)
+{
+    vp8_fast_fdct4x4_mmx(input,   output   , pitch);
+    vp8_fast_fdct4x4_mmx(input + 4, output + 16, pitch);
+}
+
+int vp8_fast_quantize_b_impl_mmx(short *coeff_ptr, short *zbin_ptr,
+                                 short *qcoeff_ptr, short *dequant_ptr,
+                                 short *scan_mask, short *round_ptr,
+                                 short *quant_ptr, short *dqcoeff_ptr);
+void vp8_fast_quantize_b_mmx(BLOCK *b, BLOCKD *d)
+{
+    short *scan_mask    = vp8_default_zig_zag_mask;//d->scan_order_mask_ptr;
+    short *coeff_ptr  = &b->coeff[0];
+    short *zbin_ptr   = &b->zbin[0][0];
+    short *round_ptr  = &b->round[0][0];
+    short *quant_ptr  = &b->quant[0][0];
+    short *qcoeff_ptr = d->qcoeff;
+    short *dqcoeff_ptr = d->dqcoeff;
+    short *dequant_ptr = &d->dequant[0][0];
+
+    d->eob = vp8_fast_quantize_b_impl_mmx(
+                 coeff_ptr,
+                 zbin_ptr,
+                 qcoeff_ptr,
+                 dequant_ptr,
+                 scan_mask,
+
+                 round_ptr,
+                 quant_ptr,
+                 dqcoeff_ptr
+             );
+}
+
+int vp8_mbblock_error_mmx_impl(short *coeff_ptr, short *dcoef_ptr, int dc);
+int vp8_mbblock_error_mmx(MACROBLOCK *mb, int dc)
+{
+    short *coeff_ptr =  mb->block[0].coeff;
+    short *dcoef_ptr =  mb->e_mbd.block[0].dqcoeff;
+    return vp8_mbblock_error_mmx_impl(coeff_ptr, dcoef_ptr, dc);
+}
+
+int vp8_mbuverror_mmx_impl(short *s_ptr, short *d_ptr);
+int vp8_mbuverror_mmx(MACROBLOCK *mb)
+{
+    short *s_ptr = &mb->coeff[256];
+    short *d_ptr = &mb->e_mbd.dqcoeff[256];
+    return vp8_mbuverror_mmx_impl(s_ptr, d_ptr);
+}
+
+void vp8_subtract_b_mmx_impl(unsigned char *z,  int src_stride,
+                             short *diff, unsigned char *predictor,
+                             int pitch);
+void vp8_subtract_b_mmx(BLOCK *be, BLOCKD *bd, int pitch)
+{
+    unsigned char *z = *(be->base_src) + be->src;
+    unsigned int  src_stride = be->src_stride;
+    short *diff = &be->src_diff[0];
+    unsigned char *predictor = &bd->predictor[0];
+    vp8_subtract_b_mmx_impl(z, src_stride, diff, predictor, pitch);
+}
+
+#endif
+
+#if HAVE_SSE2
+void vp8_short_fdct8x4_wmt(short *input, short *output, int pitch)
+{
+    vp8_short_fdct4x4_wmt(input,   output,    pitch);
+    vp8_short_fdct4x4_wmt(input + 4, output + 16, pitch);
+}
+
+int vp8_fast_quantize_b_impl_sse(short *coeff_ptr, short *zbin_ptr,
+                                 short *qcoeff_ptr, short *dequant_ptr,
+                                 short *scan_mask, short *round_ptr,
+                                 short *quant_ptr, short *dqcoeff_ptr);
+void vp8_fast_quantize_b_sse(BLOCK *b, BLOCKD *d)
+{
+    short *scan_mask    = vp8_default_zig_zag_mask;//d->scan_order_mask_ptr;
+    short *coeff_ptr  = &b->coeff[0];
+    short *zbin_ptr   = &b->zbin[0][0];
+    short *round_ptr  = &b->round[0][0];
+    short *quant_ptr  = &b->quant[0][0];
+    short *qcoeff_ptr = d->qcoeff;
+    short *dqcoeff_ptr = d->dqcoeff;
+    short *dequant_ptr = &d->dequant[0][0];
+
+    d->eob = vp8_fast_quantize_b_impl_sse(
+                 coeff_ptr,
+                 zbin_ptr,
+                 qcoeff_ptr,
+                 dequant_ptr,
+                 scan_mask,
+
+                 round_ptr,
+                 quant_ptr,
+                 dqcoeff_ptr
+             );
+}
+
+int vp8_mbblock_error_xmm_impl(short *coeff_ptr, short *dcoef_ptr, int dc);
+int vp8_mbblock_error_xmm(MACROBLOCK *mb, int dc)
+{
+    short *coeff_ptr =  mb->block[0].coeff;
+    short *dcoef_ptr =  mb->e_mbd.block[0].dqcoeff;
+    return vp8_mbblock_error_xmm_impl(coeff_ptr, dcoef_ptr, dc);
+}
+
+int vp8_mbuverror_xmm_impl(short *s_ptr, short *d_ptr);
+int vp8_mbuverror_xmm(MACROBLOCK *mb)
+{
+    short *s_ptr = &mb->coeff[256];
+    short *d_ptr = &mb->e_mbd.dqcoeff[256];
+    return vp8_mbuverror_xmm_impl(s_ptr, d_ptr);
+}
+
+#endif
+
+void vp8_arch_x86_encoder_init(VP8_COMP *cpi)
+{
+#if CONFIG_RUNTIME_CPU_DETECT
+    int flags = x86_simd_caps();
+    int mmx_enabled = flags & HAS_MMX;
+    int xmm_enabled = flags & HAS_SSE;
+    int wmt_enabled = flags & HAS_SSE2;
+    int SSE3Enabled = flags & HAS_SSE3;
+    int SSSE3Enabled = flags & HAS_SSSE3;
+
+    /* Note:
+     *
+     * This platform can be built without runtime CPU detection as well. If
+     * you modify any of the function mappings present in this file, be sure
+     * to also update them in static mapings (<arch>/filename_<arch>.h)
+     */
+
+    /* Override default functions with fastest ones for this CPU. */
+#if HAVE_MMX
+
+    if (mmx_enabled)
+    {
+        cpi->rtcd.variance.sad16x16              = vp8_sad16x16_mmx;
+        cpi->rtcd.variance.sad16x8               = vp8_sad16x8_mmx;
+        cpi->rtcd.variance.sad8x16               = vp8_sad8x16_mmx;
+        cpi->rtcd.variance.sad8x8                = vp8_sad8x8_mmx;
+        cpi->rtcd.variance.sad4x4                = vp8_sad4x4_mmx;
+
+        cpi->rtcd.variance.var4x4                = vp8_variance4x4_mmx;
+        cpi->rtcd.variance.var8x8                = vp8_variance8x8_mmx;
+        cpi->rtcd.variance.var8x16               = vp8_variance8x16_mmx;
+        cpi->rtcd.variance.var16x8               = vp8_variance16x8_mmx;
+        cpi->rtcd.variance.var16x16              = vp8_variance16x16_mmx;
+
+        cpi->rtcd.variance.subpixvar4x4          = vp8_sub_pixel_variance4x4_mmx;
+        cpi->rtcd.variance.subpixvar8x8          = vp8_sub_pixel_variance8x8_mmx;
+        cpi->rtcd.variance.subpixvar8x16         = vp8_sub_pixel_variance8x16_mmx;
+        cpi->rtcd.variance.subpixvar16x8         = vp8_sub_pixel_variance16x8_mmx;
+        cpi->rtcd.variance.subpixvar16x16        = vp8_sub_pixel_variance16x16_mmx;
+        cpi->rtcd.variance.subpixmse16x16        = vp8_sub_pixel_mse16x16_mmx;
+
+        cpi->rtcd.variance.mse16x16              = vp8_mse16x16_mmx;
+        cpi->rtcd.variance.getmbss               = vp8_get_mb_ss_mmx;
+
+        cpi->rtcd.variance.get16x16prederror     = vp8_get16x16pred_error_mmx;
+        cpi->rtcd.variance.get8x8var             = vp8_get8x8var_mmx;
+        cpi->rtcd.variance.get16x16var           = vp8_get16x16var_mmx;
+        cpi->rtcd.variance.get4x4sse_cs          = vp8_get4x4sse_cs_mmx;
+
+        cpi->rtcd.fdct.short4x4                  = vp8_short_fdct4x4_mmx;
+        cpi->rtcd.fdct.short8x4                  = vp8_short_fdct8x4_mmx;
+        cpi->rtcd.fdct.fast4x4                   = vp8_fast_fdct4x4_mmx;
+        cpi->rtcd.fdct.fast8x4                   = vp8_fast_fdct8x4_mmx;
+        cpi->rtcd.fdct.walsh_short4x4            = vp8_short_walsh4x4_c;
+
+        cpi->rtcd.encodemb.berr                  = vp8_block_error_mmx;
+        cpi->rtcd.encodemb.mberr                 = vp8_mbblock_error_mmx;
+        cpi->rtcd.encodemb.mbuverr               = vp8_mbuverror_mmx;
+        cpi->rtcd.encodemb.subb                  = vp8_subtract_b_mmx;
+        cpi->rtcd.encodemb.submby                = vp8_subtract_mby_mmx;
+        cpi->rtcd.encodemb.submbuv               = vp8_subtract_mbuv_mmx;
+
+        cpi->rtcd.quantize.fastquantb            = vp8_fast_quantize_b_mmx;
+    }
+
+#endif
+#if HAVE_SSE2
+
+    if (wmt_enabled)
+    {
+        cpi->rtcd.variance.sad16x16              = vp8_sad16x16_wmt;
+        cpi->rtcd.variance.sad16x8               = vp8_sad16x8_wmt;
+        cpi->rtcd.variance.sad8x16               = vp8_sad8x16_wmt;
+        cpi->rtcd.variance.sad8x8                = vp8_sad8x8_wmt;
+        cpi->rtcd.variance.sad4x4                = vp8_sad4x4_wmt;
+
+        cpi->rtcd.variance.var4x4                = vp8_variance4x4_wmt;
+        cpi->rtcd.variance.var8x8                = vp8_variance8x8_wmt;
+        cpi->rtcd.variance.var8x16               = vp8_variance8x16_wmt;
+        cpi->rtcd.variance.var16x8               = vp8_variance16x8_wmt;
+        cpi->rtcd.variance.var16x16              = vp8_variance16x16_wmt;
+
+        cpi->rtcd.variance.subpixvar4x4          = vp8_sub_pixel_variance4x4_wmt;
+        cpi->rtcd.variance.subpixvar8x8          = vp8_sub_pixel_variance8x8_wmt;
+        cpi->rtcd.variance.subpixvar8x16         = vp8_sub_pixel_variance8x16_wmt;
+        cpi->rtcd.variance.subpixvar16x8         = vp8_sub_pixel_variance16x8_wmt;
+        cpi->rtcd.variance.subpixvar16x16        = vp8_sub_pixel_variance16x16_wmt;
+        cpi->rtcd.variance.subpixmse16x16        = vp8_sub_pixel_mse16x16_wmt;
+
+        cpi->rtcd.variance.mse16x16              = vp8_mse16x16_wmt;
+        cpi->rtcd.variance.getmbss               = vp8_get_mb_ss_sse2;
+
+        cpi->rtcd.variance.get16x16prederror     = vp8_get16x16pred_error_sse2;
+        cpi->rtcd.variance.get8x8var             = vp8_get8x8var_sse2;
+        cpi->rtcd.variance.get16x16var           = vp8_get16x16var_sse2;
+        /* cpi->rtcd.variance.get4x4sse_cs  not implemented for wmt */;
+
+#if 0
+        /* short SSE2 DCT currently disabled, does not match the MMX version */
+        cpi->rtcd.fdct.short4x4                  = vp8_short_fdct4x4_wmt;
+        cpi->rtcd.fdct.short8x4                  = vp8_short_fdct8x4_wmt;
+#endif
+        /* cpi->rtcd.fdct.fast4x4  not implemented for wmt */;
+        cpi->rtcd.fdct.fast8x4                   = vp8_fast_fdct8x4_wmt;
+        cpi->rtcd.fdct.walsh_short4x4            = vp8_short_walsh4x4_sse2;
+
+        cpi->rtcd.encodemb.berr                  = vp8_block_error_xmm;
+        cpi->rtcd.encodemb.mberr                 = vp8_mbblock_error_xmm;
+        cpi->rtcd.encodemb.mbuverr               = vp8_mbuverror_xmm;
+        /* cpi->rtcd.encodemb.sub* not implemented for wmt */
+
+        cpi->rtcd.quantize.fastquantb            = vp8_fast_quantize_b_sse;
+    }
+
+#endif
+#if HAVE_SSE3
+
+    if (SSE3Enabled)
+    {
+        cpi->rtcd.variance.sad16x16              = vp8_sad16x16_sse3;
+        cpi->rtcd.variance.sad16x16x3            = vp8_sad16x16x3_sse3;
+        cpi->rtcd.variance.sad16x8x3             = vp8_sad16x8x3_sse3;
+        cpi->rtcd.variance.sad8x16x3             = vp8_sad8x16x3_sse3;
+        cpi->rtcd.variance.sad8x8x3              = vp8_sad8x8x3_sse3;
+        cpi->rtcd.variance.sad4x4x3              = vp8_sad4x4x3_sse3;
+        cpi->rtcd.search.full_search             = vp8_full_search_sadx3;
+
+        cpi->rtcd.variance.sad16x16x4d           = vp8_sad16x16x4d_sse3;
+        cpi->rtcd.variance.sad16x8x4d            = vp8_sad16x8x4d_sse3;
+        cpi->rtcd.variance.sad8x16x4d            = vp8_sad8x16x4d_sse3;
+        cpi->rtcd.variance.sad8x8x4d             = vp8_sad8x8x4d_sse3;
+        cpi->rtcd.variance.sad4x4x4d             = vp8_sad4x4x4d_sse3;
+        cpi->rtcd.search.diamond_search          = vp8_diamond_search_sadx4;
+    }
+
+#endif
+#if HAVE_SSSE3
+
+    if (SSSE3Enabled)
+    {
+        cpi->rtcd.variance.sad16x16x3            = vp8_sad16x16x3_ssse3;
+        cpi->rtcd.variance.sad16x8x3             = vp8_sad16x8x3_ssse3;
+    }
+
+#endif
+#endif
+}
diff --git a/vp8/vp8.h b/vp8/vp8.h
new file mode 100644
index 0000000..87ca217
--- /dev/null
+++ b/vp8/vp8.h
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/*!\defgroup vp8 VP8
+ * \ingroup codecs
+ * VP8 is vpx's newest video compression algorithm that uses motion
+ * compensated prediction, Discrete Cosine Transform (DCT) coding of the
+ * prediction error signal and context dependent entropy coding techniques
+ * based on arithmatic principles. It features:
+ *  - YUV 4:2:0 image format
+ *  - Macro-block based coding (16x16 luma plus two 8x8 chroma)
+ *  - 1/4 (1/8) pixel accuracy motion compensated prediction
+ *  - 4x4 DCT transform
+ *  - 128 level linear quantizer
+ *  - In loop deblocking filter
+ *  - Context-based entropy coding
+ *
+ * @{
+ */
+/*!\file vp8.h
+ * \brief Provides controls common to both the VP8 encoder and decoder.
+ */
+#ifndef VP8_H
+#define VP8_H
+#include "vpx_codec_impl_top.h"
+
+/*!\brief Control functions
+ *
+ * The set of macros define the control functions of VP8 interface
+ */
+enum vp8_dec_control_id
+{
+    VP8_SET_REFERENCE       = 1,    /**< pass in an external frame into decoder to be used as reference frame */
+    VP8_COPY_REFERENCE      = 2,    /**< get a copy of reference frame from the decoder */
+    VP8_SET_POSTPROC        = 3,    /**< set decoder's the post processing settings  */
+    VP8_COMMON_CTRL_ID_MAX
+};
+
+/*!\brief post process flags
+ *
+ * The set of macros define VP8 decoder post processing flags
+ */
+enum vp8_postproc_level
+{
+    VP8_NOFILTERING    = 0,
+    VP8_DEBLOCK        = 1,
+    VP8_DEMACROBLOCK   = 2,
+    VP8_ADDNOISE       = 4,
+};
+
+/*!\brief post process flags
+ *
+ * This define a structure that describe the post processing settings. For
+ * the best objective measure (using thet PSNR metric) set post_proc_flag
+ * to VP8_DEBLOCK and deblocking_level to 1.
+ */
+
+typedef struct vp8_postproc_cfg
+{
+    int post_proc_flag;           /**< the types of post processing to be done, should be combination of "vp8_postproc_level" */
+    int deblocking_level;        /**< the strength of deblocking, valid range [0, 16] */
+    int noise_level;             /**< the strength of additive noise, valid range [0, 16] */
+} vp8_postproc_cfg_t;
+
+/*!\brief reference frame type
+ *
+ * The set of macros define the type of VP8 reference frames
+ */
+typedef enum vpx_ref_frame_type
+{
+    VP8_LAST_FRAME = 1,
+    VP8_GOLD_FRAME = 2,
+    VP8_ALTR_FRAME = 4
+} vpx_ref_frame_type_t;
+
+/*!\brief reference frame data struct
+ *
+ * define the data struct to access vp8 reference frames
+ */
+
+typedef struct vpx_ref_frame
+{
+    vpx_ref_frame_type_t  frame_type;   /**< which reference frame */
+    vpx_image_t           img;          /**< reference frame data in image format */
+} vpx_ref_frame_t;
+
+
+/*!\brief vp8 decoder control funciton parameter type
+ *
+ * defines the data type for each of VP8 decoder control funciton requires
+ */
+
+VPX_CTRL_USE_TYPE(VP8_SET_REFERENCE,           vpx_ref_frame_t *)
+VPX_CTRL_USE_TYPE(VP8_COPY_REFERENCE,          vpx_ref_frame_t *)
+VPX_CTRL_USE_TYPE(VP8_SET_POSTPROC,            vp8_postproc_cfg_t *)
+
+
+/*! @} - end defgroup vp8 */
+
+#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
+/* The following definitions are provided for backward compatibility with
+ * the VP8 1.0.x SDK. USE IN PRODUCTION CODE IS NOT RECOMMENDED.
+ */
+
+DECLSPEC_DEPRECATED extern vpx_codec_iface_t vpx_codec_vp8_algo DEPRECATED;
+#endif
+
+#include "vpx_codec_impl_bottom.h"
+#endif
diff --git a/vp8/vp8_common.mk b/vp8/vp8_common.mk
new file mode 100644
index 0000000..ec467c5
--- /dev/null
+++ b/vp8/vp8_common.mk
@@ -0,0 +1,190 @@
+##
+##  Copyright (c) 2010 The VP8 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.
+##
+
+
+#add this file to the installed sources list
+VP8_COMMON_SRCS-yes += vp8_common.mk
+
+#common interface
+VP8_COMMON_SRCS-yes += vp8.h
+
+CFLAGS+=-I$(SRC_PATH_BARE)/$(VP8_PREFIX)common
+VP8_COMMON_SRCS-yes += common/type_aliases.h
+VP8_COMMON_SRCS-yes += common/pragmas.h
+
+CFLAGS+=-I$(SRC_PATH_BARE)/$(VP8_PREFIX)common
+VP8_COMMON_SRCS-yes += common/preproc.h
+VP8_COMMON_SRCS-yes += common/vpxerrors.h
+
+CFLAGS+=-I$(SRC_PATH_BARE)/$(VP8_PREFIX)common
+VP8_COMMON_SRCS-yes += common/ppflags.h
+VP8_COMMON_SRCS-yes += common/onyx.h
+VP8_COMMON_SRCS-yes += common/onyxd.h
+
+CFLAGS+=-I$(SRC_PATH_BARE)/$(VP8_PREFIX)common
+
+VP8_COMMON_SRCS-yes += common/segmentation_common.c
+VP8_COMMON_SRCS-yes += common/alloccommon.c
+VP8_COMMON_SRCS-yes += common/blockd.c
+VP8_COMMON_SRCS-yes += common/coefupdateprobs.h
+VP8_COMMON_SRCS-yes += common/debugmodes.c
+VP8_COMMON_SRCS-yes += common/defaultcoefcounts.h
+VP8_COMMON_SRCS-yes += common/entropy.c
+VP8_COMMON_SRCS-yes += common/entropymode.c
+VP8_COMMON_SRCS-yes += common/entropymv.c
+VP8_COMMON_SRCS-yes += common/extend.c
+VP8_COMMON_SRCS-yes += common/filter_c.c
+VP8_COMMON_SRCS-yes += common/findnearmv.c
+VP8_COMMON_SRCS-yes += common/generic/systemdependent.c
+VP8_COMMON_SRCS-yes += common/idctllm.c
+VP8_COMMON_SRCS-yes += common/alloccommon.h
+VP8_COMMON_SRCS-yes += common/blockd.h
+VP8_COMMON_SRCS-yes += common/common.h
+VP8_COMMON_SRCS-yes += common/common_types.h
+VP8_COMMON_SRCS-yes += common/entropy.h
+VP8_COMMON_SRCS-yes += common/entropymode.h
+VP8_COMMON_SRCS-yes += common/entropymv.h
+VP8_COMMON_SRCS-yes += common/extend.h
+VP8_COMMON_SRCS-yes += common/findnearmv.h
+VP8_COMMON_SRCS-yes += common/g_common.h
+VP8_COMMON_SRCS-yes += common/header.h
+VP8_COMMON_SRCS-yes += common/idct.h
+VP8_COMMON_SRCS-yes += common/invtrans.h
+VP8_COMMON_SRCS-yes += common/loopfilter.h
+VP8_COMMON_SRCS-yes += common/modecont.h
+VP8_COMMON_SRCS-yes += common/mv.h
+VP8_COMMON_SRCS-yes += common/onyxc_int.h
+VP8_COMMON_SRCS-yes += common/predictdc.h
+VP8_COMMON_SRCS-yes += common/quant_common.h
+VP8_COMMON_SRCS-yes += common/recon.h
+VP8_COMMON_SRCS-yes += common/reconinter.h
+VP8_COMMON_SRCS-yes += common/reconintra.h
+VP8_COMMON_SRCS-yes += common/reconintra4x4.h
+VP8_COMMON_SRCS-yes += common/segmentation_common.h
+VP8_COMMON_SRCS-yes += common/setupintrarecon.h
+VP8_COMMON_SRCS-yes += common/subpixel.h
+VP8_COMMON_SRCS-yes += common/swapyv12buffer.h
+VP8_COMMON_SRCS-yes += common/systemdependent.h
+VP8_COMMON_SRCS-yes += common/threading.h
+VP8_COMMON_SRCS-yes += common/treecoder.h
+VP8_COMMON_SRCS-yes += common/invtrans.c
+VP8_COMMON_SRCS-yes += common/loopfilter.c
+VP8_COMMON_SRCS-yes += common/loopfilter_filters.c
+VP8_COMMON_SRCS-yes += common/mbpitch.c
+VP8_COMMON_SRCS-yes += common/modecont.c
+VP8_COMMON_SRCS-yes += common/modecontext.c
+VP8_COMMON_SRCS-yes += common/predictdc.c
+VP8_COMMON_SRCS-yes += common/quant_common.c
+VP8_COMMON_SRCS-yes += common/recon.c
+VP8_COMMON_SRCS-yes += common/reconinter.c
+VP8_COMMON_SRCS-yes += common/reconintra.c
+VP8_COMMON_SRCS-yes += common/reconintra4x4.c
+VP8_COMMON_SRCS-yes += common/setupintrarecon.c
+VP8_COMMON_SRCS-yes += common/swapyv12buffer.c
+VP8_COMMON_SRCS-yes += common/textblit.c
+VP8_COMMON_SRCS-yes += common/treecoder.c
+
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/idct_x86.h
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/subpixel_x86.h
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/recon_x86.h
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/loopfilter_x86.h
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/postproc_x86.h
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/x86_systemdependent.c
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/vp8_asm_stubs.c
+VP8_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/loopfilter_x86.c
+VP8_COMMON_SRCS-$(CONFIG_POSTPROC) += common/postproc.h
+VP8_COMMON_SRCS-$(CONFIG_POSTPROC) += common/postproc.c
+VP8_COMMON_SRCS-$(CONFIG_VP8_ENCODER) += common/postproc.h
+VP8_COMMON_SRCS-$(CONFIG_VP8_ENCODER) += common/postproc.c
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/idctllm_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/iwalsh_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/recon_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/subpixel_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/loopfilter_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/recon_sse2.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/subpixel_sse2.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/loopfilter_sse2.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/iwalsh_sse2.asm
+ifeq ($(CONFIG_POSTPROC),yes)
+VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/postproc_mmx.asm
+VP8_COMMON_SRCS-$(HAVE_SSE2) += common/x86/postproc_sse2.asm
+endif
+
+# common (c)
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/bilinearfilter_arm.c
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/filter_arm.c
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/loopfilter_arm.c
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/recon_arm.c
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/reconintra4x4_arm.c
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/reconintra_arm.c
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/systemdependent.c
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/vpx_asm_offsets.c
+
+VP8_COMMON_SRCS_REMOVE-$(HAVE_ARMV6)  += common/filter_c.c
+VP8_COMMON_SRCS_REMOVE-$(HAVE_ARMV6)  += common/recon.c
+VP8_COMMON_SRCS_REMOVE-$(HAVE_ARMV6)  += common/reconintra4x4.c
+VP8_COMMON_SRCS_REMOVE-$(HAVE_ARMV6)  += common/generic/systemdependent.c
+
+# common (armv6)
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/armv6/bilinearfilter_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/armv6/copymem8x4_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/armv6/copymem8x8_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/armv6/copymem16x16_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/armv6/iwalsh_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/armv6/filter_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/armv6/idct_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/armv6/loopfilter_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/armv6/recon_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/armv6/simpleloopfilter_v6$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV6)  += common/arm/armv6/sixtappredict8x4_v6$(ASM)
+
+# common (neon)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/bilinearpredict4x4_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/bilinearpredict8x4_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/bilinearpredict8x8_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/bilinearpredict16x16_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/copymem8x4_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/copymem8x8_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/copymem16x16_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/iwalsh_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/loopfiltersimplehorizontaledge_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/loopfiltersimpleverticaledge_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/loopfilterhorizontaledge_uv_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/loopfilterhorizontaledge_y_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/loopfilterverticaledge_uv_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/loopfilterverticaledge_y_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/mbloopfilterhorizontaledge_uv_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/mbloopfilterhorizontaledge_y_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/mbloopfilterverticaledge_uv_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/mbloopfilterverticaledge_y_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/recon2b_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/recon4b_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/reconb_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/shortidct4x4llm_1_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/shortidct4x4llm_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/sixtappredict4x4_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/sixtappredict8x4_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/sixtappredict8x8_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/sixtappredict16x16_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/recon16x16mb_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/buildintrapredictorsmby_neon$(ASM)
+VP8_COMMON_SRCS-$(HAVE_ARMV7)  += common/arm/neon/save_neon_reg$(ASM)
+
+
+#
+# Rule to extract assembly constants from C sources
+#
+ifeq ($(ARCH_ARM),yes)
+vpx_asm_offsets.asm: obj_int_extract
+vpx_asm_offsets.asm: $(VP8_PREFIX)common/arm/vpx_asm_offsets.c.o
+	./obj_int_extract rvds $< $(ADS2GAS) > $@
+OBJS-yes += $(VP8_PREFIX)common/arm/vpx_asm_offsets.c.o
+CLEAN-OBJS += vpx_asm_offsets.asm
+$(filter %$(ASM).o,$(OBJS-yes)): vpx_asm_offsets.asm
+endif
diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c
new file mode 100644
index 0000000..e129ec9
--- /dev/null
+++ b/vp8/vp8_cx_iface.c
@@ -0,0 +1,1177 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vpx_codec/vpx_codec.h"
+#include "vpx_codec/internal/vpx_codec_internal.h"
+#include "vpx_version.h"
+#include "onyx_int.h"
+#include "vp8e.h"
+#include "onyx.h"
+#include <stdlib.h>
+#include <string.h>
+
+/* This value is a sentinel for determining whether the user has set a mode
+ * directly through the deprecated VP8E_SET_ENCODING_MODE control.
+ */
+#define NO_MODE_SET 255
+
+struct vp8_extracfg
+{
+    struct vpx_codec_pkt_list *pkt_list;
+    vp8e_encoding_mode      encoding_mode;               /** best, good, realtime            */
+    int                         cpu_used;                    /** available cpu percentage in 1/16*/
+    unsigned int                enable_auto_alt_ref;           /** if encoder decides to uses alternate reference frame */
+    unsigned int                noise_sensitivity;
+    unsigned int                Sharpness;
+    unsigned int                static_thresh;
+    unsigned int                token_partitions;
+    unsigned int                arnr_max_frames;    /* alt_ref Noise Reduction Max Frame Count */
+    unsigned int                arnr_strength;    /* alt_ref Noise Reduction Strength */
+    unsigned int                arnr_type;        /* alt_ref filter type */
+
+};
+
+struct extraconfig_map
+{
+    int                 usage;
+    struct vp8_extracfg cfg;
+};
+
+static const struct extraconfig_map extracfg_map[] =
+{
+    {
+        0,
+        {
+            NULL,
+#if !(CONFIG_REALTIME_ONLY)
+            VP8_BEST_QUALITY_ENCODING,  /* Encoding Mode */
+            -4,                         /* cpu_used      */
+#else
+            VP8_REAL_TIME_ENCODING,     /* Encoding Mode */
+            -8,                         /* cpu_used      */
+#endif
+            0,                          /* enable_auto_alt_ref */
+            0,                          /* noise_sensitivity */
+            0,                          /* Sharpness */
+            800,                        /* static_thresh */
+            VP8_ONE_TOKENPARTITION,     /* token_partitions */
+            0, /* arnr_max_frames */
+            0, /* arnr_strength */
+            0, /* arnr_type*/
+        }
+    }
+};
+
+struct vpx_codec_alg_priv
+{
+    vpx_codec_priv_t        base;
+    vpx_codec_enc_cfg_t     cfg;
+    struct vp8_extracfg     vp8_cfg;
+    VP8_CONFIG              oxcf;
+    VP8_PTR             cpi;
+    unsigned char          *cx_data;
+    unsigned int            cx_data_sz;
+    vpx_image_t             preview_img;
+    unsigned int            next_frame_flag;
+    vp8_postproc_cfg_t      preview_ppcfg;
+    vpx_codec_pkt_list_decl(26) pkt_list;              // changed to accomendate the maximum number of lagged frames allowed
+    int                         deprecated_mode;
+    unsigned int                fixed_kf_cntr;
+};
+
+
+static vpx_codec_err_t
+update_error_state(vpx_codec_alg_priv_t                 *ctx,
+                   const struct vpx_internal_error_info *error)
+{
+    vpx_codec_err_t res;
+
+    if ((res = error->error_code))
+        ctx->base.err_detail = error->has_detail
+                               ? error->detail
+                               : NULL;
+
+    return res;
+}
+
+
+#define ERROR(str) do {\
+        ctx->base.err_detail = str;\
+        return VPX_CODEC_INVALID_PARAM;\
+    } while(0)
+
+#define RANGE_CHECK(p,memb,lo,hi) do {\
+        if(!((p)->memb >= (lo) && (p)->memb <= hi)) \
+            ERROR(#memb " out of range ["#lo".."#hi"]");\
+    } while(0)
+
+#define RANGE_CHECK_LO(p,memb,lo) do {\
+        if(!((p)->memb >= (lo))) \
+            ERROR(#memb " out of range ["#lo"..]");\
+    } while(0)
+
+#define RANGE_CHECK_BOOL(p,memb) do {\
+        if(!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
+    } while(0)
+
+static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t      *ctx,
+                                       const vpx_codec_enc_cfg_t *cfg,
+                                       const struct vp8_extracfg *vp8_cfg)
+{
+    RANGE_CHECK(cfg, g_w,                   2, 16384);
+    RANGE_CHECK(cfg, g_h,                   2, 16384);
+    RANGE_CHECK(cfg, g_timebase.den,        1, 1000000000);
+    RANGE_CHECK(cfg, g_timebase.num,        1, cfg->g_timebase.den);
+    RANGE_CHECK(cfg, g_profile,             0, 3);
+    RANGE_CHECK(cfg, rc_min_quantizer,      0, 63);
+    RANGE_CHECK(cfg, rc_max_quantizer,      0, 63);
+    RANGE_CHECK(cfg, g_threads,             0, 64);
+#if !(CONFIG_REALTIME_ONLY)
+    RANGE_CHECK(cfg, g_lag_in_frames,       0, 25);
+#else
+    RANGE_CHECK(cfg, g_lag_in_frames,       0, 0);
+#endif
+    RANGE_CHECK(cfg, rc_end_usage,          VPX_VBR, VPX_CBR);
+    RANGE_CHECK(cfg, rc_undershoot_pct,     0, 100);
+    RANGE_CHECK(cfg, rc_2pass_vbr_bias_pct, 0, 100);
+    RANGE_CHECK(cfg, kf_mode,               VPX_KF_DISABLED, VPX_KF_AUTO);
+    //RANGE_CHECK_BOOL(cfg,                 g_delete_firstpassfile);
+    RANGE_CHECK_BOOL(cfg,                   rc_resize_allowed);
+    RANGE_CHECK(cfg, rc_dropframe_thresh,   0, 100);
+    RANGE_CHECK(cfg, rc_resize_up_thresh,   0, 100);
+    RANGE_CHECK(cfg, rc_resize_down_thresh, 0, 100);
+#if !(CONFIG_REALTIME_ONLY)
+    RANGE_CHECK(cfg,        g_pass,         VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
+#else
+    RANGE_CHECK(cfg,        g_pass,         VPX_RC_ONE_PASS, VPX_RC_ONE_PASS);
+#endif
+
+    /* VP8 does not support a lower bound on the keyframe interval in
+     * automatic keyframe placement mode.
+     */
+    if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist
+        && cfg->kf_min_dist > 0)
+        ERROR("kf_min_dist not supported in auto mode, use 0 "
+              "or kf_max_dist instead.");
+
+    RANGE_CHECK_BOOL(vp8_cfg,               enable_auto_alt_ref);
+#if !(CONFIG_REALTIME_ONLY)
+    RANGE_CHECK(vp8_cfg, encoding_mode,      VP8_BEST_QUALITY_ENCODING, VP8_REAL_TIME_ENCODING);
+    RANGE_CHECK(vp8_cfg, cpu_used,           -16, 16);
+    RANGE_CHECK(vp8_cfg, noise_sensitivity,  0, 6);
+#else
+    RANGE_CHECK(vp8_cfg, encoding_mode,      VP8_REAL_TIME_ENCODING, VP8_REAL_TIME_ENCODING);
+
+    if (!((vp8_cfg->cpu_used >= -16 && vp8_cfg->cpu_used <= -4) || (vp8_cfg->cpu_used >= 4 && vp8_cfg->cpu_used <= 16)))
+        ERROR("cpu_used out of range [-16..-4] or [4..16]");
+
+    RANGE_CHECK(vp8_cfg, noise_sensitivity,  0, 0);
+#endif
+
+    RANGE_CHECK(vp8_cfg, token_partitions,   VP8_ONE_TOKENPARTITION, VP8_EIGHT_TOKENPARTITION);
+    RANGE_CHECK(vp8_cfg, Sharpness,         0, 7);
+    RANGE_CHECK(vp8_cfg, arnr_max_frames,    0, 25);
+    RANGE_CHECK(vp8_cfg, arnr_strength,     0, 6);
+    RANGE_CHECK(vp8_cfg, arnr_type,         0, 0xffffffff);
+
+    if (cfg->g_pass == VPX_RC_LAST_PASS)
+    {
+        int n_doubles = cfg->rc_twopass_stats_in.sz / sizeof(double);
+        int n_packets = cfg->rc_twopass_stats_in.sz / sizeof(FIRSTPASS_STATS);
+        double frames;
+
+        if (!cfg->rc_twopass_stats_in.buf)
+            ERROR("rc_twopass_stats_in.buf not set.");
+
+        if (cfg->rc_twopass_stats_in.sz % sizeof(FIRSTPASS_STATS))
+            ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
+
+        if (cfg->rc_twopass_stats_in.sz < 2 * sizeof(FIRSTPASS_STATS))
+            ERROR("rc_twopass_stats_in requires at least two packets.");
+
+        frames = ((double *)cfg->rc_twopass_stats_in.buf)[n_doubles - 1];
+
+        if ((int)(frames + 0.5) != n_packets - 1)
+            ERROR("rc_twopass_stats_in missing EOS stats packet");
+    }
+
+    return VPX_CODEC_OK;
+}
+
+
+static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
+                                    const vpx_image_t    *img)
+{
+    switch (img->fmt)
+    {
+    case IMG_FMT_YV12:
+    case IMG_FMT_I420:
+    case IMG_FMT_VPXI420:
+    case IMG_FMT_VPXYV12:
+        break;
+    default:
+        ERROR("Invalid image format. Only YV12 and I420 images are supported");
+    }
+
+    if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h))
+        ERROR("Image size must match encoder init configuration size");
+
+    return VPX_CODEC_OK;
+}
+
+
+static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
+                                       vpx_codec_enc_cfg_t cfg,
+                                       struct vp8_extracfg vp8_cfg)
+{
+    oxcf->multi_threaded         = cfg.g_threads;
+    oxcf->Version               = cfg.g_profile;
+
+    oxcf->Width                 = cfg.g_w;
+    oxcf->Height                = cfg.g_h;
+    /* guess a frame rate if out of whack, use 30 */
+    oxcf->frame_rate             = (double)(cfg.g_timebase.den) / (double)(cfg.g_timebase.num);
+
+    if (oxcf->frame_rate > 180)
+    {
+        oxcf->frame_rate = 30;
+    }
+
+    oxcf->error_resilient_mode    = cfg.g_error_resilient;
+
+    switch (cfg.g_pass)
+    {
+    case VPX_RC_ONE_PASS:
+        oxcf->Mode = MODE_BESTQUALITY;
+        break;
+    case VPX_RC_FIRST_PASS:
+        oxcf->Mode = MODE_FIRSTPASS;
+        break;
+    case VPX_RC_LAST_PASS:
+        oxcf->Mode = MODE_SECONDPASS_BEST;
+        break;
+    }
+
+    if (cfg.g_pass == VPX_RC_FIRST_PASS)
+    {
+        oxcf->allow_lag              = 0;
+        oxcf->lag_in_frames           = 0;
+    }
+    else
+    {
+        oxcf->allow_lag              = (cfg.g_lag_in_frames) > 0;
+        oxcf->lag_in_frames           = cfg.g_lag_in_frames;
+    }
+
+    oxcf->allow_df               = (cfg.rc_dropframe_thresh > 0);
+    oxcf->drop_frames_water_mark   = cfg.rc_dropframe_thresh;
+
+    oxcf->allow_spatial_resampling = cfg.rc_resize_allowed;
+    oxcf->resample_up_water_mark   = cfg.rc_resize_up_thresh;
+    oxcf->resample_down_water_mark = cfg.rc_resize_down_thresh;
+
+    if (cfg.rc_end_usage == VPX_VBR)
+    {
+        oxcf->end_usage          = USAGE_LOCAL_FILE_PLAYBACK;
+    }
+    else if (cfg.rc_end_usage == VPX_CBR)
+    {
+        oxcf->end_usage          = USAGE_STREAM_FROM_SERVER;
+    }
+
+    oxcf->target_bandwidth       = cfg.rc_target_bitrate;
+
+    oxcf->best_allowed_q          = cfg.rc_min_quantizer;
+    oxcf->worst_allowed_q         = cfg.rc_max_quantizer;
+    oxcf->fixed_q = -1;
+
+    oxcf->under_shoot_pct         = cfg.rc_undershoot_pct;
+    //oxcf->over_shoot_pct        = cfg.rc_overshoot_pct;
+
+    oxcf->maximum_buffer_size     = cfg.rc_buf_sz / 1000;
+    oxcf->starting_buffer_level   = cfg.rc_buf_initial_sz / 1000;
+    oxcf->optimal_buffer_level    = cfg.rc_buf_optimal_sz / 1000;
+
+    oxcf->two_pass_vbrbias        = cfg.rc_2pass_vbr_bias_pct;
+    oxcf->two_pass_vbrmin_section  = cfg.rc_2pass_vbr_minsection_pct;
+    oxcf->two_pass_vbrmax_section  = cfg.rc_2pass_vbr_maxsection_pct;
+
+    oxcf->auto_key               = cfg.kf_mode == VPX_KF_AUTO
+                                   && cfg.kf_min_dist != cfg.kf_max_dist;
+    //oxcf->kf_min_dist         = cfg.kf_min_dis;
+    oxcf->key_freq               = cfg.kf_max_dist;
+
+    //oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile;
+    //strcpy(oxcf->first_pass_file, cfg.g_firstpass_file);
+
+    oxcf->cpu_used               =  vp8_cfg.cpu_used;
+    oxcf->encode_breakout        =  vp8_cfg.static_thresh;
+    oxcf->play_alternate         =  vp8_cfg.enable_auto_alt_ref;
+    oxcf->noise_sensitivity      =  vp8_cfg.noise_sensitivity;
+    oxcf->Sharpness             =  vp8_cfg.Sharpness;
+    oxcf->token_partitions       =  vp8_cfg.token_partitions;
+
+    oxcf->two_pass_stats_in        =  cfg.rc_twopass_stats_in;
+    oxcf->output_pkt_list         =  vp8_cfg.pkt_list;
+
+    oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames;
+    oxcf->arnr_strength =  vp8_cfg.arnr_strength;
+    oxcf->arnr_type =      vp8_cfg.arnr_type;
+
+
+    /*
+        printf("Current VP8 Settings: \n");
+        printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
+        printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
+        printf("Sharpness: %d\n",    oxcf->Sharpness);
+        printf("cpu_used: %d\n",  oxcf->cpu_used);
+        printf("Mode: %d\n",     oxcf->Mode);
+        printf("delete_first_pass_file: %d\n",  oxcf->delete_first_pass_file);
+        printf("auto_key: %d\n",  oxcf->auto_key);
+        printf("key_freq: %d\n", oxcf->key_freq);
+        printf("end_usage: %d\n", oxcf->end_usage);
+        printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
+        printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
+        printf("optimal_buffer_level: %d\n",  oxcf->optimal_buffer_level);
+        printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
+        printf("fixed_q: %d\n",  oxcf->fixed_q);
+        printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
+        printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
+        printf("allow_spatial_resampling: %d\n",  oxcf->allow_spatial_resampling);
+        printf("resample_down_water_mark: %d\n", oxcf->resample_down_water_mark);
+        printf("resample_up_water_mark: %d\n", oxcf->resample_up_water_mark);
+        printf("allow_df: %d\n", oxcf->allow_df);
+        printf("drop_frames_water_mark: %d\n", oxcf->drop_frames_water_mark);
+        printf("two_pass_vbrbias: %d\n",  oxcf->two_pass_vbrbias);
+        printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
+        printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
+        printf("allow_lag: %d\n", oxcf->allow_lag);
+        printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
+        printf("play_alternate: %d\n", oxcf->play_alternate);
+        printf("Version: %d\n", oxcf->Version);
+        printf("multi_threaded: %d\n",   oxcf->multi_threaded);
+        printf("encode_breakout: %d\n", oxcf->encode_breakout);
+    */
+    return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t vp8e_set_config(vpx_codec_alg_priv_t       *ctx,
+                                       const vpx_codec_enc_cfg_t  *cfg)
+{
+    vpx_codec_err_t res;
+
+    if ((cfg->g_w != ctx->cfg.g_w) || (cfg->g_h != ctx->cfg.g_h))
+        ERROR("Cannot change width or height after initialization");
+
+    /* Prevent increasing lag_in_frames. This check is stricter than it needs
+     * to be -- the limit is not increasing past the first lag_in_frames
+     * value, but we don't track the initial config, only the last successful
+     * config.
+     */
+    if ((cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames))
+        ERROR("Cannot increase lag_in_frames");
+
+    res = validate_config(ctx, cfg, &ctx->vp8_cfg);
+
+    if (!res)
+    {
+        ctx->cfg = *cfg;
+        set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
+        vp8_change_config(ctx->cpi, &ctx->oxcf);
+    }
+
+    return res;
+}
+
+
+int vp8_reverse_trans(int);
+
+
+static vpx_codec_err_t get_param(vpx_codec_alg_priv_t *ctx,
+                                 int                   ctrl_id,
+                                 va_list               args)
+{
+    void *arg = va_arg(args, void *);
+
+#define MAP(id, var) case id: *(RECAST(id, arg)) = var; break
+
+    if (!arg)
+        return VPX_CODEC_INVALID_PARAM;
+
+    switch (ctrl_id)
+    {
+        MAP(VP8E_GET_LAST_QUANTIZER, vp8_get_quantizer(ctx->cpi));
+        MAP(VP8E_GET_LAST_QUANTIZER_64, vp8_reverse_trans(vp8_get_quantizer(ctx->cpi)));
+    }
+
+    return VPX_CODEC_OK;
+#undef MAP
+}
+
+
+static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
+                                 int                   ctrl_id,
+                                 va_list               args)
+{
+    vpx_codec_err_t     res  = VPX_CODEC_OK;
+    struct vp8_extracfg xcfg = ctx->vp8_cfg;
+
+#define MAP(id, var) case id: var = CAST(id, args); break;
+
+    switch (ctrl_id)
+    {
+        MAP(VP8E_SET_ENCODING_MODE,         ctx->deprecated_mode);
+        MAP(VP8E_SET_CPUUSED,               xcfg.cpu_used);
+        MAP(VP8E_SET_ENABLEAUTOALTREF,      xcfg.enable_auto_alt_ref);
+        MAP(VP8E_SET_NOISE_SENSITIVITY,     xcfg.noise_sensitivity);
+        MAP(VP8E_SET_SHARPNESS,             xcfg.Sharpness);
+        MAP(VP8E_SET_STATIC_THRESHOLD,      xcfg.static_thresh);
+        MAP(VP8E_SET_TOKEN_PARTITIONS,      xcfg.token_partitions);
+
+        MAP(VP8E_SET_ARNR_MAXFRAMES,        xcfg.arnr_max_frames);
+        MAP(VP8E_SET_ARNR_STRENGTH ,        xcfg.arnr_strength);
+        MAP(VP8E_SET_ARNR_TYPE     ,        xcfg.arnr_type);
+
+    }
+
+    res = validate_config(ctx, &ctx->cfg, &xcfg);
+
+    if (!res)
+    {
+        ctx->vp8_cfg = xcfg;
+        set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
+        vp8_change_config(ctx->cpi, &ctx->oxcf);
+    }
+
+    return res;
+#undef MAP
+}
+static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx)
+{
+    vpx_codec_err_t        res = VPX_DEC_OK;
+    struct vpx_codec_alg_priv *priv;
+    vpx_codec_enc_cfg_t       *cfg;
+    unsigned int               i;
+
+    VP8_PTR optr;
+
+    if (!ctx->priv)
+    {
+        priv = calloc(1, sizeof(struct vpx_codec_alg_priv));
+
+        if (priv)
+        {
+            ctx->priv = &priv->base;
+            ctx->priv->sz = sizeof(*ctx->priv);
+            ctx->priv->iface = ctx->iface;
+            ctx->priv->alg_priv = priv;
+            ctx->priv->init_flags = ctx->init_flags;
+
+            if (ctx->config.enc)
+            {
+                /* Update the reference to the config structure to an
+                 * internal copy.
+                 */
+                ctx->priv->alg_priv->cfg = *ctx->config.enc;
+                ctx->config.enc = &ctx->priv->alg_priv->cfg;
+            }
+
+            cfg =  &ctx->priv->alg_priv->cfg;
+
+            /* Select the extra vp6 configuration table based on the current
+             * usage value. If the current usage value isn't found, use the
+             * values for usage case 0.
+             */
+            for (i = 0;
+                 extracfg_map[i].usage && extracfg_map[i].usage != cfg->g_usage;
+                 i++);
+
+            priv->vp8_cfg = extracfg_map[i].cfg;
+            priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
+
+            priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
+
+            if (priv->cx_data_sz < 4096) priv->cx_data_sz = 4096;
+
+            priv->cx_data = malloc(priv->cx_data_sz);
+            priv->deprecated_mode = NO_MODE_SET;
+
+            vp8_initialize();
+
+            res = validate_config(priv, &priv->cfg, &priv->vp8_cfg);
+
+            if (!res)
+            {
+                set_vp8e_config(&ctx->priv->alg_priv->oxcf, ctx->priv->alg_priv->cfg, ctx->priv->alg_priv->vp8_cfg);
+                optr = vp8_create_compressor(&ctx->priv->alg_priv->oxcf);
+
+                if (!optr)
+                    res = VPX_CODEC_MEM_ERROR;
+                else
+                    ctx->priv->alg_priv->cpi = optr;
+            }
+        }
+    }
+
+    return res;
+}
+
+static vpx_codec_err_t vp8e_destroy(vpx_codec_alg_priv_t *ctx)
+{
+
+    free(ctx->cx_data);
+    vp8_remove_compressor(&ctx->cpi);
+    free(ctx);
+    return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t image2yuvconfig(const vpx_image_t   *img,
+                                       YV12_BUFFER_CONFIG  *yv12)
+{
+    vpx_codec_err_t        res = VPX_CODEC_OK;
+    yv12->y_buffer = img->planes[PLANE_Y];
+    yv12->u_buffer = img->planes[PLANE_U];
+    yv12->v_buffer = img->planes[PLANE_V];
+
+    yv12->y_width  = img->d_w;
+    yv12->y_height = img->d_h;
+    yv12->uv_width = (1 + yv12->y_width) / 2;
+    yv12->uv_height = (1 + yv12->y_height) / 2;
+
+    yv12->y_stride = img->stride[PLANE_Y];
+    yv12->uv_stride = img->stride[PLANE_U];
+
+    yv12->border  = (img->stride[PLANE_Y] - img->w) / 2;
+    yv12->clrtype = (img->fmt == IMG_FMT_VPXI420 || img->fmt == IMG_FMT_VPXYV12); //REG_YUV = 0
+    return res;
+}
+
+static void pick_quickcompress_mode(vpx_codec_alg_priv_t  *ctx,
+                                    unsigned long          duration,
+                                    unsigned long          deadline)
+{
+    unsigned int new_qc;
+
+#if !(CONFIG_REALTIME_ONLY)
+    /* Use best quality mode if no deadline is given. */
+    new_qc = MODE_BESTQUALITY;
+
+    if (deadline)
+    {
+        uint64_t     duration_us;
+
+        /* Convert duration parameter from stream timebase to microseconds */
+        duration_us = (uint64_t)duration * 1000000
+                      * (uint64_t)ctx->cfg.g_timebase.num
+                      / (uint64_t)ctx->cfg.g_timebase.den;
+
+        /* If the deadline is more that the duration this frame is to be shown,
+         * use good quality mode. Otherwise use realtime mode.
+         */
+        new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
+    }
+
+#else
+    new_qc = MODE_REALTIME;
+#endif
+
+    switch (ctx->deprecated_mode)
+    {
+    case VP8_BEST_QUALITY_ENCODING:
+        new_qc = MODE_BESTQUALITY;
+        break;
+    case VP8_GOOD_QUALITY_ENCODING:
+        new_qc = MODE_GOODQUALITY;
+        break;
+    case VP8_REAL_TIME_ENCODING:
+        new_qc = MODE_REALTIME;
+        break;
+    }
+
+    if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
+        new_qc = MODE_FIRSTPASS;
+    else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
+        new_qc = (new_qc == MODE_BESTQUALITY)
+                 ? MODE_SECONDPASS_BEST
+                 : MODE_SECONDPASS;
+
+    if (ctx->oxcf.Mode != new_qc)
+    {
+        ctx->oxcf.Mode = new_qc;
+        vp8_change_config(ctx->cpi, &ctx->oxcf);
+    }
+}
+
+
+static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t  *ctx,
+                                   const vpx_image_t     *img,
+                                   vpx_codec_pts_t        pts,
+                                   unsigned long          duration,
+                                   vpx_enc_frame_flags_t  flags,
+                                   unsigned long          deadline)
+{
+    vpx_codec_err_t res = VPX_CODEC_OK;
+
+    if (img)
+        res = validate_img(ctx, img);
+
+    pick_quickcompress_mode(ctx, duration, deadline);
+    vpx_codec_pkt_list_init(&ctx->pkt_list);
+
+    /* Handle Flags */
+    if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF))
+        || ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF)))
+    {
+        ctx->base.err_detail = "Conflicting flags.";
+        return VPX_CODEC_INVALID_PARAM;
+    }
+
+    if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF
+                 | VP8_EFLAG_NO_REF_ARF))
+    {
+        int ref = 7;
+
+        if (flags & VP8_EFLAG_NO_REF_LAST)
+            ref ^= VP8_LAST_FLAG;
+
+        if (flags & VP8_EFLAG_NO_REF_GF)
+            ref ^= VP8_GOLD_FLAG;
+
+        if (flags & VP8_EFLAG_NO_REF_ARF)
+            ref ^= VP8_ALT_FLAG;
+
+        vp8_use_as_reference(ctx->cpi, ref);
+    }
+
+    if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF
+                 | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF
+                 | VP8_EFLAG_FORCE_ARF))
+    {
+        int upd = 7;
+
+        if (flags & VP8_EFLAG_NO_UPD_LAST)
+            upd ^= VP8_LAST_FLAG;
+
+        if (flags & VP8_EFLAG_NO_UPD_GF)
+            upd ^= VP8_GOLD_FLAG;
+
+        if (flags & VP8_EFLAG_NO_UPD_ARF)
+            upd ^= VP8_ALT_FLAG;
+
+        vp8_update_reference(ctx->cpi, upd);
+    }
+
+    if (flags & VP8_EFLAG_NO_UPD_ENTROPY)
+    {
+        vp8_update_entropy(ctx->cpi, 0);
+    }
+
+    /* Handle fixed keyframe intervals */
+    if (ctx->cfg.kf_mode == VPX_KF_AUTO
+        && ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist)
+    {
+        if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist)
+        {
+            flags |= VPX_EFLAG_FORCE_KF;
+            ctx->fixed_kf_cntr = 0;
+        }
+    }
+
+    /* Initialize the encoder instance on the first frame*/
+    if (!res && ctx->cpi)
+    {
+        unsigned int lib_flags;
+        YV12_BUFFER_CONFIG sd;
+        INT64 dst_time_stamp, dst_end_time_stamp;
+        unsigned long size, cx_data_sz;
+        unsigned char *cx_data;
+
+        /* Set up internal flags */
+        if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
+            ((VP8_COMP *)ctx->cpi)->b_calculate_psnr = 1;
+
+        /* Convert API flags to internal codec lib flags */
+        lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
+
+        /* vp8 use 10,000,000 ticks/second as time stamp */
+        dst_time_stamp    = pts * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
+        dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
+
+        if (img != NULL)
+        {
+            res = image2yuvconfig(img, &sd);
+
+            if (vp8_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags,
+                                      &sd, dst_time_stamp, dst_end_time_stamp))
+            {
+                VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
+                res = update_error_state(ctx, &cpi->common.error);
+            }
+
+            /* reset for next frame */
+            ctx->next_frame_flag = 0;
+        }
+
+        cx_data = ctx->cx_data;
+        cx_data_sz = ctx->cx_data_sz;
+        lib_flags = 0;
+
+        while (cx_data_sz >= ctx->cx_data_sz / 2
+               && -1 != vp8_get_compressed_data(ctx->cpi, &lib_flags, &size, cx_data, &dst_time_stamp, &dst_end_time_stamp, !img))
+        {
+            if (size)
+            {
+                vpx_codec_pts_t    round, delta;
+                vpx_codec_cx_pkt_t pkt;
+                VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
+
+                /* Add the frame packet to the list of returned packets. */
+                round = 1000000 * ctx->cfg.g_timebase.num / 2 - 1;
+                delta = (dst_end_time_stamp - dst_time_stamp);
+                pkt.kind = VPX_CODEC_CX_FRAME_PKT;
+                pkt.data.frame.buf = cx_data;
+                pkt.data.frame.sz  = size;
+                pkt.data.frame.pts =
+                    (dst_time_stamp * ctx->cfg.g_timebase.den + round)
+                    / ctx->cfg.g_timebase.num / 10000000;
+                pkt.data.frame.duration =
+                    (delta * ctx->cfg.g_timebase.den + round)
+                    / ctx->cfg.g_timebase.num / 10000000;
+                pkt.data.frame.flags = lib_flags << 16;
+
+                if (lib_flags & FRAMEFLAGS_KEY)
+                    pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
+
+                if (!cpi->common.show_frame)
+                {
+                    pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;
+
+                    // TODO: ideally this timestamp should be as close as
+                    // possible to the prior PTS so that if a decoder uses
+                    // pts to schedule when to do this, we start right after
+                    // last frame was decoded.  Maybe should be set to
+                    // last time stamp. Invisible frames have no duration..
+                    pkt.data.frame.pts --;
+                    pkt.data.frame.duration = 0;
+                }
+
+                vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
+
+                //printf("timestamp: %lld, duration: %d\n", pkt->data.frame.pts, pkt->data.frame.duration);
+                cx_data += size;
+                cx_data_sz -= size;
+            }
+        }
+    }
+
+    return res;
+}
+
+
+static const vpx_codec_cx_pkt_t *vp8e_get_cxdata(vpx_codec_alg_priv_t  *ctx,
+        vpx_codec_iter_t      *iter)
+{
+    return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
+}
+
+static vpx_codec_err_t vp8e_set_reference(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+    vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
+
+    if (data)
+    {
+        vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
+        YV12_BUFFER_CONFIG sd;
+
+        image2yuvconfig(&frame->img, &sd);
+        vp8_set_reference(ctx->cpi, frame->frame_type, &sd);
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+
+}
+
+static vpx_codec_err_t vp8e_get_reference(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+
+    vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
+
+    if (data)
+    {
+        vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
+        YV12_BUFFER_CONFIG sd;
+
+        image2yuvconfig(&frame->img, &sd);
+        vp8_get_reference(ctx->cpi, frame->frame_type, &sd);
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+}
+
+static vpx_codec_err_t vp8e_set_previewpp(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+    vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
+
+    if (data)
+    {
+        ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data);
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+}
+
+
+static vpx_image_t *vp8e_get_preview(vpx_codec_alg_priv_t *ctx)
+{
+
+    YV12_BUFFER_CONFIG sd;
+
+    if (0 == vp8_get_preview_raw_frame(ctx->cpi, &sd, ctx->preview_ppcfg.deblocking_level, ctx->preview_ppcfg.noise_level, ctx->preview_ppcfg.post_proc_flag))
+    {
+
+        /*
+        vpx_img_wrap(&ctx->preview_img, IMG_FMT_YV12,
+            sd.y_width + 2*VP8BORDERINPIXELS,
+            sd.y_height + 2*VP8BORDERINPIXELS,
+            1,
+            sd.buffer_alloc);
+        vpx_img_set_rect(&ctx->preview_img,
+            VP8BORDERINPIXELS, VP8BORDERINPIXELS,
+            sd.y_width, sd.y_height);
+            */
+
+        ctx->preview_img.bps = 12;
+        ctx->preview_img.planes[PLANE_Y] = sd.y_buffer;
+        ctx->preview_img.planes[PLANE_U] = sd.u_buffer;
+        ctx->preview_img.planes[PLANE_V] = sd.v_buffer;
+
+        if (sd.clrtype == REG_YUV)
+            ctx->preview_img.fmt = IMG_FMT_I420;
+        else
+            ctx->preview_img.fmt = IMG_FMT_VPXI420;
+
+        ctx->preview_img.x_chroma_shift = 1;
+        ctx->preview_img.y_chroma_shift = 1;
+
+        ctx->preview_img.d_w = ctx->cfg.g_w;
+        ctx->preview_img.d_h = ctx->cfg.g_h;
+        ctx->preview_img.stride[PLANE_Y] = sd.y_stride;
+        ctx->preview_img.stride[PLANE_U] = sd.uv_stride;
+        ctx->preview_img.stride[PLANE_V] = sd.uv_stride;
+        ctx->preview_img.w   = sd.y_width;
+        ctx->preview_img.h   = sd.y_height;
+
+        return &ctx->preview_img;
+    }
+    else
+        return NULL;
+}
+
+static vpx_codec_err_t vp8e_update_entropy(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+    int update = va_arg(args, int);
+    vp8_update_entropy(ctx->cpi, update);
+    return VPX_CODEC_OK;
+
+}
+
+static vpx_codec_err_t vp8e_update_reference(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+    int update = va_arg(args, int);
+    vp8_update_reference(ctx->cpi, update);
+    return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t vp8e_use_reference(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+    int reference_flag = va_arg(args, int);
+    vp8_use_as_reference(ctx->cpi, reference_flag);
+    return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t vp8e_set_roi_map(vpx_codec_alg_priv_t *ctx,
+                                        int ctr_id,
+                                        va_list args)
+{
+    vpx_roi_map_t *data = va_arg(args, vpx_roi_map_t *);
+
+    if (data)
+    {
+        vpx_roi_map_t *roi = (vpx_roi_map_t *)data;
+
+        if (!vp8_set_roimap(ctx->cpi, roi->roi_map, roi->rows, roi->cols, roi->delta_q, roi->delta_lf, roi->static_threshold))
+            return VPX_CODEC_OK;
+        else
+            return VPX_CODEC_INVALID_PARAM;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+}
+
+
+static vpx_codec_err_t vp8e_set_activemap(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+    vpx_active_map_t *data = va_arg(args, vpx_active_map_t *);
+
+    if (data)
+    {
+
+        vpx_active_map_t *map = (vpx_active_map_t *)data;
+
+        if (!vp8_set_active_map(ctx->cpi, map->active_map, map->rows, map->cols))
+            return VPX_CODEC_OK;
+        else
+            return VPX_CODEC_INVALID_PARAM;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+}
+
+static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+
+    vpx_scaling_mode_t *data =  va_arg(args, vpx_scaling_mode_t *);
+
+    if (data)
+    {
+        int res;
+        vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data ;
+        res = vp8_set_internal_size(ctx->cpi, scalemode.h_scaling_mode, scalemode.v_scaling_mode);
+
+        if (!res)
+        {
+            /*force next frame a key frame to effect scaling mode */
+            ctx->next_frame_flag |= FRAMEFLAGS_KEY;
+            return VPX_CODEC_OK;
+        }
+        else
+            return VPX_CODEC_INVALID_PARAM;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+}
+
+
+static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] =
+{
+    {VP8_SET_REFERENCE,                 vp8e_set_reference},
+    {VP8_COPY_REFERENCE,                vp8e_get_reference},
+    {VP8_SET_POSTPROC,                  vp8e_set_previewpp},
+    {VP8E_UPD_ENTROPY,                  vp8e_update_entropy},
+    {VP8E_UPD_REFERENCE,                vp8e_update_reference},
+    {VP8E_USE_REFERENCE,                vp8e_use_reference},
+    {VP8E_SET_ROI_MAP,                  vp8e_set_roi_map},
+    {VP8E_SET_ACTIVEMAP,                vp8e_set_activemap},
+    {VP8E_SET_SCALEMODE,                vp8e_set_scalemode},
+    {VP8E_SET_ENCODING_MODE,            set_param},
+    {VP8E_SET_CPUUSED,                  set_param},
+    {VP8E_SET_NOISE_SENSITIVITY,        set_param},
+    {VP8E_SET_ENABLEAUTOALTREF,         set_param},
+    {VP8E_SET_SHARPNESS,                set_param},
+    {VP8E_SET_STATIC_THRESHOLD,         set_param},
+    {VP8E_SET_TOKEN_PARTITIONS,         set_param},
+    {VP8E_GET_LAST_QUANTIZER,           get_param},
+    {VP8E_GET_LAST_QUANTIZER_64,        get_param},
+    {VP8E_SET_ARNR_MAXFRAMES,           set_param},
+    {VP8E_SET_ARNR_STRENGTH ,           set_param},
+    {VP8E_SET_ARNR_TYPE     ,           set_param},
+    { -1, NULL},
+};
+
+static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] =
+{
+    {
+    0,
+    {
+        0,                  /* g_usage */
+        0,                  /* g_threads */
+        0,                  /* g_profile */
+
+        320,                /* g_width */
+        240,                /* g_height */
+        {1, 30},            /* g_timebase */
+
+        0,                  /* g_error_resilient */
+
+        VPX_RC_ONE_PASS,    /* g_pass */
+
+        0,                  /* g_lag_in_frames */
+
+        70,                 /* rc_dropframe_thresh */
+        0,                  /* rc_resize_allowed */
+        60,                 /* rc_resize_down_thresold */
+        30,                 /* rc_resize_up_thresold */
+
+        VPX_VBR,            /* rc_end_usage */
+#if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION)
+        {0},                /* rc_twopass_stats_in */
+#endif
+        256,                /* rc_target_bandwidth */
+
+        4,                  /* rc_min_quantizer */
+        63,                 /* rc_max_quantizer */
+
+        95,                 /* rc_undershoot_pct */
+        200,                /* rc_overshoot_pct */
+
+        6000,               /* rc_max_buffer_size */
+        4000,               /* rc_buffer_initial_size; */
+        5000,               /* rc_buffer_optimal_size; */
+
+        50,                 /* rc_two_pass_vbrbias  */
+        0,                  /* rc_two_pass_vbrmin_section */
+        400,                /* rc_two_pass_vbrmax_section */
+
+        /* keyframing settings (kf) */
+        VPX_KF_AUTO,        /* g_kfmode*/
+        0,                  /* kf_min_dist */
+        9999,               /* kf_max_dist */
+
+#if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
+        1,                  /* g_delete_first_pass_file */
+        "vp8.fpf"           /* first pass filename */
+#endif
+    }},
+    { -1, {NOT_IMPLEMENTED}}
+};
+
+
+#ifndef VERSION_STRING
+#define VERSION_STRING
+#endif
+vpx_codec_iface_t vpx_codec_vp8_cx_algo =
+{
+    "vpx Technologies VP8 Encoder" VERSION_STRING,
+    VPX_CODEC_INTERNAL_ABI_VERSION,
+    VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR,
+    /* vpx_codec_caps_t          caps; */
+    vp8e_init,          /* vpx_codec_init_fn_t       init; */
+    vp8e_destroy,       /* vpx_codec_destroy_fn_t    destroy; */
+    vp8e_ctf_maps,      /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
+    NOT_IMPLEMENTED,    /* vpx_codec_get_mmap_fn_t   get_mmap; */
+    NOT_IMPLEMENTED,    /* vpx_codec_set_mmap_fn_t   set_mmap; */
+    {
+        NOT_IMPLEMENTED,    /* vpx_codec_peek_si_fn_t    peek_si; */
+        NOT_IMPLEMENTED,    /* vpx_codec_get_si_fn_t     get_si; */
+        NOT_IMPLEMENTED,    /* vpx_codec_decode_fn_t     decode; */
+        NOT_IMPLEMENTED,    /* vpx_codec_frame_get_fn_t  frame_get; */
+    },
+    {
+        vp8e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t    peek_si; */
+        vp8e_encode,        /* vpx_codec_encode_fn_t      encode; */
+        vp8e_get_cxdata,    /* vpx_codec_get_cx_data_fn_t   frame_get; */
+        vp8e_set_config,
+        NOT_IMPLEMENTED,
+        vp8e_get_preview,
+    } /* encoder functions */
+};
+
+
+/*
+ * BEGIN BACKWARDS COMPATIBILITY SHIM.
+ */
+#define FORCE_KEY   2
+static vpx_codec_err_t api1_control(vpx_codec_alg_priv_t *ctx,
+                                    int                   ctrl_id,
+                                    va_list               args)
+{
+    vpx_codec_ctrl_fn_map_t *entry;
+
+    switch (ctrl_id)
+    {
+    case VP8E_SET_FLUSHFLAG:
+        /* VP8 sample code did VP8E_SET_FLUSHFLAG followed by
+         * vpx_codec_get_cx_data() rather than vpx_codec_encode().
+         */
+        return vp8e_encode(ctx, NULL, 0, 0, 0, 0);
+    case VP8E_SET_FRAMETYPE:
+        ctx->base.enc.tbd |= FORCE_KEY;
+        return VPX_CODEC_OK;
+    }
+
+    for (entry = vp8e_ctf_maps; entry && entry->fn; entry++)
+    {
+        if (!entry->ctrl_id || entry->ctrl_id == ctrl_id)
+        {
+            return entry->fn(ctx, ctrl_id, args);
+        }
+    }
+
+    return VPX_CODEC_ERROR;
+}
+
+
+static vpx_codec_ctrl_fn_map_t api1_ctrl_maps[] =
+{
+    {0, api1_control},
+    { -1, NULL}
+};
+
+
+static vpx_codec_err_t api1_encode(vpx_codec_alg_priv_t  *ctx,
+                                   const vpx_image_t     *img,
+                                   vpx_codec_pts_t        pts,
+                                   unsigned long          duration,
+                                   vpx_enc_frame_flags_t  flags,
+                                   unsigned long          deadline)
+{
+    int force = ctx->base.enc.tbd;
+
+    ctx->base.enc.tbd = 0;
+    return vp8e_encode
+           (ctx,
+            img,
+            pts,
+            duration,
+            flags | ((force & FORCE_KEY) ? VPX_EFLAG_FORCE_KF : 0),
+            deadline);
+}
+
+
+vpx_codec_iface_t vpx_enc_vp8_algo =
+{
+    "vpx Technologies VP8 Encoder (Deprecated API)" VERSION_STRING,
+    VPX_CODEC_INTERNAL_ABI_VERSION,
+    VPX_CODEC_CAP_ENCODER,
+    /* vpx_codec_caps_t          caps; */
+    vp8e_init,          /* vpx_codec_init_fn_t       init; */
+    vp8e_destroy,       /* vpx_codec_destroy_fn_t    destroy; */
+    api1_ctrl_maps,     /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
+    NOT_IMPLEMENTED,    /* vpx_codec_get_mmap_fn_t   get_mmap; */
+    NOT_IMPLEMENTED,    /* vpx_codec_set_mmap_fn_t   set_mmap; */
+    {NOT_IMPLEMENTED},  /* decoder functions */
+    {
+        vp8e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t    peek_si; */
+        api1_encode,        /* vpx_codec_encode_fn_t      encode; */
+        vp8e_get_cxdata,    /* vpx_codec_get_cx_data_fn_t   frame_get; */
+        vp8e_set_config,
+        NOT_IMPLEMENTED,
+        vp8e_get_preview,
+    } /* encoder functions */
+};
diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c
new file mode 100644
index 0000000..3e6cdf4
--- /dev/null
+++ b/vp8/vp8_dx_iface.c
@@ -0,0 +1,698 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "vpx_codec/vpx_decoder.h"
+#include "vp8dx.h"
+#include "vpx_codec/internal/vpx_codec_internal.h"
+#include "vpx_version.h"
+#include "onyxd.h"
+#include "onyxd_int.h"
+
+#define VP8_CAP_POSTPROC (CONFIG_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
+
+#if CONFIG_BIG_ENDIAN
+# define swap4(d)\
+    ((d&0x000000ff)<<24) |  \
+    ((d&0x0000ff00)<<8)  |  \
+    ((d&0x00ff0000)>>8)  |  \
+    ((d&0xff000000)>>24)
+# define swap2(d)\
+    ((d&0x000000ff)<<8) |  \
+    ((d&0x0000ff00)>>8)
+#else
+# define swap4(d) d
+# define swap2(d) d
+#endif
+typedef vpx_codec_stream_info_t  vp8_stream_info_t;
+
+/* Structures for handling memory allocations */
+typedef enum
+{
+    VP8_SEG_ALG_PRIV     = 256,
+    VP8_SEG_MAX
+} mem_seg_id_t;
+#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
+
+static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_t);
+
+typedef struct
+{
+    unsigned int   id;
+    unsigned long  sz;
+    unsigned int   align;
+    unsigned int   flags;
+    unsigned long(*calc_sz)(const vpx_codec_dec_cfg_t *, vpx_codec_flags_t);
+} mem_req_t;
+
+static const mem_req_t vp8_mem_req_segs[] =
+{
+    {VP8_SEG_ALG_PRIV,    0, 8, VPX_CODEC_MEM_ZERO, vp8_priv_sz},
+    {VP8_SEG_MAX, 0, 0, 0, NULL}
+};
+
+struct vpx_codec_alg_priv
+{
+    vpx_codec_priv_t        base;
+    vpx_codec_mmap_t        mmaps[NELEMENTS(vp8_mem_req_segs)-1];
+    vpx_codec_dec_cfg_t     cfg;
+    vp8_stream_info_t   si;
+    int                     defer_alloc;
+    int                     decoder_init;
+    VP8D_PTR                pbi;
+    int                     postproc_cfg_set;
+    vp8_postproc_cfg_t      postproc_cfg;
+    vpx_image_t             img;
+    int                     img_setup;
+    int                     img_avail;
+};
+
+static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_t flags)
+{
+    /* Although this declaration is constant, we can't use it in the requested
+     * segments list because we want to define the requested segments list
+     * before defining the private type (so that the number of memory maps is
+     * known)
+     */
+    (void)si;
+    return sizeof(vpx_codec_alg_priv_t);
+}
+
+
+static void vp8_mmap_dtor(vpx_codec_mmap_t *mmap)
+{
+    free(mmap->priv);
+}
+
+static vpx_codec_err_t vp8_mmap_alloc(vpx_codec_mmap_t *mmap)
+{
+    vpx_codec_err_t  res;
+    unsigned int   align;
+
+    align = mmap->align ? mmap->align - 1 : 0;
+
+    if (mmap->flags & VPX_CODEC_MEM_ZERO)
+        mmap->priv = calloc(1, mmap->sz + align);
+    else
+        mmap->priv = malloc(mmap->sz + align);
+
+    res = (mmap->priv) ? VPX_CODEC_OK : VPX_CODEC_MEM_ERROR;
+    mmap->base = (void *)((((uintptr_t)mmap->priv) + align) & ~(uintptr_t)align);
+    mmap->dtor = vp8_mmap_dtor;
+    return res;
+}
+
+static vpx_codec_err_t vp8_validate_mmaps(const vp8_stream_info_t *si,
+        const vpx_codec_mmap_t        *mmaps,
+        vpx_codec_flags_t              init_flags)
+{
+    int i;
+    vpx_codec_err_t res = VPX_CODEC_OK;
+
+    for (i = 0; i < NELEMENTS(vp8_mem_req_segs) - 1; i++)
+    {
+        /* Ensure the segment has been allocated */
+        if (!mmaps[i].base)
+        {
+            res = VPX_CODEC_MEM_ERROR;
+            break;
+        }
+
+        /* Verify variable size segment is big enough for the current si. */
+        if (vp8_mem_req_segs[i].calc_sz)
+        {
+            vpx_codec_dec_cfg_t cfg;
+
+            cfg.w = si->w;
+            cfg.h = si->h;
+
+            if (mmaps[i].sz < vp8_mem_req_segs[i].calc_sz(&cfg, init_flags))
+            {
+                res = VPX_CODEC_MEM_ERROR;
+                break;
+            }
+        }
+    }
+
+    return res;
+}
+
+static void vp8_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap)
+{
+    int i;
+
+    ctx->priv = mmap->base;
+    ctx->priv->sz = sizeof(*ctx->priv);
+    ctx->priv->iface = ctx->iface;
+    ctx->priv->alg_priv = mmap->base;
+
+    for (i = 0; i < NELEMENTS(ctx->priv->alg_priv->mmaps); i++)
+        ctx->priv->alg_priv->mmaps[i].id = vp8_mem_req_segs[i].id;
+
+    ctx->priv->alg_priv->mmaps[0] = *mmap;
+    ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si);
+    ctx->priv->init_flags = ctx->init_flags;
+
+    if (ctx->config.dec)
+    {
+        /* Update the reference to the config structure to an internal copy. */
+        ctx->priv->alg_priv->cfg = *ctx->config.dec;
+        ctx->config.dec = &ctx->priv->alg_priv->cfg;
+    }
+}
+
+static void *mmap_lkup(vpx_codec_alg_priv_t *ctx, int id)
+{
+    int i;
+
+    for (i = 0; i < NELEMENTS(vp8_mem_req_segs); i++)
+        if (ctx->mmaps[i].id == id)
+            return ctx->mmaps[i].base;
+
+    return NULL;
+}
+static void vp8_finalize_mmaps(vpx_codec_alg_priv_t *ctx)
+{
+    /*
+    ctx->pbi = mmap_lkup(ctx, VP6_SEG_PB_INSTANCE);
+    ctx->pbi->mbi.block_dx_info[0].idct_output_ptr = mmap_lkup(ctx, VP6_SEG_IDCT_BUFFER);
+    ctx->pbi->loop_filtered_block = mmap_lkup(ctx, VP6_SEG_LF_BLOCK);
+    ctx->pbi->huff = mmap_lkup(ctx, VP6_SEG_HUFF);
+    ctx->pbi->mbi.coeffs_base_ptr = mmap_lkup(ctx, VP6_SEG_COEFFS);
+    ctx->pbi->fc.above_y = mmap_lkup(ctx, VP6_SEG_ABOVEY);
+    ctx->pbi->fc.above_u = mmap_lkup(ctx, VP6_SEG_ABOVEU);
+    ctx->pbi->fc.above_v = mmap_lkup(ctx, VP6_SEG_ABOVEV);
+    ctx->pbi->prediction_mode = mmap_lkup(ctx, VP6_SEG_PRED_MODES);
+    ctx->pbi->mbmotion_vector = mmap_lkup(ctx, VP6_SEG_MV_FIELD);
+    ctx->pbi->fb_storage_ptr[0] = mmap_lkup(ctx, VP6_SEG_IMG0_STRG);
+    ctx->pbi->fb_storage_ptr[1] = mmap_lkup(ctx, VP6_SEG_IMG1_STRG);
+    ctx->pbi->fb_storage_ptr[2] = mmap_lkup(ctx, VP6_SEG_IMG2_STRG);
+    #if CONFIG_NEW_TOKENS
+    ctx->pbi->token_graph = mmap_lkup(ctx, VP6_SEG_TOKEN_GRAPH);
+    #endif
+    #if CONFIG_POSTPROC
+    ctx->pbi->postproc.deblock.fragment_variances = mmap_lkup(ctx, VP6_SEG_DEBLOCKER);
+    ctx->pbi->fb_storage_ptr[3] = mmap_lkup(ctx, VP6_SEG_PP_IMG_STRG);
+    #endif
+    */
+}
+
+static vpx_codec_err_t vp8_init(vpx_codec_ctx_t *ctx)
+{
+    vpx_codec_err_t        res = VPX_CODEC_OK;
+
+    /* This function only allocates space for the vpx_codec_alg_priv_t
+     * structure. More memory may be required at the time the stream
+     * information becomes known.
+     */
+    if (!ctx->priv)
+    {
+        vpx_codec_mmap_t mmap;
+
+        mmap.id = vp8_mem_req_segs[0].id;
+        mmap.sz = sizeof(vpx_codec_alg_priv_t);
+        mmap.align = vp8_mem_req_segs[0].align;
+        mmap.flags = vp8_mem_req_segs[0].flags;
+
+        res = vp8_mmap_alloc(&mmap);
+
+        if (!res)
+            vp8_init_ctx(ctx, &mmap);
+
+        ctx->priv->alg_priv->defer_alloc = 1;
+        /*post processing level initialized to do nothing */
+
+    }
+
+    return res;
+}
+
+static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx)
+{
+    int i;
+
+    vp8dx_remove_decompressor(ctx->pbi);
+
+    for (i = NELEMENTS(ctx->mmaps) - 1; i >= 0; i--)
+    {
+        if (ctx->mmaps[i].dtor)
+            ctx->mmaps[i].dtor(&ctx->mmaps[i]);
+    }
+
+    return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t vp8_peek_si(const uint8_t         *data,
+                                   unsigned int           data_sz,
+                                   vpx_codec_stream_info_t *si)
+{
+
+    vpx_codec_err_t res = VPX_CODEC_OK;
+    {
+        /*Parse from VP8 compressed data, the implies knowledge of the
+         *VP8 bitsteam.
+         * First 3 byte header including version, frame type and an offset
+         * Next 3 bytes are image sizewith 12 bit each for width and height
+         */
+
+        si->is_kf = 0;
+
+        if (data_sz >= 10 && !(data[0] & 0x01))  /* I-Frame */
+        {
+            const uint8_t *c = data + 3;
+            si->is_kf = 1;
+
+            // vet via sync code
+            if (c[0] != 0x9d || c[1] != 0x01 || c[2] != 0x2a)
+                res = VPX_CODEC_UNSUP_BITSTREAM;
+
+            si->w = swap2(*(const unsigned short *)(c + 3)) & 0x3fff;
+            si->h = swap2(*(const unsigned short *)(c + 5)) & 0x3fff;
+
+            //printf("w=%d, h=%d\n", si->w, si->h);
+            if (!(si->h | si->w))
+                res = VPX_CODEC_UNSUP_BITSTREAM;
+        }
+        else
+            res = VPX_CODEC_UNSUP_BITSTREAM;
+    }
+
+    return res;
+
+}
+
+static vpx_codec_err_t vp8_get_si(vpx_codec_alg_priv_t    *ctx,
+                                  vpx_codec_stream_info_t *si)
+{
+
+    unsigned int sz;
+
+    if (si->sz >= sizeof(vp8_stream_info_t))
+        sz = sizeof(vp8_stream_info_t);
+    else
+        sz = sizeof(vpx_codec_stream_info_t);
+
+    memcpy(si, &ctx->si, sz);
+    si->sz = sz;
+
+    return VPX_CODEC_OK;
+}
+
+
+static vpx_codec_err_t
+update_error_state(vpx_codec_alg_priv_t                 *ctx,
+                   const struct vpx_internal_error_info *error)
+{
+    vpx_codec_err_t res;
+
+    if ((res = error->error_code))
+        ctx->base.err_detail = error->has_detail
+                               ? error->detail
+                               : NULL;
+
+    return res;
+}
+
+
+static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t  *ctx,
+                                  const uint8_t         *data,
+                                  unsigned int            data_sz,
+                                  void                    *user_priv,
+                                  long                    deadline)
+{
+    vpx_codec_err_t res = VPX_CODEC_OK;
+
+    ctx->img_avail = 0;
+
+    /* Determine the stream parameters */
+    if (!ctx->si.h)
+        res = ctx->base.iface->dec.peek_si(data, data_sz, &ctx->si);
+
+
+    /* Perform deferred allocations, if required */
+    if (!res && ctx->defer_alloc)
+    {
+        int i;
+
+        for (i = 1; !res && i < NELEMENTS(ctx->mmaps); i++)
+        {
+            vpx_codec_dec_cfg_t cfg;
+
+            cfg.w = ctx->si.w;
+            cfg.h = ctx->si.h;
+            ctx->mmaps[i].id = vp8_mem_req_segs[i].id;
+            ctx->mmaps[i].sz = vp8_mem_req_segs[i].sz;
+            ctx->mmaps[i].align = vp8_mem_req_segs[i].align;
+            ctx->mmaps[i].flags = vp8_mem_req_segs[i].flags;
+
+            if (!ctx->mmaps[i].sz)
+                ctx->mmaps[i].sz = vp8_mem_req_segs[i].calc_sz(&cfg,
+                                   ctx->base.init_flags);
+
+            res = vp8_mmap_alloc(&ctx->mmaps[i]);
+        }
+
+        if (!res)
+            vp8_finalize_mmaps(ctx);
+
+        ctx->defer_alloc = 0;
+    }
+
+    /* Initialize the decoder instance on the first frame*/
+    if (!res && !ctx->decoder_init)
+    {
+        res = vp8_validate_mmaps(&ctx->si, ctx->mmaps, ctx->base.init_flags);
+
+        if (!res)
+        {
+            VP8D_CONFIG oxcf;
+            VP8D_PTR optr;
+
+            vp8dx_initialize();
+
+            oxcf.Width = ctx->si.w;
+            oxcf.Height = ctx->si.h;
+            oxcf.Version = 9;
+            oxcf.postprocess = 0;
+            oxcf.max_threads = ctx->cfg.threads;
+
+            optr = vp8dx_create_decompressor(&oxcf);
+
+            /* If postprocessing was enabled by the application and a
+             * configuration has not been provided, default it.
+             */
+            if (!ctx->postproc_cfg_set
+                && (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC))
+            {
+                ctx->postproc_cfg.post_proc_flag =
+                    VP8_DEBLOCK | VP8_DEMACROBLOCK;
+                ctx->postproc_cfg.deblocking_level = 4;
+                ctx->postproc_cfg.noise_level = 0;
+            }
+
+            if (!optr)
+                res = VPX_CODEC_ERROR;
+            else
+                ctx->pbi = optr;
+        }
+
+        ctx->decoder_init = 1;
+    }
+
+    if (!res && ctx->pbi)
+    {
+        YV12_BUFFER_CONFIG sd;
+        INT64 time_stamp = 0, time_end_stamp = 0;
+        int ppflag       = 0;
+        int ppdeblocking = 0;
+        int ppnoise      = 0;
+
+        if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)
+        {
+            ppflag      = ctx->postproc_cfg.post_proc_flag;
+            ppdeblocking = ctx->postproc_cfg.deblocking_level;
+            ppnoise     = ctx->postproc_cfg.noise_level;
+        }
+
+        if (vp8dx_receive_compressed_data(ctx->pbi, data_sz, data, deadline))
+        {
+            VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi;
+            res = update_error_state(ctx, &pbi->common.error);
+        }
+
+        if (!res && 0 == vp8dx_get_raw_frame(ctx->pbi, &sd, &time_stamp, &time_end_stamp, ppdeblocking, ppnoise, ppflag))
+        {
+            /* Align width/height */
+            unsigned int a_w = (sd.y_width + 15) & ~15;
+            unsigned int a_h = (sd.y_height + 15) & ~15;
+
+            vpx_img_wrap(&ctx->img, IMG_FMT_I420,
+                         a_w + 2 * VP8BORDERINPIXELS,
+                         a_h + 2 * VP8BORDERINPIXELS,
+                         1,
+                         sd.buffer_alloc);
+            vpx_img_set_rect(&ctx->img,
+                             VP8BORDERINPIXELS, VP8BORDERINPIXELS,
+                             sd.y_width, sd.y_height);
+            ctx->img_avail = 1;
+
+        }
+    }
+
+    return res;
+}
+
+static vpx_image_t *vp8_get_frame(vpx_codec_alg_priv_t  *ctx,
+                                  vpx_codec_iter_t      *iter)
+{
+    vpx_image_t *img = NULL;
+
+    if (ctx->img_avail)
+    {
+        /* iter acts as a flip flop, so an image is only returned on the first
+         * call to get_frame.
+         */
+        if (!(*iter))
+        {
+            img = &ctx->img;
+            *iter = img;
+        }
+    }
+
+    return img;
+}
+
+
+static
+vpx_codec_err_t vp8_xma_get_mmap(const vpx_codec_ctx_t      *ctx,
+                                 vpx_codec_mmap_t           *mmap,
+                                 vpx_codec_iter_t           *iter)
+{
+    vpx_codec_err_t     res;
+    const mem_req_t  *seg_iter = *iter;
+
+    /* Get address of next segment request */
+    do
+    {
+        if (!seg_iter)
+            seg_iter = vp8_mem_req_segs;
+        else if (seg_iter->id != VP8_SEG_MAX)
+            seg_iter++;
+
+        *iter = (vpx_codec_iter_t)seg_iter;
+
+        if (seg_iter->id != VP8_SEG_MAX)
+        {
+            mmap->id = seg_iter->id;
+            mmap->sz = seg_iter->sz;
+            mmap->align = seg_iter->align;
+            mmap->flags = seg_iter->flags;
+
+            if (!seg_iter->sz)
+                mmap->sz = seg_iter->calc_sz(ctx->config.dec, ctx->init_flags);
+
+            res = VPX_CODEC_OK;
+        }
+        else
+            res = VPX_CODEC_LIST_END;
+    }
+    while (!mmap->sz && res != VPX_CODEC_LIST_END);
+
+    return res;
+}
+
+static vpx_codec_err_t vp8_xma_set_mmap(vpx_codec_ctx_t         *ctx,
+                                        const vpx_codec_mmap_t  *mmap)
+{
+    vpx_codec_err_t res = VPX_CODEC_MEM_ERROR;
+    int i, done;
+
+    if (!ctx->priv)
+    {
+        if (mmap->id == VP8_SEG_ALG_PRIV)
+        {
+            if (!ctx->priv)
+            {
+                vp8_init_ctx(ctx, mmap);
+                res = VPX_CODEC_OK;
+            }
+        }
+    }
+
+    done = 1;
+
+    if (ctx->priv->alg_priv)
+    {
+        for (i = 0; i < NELEMENTS(vp8_mem_req_segs); i++)
+        {
+            if (ctx->priv->alg_priv->mmaps[i].id == mmap->id)
+                if (!ctx->priv->alg_priv->mmaps[i].base)
+                {
+                    ctx->priv->alg_priv->mmaps[i] = *mmap;
+                    res = VPX_CODEC_OK;
+                }
+
+            done &= (ctx->priv->alg_priv->mmaps[i].base != NULL);
+        }
+    }
+
+    if (done && !res)
+    {
+        vp8_finalize_mmaps(ctx->priv->alg_priv);
+        res = ctx->iface->init(ctx);
+    }
+
+    return res;
+}
+
+static vpx_codec_err_t image2yuvconfig(const vpx_image_t   *img,
+                                       YV12_BUFFER_CONFIG  *yv12)
+{
+    vpx_codec_err_t        res = VPX_CODEC_OK;
+    yv12->y_buffer = img->planes[PLANE_Y];
+    yv12->u_buffer = img->planes[PLANE_U];
+    yv12->v_buffer = img->planes[PLANE_V];
+
+    yv12->y_width  = img->d_w;
+    yv12->y_height = img->d_h;
+    yv12->uv_width = yv12->y_width / 2;
+    yv12->uv_height = yv12->y_height / 2;
+
+    yv12->y_stride = img->stride[PLANE_Y];
+    yv12->uv_stride = img->stride[PLANE_U];
+
+    yv12->border  = (img->stride[PLANE_Y] - img->d_w) / 2;
+    yv12->clrtype = (img->fmt == IMG_FMT_VPXI420 || img->fmt == IMG_FMT_VPXYV12);
+
+    return res;
+}
+
+
+static vpx_codec_err_t vp8_set_reference(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+
+    vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
+
+    if (data)
+    {
+        vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
+        YV12_BUFFER_CONFIG sd;
+
+        image2yuvconfig(&frame->img, &sd);
+
+        vp8dx_set_reference(ctx->pbi, frame->frame_type, &sd);
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+
+}
+
+static vpx_codec_err_t vp8_get_reference(vpx_codec_alg_priv_t *ctx,
+        int ctr_id,
+        va_list args)
+{
+
+    vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
+
+    if (data)
+    {
+        vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
+        YV12_BUFFER_CONFIG sd;
+
+        image2yuvconfig(&frame->img, &sd);
+
+        vp8dx_get_reference(ctx->pbi, frame->frame_type, &sd);
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+
+}
+
+static vpx_codec_err_t vp8_set_postproc(vpx_codec_alg_priv_t *ctx,
+                                        int ctr_id,
+                                        va_list args)
+{
+    vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
+#if CONFIG_POSTPROC
+
+    if (data)
+    {
+        ctx->postproc_cfg_set = 1;
+        ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data);
+        return VPX_CODEC_OK;
+    }
+    else
+        return VPX_CODEC_INVALID_PARAM;
+
+#else
+    return VPX_CODEC_INCAPABLE;
+#endif
+}
+
+
+vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] =
+{
+    {VP8_SET_REFERENCE,  vp8_set_reference},
+    {VP8_COPY_REFERENCE, vp8_get_reference},
+    {VP8_SET_POSTPROC,   vp8_set_postproc},
+    { -1, NULL},
+};
+
+
+#ifndef VERSION_STRING
+#define VERSION_STRING
+#endif
+vpx_codec_iface_t vpx_codec_vp8_dx_algo =
+{
+    "vpx Technologies VP8 Decoder" VERSION_STRING,
+    VPX_CODEC_INTERNAL_ABI_VERSION,
+    VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC,
+    /* vpx_codec_caps_t          caps; */
+    vp8_init,         /* vpx_codec_init_fn_t       init; */
+    vp8_destroy,      /* vpx_codec_destroy_fn_t    destroy; */
+    vp8_ctf_maps,     /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
+    vp8_xma_get_mmap, /* vpx_codec_get_mmap_fn_t   get_mmap; */
+    vp8_xma_set_mmap, /* vpx_codec_set_mmap_fn_t   set_mmap; */
+    {
+        vp8_peek_si,      /* vpx_codec_peek_si_fn_t    peek_si; */
+        vp8_get_si,       /* vpx_codec_get_si_fn_t     get_si; */
+        vp8_decode,       /* vpx_codec_decode_fn_t     decode; */
+        vp8_get_frame,    /* vpx_codec_frame_get_fn_t  frame_get; */
+    },
+    {NOT_IMPLEMENTED} /* encoder functions */
+};
+
+/*
+ * BEGIN BACKWARDS COMPATIBILITY SHIM.
+ */
+vpx_codec_iface_t vpx_codec_vp8_algo =
+{
+    "vpx Technologies VP8 Decoder (Deprecated API)" VERSION_STRING,
+    VPX_CODEC_INTERNAL_ABI_VERSION,
+    VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC,
+    /* vpx_codec_caps_t          caps; */
+    vp8_init,         /* vpx_codec_init_fn_t       init; */
+    vp8_destroy,      /* vpx_codec_destroy_fn_t    destroy; */
+    vp8_ctf_maps,     /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
+    vp8_xma_get_mmap, /* vpx_codec_get_mmap_fn_t   get_mmap; */
+    vp8_xma_set_mmap, /* vpx_codec_set_mmap_fn_t   set_mmap; */
+    {
+        vp8_peek_si,      /* vpx_codec_peek_si_fn_t    peek_si; */
+        vp8_get_si,       /* vpx_codec_get_si_fn_t     get_si; */
+        vp8_decode,       /* vpx_codec_decode_fn_t     decode; */
+        vp8_get_frame,    /* vpx_codec_frame_get_fn_t  frame_get; */
+    },
+    {NOT_IMPLEMENTED} /* encoder functions */
+};
diff --git a/vp8/vp8cx.h b/vp8/vp8cx.h
new file mode 100644
index 0000000..dd48c07
--- /dev/null
+++ b/vp8/vp8cx.h
@@ -0,0 +1,261 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/*!\defgroup vp8_encoder WebM VP8 Encoder
+ * \ingroup vp8
+ *
+ * @{
+ */
+#include "vp8.h"
+
+/*!\file vp8cx.h
+ * \brief Provides definitions for using the VP8 encoder algorithm within the
+ *        vpx Codec Interface.
+ */
+#ifndef VP8CX_H
+#define VP8CX_H
+#include "vpx_codec_impl_top.h"
+
+/*!\brief Algorithm interface for VP8
+ *
+ * This interface provides the capability to encode raw VP8 streams, as would
+ * be found in AVI files.
+ */
+extern vpx_codec_iface_t vpx_codec_vp8_cx_algo;
+
+
+/*
+ * Algorithm Flags
+ */
+
+/*!\brief Don't reference the last frame
+ *
+ * When this flag is set, the encoder will not use the last frame as a
+ * predictor. When not set, the encoder will choose whether to use the
+ * last frame or not automatically.
+ */
+#define VP8_EFLAG_NO_REF_LAST      (1<<16)
+
+
+/*!\brief Don't reference the golden frame
+ *
+ * When this flag is set, the encoder will not use the golden frame as a
+ * predictor. When not set, the encoder will choose whether to use the
+ * golden frame or not automatically.
+ */
+#define VP8_EFLAG_NO_REF_GF        (1<<17)
+
+
+/*!\brief Don't reference the alternate reference frame
+ *
+ * When this flag is set, the encoder will not use the alt ref frame as a
+ * predictor. When not set, the encoder will choose whether to use the
+ * alt ref frame or not automatically.
+ */
+#define VP8_EFLAG_NO_REF_ARF       (1<<21)
+
+
+/*!\brief Don't update the last frame
+ *
+ * When this flag is set, the encoder will not update the last frame with
+ * the contents of the current frame.
+ */
+#define VP8_EFLAG_NO_UPD_LAST      (1<<18)
+
+
+/*!\brief Don't update the golden frame
+ *
+ * When this flag is set, the encoder will not update the golden frame with
+ * the contents of the current frame.
+ */
+#define VP8_EFLAG_NO_UPD_GF        (1<<22)
+
+
+/*!\brief Don't update the alternate reference frame
+ *
+ * When this flag is set, the encoder will not update the alt ref frame with
+ * the contents of the current frame.
+ */
+#define VP8_EFLAG_NO_UPD_ARF       (1<<23)
+
+
+/*!\brief Force golden frame update
+ *
+ * When this flag is set, the encoder copy the contents of the current frame
+ * to the golden frame buffer.
+ */
+#define VP8_EFLAG_FORCE_GF         (1<<19)
+
+
+/*!\brief Force alternate reference frame update
+ *
+ * When this flag is set, the encoder copy the contents of the current frame
+ * to the alternate reference frame buffer.
+ */
+#define VP8_EFLAG_FORCE_ARF        (1<<24)
+
+
+/*!\brief Disable entropy update
+ *
+ * When this flag is set, the encoder will not update its internal entropy
+ * model based on the entropy of this frame.
+ */
+#define VP8_EFLAG_NO_UPD_ENTROPY   (1<<20)
+
+
+/*!\brief VP8 encoder control functions
+ *
+ * The set of macros define the control functions of VP8 encoder interface
+ */
+enum vp8e_enc_control_id
+{
+    VP8E_UPD_ENTROPY           = 5,  /**< control function to set mode of entropy update in encoder */
+    VP8E_UPD_REFERENCE,              /**< control function to set reference update mode in encoder */
+    VP8E_USE_REFERENCE,              /**< control function to set which reference frame encoder can use */
+    VP8E_SET_ROI_MAP,                /**< control function to pass an ROI map to encoder */
+    VP8E_SET_ACTIVEMAP,              /**< control function to pass an Active map to encoder */
+    VP8E_SET_SCALEMODE         = 11, /**< control function to set encoder scaling mode */
+    VP8E_SET_CPUUSED           = 13, /**< control function to set vp8 encoder cpuused  */
+    VP8E_SET_ENABLEAUTOALTREF,       /**< control function to enable vp8 to automatic set and use altref frame */
+    VP8E_SET_NOISE_SENSITIVITY,      /**< control function to set noise sensitivity */
+    VP8E_SET_SHARPNESS,              /**< control function to set sharpness */
+    VP8E_SET_STATIC_THRESHOLD,       /**< control function to set the threshold for macroblocks treated static */
+    VP8E_SET_TOKEN_PARTITIONS,       /**< control function to set the number of token partitions  */
+    VP8E_GET_LAST_QUANTIZER,         /**< return the quantizer chosen by the
+                                          encoder for the last frame using the internal
+                                          scale */
+    VP8E_GET_LAST_QUANTIZER_64,      /**< return the quantizer chosen by the
+                                          encoder for the last frame, using the 0..63
+                                          scale as used by the rc_*_quantizer config
+                                          parameters */
+    VP8E_SET_ARNR_MAXFRAMES,         /**< control function to set the max number of frames blurred creating arf*/
+    VP8E_SET_ARNR_STRENGTH ,         /**< control function to set the filter strength for the arf */
+    VP8E_SET_ARNR_TYPE     ,         /**< control function to set the type of filter to use for the arf*/
+} ;
+
+/*!\brief vpx 1-D scaling mode
+ *
+ * This set of constants define 1-D vpx scaling modes
+ */
+typedef enum vpx_scaling_mode_1d
+{
+    VP8E_NORMAL      = 0,
+    VP8E_FOURFIVE    = 1,
+    VP8E_THREEFIVE   = 2,
+    VP8E_ONETWO      = 3
+} VPX_SCALING_MODE;
+
+
+/*!\brief  vpx region of interest map
+ *
+ * These defines the data structures for the region of interest map
+ *
+ */
+
+typedef struct vpx_roi_map
+{
+    unsigned char *roi_map;      /**< specify an id between 0 and 3 for each 16x16 region within a frame */
+    unsigned int   rows;         /**< number of rows */
+    unsigned int   cols;         /**< number of cols */
+    int     delta_q[4];          /**< quantizer delta [-64, 64] off baseline for regions with id between 0 and 3*/
+    int     delta_lf[4];         /**< loop filter strength delta [-32, 32] for regions with id between 0 and 3 */
+    unsigned int   static_threshold[4];/**< threshold for region to be treated as static */
+} vpx_roi_map_t;
+
+/*!\brief  vpx active region map
+ *
+ * These defines the data structures for active region map
+ *
+ */
+
+
+typedef struct vpx_active_map
+{
+    unsigned char  *active_map; /**< specify an on (1) or off (0) each 16x16 region within a frame */
+    unsigned int    rows;       /**< number of rows */
+    unsigned int    cols;       /**< number of cols */
+} vpx_active_map_t;
+
+/*!\brief  vpx image scaling mode
+ *
+ * This defines the data structure for image scaling mode
+ *
+ */
+typedef struct vpx_scaling_mode
+{
+    VPX_SCALING_MODE    h_scaling_mode;  /**< horizontal scaling mode */
+    VPX_SCALING_MODE    v_scaling_mode;  /**< vertical scaling mode   */
+} vpx_scaling_mode_t;
+
+/*!\brief VP8 encoding mode
+ *
+ * This defines VP8 encoding mode
+ *
+ */
+typedef enum
+{
+    VP8_BEST_QUALITY_ENCODING,
+    VP8_GOOD_QUALITY_ENCODING,
+    VP8_REAL_TIME_ENCODING
+} vp8e_encoding_mode;
+
+/*!\brief VP8 token partition mode
+ *
+ * This defines VP8 partitioning mode for compressed data, i.e., the number of
+ * sub-streams in the bitstream. Used for parallelized decoding.
+ *
+ */
+
+typedef enum
+{
+    VP8_ONE_TOKENPARTITION   = 0,
+    VP8_TWO_TOKENPARTITION   = 1,
+    VP8_FOUR_TOKENPARTITION  = 2,
+    VP8_EIGHT_TOKENPARTITION = 3,
+} vp8e_token_partitions;
+
+
+/*!\brief VP8 encoder control function parameter type
+ *
+ * Defines the data types that VP8E control functions take. Note that
+ * additional common controls are defined in vp8.h
+ *
+ */
+
+
+/* These controls have been deprecated in favor of the flags parameter to
+ * vpx_codec_encode(). See the definition of VP8_EFLAG_* above.
+ */
+VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_UPD_ENTROPY,            int)
+VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_UPD_REFERENCE,          int)
+VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_USE_REFERENCE,          int)
+
+VPX_CTRL_USE_TYPE(VP8E_SET_ROI_MAP,            vpx_roi_map_t *)
+VPX_CTRL_USE_TYPE(VP8E_SET_ACTIVEMAP,          vpx_active_map_t *)
+VPX_CTRL_USE_TYPE(VP8E_SET_SCALEMODE,          vpx_scaling_mode_t *)
+
+VPX_CTRL_USE_TYPE(VP8E_SET_CPUUSED,            int)
+VPX_CTRL_USE_TYPE(VP8E_SET_ENABLEAUTOALTREF,   unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_NOISE_SENSITIVITY,  unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_SHARPNESS,          unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_STATIC_THRESHOLD,   unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_TOKEN_PARTITIONS,   vp8e_token_partitions)
+
+VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_MAXFRAMES,     unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_STRENGTH ,     unsigned int)
+VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_TYPE     ,     unsigned int)
+
+
+VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER,     int *)
+VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER_64,  int *)
+
+/*! @} - end defgroup vp8_encoder */
+#include "vpx_codec_impl_bottom.h"
+#endif
diff --git a/vp8/vp8cx.mk b/vp8/vp8cx.mk
new file mode 100644
index 0000000..e7e7663
--- /dev/null
+++ b/vp8/vp8cx.mk
@@ -0,0 +1,104 @@
+##
+##  Copyright (c) 2010 The VP8 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.
+##
+
+
+include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8_common.mk
+VP8_CX_SRCS-yes += $(VP8_COMMON_SRCS-yes)
+VP8_CX_SRCS-no  += $(VP8_COMMON_SRCS-no)
+VP8_CX_SRCS_REMOVE-yes += $(VP8_COMMON_SRCS_REMOVE-yes)
+VP8_CX_SRCS_REMOVE-no  += $(VP8_COMMON_SRCS_REMOVE-no)
+
+ifeq ($(ARCH_ARM),yes)
+  include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8cx_arm.mk
+endif
+
+VP8_CX_SRCS-yes += vp8cx.h vp8e.h vp8_cx_iface.c
+
+# encoder
+#INCLUDES += algo/vpx_common/vpx_mem/include
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += algo/vpx_ref/cpu_id/include
+#INCLUDES += common
+#INCLUDES += encoder
+
+CFLAGS+=-I$(SRC_PATH_BARE)/$(VP8_PREFIX)encoder
+
+VP8_CX_SRCS-yes += encoder/bitstream.c
+VP8_CX_SRCS-yes += encoder/boolhuff.c
+VP8_CX_SRCS-yes += encoder/dct.c
+VP8_CX_SRCS-yes += encoder/encodeframe.c
+VP8_CX_SRCS-yes += encoder/encodeintra.c
+VP8_CX_SRCS-yes += encoder/encodemb.c
+VP8_CX_SRCS-yes += encoder/encodemv.c
+VP8_CX_SRCS-yes += encoder/ethreading.c
+VP8_CX_SRCS-yes += encoder/firstpass.c
+VP8_CX_SRCS-yes += encoder/generic/csystemdependent.c
+VP8_CX_SRCS-yes += encoder/block.h
+VP8_CX_SRCS-yes += encoder/boolhuff.h
+VP8_CX_SRCS-yes += encoder/bitstream.h
+VP8_CX_SRCS-yes += encoder/dct.h
+VP8_CX_SRCS-yes += encoder/encodeintra.h
+VP8_CX_SRCS-yes += encoder/encodemb.h
+VP8_CX_SRCS-yes += encoder/encodemv.h
+VP8_CX_SRCS-yes += encoder/firstpass.h
+VP8_CX_SRCS-yes += encoder/mcomp.h
+VP8_CX_SRCS-yes += encoder/modecosts.h
+VP8_CX_SRCS-yes += encoder/onyx_int.h
+VP8_CX_SRCS-yes += encoder/pickinter.h
+VP8_CX_SRCS-yes += encoder/psnr.h
+VP8_CX_SRCS-yes += encoder/quantize.h
+VP8_CX_SRCS-yes += encoder/ratectrl.h
+VP8_CX_SRCS-yes += encoder/rdopt.h
+VP8_CX_SRCS-yes += encoder/tokenize.h
+VP8_CX_SRCS-yes += encoder/treewriter.h
+VP8_CX_SRCS-yes += encoder/variance.h
+VP8_CX_SRCS-yes += encoder/mcomp.c
+VP8_CX_SRCS-yes += encoder/modecosts.c
+VP8_CX_SRCS-yes += encoder/onyx_if.c
+VP8_CX_SRCS-yes += encoder/pickinter.c
+VP8_CX_SRCS-yes += encoder/picklpf.c
+VP8_CX_SRCS-yes += encoder/psnr.c
+VP8_CX_SRCS-yes += encoder/quantize.c
+VP8_CX_SRCS-yes += encoder/ratectrl.c
+VP8_CX_SRCS-yes += encoder/rdopt.c
+VP8_CX_SRCS-yes += encoder/sad_c.c
+VP8_CX_SRCS-yes += encoder/ssim.c
+VP8_CX_SRCS-yes += encoder/tokenize.c
+VP8_CX_SRCS-yes += encoder/treewriter.c
+VP8_CX_SRCS-yes += encoder/variance_c.c
+
+ifeq ($(CONFIG_REALTIME_ONLY),yes)
+VP8_CX_SRCS_REMOVE-yes += encoder/firstpass.c
+endif
+
+VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/encodemb_x86.h
+VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/dct_x86.h
+VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/mcomp_x86.h
+VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/variance_x86.h
+VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/x86_csystemdependent.c
+VP8_CX_SRCS-$(HAVE_MMX) += encoder/x86/variance_mmx.c
+VP8_CX_SRCS-$(HAVE_MMX) += encoder/x86/variance_impl_mmx.asm
+VP8_CX_SRCS-$(HAVE_MMX) += encoder/x86/sad_mmx.asm
+VP8_CX_SRCS-$(HAVE_MMX) += encoder/x86/dct_mmx.asm
+VP8_CX_SRCS-$(HAVE_MMX) += encoder/x86/subtract_mmx.asm
+VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/variance_sse2.c
+VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/variance_impl_sse2.asm
+VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/sad_sse2.asm
+VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/dct_sse2.asm
+VP8_CX_SRCS-$(HAVE_SSE2) += encoder/x86/fwalsh_sse2.asm
+VP8_CX_SRCS-$(HAVE_SSE3) += encoder/x86/sad_sse3.asm
+VP8_CX_SRCS-$(HAVE_SSSE3) += encoder/x86/sad_ssse3.asm
+VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/quantize_mmx.asm
+VP8_CX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += encoder/x86/encodeopt.asm
+
+VP8_CX_SRCS-yes := $(filter-out $(VP8_CX_SRCS_REMOVE-yes),$(VP8_CX_SRCS-yes))
+
+INSTALL-LIBS-yes += include/vp8.h include/vp8e.h include/vp8cx.h
diff --git a/vp8/vp8cx_arm.mk b/vp8/vp8cx_arm.mk
new file mode 100644
index 0000000..f0753d9
--- /dev/null
+++ b/vp8/vp8cx_arm.mk
@@ -0,0 +1,64 @@
+##
+##  Copyright (c) 2010 The VP8 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.
+##
+
+
+#VP8_CX_SRCS list is modified according to different platforms.
+
+#File list for arm
+# encoder
+VP8_CX_SRCS-$(HAVE_ARMV6)  += encoder/arm/csystemdependent.c
+
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/encodemb_arm.c
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/quantize_arm.c
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/picklpf_arm.c
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/boolhuff_arm.c
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/mcomp_arm.c
+
+VP8_CX_SRCS_REMOVE-$(HAVE_ARMV6)  += encoder/generic/csystemdependent.c
+VP8_CX_SRCS_REMOVE-$(HAVE_ARMV7)  += encoder/boolhuff.c
+VP8_CX_SRCS_REMOVE-$(HAVE_ARMV7)  += encoder/mcomp.c
+
+#File list for armv6
+# encoder
+VP8_CX_SRCS-$(HAVE_ARMV6)  += encoder/arm/armv6/walsh_v6$(ASM)
+
+#File list for neon
+# encoder
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/fastfdct4x4_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/fastfdct8x4_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/fastquantizeb_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/sad8_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/sad16_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/shortfdct_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/subtract_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/variance_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/vp8_mse16x16_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/vp8_subpixelvariance8x8_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/vp8_subpixelvariance16x16_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/vp8_subpixelvariance16x16s_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/vp8_memcpy_neon$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/vp8_packtokens_armv7$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/vp8_packtokens_mbrow_armv7$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/vp8_packtokens_partitions_armv7$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/boolhuff_armv7$(ASM)
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/neon/vp8_shortwalsh4x4_neon$(ASM)
+
+VP8_CX_SRCS-$(HAVE_ARMV7)  += encoder/arm/vpx_vp8_enc_asm_offsets.c
+
+#
+# Rule to extract assembly constants from C sources
+#
+ifeq ($(ARCH_ARM),yes)
+vpx_vp8_enc_asm_offsets.asm: obj_int_extract
+vpx_vp8_enc_asm_offsets.asm: $(VP8_PREFIX)encoder/arm/vpx_vp8_enc_asm_offsets.c.o
+	./obj_int_extract rvds $< $(ADS2GAS) > $@
+OBJS-yes += $(VP8_PREFIX)encoder/arm/vpx_vp7_enc_asm_offsets.c.o
+CLEAN-OBJS += vpx_vp8_enc_asm_offsets.asm
+$(filter %$(ASM).o,$(OBJS-yes)): vpx_vp8_enc_asm_offsets.asm
+endif
diff --git a/vp8/vp8dx.h b/vp8/vp8dx.h
new file mode 100644
index 0000000..7310b3b
--- /dev/null
+++ b/vp8/vp8dx.h
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+#include "vp8.h"
+
+/*!\defgroup vp8_decoder WebM VP8 Decoder
+ * \ingroup vp8
+ *
+ * @{
+ */
+/*!\file vp8dx.h
+ * \brief Provides definitions for using the VP8 algorithm within the vpx Decoder
+ *        interface.
+ */
+#ifndef VP8DX_H
+#define VP8DX_H
+#include "vpx_codec_impl_top.h"
+
+/*!\brief Algorithm interface for VP8
+ *
+ * This interface provides the capability to decode raw VP8 streams, as would
+ * be found in AVI files and other non-Flash uses.
+ */
+extern vpx_codec_iface_t vpx_codec_vp8_dx_algo;
+
+/* Include controls common to both the encoder and decoder */
+#include "vp8.h"
+
+
+/*! @} - end defgroup vp8_decoder */
+
+
+#include "vpx_codec_impl_bottom.h"
+#endif
diff --git a/vp8/vp8dx.mk b/vp8/vp8dx.mk
new file mode 100644
index 0000000..e6af543
--- /dev/null
+++ b/vp8/vp8dx.mk
@@ -0,0 +1,76 @@
+##
+##  Copyright (c) 2010 The VP8 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.
+##
+
+
+include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8_common.mk
+VP8_DX_SRCS-yes += $(VP8_COMMON_SRCS-yes)
+VP8_DX_SRCS-no  += $(VP8_COMMON_SRCS-no)
+VP8_DX_SRCS_REMOVE-yes += $(VP8_COMMON_SRCS_REMOVE-yes)
+VP8_DX_SRCS_REMOVE-no  += $(VP8_COMMON_SRCS_REMOVE-no)
+
+ifeq ($(ARCH_ARM),yes)
+  include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8dx_arm.mk
+endif
+
+VP8_DX_SRCS-yes += vp8dx.h vp8_dx_iface.c
+
+CFLAGS+=-I$(SRC_PATH_BARE)/$(VP8_PREFIX)decoder
+
+
+# common
+#define ARM
+#define DISABLE_THREAD
+#define INLINE=__forceinline
+
+#INCLUDES += algo/vpx_common/vpx_mem/include
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += decoder
+
+
+
+# decoder
+#define ARM
+#define DISABLE_THREAD
+#define INLINE=__forceinline
+
+#INCLUDES += algo/vpx_common/vpx_mem/include
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += common
+#INCLUDES += decoder
+
+VP8_DX_SRCS-yes += decoder/dboolhuff.c
+VP8_DX_SRCS-yes += decoder/decodemv.c
+VP8_DX_SRCS-yes += decoder/decodframe.c
+VP8_DX_SRCS-yes += decoder/demode.c
+VP8_DX_SRCS-yes += decoder/dequantize.c
+VP8_DX_SRCS-yes += decoder/detokenize.c
+VP8_DX_SRCS-yes += decoder/generic/dsystemdependent.c
+VP8_DX_SRCS-yes += decoder/dboolhuff.h
+VP8_DX_SRCS-yes += decoder/decodemv.h
+VP8_DX_SRCS-yes += decoder/decoderthreading.h
+VP8_DX_SRCS-yes += decoder/demode.h
+VP8_DX_SRCS-yes += decoder/dequantize.h
+VP8_DX_SRCS-yes += decoder/detokenize.h
+VP8_DX_SRCS-yes += decoder/onyxd_int.h
+VP8_DX_SRCS-yes += decoder/treereader.h
+VP8_DX_SRCS-yes += decoder/onyxd_if.c
+VP8_DX_SRCS-yes += decoder/threading.c
+
+VP8_DX_SRCS-yes := $(filter-out $(VP8_DX_SRCS_REMOVE-yes),$(VP8_DX_SRCS-yes))
+
+INSTALL-LIBS-yes += include/vp8.h include/vp8dx.h
+
+VP8_DX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += decoder/x86/dequantize_x86.h
+VP8_DX_SRCS-$(ARCH_X86)$(ARCH_X86_64) += decoder/x86/x86_dsystemdependent.c
+VP8_DX_SRCS-$(HAVE_MMX) += decoder/x86/dequantize_mmx.asm
diff --git a/vp8/vp8dx_arm.mk b/vp8/vp8dx_arm.mk
new file mode 100644
index 0000000..1b4a7ec
--- /dev/null
+++ b/vp8/vp8dx_arm.mk
@@ -0,0 +1,44 @@
+##
+##  Copyright (c) 2010 The VP8 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.
+##
+
+
+#VP8_DX_SRCS list is modified according to different platforms.
+
+#File list for arm
+# decoder
+#VP8_DX_SRCS-$(HAVE_ARMV6)  += decoder/arm/decodframe_arm.c
+VP8_DX_SRCS-$(HAVE_ARMV6)  += decoder/arm/dequantize_arm.c
+VP8_DX_SRCS-$(HAVE_ARMV6)  += decoder/arm/dsystemdependent.c
+
+#VP8_DX_SRCS_REMOVE-$(HAVE_ARMV6)  += decoder/decodframe.c
+VP8_DX_SRCS_REMOVE-$(HAVE_ARMV6)  += decoder/dequantize.c
+VP8_DX_SRCS_REMOVE-$(HAVE_ARMV6)  += decoder/generic/dsystemdependent.c
+
+#File list for armv6
+# decoder
+VP8_DX_SRCS-$(HAVE_ARMV6)  += decoder/arm/armv6/dequantdcidct_v6$(ASM)
+VP8_DX_SRCS-$(HAVE_ARMV6)  += decoder/arm/armv6/dequantidct_v6$(ASM)
+VP8_DX_SRCS-$(HAVE_ARMV6)  += decoder/arm/armv6/dequantize_v6$(ASM)
+
+#File list for neon
+# decoder
+VP8_DX_SRCS-$(HAVE_ARMV7)  += decoder/arm/neon/dequantdcidct_neon$(ASM)
+VP8_DX_SRCS-$(HAVE_ARMV7)  += decoder/arm/neon/dequantidct_neon$(ASM)
+VP8_DX_SRCS-$(HAVE_ARMV7)  += decoder/arm/neon/dequantizeb_neon$(ASM)
+
+
+#for new token test
+ifeq ($(ARCH_ARM),yes)
+VP8_DX_SRCS-$(CONFIG_NEW_TOKENS)  += decoder/arm/detokenize_arm_sjl.c
+VP8_DX_SRCS-$(CONFIG_NEW_TOKENS)  += decoder/arm/detokenize_arm_v6$(ASM)
+VP8_DX_SRCS-$(CONFIG_NEW_TOKENS)  += decoder/onyxd_if_sjl.c
+
+VP8_DX_SRCS_REMOVE-$(CONFIG_NEW_TOKENS)  += decoder/arm/detokenize_arm.c
+VP8_DX_SRCS_REMOVE-$(CONFIG_NEW_TOKENS)  += decoder/onyxd_if.c
+endif
diff --git a/vp8/vp8e.h b/vp8/vp8e.h
new file mode 100644
index 0000000..a90aa2a
--- /dev/null
+++ b/vp8/vp8e.h
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (c) 2010 The VP8 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.
+ */
+
+
+/* This file contains backwards compatibility stubs for applications using
+ * the VP8 version 1.0 API.
+ */
+#ifndef VP8E_H
+#define VP8E_H
+#include "vpx_codec_impl_top.h"
+
+#if defined(VPX_CODEC_DISABLE_COMPAT) && VPX_CODEC_DISABLE_COMPAT
+#error "Backwards compatibility disabled: don't include vp8e.h"
+#endif
+
+#include "vp8cx.h"
+DECLSPEC_DEPRECATED extern vpx_codec_iface_t vpx_enc_vp8_algo DEPRECATED;
+
+
+enum
+{
+    VP8E_SET_REFERENCE     = VP8_SET_REFERENCE,
+    VP8E_COPY_REFERENCE    = VP8_COPY_REFERENCE,
+    VP8E_SET_PREVIEWPP     = VP8_SET_POSTPROC,
+    VP8E_SET_FLUSHFLAG     = 4,
+    VP8E_SET_FRAMETYPE     = 10,
+    VP8E_SET_ENCODING_MODE = 12
+};
+
+#define NORMAL_FRAME   (0)
+#define KEY_FRAME      (1)
+
+/* Change VP8E to VP8 to get the undeprecated version of these (defined in
+ * vp8.h)
+ */
+VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_REFERENCE,   vpx_ref_frame_t *)
+VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_COPY_REFERENCE,  vpx_ref_frame_t *)
+VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_PREVIEWPP,   vp8_postproc_cfg_t *)
+
+
+/* Flush is done by calling vpx_codec_encode with a NULL input image. */
+VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_FLUSHFLAG,          int)
+
+
+/* Frame type is set with a flag to vpx_codec_control. See VPX_EFLAG_FORCE_KF
+ */
+VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_FRAMETYPE,          int)
+
+
+/* This control has been deprecated in favor of the duration parameter to
+ * vpx_codec_encode(). Use the #VPX_DL_REALTIME, #VPX_DL_GOOD_QUALITY,
+ * #VPX_DL_BEST_QUALITY constants to that parameter instead.
+ */
+VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_SET_ENCODING_MODE, vp8e_encoding_mode)
+#include "vpx_codec_impl_bottom.h"
+#endif