]> git.sesse.net Git - x264/blobdiff - encoder/analyse.c
fix shared libs on MacOSX
[x264] / encoder / analyse.c
index 95f111610454071b25a024a9e3de4ae131e2da12..de3cf57234e3e21d0fdee267d77e115f59db7990 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
-#include <stdio.h>
-#include <string.h>
 #include <math.h>
 #include <limits.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
 
 #include "common/common.h"
 #include "macroblock.h"
@@ -43,8 +44,8 @@ typedef struct
 
     /* 8x8 */
     int       i_cost8x8;
-    int       mvc[16][5][2]; /* [ref][0] is 16x16 mv,
-                                [ref][1..4] are 8x8 mv from partition [0..3] */
+    /* [ref][0] is 16x16 mv, [ref][1..4] are 8x8 mv from partition [0..3] */
+    DECLARE_ALIGNED_8( int mvc[32][5][2] );
     x264_me_t me8x8[4];
 
     /* Sub 4x4 */
@@ -57,7 +58,7 @@ typedef struct
 
     /* Sub 4x8 */
     int       i_cost4x8[4]; /* cost per 8x8 partition */
-    x264_me_t me4x8[4][4];
+    x264_me_t me4x8[4][2];
 
     /* 16x8 */
     int       i_cost16x8;
@@ -98,6 +99,7 @@ typedef struct
 
     /* Chroma part */
     int i_satd_i8x8chroma;
+    int i_satd_i8x8chroma_dir[4];
     int i_predict8x8chroma;
 
     /* II: Inter part P/B frame */
@@ -136,21 +138,19 @@ static const int i_qp0_cost_table[52] = {
   40,45,51,57,64,72,81,91   /* 44-51 */
 };
 
-/* pow(lambda,2) * .9 */
+/* lambda2 = pow(lambda,2) * .9 * 256 */
 static const int i_qp0_cost2_table[52] = {
-   1,   1,   1,   1,   1,   1, /*  0-5  */
-   1,   1,   1,   1,   1,   1, /*  6-11 */
-   1,   1,   1,   2,   2,   3, /* 12-17 */
-   4,   5,   6,   7,   9,  11, /* 18-23 */
-  14,  18,  23,  29,  36,  46, /* 24-29 */
-  58,  73,  91, 115, 145, 183, /* 30-35 */
- 230, 290, 366, 461, 581, 731, /* 36-41 */
- 922,1161,1463,1843,2322,2926, /* 42-47 */
-3686,4645,5852,7373
+    14,      18,      22,      28,     36,     45,     57,     72, /*  0 -  7 */
+    91,     115,     145,     182,    230,    290,    365,    460, /*  8 - 15 */
+   580,     731,     921,    1161,   1462,   1843,   2322,   2925, /* 16 - 23 */
+  3686,    4644,    5851,    7372,   9289,  11703,  14745,  18578, /* 24 - 31 */
+ 23407,   29491,   37156,   46814,  58982,  74313,  93628, 117964, /* 32 - 39 */
+148626,  187257,  235929,  297252, 374514, 471859, 594505, 749029, /* 40 - 47 */
+943718, 1189010, 1498059, 1887436                                  /* 48 - 51 */
 };
 
 /* TODO: calculate CABAC costs */
-static const int i_mb_b_cost_table[19] = {
+static const int i_mb_b_cost_table[X264_MBTYPE_MAX] = {
     9, 9, 9, 9, 0, 0, 0, 1, 3, 7, 7, 7, 3, 7, 7, 7, 5, 9, 0
 };
 static const int i_mb_b16x8_cost_table[17] = {
@@ -165,16 +165,18 @@ static const int i_sub_mb_p_cost_table[4] = {
 
 static void x264_analyse_update_cache( x264_t *h, x264_mb_analysis_t *a );
 
+uint16_t *x264_cost_mv_fpel[52][4];
+
 /* initialize an array of lambda*nbits for all possible mvs */
 static void x264_mb_analyse_load_costs( x264_t *h, x264_mb_analysis_t *a )
 {
     static int16_t *p_cost_mv[52];
+    int i, j;
 
     if( !p_cost_mv[a->i_qp] )
     {
         /* could be faster, but isn't called many times */
         /* factor of 4 from qpel, 2 from sign, and 2 because mv can be opposite from mvp */
-        int i;
         p_cost_mv[a->i_qp] = x264_malloc( (4*4*2048 + 1) * sizeof(int16_t) );
         p_cost_mv[a->i_qp] += 2*4*2048;
         for( i = 0; i <= 2*4*2048; i++ )
@@ -183,16 +185,26 @@ static void x264_mb_analyse_load_costs( x264_t *h, x264_mb_analysis_t *a )
             p_cost_mv[a->i_qp][i]  = a->i_lambda * bs_size_se( i );
         }
     }
-
     a->p_cost_mv = p_cost_mv[a->i_qp];
+
+    /* FIXME is this useful for all me methods? */
+    if( h->param.analyse.i_me_method >= X264_ME_ESA && !x264_cost_mv_fpel[a->i_qp][0] )
+    {
+        for( j=0; j<4; j++ )
+        {
+            x264_cost_mv_fpel[a->i_qp][j] = x264_malloc( (4*2048 + 1) * sizeof(int16_t) );
+            x264_cost_mv_fpel[a->i_qp][j] += 2*2048;
+            for( i = -2*2048; i < 2*2048; i++ )
+                x264_cost_mv_fpel[a->i_qp][j][i] = p_cost_mv[a->i_qp][i*4+j];
+        }
+    }
 }
 
 static void x264_mb_analyse_init( x264_t *h, x264_mb_analysis_t *a, int i_qp )
 {
-    memset( a, 0, sizeof( x264_mb_analysis_t ) );
-
     /* conduct the analysis using this lamda and QP */
     a->i_qp = h->mb.i_qp = i_qp;
+    h->mb.i_chroma_qp = i_chroma_qp_table[x264_clip3( i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )];
     a->i_lambda = i_qp0_cost_table[i_qp];
     a->i_lambda2 = i_qp0_cost2_table[i_qp];
     a->b_mbrd = h->param.analyse.i_subpel_refine >= 6 &&
@@ -213,29 +225,62 @@ static void x264_mb_analyse_init( x264_t *h, x264_mb_analysis_t *a, int i_qp )
     a->i_satd_i8x8chroma = COST_MAX;
 
     a->b_fast_intra = 0;
+    h->mb.i_skip_intra =
+        h->mb.b_lossless ? 0 :
+        a->b_mbrd ? 2 :
+        !h->param.analyse.i_trellis && !h->param.analyse.i_noise_reduction;
 
     /* II: Inter part P/B frame */
     if( h->sh.i_type != SLICE_TYPE_I )
     {
-        int i;
-        int i_fmv_range = h->param.analyse.i_mv_range - 16;
+        int i, j;
+        int i_fmv_range = 4 * h->param.analyse.i_mv_range;
+        // limit motion search to a slightly smaller range than the theoretical limit,
+        // since the search may go a few iterations past its given range
+        int i_fpel_border = 5; // umh unconditional radius
+        int i_spel_border = 8; // 1.5 for subpel_satd, 1.5 for subpel_rd, 2 for bime, round up
 
         /* Calculate max allowed MV range */
-#define CLIP_FMV(mv) x264_clip3( mv, -i_fmv_range, i_fmv_range )
+#define CLIP_FMV(mv) x264_clip3( mv, -i_fmv_range, i_fmv_range-1 )
         h->mb.mv_min[0] = 4*( -16*h->mb.i_mb_x - 24 );
         h->mb.mv_max[0] = 4*( 16*( h->sps->i_mb_width - h->mb.i_mb_x - 1 ) + 24 );
-        h->mb.mv_min_fpel[0] = CLIP_FMV( -16*h->mb.i_mb_x - 8 );
-        h->mb.mv_max_fpel[0] = CLIP_FMV( 16*( h->sps->i_mb_width - h->mb.i_mb_x - 1 ) + 8 );
-        h->mb.mv_min_spel[0] = 4*( h->mb.mv_min_fpel[0] - 16 );
-        h->mb.mv_max_spel[0] = 4*( h->mb.mv_max_fpel[0] + 16 );
+        h->mb.mv_min_spel[0] = CLIP_FMV( h->mb.mv_min[0] );
+        h->mb.mv_max_spel[0] = CLIP_FMV( h->mb.mv_max[0] );
+        h->mb.mv_min_fpel[0] = (h->mb.mv_min_spel[0]>>2) + i_fpel_border;
+        h->mb.mv_max_fpel[0] = (h->mb.mv_max_spel[0]>>2) - i_fpel_border;
         if( h->mb.i_mb_x == 0)
         {
-            h->mb.mv_min[1] = 4*( -16*h->mb.i_mb_y - 24 );
-            h->mb.mv_max[1] = 4*( 16*( h->sps->i_mb_height - h->mb.i_mb_y - 1 ) + 24 );
-            h->mb.mv_min_fpel[1] = CLIP_FMV( -16*h->mb.i_mb_y - 8 );
-            h->mb.mv_max_fpel[1] = CLIP_FMV( 16*( h->sps->i_mb_height - h->mb.i_mb_y - 1 ) + 8 );
-            h->mb.mv_min_spel[1] = 4*( h->mb.mv_min_fpel[1] - 16 );
-            h->mb.mv_max_spel[1] = 4*( h->mb.mv_max_fpel[1] + 16 );
+            int mb_y = h->mb.i_mb_y >> h->sh.b_mbaff;
+            int mb_height = h->sps->i_mb_height >> h->sh.b_mbaff;
+            int thread_mvy_range = i_fmv_range;
+
+            if( h->param.i_threads > 1 )
+            {
+                int pix_y = (h->mb.i_mb_y | h->mb.b_interlaced) * 16;
+                int thresh = pix_y + h->param.analyse.i_mv_range_thread;
+                for( i = (h->sh.i_type == SLICE_TYPE_B); i >= 0; i-- )
+                {
+                    x264_frame_t **fref = i ? h->fref1 : h->fref0;
+                    int i_ref = i ? h->i_ref1 : h->i_ref0;
+                    for( j=0; j<i_ref; j++ )
+                    {
+                        x264_frame_cond_wait( fref[j], thresh );
+                        thread_mvy_range = X264_MIN( thread_mvy_range, fref[j]->i_lines_completed - pix_y );
+                    }
+                }
+                if( h->param.b_deterministic )
+                    thread_mvy_range = h->param.analyse.i_mv_range_thread;
+                if( h->mb.b_interlaced )
+                    thread_mvy_range >>= 1;
+            }
+
+            h->mb.mv_min[1] = 4*( -16*mb_y - 24 );
+            h->mb.mv_max[1] = 4*( 16*( mb_height - mb_y - 1 ) + 24 );
+            h->mb.mv_min_spel[1] = x264_clip3( h->mb.mv_min[1], X264_MAX(4*(-512+i_spel_border), -i_fmv_range), i_fmv_range );
+            h->mb.mv_max_spel[1] = CLIP_FMV( h->mb.mv_max[1] );
+            h->mb.mv_max_spel[1] = X264_MIN( h->mb.mv_max_spel[1], thread_mvy_range*4 );
+            h->mb.mv_min_fpel[1] = (h->mb.mv_min_spel[1]>>2) + i_fpel_border;
+            h->mb.mv_max_fpel[1] = (h->mb.mv_max_spel[1]>>2) - i_fpel_border;
         }
 #undef CLIP_FMV
 
@@ -308,7 +353,7 @@ static void predict_16x16_mode_available( unsigned int i_neighbour, int *mode, i
 {
     if( i_neighbour & MB_TOPLEFT )
     {
-        /* top and left avaible */
+        /* top and left available */
         *mode++ = I_PRED_16x16_V;
         *mode++ = I_PRED_16x16_H;
         *mode++ = I_PRED_16x16_DC;
@@ -331,7 +376,7 @@ static void predict_16x16_mode_available( unsigned int i_neighbour, int *mode, i
     }
     else
     {
-        /* none avaible */
+        /* none available */
         *mode = I_PRED_16x16_DC_128;
         *pi_count = 1;
     }
@@ -342,7 +387,7 @@ static void predict_8x8chroma_mode_available( unsigned int i_neighbour, int *mod
 {
     if( i_neighbour & MB_TOPLEFT )
     {
-        /* top and left avaible */
+        /* top and left available */
         *mode++ = I_PRED_CHROMA_V;
         *mode++ = I_PRED_CHROMA_H;
         *mode++ = I_PRED_CHROMA_DC;
@@ -365,7 +410,7 @@ static void predict_8x8chroma_mode_available( unsigned int i_neighbour, int *mod
     }
     else
     {
-        /* none avaible */
+        /* none available */
         *mode = I_PRED_CHROMA_DC_128;
         *pi_count = 1;
     }
@@ -422,7 +467,7 @@ static void x264_mb_analyse_intra_chroma( x264_t *h, x264_mb_analysis_t *a )
     int i;
 
     int i_max;
-    int predict_mode[9];
+    int predict_mode[4];
 
     uint8_t *p_dstc[2], *p_srcc[2];
 
@@ -437,25 +482,49 @@ static void x264_mb_analyse_intra_chroma( x264_t *h, x264_mb_analysis_t *a )
 
     predict_8x8chroma_mode_available( h->mb.i_neighbour, predict_mode, &i_max );
     a->i_satd_i8x8chroma = COST_MAX;
-    for( i = 0; i < i_max; i++ )
-    {
-        int i_satd;
-        int i_mode;
+    if( i_max == 4 && h->pixf.intra_satd_x3_8x8c && h->pixf.mbcmp[0] == h->pixf.satd[0] )
+    {
+        int satdu[4], satdv[4];
+        h->pixf.intra_satd_x3_8x8c( p_srcc[0], p_dstc[0], satdu );
+        h->pixf.intra_satd_x3_8x8c( p_srcc[1], p_dstc[1], satdv );
+        h->predict_8x8c[I_PRED_CHROMA_P]( p_dstc[0] );
+        h->predict_8x8c[I_PRED_CHROMA_P]( p_dstc[1] );
+        satdu[I_PRED_CHROMA_P] =
+            h->pixf.mbcmp[PIXEL_8x8]( p_dstc[0], FDEC_STRIDE, p_srcc[0], FENC_STRIDE );
+        satdv[I_PRED_CHROMA_P] =
+            h->pixf.mbcmp[PIXEL_8x8]( p_dstc[1], FDEC_STRIDE, p_srcc[1], FENC_STRIDE );
+        
+        for( i=0; i<i_max; i++ )
+        {
+            int i_mode = predict_mode[i];
+            int i_satd = satdu[i_mode] + satdv[i_mode]
+                       + a->i_lambda * bs_size_ue(i_mode);
 
-        i_mode = predict_mode[i];
+            a->i_satd_i8x8chroma_dir[i] = i_satd;
+            COPY2_IF_LT( a->i_satd_i8x8chroma, i_satd, a->i_predict8x8chroma, i_mode );
+        }
+    }
+    else
+    {
+        for( i=0; i<i_max; i++ )
+        {
+            int i_satd;
+            int i_mode = predict_mode[i];
 
-        /* we do the prediction */
-        h->predict_8x8c[i_mode]( p_dstc[0] );
-        h->predict_8x8c[i_mode]( p_dstc[1] );
+            /* we do the prediction */
+            h->predict_8x8c[i_mode]( p_dstc[0] );
+            h->predict_8x8c[i_mode]( p_dstc[1] );
 
-        /* we calculate the cost */
-        i_satd = h->pixf.mbcmp[PIXEL_8x8]( p_dstc[0], FDEC_STRIDE,
-                                          p_srcc[0], FENC_STRIDE ) +
-                h->pixf.mbcmp[PIXEL_8x8]( p_dstc[1], FDEC_STRIDE,
-                                          p_srcc[1], FENC_STRIDE ) +
-                a->i_lambda * bs_size_ue( x264_mb_pred_mode8x8c_fix[i_mode] );
+            /* we calculate the cost */
+            i_satd = h->pixf.mbcmp[PIXEL_8x8]( p_dstc[0], FDEC_STRIDE,
+                                               p_srcc[0], FENC_STRIDE ) +
+                     h->pixf.mbcmp[PIXEL_8x8]( p_dstc[1], FDEC_STRIDE,
+                                               p_srcc[1], FENC_STRIDE ) +
+                     a->i_lambda * bs_size_ue( x264_mb_pred_mode8x8c_fix[i_mode] );
 
-        COPY2_IF_LT( a->i_satd_i8x8chroma, i_satd, a->i_predict8x8chroma, i_mode );
+            a->i_satd_i8x8chroma_dir[i] = i_satd;
+            COPY2_IF_LT( a->i_satd_i8x8chroma, i_satd, a->i_predict8x8chroma, i_mode );
+        }
     }
 
     h->mb.i_chroma_pred_mode = a->i_predict8x8chroma;
@@ -470,21 +539,38 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
     int i, idx;
     int i_max;
     int predict_mode[9];
+    int b_merged_satd = h->pixf.intra_satd_x3_16x16 && h->pixf.mbcmp[0] == h->pixf.satd[0];
 
     /*---------------- Try all mode and calculate their score ---------------*/
 
     /* 16x16 prediction selection */
     predict_16x16_mode_available( h->mb.i_neighbour, predict_mode, &i_max );
-    for( i = 0; i < i_max; i++ )
+
+    if( b_merged_satd && i_max == 4 )
     {
-        int i_satd;
-        int i_mode = predict_mode[i];
-        h->predict_16x16[i_mode]( p_dst );
+        h->pixf.intra_satd_x3_16x16( p_src, p_dst, a->i_satd_i16x16_dir );
+        h->predict_16x16[I_PRED_16x16_P]( p_dst );
+        a->i_satd_i16x16_dir[I_PRED_16x16_P] =
+            h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE );
+        for( i=0; i<4; i++ )
+        {
+            int cost = a->i_satd_i16x16_dir[i] += a->i_lambda * bs_size_ue(i);
+            COPY2_IF_LT( a->i_satd_i16x16, cost, a->i_predict16x16, i );
+        }
+    }
+    else
+    {
+        for( i = 0; i < i_max; i++ )
+        {
+            int i_satd;
+            int i_mode = predict_mode[i];
+            h->predict_16x16[i_mode]( p_dst );
 
-        i_satd = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE ) +
-                a->i_lambda * bs_size_ue( x264_mb_pred_mode16x16_fix[i_mode] );
-        COPY2_IF_LT( a->i_satd_i16x16, i_satd, a->i_predict16x16, i_mode );
-        a->i_satd_i16x16_dir[i_mode] = i_satd;
+            i_satd = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE ) +
+                    a->i_lambda * bs_size_ue( x264_mb_pred_mode16x16_fix[i_mode] );
+            COPY2_IF_LT( a->i_satd_i16x16, i_satd, a->i_predict16x16, i_mode );
+            a->i_satd_i16x16_dir[i_mode] = i_satd;
+        }
     }
 
     if( h->sh.i_type == SLICE_TYPE_B )
@@ -496,9 +582,11 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
     /* 8x8 prediction selection */
     if( flags & X264_ANALYSE_I8x8 )
     {
+        DECLARE_ALIGNED_16( uint8_t edge[33] );
         x264_pixel_cmp_t sa8d = (*h->pixf.mbcmp == *h->pixf.sad) ? h->pixf.sad[PIXEL_8x8] : h->pixf.sa8d[PIXEL_8x8];
         int i_satd_thresh = a->b_mbrd ? COST_MAX : X264_MIN( i_satd_inter, a->i_satd_i16x16 );
         int i_cost = 0;
+        b_merged_satd = h->pixf.intra_sa8d_x3_8x8 && h->pixf.mbcmp[0] == h->pixf.satd[0];
 
         // FIXME some bias like in i4x4?
         if( h->sh.i_type == SLICE_TYPE_B )
@@ -514,12 +602,30 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
             int i_pred_mode = x264_mb_predict_intra4x4_mode( h, 4*idx );
 
             predict_4x4_mode_available( h->mb.i_neighbour8[idx], predict_mode, &i_max );
-            for( i = 0; i < i_max; i++ )
+            x264_predict_8x8_filter( p_dst_by, edge, h->mb.i_neighbour8[idx], ALL_NEIGHBORS );
+
+            if( b_merged_satd && i_max == 9 )
+            {
+                int satd[3];
+                h->pixf.intra_sa8d_x3_8x8( p_src_by, edge, satd );
+                if( i_pred_mode < 3 )
+                    satd[i_pred_mode] -= 3 * a->i_lambda;
+                for( i=2; i>=0; i-- )
+                {
+                    int cost = a->i_satd_i8x8_dir[i][idx] = satd[i] + 4 * a->i_lambda;
+                    COPY2_IF_LT( i_best, cost, a->i_predict8x8[idx], i );
+                }
+                i = 3;
+            }
+            else
+                i = 0;
+
+            for( ; i<i_max; i++ )
             {
                 int i_satd;
                 int i_mode = predict_mode[i];
 
-                h->predict_8x8[i_mode]( p_dst_by, h->mb.i_neighbour8[idx] );
+                h->predict_8x8[i_mode]( p_dst_by, edge );
 
                 i_satd = sa8d( p_dst_by, FDEC_STRIDE, p_src_by, FENC_STRIDE )
                        + a->i_lambda * (i_pred_mode == x264_mb_pred_mode4x4_fix(i_mode) ? 1 : 4);
@@ -533,14 +639,22 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
                 break;
 
             /* we need to encode this block now (for next ones) */
-            h->predict_8x8[a->i_predict8x8[idx]]( p_dst_by, h->mb.i_neighbour8[idx] );
+            h->predict_8x8[a->i_predict8x8[idx]]( p_dst_by, edge );
             x264_mb_encode_i8x8( h, idx, a->i_qp );
 
             x264_macroblock_cache_intra8x8_pred( h, 2*x, 2*y, a->i_predict8x8[idx] );
         }
 
         if( idx == 3 )
+        {
             a->i_satd_i8x8 = i_cost;
+            if( h->mb.i_skip_intra )
+            {
+                h->mc.copy[PIXEL_16x16]( h->mb.pic.i8x8_fdec_buf, 16, p_dst, FDEC_STRIDE, 16 );
+                if( h->mb.i_skip_intra == 2 )
+                    h->mc.memcpy_aligned( h->mb.pic.i8x8_dct_buf, h->dct.luma8x8, sizeof(h->mb.pic.i8x8_dct_buf) );
+            }
+        }
         else
         {
             a->i_satd_i8x8 = COST_MAX;
@@ -555,6 +669,7 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
     {
         int i_cost;
         int i_satd_thresh = X264_MIN3( i_satd_inter, a->i_satd_i16x16, a->i_satd_i8x8 );
+        b_merged_satd = h->pixf.intra_satd_x3_4x4 && h->pixf.mbcmp[0] == h->pixf.satd[0];
         if( a->b_mbrd )
             i_satd_thresh = i_satd_thresh * (10-a->b_fast_intra)/8;
 
@@ -577,16 +692,29 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
                 /* emulate missing topright samples */
                 *(uint32_t*) &p_dst_by[4 - FDEC_STRIDE] = p_dst_by[3 - FDEC_STRIDE] * 0x01010101U;
 
-            for( i = 0; i < i_max; i++ )
+            if( b_merged_satd && i_max >= 6 )
+            {
+                int satd[3];
+                h->pixf.intra_satd_x3_4x4( p_src_by, p_dst_by, satd );
+                if( i_pred_mode < 3 )
+                    satd[i_pred_mode] -= 3 * a->i_lambda;
+                for( i=2; i>=0; i-- )
+                    COPY2_IF_LT( i_best, satd[i] + 4 * a->i_lambda,
+                                 a->i_predict4x4[idx], i );
+                i = 3;
+            }
+            else
+                i = 0;
+
+            for( ; i<i_max; i++ )
             {
                 int i_satd;
-                int i_mode;
+                int i_mode = predict_mode[i];
 
-                i_mode = predict_mode[i];
                 h->predict_4x4[i_mode]( p_dst_by );
 
                 i_satd = h->pixf.mbcmp[PIXEL_4x4]( p_dst_by, FDEC_STRIDE,
-                                                  p_src_by, FENC_STRIDE )
+                                                   p_src_by, FENC_STRIDE )
                        + a->i_lambda * (i_pred_mode == x264_mb_pred_mode4x4_fix(i_mode) ? 1 : 4);
 
                 COPY2_IF_LT( i_best, i_satd, a->i_predict4x4[idx], i_mode );
@@ -603,7 +731,15 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
             h->mb.cache.intra4x4_pred_mode[x264_scan8[idx]] = a->i_predict4x4[idx];
         }
         if( idx == 15 )
+        {
             a->i_satd_i4x4 = i_cost;
+            if( h->mb.i_skip_intra )
+            {
+                h->mc.copy[PIXEL_16x16]( h->mb.pic.i4x4_fdec_buf, 16, p_dst, FDEC_STRIDE, 16 );
+                if( h->mb.i_skip_intra == 2 )
+                    h->mc.memcpy_aligned( h->mb.pic.i4x4_dct_buf, h->dct.luma4x4, sizeof(h->mb.pic.i4x4_dct_buf) );
+            }
+        }
         else
             a->i_satd_i4x4 = COST_MAX;
     }
@@ -644,15 +780,16 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
     uint8_t  *p_src = h->mb.pic.p_fenc[0];
     uint8_t  *p_dst = h->mb.pic.p_fdec[0];
 
-    int i, idx, x, y;
-    int i_max, i_satd, i_best, i_mode;
+    int i, j, idx, x, y;
+    int i_max, i_satd, i_best, i_mode, i_thresh;
     int i_pred_mode;
     int predict_mode[9];
+    h->mb.i_skip_intra = 0;
 
     if( h->mb.i_type == I_16x16 )
     {
         int old_pred_mode = a->i_predict16x16;
-        int i_thresh = a->i_satd_i16x16_dir[old_pred_mode] * 9/8;
+        i_thresh = a->i_satd_i16x16_dir[old_pred_mode] * 9/8;
         i_best = a->i_satd_i16x16;
         predict_16x16_mode_available( h->mb.i_neighbour, predict_mode, &i_max );
         for( i = 0; i < i_max; i++ )
@@ -716,6 +853,7 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
     }
     else if( h->mb.i_type == I_8x8 )
     {
+        DECLARE_ALIGNED_16( uint8_t edge[33] );
         for( idx = 0; idx < 4; idx++ )
         {
             uint64_t pels_h = 0;
@@ -724,7 +862,7 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
             uint8_t *p_src_by;
             uint8_t *p_dst_by;
             int j;
-            int i_thresh = a->i_satd_i8x8_dir[a->i_predict8x8[idx]][idx] * 11/8;
+            i_thresh = a->i_satd_i8x8_dir[a->i_predict8x8[idx]][idx] * 11/8;
 
             i_best = COST_MAX;
             i_pred_mode = x264_mb_predict_intra4x4_mode( h, 4*idx );
@@ -734,12 +872,14 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
             p_src_by = p_src + 8*x + 8*y*FENC_STRIDE;
             p_dst_by = p_dst + 8*x + 8*y*FDEC_STRIDE;
             predict_4x4_mode_available( h->mb.i_neighbour8[idx], predict_mode, &i_max );
+            x264_predict_8x8_filter( p_dst_by, edge, h->mb.i_neighbour8[idx], ALL_NEIGHBORS );
+
             for( i = 0; i < i_max; i++ )
             {
                 i_mode = predict_mode[i];
                 if( a->i_satd_i8x8_dir[i_mode][idx] > i_thresh )
                     continue;
-                h->predict_8x8[i_mode]( p_dst_by, h->mb.i_neighbour8[idx] );
+                h->predict_8x8[i_mode]( p_dst_by, edge );
                 i_satd = x264_rd_cost_i8x8( h, a->i_lambda2, idx, i_mode );
 
                 if( i_best > i_satd )
@@ -766,6 +906,42 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
             x264_macroblock_cache_intra8x8_pred( h, 2*x, 2*y, a->i_predict8x8[idx] );
         }
     }
+
+    /* RD selection for chroma prediction */
+    predict_8x8chroma_mode_available( h->mb.i_neighbour, predict_mode, &i_max );
+    if( i_max > 1 )
+    {
+        i_thresh = a->i_satd_i8x8chroma * 5/4;
+
+        for( i = j = 0; i < i_max; i++ )
+            if( a->i_satd_i8x8chroma_dir[i] < i_thresh &&
+                predict_mode[i] != a->i_predict8x8chroma )
+            {
+                predict_mode[j++] = predict_mode[i];
+            }
+        i_max = j;
+
+        if( i_max > 0 )
+        {
+            int i_chroma_lambda = i_qp0_cost2_table[h->mb.i_chroma_qp];
+            /* the previous thing encoded was x264_intra_rd(), so the pixels and
+             * coefs for the current chroma mode are still around, so we only
+             * have to recount the bits. */
+            i_best = x264_rd_cost_i8x8_chroma( h, i_chroma_lambda, a->i_predict8x8chroma, 0 );
+            for( i = 0; i < i_max; i++ )
+            {
+                i_mode = predict_mode[i];
+                h->predict_8x8c[i_mode]( h->mb.pic.p_fdec[1] );
+                h->predict_8x8c[i_mode]( h->mb.pic.p_fdec[2] );
+                /* if we've already found a mode that needs no residual, then
+                 * probably any mode with a residual will be worse.
+                 * so avoid dct on the remaining modes to improve speed. */
+                i_satd = x264_rd_cost_i8x8_chroma( h, i_chroma_lambda, i_mode, h->mb.i_cbp_chroma != 0x00 );
+                COPY2_IF_LT( i_best, i_satd, a->i_predict8x8chroma, i_mode );
+            }
+            h->mb.i_chroma_pred_mode = a->i_predict8x8chroma;
+        }
+    }
 }
 
 #define LOAD_FENC( m, src, xoff, yoff) \
@@ -793,7 +969,7 @@ static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a )
     int i_ref;
     int mvc[7][2], i_mvc;
     int i_halfpel_thresh = INT_MAX;
-    int *p_halfpel_thresh = h->i_ref0>1 ? &i_halfpel_thresh : NULL;
+    int *p_halfpel_thresh = h->mb.pic.i_fref[0]>1 ? &i_halfpel_thresh : NULL;
 
     /* 16x16 Search on all ref frame */
     m.i_pixel = PIXEL_16x16;
@@ -801,7 +977,7 @@ static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a )
     LOAD_FENC( &m, h->mb.pic.p_fenc, 0, 0 );
 
     a->l0.me16x16.cost = INT_MAX;
-    for( i_ref = 0; i_ref < h->i_ref0; i_ref++ )
+    for( i_ref = 0; i_ref < h->mb.pic.i_fref[0]; i_ref++ )
     {
         const int i_ref_cost = REF_COST( 0, i_ref );
         i_halfpel_thresh -= i_ref_cost;
@@ -816,17 +992,17 @@ static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a )
 
         /* early termination
          * SSD threshold would probably be better than SATD */
-        if( i_ref == 0 && a->b_try_pskip && m.cost-m.cost_mv < 300*a->i_lambda )
+        if( i_ref == 0
+            && a->b_try_pskip
+            && m.cost-m.cost_mv < 300*a->i_lambda
+            &&  abs(m.mv[0]-h->mb.cache.pskip_mv[0])
+              + abs(m.mv[1]-h->mb.cache.pskip_mv[1]) <= 1
+            && x264_macroblock_probe_pskip( h ) )
         {
-            int mvskip[2];
-            x264_mb_predict_mv_pskip( h, mvskip );
-            if( abs(m.mv[0]-mvskip[0]) + abs(m.mv[1]-mvskip[1]) <= 1
-                && x264_macroblock_probe_pskip( h ) )
-            {
-                h->mb.i_type = P_SKIP;
-                x264_analyse_update_cache( h, a );
-                return;
-            }
+            h->mb.i_type = P_SKIP;
+            x264_analyse_update_cache( h, a );
+            assert( h->mb.cache.pskip_mv[1] <= h->mb.mv_max_spel[1] || h->param.i_threads == 1 );
+            return;
         }
 
         m.cost += i_ref_cost;
@@ -843,18 +1019,16 @@ static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a )
     }
 
     x264_macroblock_cache_ref( h, 0, 0, 4, 4, 0, a->l0.me16x16.i_ref );
+    assert( a->l0.me16x16.mv[1] <= h->mb.mv_max_spel[1] || h->param.i_threads == 1 );
 
     h->mb.i_type = P_L0;
-    if( a->b_mbrd && a->l0.i_ref == 0 )
+    if( a->b_mbrd && a->l0.me16x16.i_ref == 0
+        && a->l0.me16x16.mv[0] == h->mb.cache.pskip_mv[0]
+        && a->l0.me16x16.mv[1] == h->mb.cache.pskip_mv[1] )
     {
-        int mvskip[2];
-        x264_mb_predict_mv_pskip( h, mvskip );
-        if( a->l0.me16x16.mv[0] == mvskip[0] && a->l0.me16x16.mv[1] == mvskip[1] )
-        {
-            h->mb.i_partition = D_16x16;
-            x264_macroblock_cache_mv( h, 0, 0, 4, 4, 0, a->l0.me16x16.mv[0], a->l0.me16x16.mv[1] );
-            a->l0.i_rd16x16 = x264_rd_cost_mb( h, a->i_lambda2 );
-        }
+        h->mb.i_partition = D_16x16;
+        x264_macroblock_cache_mv( h, 0, 0, 4, 4, 0, a->l0.me16x16.mv[0], a->l0.me16x16.mv[1] );
+        a->l0.i_rd16x16 = x264_rd_cost_mb( h, a->i_lambda2 );
     }
 }
 
@@ -864,9 +1038,9 @@ static void x264_mb_analyse_inter_p8x8_mixed_ref( x264_t *h, x264_mb_analysis_t
     int i_ref;
     uint8_t  **p_fenc = h->mb.pic.p_fenc;
     int i_halfpel_thresh = INT_MAX;
-    int *p_halfpel_thresh = /*h->i_ref0>1 ? &i_halfpel_thresh : */NULL;
+    int *p_halfpel_thresh = /*h->mb.pic.i_fref[0]>1 ? &i_halfpel_thresh : */NULL;
     int i;
-    int i_maxref = h->i_ref0-1;
+    int i_maxref = h->mb.pic.i_fref[0]-1;
 
     h->mb.i_partition = D_8x8;
 
@@ -988,7 +1162,7 @@ static void x264_mb_analyse_inter_p16x8( x264_t *h, x264_mb_analysis_t *a )
 {
     x264_me_t m;
     uint8_t  **p_fenc = h->mb.pic.p_fenc;
-    int mvc[3][2];
+    DECLARE_ALIGNED_8( int mvc[3][2] );
     int i, j;
 
     /* XXX Needed for x264_mb_predict_mv */
@@ -1038,7 +1212,7 @@ static void x264_mb_analyse_inter_p8x16( x264_t *h, x264_mb_analysis_t *a )
 {
     x264_me_t m;
     uint8_t  **p_fenc = h->mb.pic.p_fenc;
-    int mvc[3][2];
+    DECLARE_ALIGNED_8( int mvc[3][2] );
     int i, j;
 
     /* XXX Needed for x264_mb_predict_mv */
@@ -1085,21 +1259,21 @@ static void x264_mb_analyse_inter_p8x16( x264_t *h, x264_mb_analysis_t *a )
 
 static int x264_mb_analyse_inter_p4x4_chroma( x264_t *h, x264_mb_analysis_t *a, uint8_t **p_fref, int i8x8, int pixel )
 {
-    DECLARE_ALIGNED( uint8_t, pix1[8*8], 8 );
-    DECLARE_ALIGNED( uint8_t, pix2[8*8], 8 );
+    DECLARE_ALIGNED_8( uint8_t pix1[16*8] );
+    uint8_t *pix2 = pix1+8;
     const int i_stride = h->mb.pic.i_stride[1];
     const int or = 4*(i8x8&1) + 2*(i8x8&2)*i_stride;
     const int oe = 4*(i8x8&1) + 2*(i8x8&2)*FENC_STRIDE;
 
 #define CHROMA4x4MC( width, height, me, x, y ) \
-    h->mc.mc_chroma( &p_fref[4][or+x+y*i_stride], i_stride, &pix1[x+y*8], 8, (me).mv[0], (me).mv[1], width, height ); \
-    h->mc.mc_chroma( &p_fref[5][or+x+y*i_stride], i_stride, &pix2[x+y*8], 8, (me).mv[0], (me).mv[1], width, height );
+    h->mc.mc_chroma( &pix1[x+y*16], 16, &p_fref[4][or+x+y*i_stride], i_stride, (me).mv[0], (me).mv[1], width, height ); \
+    h->mc.mc_chroma( &pix2[x+y*16], 16, &p_fref[5][or+x+y*i_stride], i_stride, (me).mv[0], (me).mv[1], width, height );
 
     if( pixel == PIXEL_4x4 )
     {
         CHROMA4x4MC( 2,2, a->l0.me4x4[i8x8][0], 0,0 );
-        CHROMA4x4MC( 2,2, a->l0.me4x4[i8x8][1], 0,2 );
-        CHROMA4x4MC( 2,2, a->l0.me4x4[i8x8][2], 2,0 );
+        CHROMA4x4MC( 2,2, a->l0.me4x4[i8x8][1], 2,0 );
+        CHROMA4x4MC( 2,2, a->l0.me4x4[i8x8][2], 0,2 );
         CHROMA4x4MC( 2,2, a->l0.me4x4[i8x8][3], 2,2 );
     }
     else if( pixel == PIXEL_8x4 )
@@ -1113,8 +1287,8 @@ static int x264_mb_analyse_inter_p4x4_chroma( x264_t *h, x264_mb_analysis_t *a,
         CHROMA4x4MC( 2,4, a->l0.me4x8[i8x8][1], 2,0 );
     }
 
-    return h->pixf.mbcmp[PIXEL_4x4]( &h->mb.pic.p_fenc[1][oe], FENC_STRIDE, pix1, 8 )
-         + h->pixf.mbcmp[PIXEL_4x4]( &h->mb.pic.p_fenc[2][oe], FENC_STRIDE, pix2, 8 );
+    return h->pixf.mbcmp[PIXEL_4x4]( &h->mb.pic.p_fenc[1][oe], FENC_STRIDE, pix1, 16 )
+         + h->pixf.mbcmp[PIXEL_4x4]( &h->mb.pic.p_fenc[2][oe], FENC_STRIDE, pix2, 16 );
 }
 
 static void x264_mb_analyse_inter_p4x4( x264_t *h, x264_mb_analysis_t *a, int i8x8 )
@@ -1265,7 +1439,8 @@ static void x264_mb_analyse_inter_direct( x264_t *h, x264_mb_analysis_t *a )
 
 static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
 {
-    uint8_t pix1[16*16], pix2[16*16];
+    DECLARE_ALIGNED_16( uint8_t pix1[16*16] );
+    DECLARE_ALIGNED_16( uint8_t pix2[16*16] );
     uint8_t *src2;
     int stride2 = 16;
     int weight;
@@ -1274,7 +1449,7 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
     int i_ref;
     int mvc[8][2], i_mvc;
     int i_halfpel_thresh = INT_MAX;
-    int *p_halfpel_thresh = h->i_ref0>1 ? &i_halfpel_thresh : NULL;
+    int *p_halfpel_thresh = h->mb.pic.i_fref[0]>1 ? &i_halfpel_thresh : NULL;
 
     /* 16x16 Search on all ref frame */
     m.i_pixel = PIXEL_16x16;
@@ -1283,7 +1458,7 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
 
     /* ME for List 0 */
     a->l0.me16x16.cost = INT_MAX;
-    for( i_ref = 0; i_ref < h->i_ref0; i_ref++ )
+    for( i_ref = 0; i_ref < h->mb.pic.i_fref[0]; i_ref++ )
     {
         /* search with ref */
         LOAD_HPELS( &m, h->mb.pic.p_fref[0][i_ref], 0, i_ref, 0, 0 );
@@ -1309,9 +1484,9 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
 
     /* ME for list 1 */
     i_halfpel_thresh = INT_MAX;
-    p_halfpel_thresh = h->i_ref1>1 ? &i_halfpel_thresh : NULL;
+    p_halfpel_thresh = h->mb.pic.i_fref[1]>1 ? &i_halfpel_thresh : NULL;
     a->l1.me16x16.cost = INT_MAX;
-    for( i_ref = 0; i_ref < h->i_ref1; i_ref++ )
+    for( i_ref = 0; i_ref < h->mb.pic.i_fref[1]; i_ref++ )
     {
         /* search with ref */
         LOAD_HPELS( &m, h->mb.pic.p_fref[1][i_ref], 1, i_ref, 0, 0 );
@@ -1344,27 +1519,29 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
     if ( ((a->l0.me16x16.mv[0] | a->l0.me16x16.mv[1]) & 1) == 0 )
     {
         /* l0 reference is halfpel, so get_ref on it will make it faster */
-        src2 = h->mc.get_ref( h->mb.pic.p_fref[0][a->l0.i_ref], h->mb.pic.i_stride[0],
-                        pix2, &stride2,
-                        a->l0.me16x16.mv[0], a->l0.me16x16.mv[1],
-                        16, 16 );
-        h->mc.mc_luma( h->mb.pic.p_fref[1][a->l1.i_ref], h->mb.pic.i_stride[0],
-                        pix1, 16,
-                        a->l1.me16x16.mv[0], a->l1.me16x16.mv[1],
-                        16, 16 );
+        src2 = 
+        h->mc.get_ref( pix2, &stride2,
+                       h->mb.pic.p_fref[0][a->l0.i_ref], h->mb.pic.i_stride[0],
+                       a->l0.me16x16.mv[0], a->l0.me16x16.mv[1],
+                       16, 16 );
+        h->mc.mc_luma( pix1, 16,
+                       h->mb.pic.p_fref[1][a->l1.i_ref], h->mb.pic.i_stride[0],
+                       a->l1.me16x16.mv[0], a->l1.me16x16.mv[1],
+                       16, 16 );
         weight = 64 - weight;
     } 
     else
     {
         /* if l0 was qpel, we'll use get_ref on l1 instead */
-        h->mc.mc_luma( h->mb.pic.p_fref[0][a->l0.i_ref], h->mb.pic.i_stride[0],
-                        pix1, 16,
-                        a->l0.me16x16.mv[0], a->l0.me16x16.mv[1],
-                        16, 16 );
-        src2 = h->mc.get_ref( h->mb.pic.p_fref[1][a->l1.i_ref], h->mb.pic.i_stride[0],
-                        pix2, &stride2,
-                        a->l1.me16x16.mv[0], a->l1.me16x16.mv[1],
-                        16, 16 );
+        h->mc.mc_luma( pix1, 16,
+                       h->mb.pic.p_fref[0][a->l0.i_ref], h->mb.pic.i_stride[0],
+                       a->l0.me16x16.mv[0], a->l0.me16x16.mv[1],
+                       16, 16 );
+        src2 =
+        h->mc.get_ref( pix2, &stride2,
+                       h->mb.pic.p_fref[1][a->l1.i_ref], h->mb.pic.i_stride[0],
+                       a->l1.me16x16.mv[0], a->l1.me16x16.mv[1],
+                       16, 16 );
     }
 
     if( h->param.analyse.b_weighted_bipred )
@@ -1474,7 +1651,7 @@ static void x264_mb_analyse_inter_b8x8( x264_t *h, x264_mb_analysis_t *a )
     uint8_t **p_fref[2] =
         { h->mb.pic.p_fref[0][a->l0.i_ref],
           h->mb.pic.p_fref[1][a->l1.i_ref] };
-    uint8_t pix[2][8*8];
+    DECLARE_ALIGNED_8( uint8_t pix[2][8*8] );
     int i, l;
 
     /* XXX Needed for x264_mb_predict_mv */
@@ -1506,8 +1683,8 @@ static void x264_mb_analyse_inter_b8x8( x264_t *h, x264_mb_analysis_t *a )
             x264_macroblock_cache_mv( h, 2*x8, 2*y8, 2, 2, l, m->mv[0], m->mv[1] );
 
             /* BI mode */
-            h->mc.mc_luma( m->p_fref, m->i_stride[0], pix[l], 8,
-                            m->mv[0], m->mv[1], 8, 8 );
+            h->mc.mc_luma( pix[l], 8, m->p_fref, m->i_stride[0],
+                           m->mv[0], m->mv[1], 8, 8 );
             i_part_cost_bi += m->cost_mv;
             /* FIXME: ref cost */
         }
@@ -1538,8 +1715,8 @@ static void x264_mb_analyse_inter_b16x8( x264_t *h, x264_mb_analysis_t *a )
     uint8_t **p_fref[2] =
         { h->mb.pic.p_fref[0][a->l0.i_ref],
           h->mb.pic.p_fref[1][a->l1.i_ref] };
-    DECLARE_ALIGNED( uint8_t,  pix[2][16*8], 16 );
-    int mvc[2][2];
+    DECLARE_ALIGNED_16( uint8_t  pix[2][16*8] );
+    DECLARE_ALIGNED_8( int mvc[2][2] );
     int i, l;
 
     h->mb.i_partition = D_16x8;
@@ -1562,17 +1739,15 @@ static void x264_mb_analyse_inter_b16x8( x264_t *h, x264_mb_analysis_t *a )
             LOAD_FENC( m, h->mb.pic.p_fenc, 0, 8*i );
             LOAD_HPELS( m, p_fref[l], l, lX->i_ref, 0, 8*i );
 
-            mvc[0][0] = lX->me8x8[2*i].mv[0];
-            mvc[0][1] = lX->me8x8[2*i].mv[1];
-            mvc[1][0] = lX->me8x8[2*i+1].mv[0];
-            mvc[1][1] = lX->me8x8[2*i+1].mv[1];
+            *(uint64_t*)mvc[0] = *(uint64_t*)lX->me8x8[2*i].mv;
+            *(uint64_t*)mvc[1] = *(uint64_t*)lX->me8x8[2*i+1].mv;
 
-            x264_mb_predict_mv( h, 0, 8*i, 2, m->mvp );
+            x264_mb_predict_mv( h, l, 8*i, 2, m->mvp );
             x264_me_search( h, m, mvc, 2 );
 
             /* BI mode */
-            h->mc.mc_luma( m->p_fref, m->i_stride[0], pix[l], 16,
-                            m->mv[0], m->mv[1], 16, 8 );
+            h->mc.mc_luma( pix[l], 16, m->p_fref, m->i_stride[0],
+                           m->mv[0], m->mv[1], 16, 8 );
             /* FIXME: ref cost */
             i_part_cost_bi += m->cost_mv;
         }
@@ -1609,8 +1784,8 @@ static void x264_mb_analyse_inter_b8x16( x264_t *h, x264_mb_analysis_t *a )
     uint8_t **p_fref[2] =
         { h->mb.pic.p_fref[0][a->l0.i_ref],
           h->mb.pic.p_fref[1][a->l1.i_ref] };
-    uint8_t pix[2][8*16];
-    int mvc[2][2];
+    DECLARE_ALIGNED_8( uint8_t pix[2][8*16] );
+    DECLARE_ALIGNED_8( int mvc[2][2] );
     int i, l;
 
     h->mb.i_partition = D_8x16;
@@ -1632,17 +1807,15 @@ static void x264_mb_analyse_inter_b8x16( x264_t *h, x264_mb_analysis_t *a )
             LOAD_FENC( m, h->mb.pic.p_fenc, 8*i, 0 );
             LOAD_HPELS( m, p_fref[l], l, lX->i_ref, 8*i, 0 );
 
-            mvc[0][0] = lX->me8x8[i].mv[0];
-            mvc[0][1] = lX->me8x8[i].mv[1];
-            mvc[1][0] = lX->me8x8[i+2].mv[0];
-            mvc[1][1] = lX->me8x8[i+2].mv[1];
+            *(uint64_t*)mvc[0] = *(uint64_t*)lX->me8x8[i].mv;
+            *(uint64_t*)mvc[1] = *(uint64_t*)lX->me8x8[i+2].mv;
 
-            x264_mb_predict_mv( h, 0, 4*i, 2, m->mvp );
+            x264_mb_predict_mv( h, l, 4*i, 2, m->mvp );
             x264_me_search( h, m, mvc, 2 );
 
             /* BI mode */
-            h->mc.mc_luma( m->p_fref, m->i_stride[0], pix[l], 8,
-                            m->mv[0], m->mv[1], 8, 16 );
+            h->mc.mc_luma( pix[l], 8, m->p_fref, m->i_stride[0],
+                           m->mv[0], m->mv[1], 8, 16 );
             /* FIXME: ref cost */
             i_part_cost_bi += m->cost_mv;
         }
@@ -1838,11 +2011,7 @@ static void refine_bidir( x264_t *h, x264_mb_analysis_t *a )
 
 static inline void x264_mb_analyse_transform( x264_t *h )
 {
-    h->mb.cache.b_transform_8x8_allowed =
-        h->param.analyse.b_transform_8x8
-        && !IS_INTRA( h->mb.i_type ) && x264_mb_transform_8x8_allowed( h );
-
-    if( h->mb.cache.b_transform_8x8_allowed )
+    if( x264_mb_transform_8x8_allowed( h ) && h->param.analyse.b_transform_8x8 )
     {
         int i_cost4, i_cost8;
         /* FIXME only luma mc is needed */
@@ -1859,10 +2028,7 @@ static inline void x264_mb_analyse_transform( x264_t *h )
 
 static inline void x264_mb_analyse_transform_rd( x264_t *h, x264_mb_analysis_t *a, int *i_satd, int *i_rd )
 {
-    h->mb.cache.b_transform_8x8_allowed =
-        h->param.analyse.b_transform_8x8 && x264_mb_transform_8x8_allowed( h );
-
-    if( h->mb.cache.b_transform_8x8_allowed )
+    if( x264_mb_transform_8x8_allowed( h ) && h->param.analyse.b_transform_8x8 )
     {
         int i_rd8;
         x264_analyse_update_cache( h, a );
@@ -1895,8 +2061,11 @@ void x264_macroblock_analyse( x264_t *h )
     int i_cost = COST_MAX;
     int i;
 
-    /* init analysis */
-    x264_mb_analyse_init( h, &analysis, x264_ratecontrol_qp( h ) );
+    h->mb.i_qp = x264_ratecontrol_qp( h );
+    if( h->param.rc.i_aq_mode )
+        x264_adaptive_quant( h );
+
+    x264_mb_analyse_init( h, &analysis, h->mb.i_qp );
 
     /*--------------------------- Do the analysis ---------------------------*/
     if( h->sh.i_type == SLICE_TYPE_I )
@@ -1923,11 +2092,16 @@ void x264_macroblock_analyse( x264_t *h )
         int b_skip = 0;
         int i_intra_cost, i_intra_type;
 
+        h->mc.prefetch_ref( h->mb.pic.p_fref[0][0][h->mb.i_mb_x&3], h->mb.pic.i_stride[0], 0 );
+
         /* Fast P_SKIP detection */
         analysis.b_try_pskip = 0;
         if( h->param.analyse.b_fast_pskip )
         {
-            if( h->param.analyse.i_subpel_refine >= 3 )
+            if( h->param.i_threads > 1 && h->mb.cache.pskip_mv[1] > h->mb.mv_max_spel[1] )
+                // FIXME don't need to check this if the reference frame is done
+                {}
+            else if( h->param.analyse.i_subpel_refine >= 3 )
                 analysis.b_try_pskip = 1;
             else if( h->mb.i_mb_type_left == P_SKIP ||
                      h->mb.i_mb_type_top == P_SKIP ||
@@ -1936,10 +2110,13 @@ void x264_macroblock_analyse( x264_t *h )
                 b_skip = x264_macroblock_probe_pskip( h );
         }
 
+        h->mc.prefetch_ref( h->mb.pic.p_fref[0][0][h->mb.i_mb_x&3], h->mb.pic.i_stride[0], 1 );
+
         if( b_skip )
         {
             h->mb.i_type = P_SKIP;
             h->mb.i_partition = D_16x16;
+            assert( h->mb.cache.pskip_mv[1] <= h->mb.mv_max_spel[1] || h->param.i_threads == 1 );
         }
         else
         {
@@ -2126,6 +2303,7 @@ void x264_macroblock_analyse( x264_t *h )
             h->mb.i_type = i_type;
             h->stat.frame.i_intra_cost += i_intra_cost;
             h->stat.frame.i_inter_cost += i_cost;
+            h->stat.frame.i_mbs_analysed++;
 
             if( h->mb.i_subpel_refine >= 7 )
             {
@@ -2206,7 +2384,7 @@ void x264_macroblock_analyse( x264_t *h )
                 i_bskip_cost = ssd_mb( h );
 
                 /* 6 = minimum cavlc cost of a non-skipped MB */
-                if( i_bskip_cost <= 6 * analysis.i_lambda2 )
+                if( i_bskip_cost <= ((6 * analysis.i_lambda2 + 128) >> 8) )
                 {
                     h->mb.i_type = B_SKIP;
                     x264_analyse_update_cache( h, &analysis );
@@ -2398,7 +2576,9 @@ void x264_macroblock_analyse( x264_t *h )
             h->mb.i_type = i_type;
             h->mb.i_partition = i_partition;
 
-            if( h->param.analyse.b_bidir_me )
+            if( h->mb.i_subpel_refine >= 7 && IS_INTRA( i_type ) )
+                x264_intra_rd_refine( h, &analysis );
+            else if( h->param.analyse.b_bidir_me )
                 refine_bidir( h, &analysis );
         }
     }
@@ -2410,6 +2590,8 @@ void x264_macroblock_analyse( x264_t *h )
 
     h->mb.b_trellis = h->param.analyse.i_trellis;
     h->mb.b_noise_reduction = h->param.analyse.i_noise_reduction;
+    if( h->mb.b_trellis == 1 || h->mb.b_noise_reduction )
+        h->mb.i_skip_intra = 0;
 }
 
 /*-------------------- Update MB from the analysis ----------------------*/
@@ -2475,12 +2657,10 @@ static void x264_analyse_update_cache( x264_t *h, x264_mb_analysis_t *a  )
 
         case P_SKIP:
         {
-            int mvp[2];
-            x264_mb_predict_mv_pskip( h, mvp );
-            /* */
             h->mb.i_partition = D_16x16;
             x264_macroblock_cache_ref( h, 0, 0, 4, 4, 0, 0 );
-            x264_macroblock_cache_mv ( h, 0, 0, 4, 4, 0, mvp[0], mvp[1] );
+            x264_macroblock_cache_mv ( h, 0, 0, 4, 4, 0, h->mb.cache.pskip_mv[0],
+                                                         h->mb.cache.pskip_mv[1] );
             break;
         }
 
@@ -2542,7 +2722,38 @@ static void x264_analyse_update_cache( x264_t *h, x264_mb_analysis_t *a  )
                 break;
             }
     }
+
+#ifndef NDEBUG
+    if( h->param.i_threads > 1 && !IS_INTRA(h->mb.i_type) )
+    {
+        int l;
+        for( l=0; l <= (h->sh.i_type == SLICE_TYPE_B); l++ )
+        {
+            int completed;
+            int ref = h->mb.cache.ref[l][x264_scan8[0]];
+            if( ref < 0 )
+                continue;
+            completed = (l ? h->fref1 : h->fref0)[ ref >> h->mb.b_interlaced ]->i_lines_completed;
+            if( (h->mb.cache.mv[l][x264_scan8[15]][1] >> (2 - h->mb.b_interlaced)) + h->mb.i_mb_y*16 > completed )
+            {
+                x264_log( h, X264_LOG_WARNING, "internal error (MV out of thread range)\n");
+                fprintf(stderr, "mb type: %d \n", h->mb.i_type);
+                fprintf(stderr, "mv: l%dr%d (%d,%d) \n", l, ref,
+                                h->mb.cache.mv[l][x264_scan8[15]][0],
+                                h->mb.cache.mv[l][x264_scan8[15]][1] );
+                fprintf(stderr, "limit: %d \n", h->mb.mv_max_spel[1]);
+                fprintf(stderr, "mb_xy: %d,%d \n", h->mb.i_mb_x, h->mb.i_mb_y);
+                fprintf(stderr, "completed: %d \n", completed );
+                x264_log( h, X264_LOG_WARNING, "recovering by using intra mode\n");
+                x264_mb_analyse_intra( h, a, COST_MAX );
+                h->mb.i_type = I_16x16;
+                h->mb.i_intra16x16_pred_mode = a->i_predict16x16;
+                x264_mb_analyse_intra_chroma( h, a );
+            }
+        }
+    }
+#endif
 }
 
-#include "slicetype_decision.c"
+#include "slicetype.c"