]> git.sesse.net Git - x264/blobdiff - common/macroblock.c
Threaded lookahead
[x264] / common / macroblock.c
index d4ed3784b513d00adecf4d981550dfed0b83c731..6e866d4c04ed7e52730ef35991d92a66db4fe91a 100644 (file)
@@ -23,6 +23,7 @@
  *****************************************************************************/
 
 #include "common.h"
+#include "encoder/me.h"
 
 void x264_mb_predict_mv( x264_t *h, int i_list, int idx, int i_width, int16_t mvp[2] )
 {
@@ -35,9 +36,9 @@ void x264_mb_predict_mv( x264_t *h, int i_list, int idx, int i_width, int16_t mv
     int     i_refc = h->mb.cache.ref[i_list][i8 - 8 + i_width ];
     int16_t *mv_c  = h->mb.cache.mv[i_list][i8 - 8 + i_width];
 
-    int i_count;
+    int i_count = 0;
 
-    if( (idx&0x03) == 3 || ( i_width == 2 && (idx&0x3) == 2 )|| i_refc == -2 )
+    if( (idx&3) >= 2 + (i_width&1) || i_refc == -2 )
     {
         i_refc = h->mb.cache.ref[i_list][i8 - 8 - 1];
         mv_c   = h->mb.cache.mv[i_list][i8 - 8 - 1];
@@ -45,38 +46,52 @@ void x264_mb_predict_mv( x264_t *h, int i_list, int idx, int i_width, int16_t mv
 
     if( h->mb.i_partition == D_16x8 )
     {
-        if( idx == 0 && i_refb == i_ref )
+        if( idx == 0 )
         {
-            *(uint32_t*)mvp = *(uint32_t*)mv_b;
-            return;
+            if( i_refb == i_ref )
+            {
+                *(uint32_t*)mvp = *(uint32_t*)mv_b;
+                return;
+            }
         }
-        else if( idx != 0 && i_refa == i_ref )
+        else
         {
-            *(uint32_t*)mvp = *(uint32_t*)mv_a;
-            return;
+            if( i_refa == i_ref )
+            {
+                *(uint32_t*)mvp = *(uint32_t*)mv_a;
+                return;
+            }
         }
     }
     else if( h->mb.i_partition == D_8x16 )
     {
-        if( idx == 0 && i_refa == i_ref )
+        if( idx == 0 )
         {
-            *(uint32_t*)mvp = *(uint32_t*)mv_a;
-            return;
+            if( i_refa == i_ref )
+            {
+                *(uint32_t*)mvp = *(uint32_t*)mv_a;
+                return;
+            }
         }
-        else if( idx != 0 && i_refc == i_ref )
+        else
         {
-            *(uint32_t*)mvp = *(uint32_t*)mv_c;
-            return;
+            if( i_refc == i_ref )
+            {
+                *(uint32_t*)mvp = *(uint32_t*)mv_c;
+                return;
+            }
         }
     }
 
-    i_count = 0;
     if( i_refa == i_ref ) i_count++;
     if( i_refb == i_ref ) i_count++;
     if( i_refc == i_ref ) i_count++;
 
     if( i_count > 1 )
+    {
+median:
         x264_median_mv( mvp, mv_a, mv_b, mv_c );
+    }
     else if( i_count == 1 )
     {
         if( i_refa == i_ref )
@@ -89,7 +104,7 @@ void x264_mb_predict_mv( x264_t *h, int i_list, int idx, int i_width, int16_t mv
     else if( i_refb == -2 && i_refc == -2 && i_refa != -2 )
         *(uint32_t*)mvp = *(uint32_t*)mv_a;
     else
-        x264_median_mv( mvp, mv_a, mv_b, mv_c );
+        goto median;
 }
 
 void x264_mb_predict_mv_16x16( x264_t *h, int i_list, int i_ref, int16_t mvp[2] )
@@ -101,7 +116,7 @@ void x264_mb_predict_mv_16x16( x264_t *h, int i_list, int i_ref, int16_t mvp[2]
     int     i_refc = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8 + 4];
     int16_t *mv_c  = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8 + 4];
 
-    int i_count;
+    int i_count = 0;
 
     if( i_refc == -2 )
     {
@@ -109,13 +124,15 @@ void x264_mb_predict_mv_16x16( x264_t *h, int i_list, int i_ref, int16_t mvp[2]
         mv_c   = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8 - 1];
     }
 
-    i_count = 0;
     if( i_refa == i_ref ) i_count++;
     if( i_refb == i_ref ) i_count++;
     if( i_refc == i_ref ) i_count++;
 
     if( i_count > 1 )
+    {
+median:
         x264_median_mv( mvp, mv_a, mv_b, mv_c );
+    }
     else if( i_count == 1 )
     {
         if( i_refa == i_ref )
@@ -128,7 +145,7 @@ void x264_mb_predict_mv_16x16( x264_t *h, int i_list, int i_ref, int16_t mvp[2]
     else if( i_refb == -2 && i_refc == -2 && i_refa != -2 )
         *(uint32_t*)mvp = *(uint32_t*)mv_a;
     else
-        x264_median_mv( mvp, mv_a, mv_b, mv_c );
+        goto median;
 }
 
 
@@ -140,8 +157,8 @@ void x264_mb_predict_mv_pskip( x264_t *h, int16_t mv[2] )
     int16_t *mv_b  = h->mb.cache.mv[0][X264_SCAN8_0 - 8];
 
     if( i_refa == -2 || i_refb == -2 ||
-        ( i_refa == 0 && *(uint32_t*)mv_a == 0 ) ||
-        ( i_refb == 0 && *(uint32_t*)mv_b == 0 ) )
+        !( i_refa | *(uint32_t*)mv_a ) ||
+        !( i_refb | *(uint32_t*)mv_b ) )
     {
         *(uint32_t*)mv = 0;
     }
@@ -155,8 +172,7 @@ static int x264_mb_predict_mv_direct16x16_temporal( x264_t *h )
 {
     int i_mb_4x4 = 16 * h->mb.i_mb_stride * h->mb.i_mb_y + 4 * h->mb.i_mb_x;
     int i_mb_8x8 =  4 * h->mb.i_mb_stride * h->mb.i_mb_y + 2 * h->mb.i_mb_x;
-    int i8, i4;
-    int b8x8;
+    int i8;
     const int type_col = h->fref1[0]->mb_type[ h->mb.i_mb_xy ];
 
     x264_macroblock_cache_ref( h, 0, 0, 4, 4, 1, 0 );
@@ -168,8 +184,6 @@ static int x264_mb_predict_mv_direct16x16_temporal( x264_t *h )
         x264_macroblock_cache_mv(  h, 0, 0, 4, 4, 1, 0 );
         return 1;
     }
-    b8x8 = h->sps->b_direct8x8_inference ||
-           (type_col != P_8x8 && type_col != B_SKIP && type_col != B_DIRECT && type_col != B_8x8);
 
     for( i8 = 0; i8 < 4; i8++ )
     {
@@ -181,30 +195,14 @@ static int x264_mb_predict_mv_direct16x16_temporal( x264_t *h )
         if( i_ref >= 0 )
         {
             const int dist_scale_factor = h->mb.dist_scale_factor[i_ref][0];
-
+            const int16_t *mv_col = h->fref1[0]->mv[0][ i_mb_4x4 + 3*x8 + 3*y8 * h->mb.i_b4_stride];
+            const int l0x = ( dist_scale_factor * mv_col[0] + 128 ) >> 8;
+            const int l0y = ( dist_scale_factor * mv_col[1] + 128 ) >> 8;
+            if( h->param.i_threads > 1 && (l0y > h->mb.mv_max_spel[1] || l0y-mv_col[1] > h->mb.mv_max_spel[1]) )
+                return 0;
             x264_macroblock_cache_ref( h, 2*x8, 2*y8, 2, 2, 0, i_ref );
-
-            if( b8x8 )
-            {
-                const int16_t *mv_col = h->fref1[0]->mv[0][ i_mb_4x4 + 3*x8 + 3*y8 * h->mb.i_b4_stride];
-                const int l0x = ( dist_scale_factor * mv_col[0] + 128 ) >> 8;
-                const int l0y = ( dist_scale_factor * mv_col[1] + 128 ) >> 8;
-                x264_macroblock_cache_mv( h, 2*x8, 2*y8, 2, 2, 0, pack16to32_mask(l0x, l0y) );
-                x264_macroblock_cache_mv( h, 2*x8, 2*y8, 2, 2, 1, pack16to32_mask(l0x-mv_col[0], l0y-mv_col[1]) );
-            }
-            else
-            {
-                for( i4 = 0; i4 < 4; i4++ )
-                {
-                    const int x4 = i4%2 + 2*x8;
-                    const int y4 = i4/2 + 2*y8;
-                    const int16_t *mv_col = h->fref1[0]->mv[0][ i_mb_4x4 + x4 + y4 * h->mb.i_b4_stride ];
-                    const int l0x = ( dist_scale_factor * mv_col[0] + 128 ) >> 8;
-                    const int l0y = ( dist_scale_factor * mv_col[1] + 128 ) >> 8;
-                    x264_macroblock_cache_mv( h, x4, y4, 1, 1, 0, pack16to32_mask(l0x, l0y) );
-                    x264_macroblock_cache_mv( h, x4, y4, 1, 1, 1, pack16to32_mask(l0x-mv_col[0], l0y-mv_col[1]) );
-                }
-            }
+            x264_macroblock_cache_mv( h, 2*x8, 2*y8, 2, 2, 0, pack16to32_mask(l0x, l0y) );
+            x264_macroblock_cache_mv( h, 2*x8, 2*y8, 2, 2, 1, pack16to32_mask(l0x-mv_col[0], l0y-mv_col[1]) );
         }
         else
         {
@@ -217,37 +215,15 @@ static int x264_mb_predict_mv_direct16x16_temporal( x264_t *h )
         }
     }
 
-    if( h->param.i_threads > 1 )
-    {
-        int di = b8x8 ? 4 : 1;
-        for( i4=0; i4<16; i4+=di )
-        {
-            if( h->mb.cache.mv[0][x264_scan8[i4]][1] > h->mb.mv_max_spel[1]
-             || h->mb.cache.mv[1][x264_scan8[i4]][1] > h->mb.mv_max_spel[1] )
-            {
-#if 0
-                fprintf(stderr, "direct_temporal: (%d,%d) (%d,%d) > %d \n",
-                        h->mb.cache.mv[0][x264_scan8[i4]][0],
-                        h->mb.cache.mv[0][x264_scan8[i4]][1],
-                        h->mb.cache.mv[1][x264_scan8[i4]][0],
-                        h->mb.cache.mv[1][x264_scan8[i4]][1],
-                        h->mb.mv_max_spel[1]);
-#endif
-                return 0;
-            }
-        }
-    }
-
     return 1;
 }
 
 static int x264_mb_predict_mv_direct16x16_spatial( x264_t *h )
 {
     int ref[2];
-    DECLARE_ALIGNED_8( int16_t mv[2][2] );
+    ALIGNED_8( int16_t mv[2][2] );
     int i_list;
-    int i8, i4;
-    int b8x8;
+    int i8;
     const int8_t *l1ref0 = &h->fref1[0]->ref[0][ h->mb.i_b8_xy ];
     const int8_t *l1ref1 = &h->fref1[0]->ref[1][ h->mb.i_b8_xy ];
     const int16_t (*l1mv0)[2] = (const int16_t (*)[2]) &h->fref1[0]->mv[0][ h->mb.i_b4_xy ];
@@ -309,44 +285,27 @@ static int x264_mb_predict_mv_direct16x16_spatial( x264_t *h )
     if( IS_INTRA( type_col ) || (ref[0]&&ref[1]) )
         return 1;
 
-    b8x8 = h->sps->b_direct8x8_inference ||
-           (type_col != P_8x8 && type_col != B_SKIP && type_col != B_DIRECT && type_col != B_8x8);
-
     /* col_zero_flag */
     for( i8=0; i8<4; i8++ )
     {
         const int x8 = i8%2;
         const int y8 = i8/2;
         const int o8 = x8 + y8 * h->mb.i_b8_stride;
-        if( l1ref0[o8] == 0 || ( l1ref0[o8] < 0 && l1ref1[o8] == 0 ) )
+        const int o4 = 3*(x8 + y8 * h->mb.i_b4_stride);
+        if( l1ref0[o8] == 0 )
         {
-            const int16_t (*l1mv)[2] = (l1ref0[o8] == 0) ? l1mv0 : l1mv1;
-            if( b8x8 )
+            if( abs( l1mv0[o4][0] ) <= 1 && abs( l1mv0[o4][1] ) <= 1 )
             {
-                const int16_t *mvcol = l1mv[3*x8 + 3*y8 * h->mb.i_b4_stride];
-                if( abs( mvcol[0] ) <= 1 && abs( mvcol[1] ) <= 1 )
-                {
-                    if( ref[0] == 0 )
-                        x264_macroblock_cache_mv( h, 2*x8, 2*y8, 2, 2, 0, 0 );
-                    if( ref[1] == 0 )
-                        x264_macroblock_cache_mv( h, 2*x8, 2*y8, 2, 2, 1, 0 );
-                }
+                if( ref[0] == 0 ) x264_macroblock_cache_mv( h, 2*x8, 2*y8, 2, 2, 0, 0 );
+                if( ref[1] == 0 ) x264_macroblock_cache_mv( h, 2*x8, 2*y8, 2, 2, 1, 0 );
             }
-            else
+        }
+        else if( l1ref0[o8] < 0 && l1ref1[o8] == 0 )
+        {
+            if( abs( l1mv1[o4][0] ) <= 1 && abs( l1mv1[o4][1] ) <= 1 )
             {
-                for( i4=0; i4<4; i4++ )
-                {
-                    const int x4 = i4%2 + 2*x8;
-                    const int y4 = i4/2 + 2*y8;
-                    const int16_t *mvcol = l1mv[x4 + y4 * h->mb.i_b4_stride];
-                    if( abs( mvcol[0] ) <= 1 && abs( mvcol[1] ) <= 1 )
-                    {
-                        if( ref[0] == 0 )
-                            x264_macroblock_cache_mv( h, x4, y4, 1, 1, 0, 0 );
-                        if( ref[1] == 0 )
-                            x264_macroblock_cache_mv( h, x4, y4, 1, 1, 1, 0 );
-                    }
-                }
+                if( ref[0] == 0 ) x264_macroblock_cache_mv( h, 2*x8, 2*y8, 2, 2, 0, 0 );
+                if( ref[1] == 0 ) x264_macroblock_cache_mv( h, 2*x8, 2*y8, 2, 2, 1, 0 );
             }
         }
     }
@@ -561,8 +520,8 @@ static inline void x264_mb_mc_01xywh( x264_t *h, int x, int y, int width, int he
     int       mvy1   = x264_clip3( h->mb.cache.mv[1][i8][1], h->mb.mv_min[1], h->mb.mv_max[1] );
     int       i_mode = x264_size2pixel[height][width];
     int       i_stride0 = 16, i_stride1 = 16;
-    DECLARE_ALIGNED_16( uint8_t tmp0[16*16] );
-    DECLARE_ALIGNED_16( uint8_t tmp1[16*16] );
+    ALIGNED_ARRAY_16( uint8_t, tmp0,[16*16] );
+    ALIGNED_ARRAY_16( uint8_t, tmp1,[16*16] );
     uint8_t *src0, *src1;
 
     src0 = h->mc.get_ref( tmp0, &i_stride0, h->mb.pic.p_fref[0][i_ref0], h->mb.pic.i_stride[0],
@@ -593,44 +552,13 @@ static void x264_mb_mc_direct8x8( x264_t *h, int x, int y )
 {
     const int i8 = x264_scan8[0] + x + 8*y;
 
-    /* FIXME: optimize based on current block size, not global settings? */
-    if( h->sps->b_direct8x8_inference )
-    {
-        if( h->mb.cache.ref[0][i8] >= 0 )
-            if( h->mb.cache.ref[1][i8] >= 0 )
-                x264_mb_mc_01xywh( h, x, y, 2, 2 );
-            else
-                x264_mb_mc_0xywh( h, x, y, 2, 2 );
+    if( h->mb.cache.ref[0][i8] >= 0 )
+        if( h->mb.cache.ref[1][i8] >= 0 )
+            x264_mb_mc_01xywh( h, x, y, 2, 2 );
         else
-            x264_mb_mc_1xywh( h, x, y, 2, 2 );
-    }
+            x264_mb_mc_0xywh( h, x, y, 2, 2 );
     else
-    {
-        if( h->mb.cache.ref[0][i8] >= 0 )
-        {
-            if( h->mb.cache.ref[1][i8] >= 0 )
-            {
-                x264_mb_mc_01xywh( h, x+0, y+0, 1, 1 );
-                x264_mb_mc_01xywh( h, x+1, y+0, 1, 1 );
-                x264_mb_mc_01xywh( h, x+0, y+1, 1, 1 );
-                x264_mb_mc_01xywh( h, x+1, y+1, 1, 1 );
-            }
-            else
-            {
-                x264_mb_mc_0xywh( h, x+0, y+0, 1, 1 );
-                x264_mb_mc_0xywh( h, x+1, y+0, 1, 1 );
-                x264_mb_mc_0xywh( h, x+0, y+1, 1, 1 );
-                x264_mb_mc_0xywh( h, x+1, y+1, 1, 1 );
-            }
-        }
-        else
-        {
-            x264_mb_mc_1xywh( h, x+0, y+0, 1, 1 );
-            x264_mb_mc_1xywh( h, x+1, y+0, 1, 1 );
-            x264_mb_mc_1xywh( h, x+0, y+1, 1, 1 );
-            x264_mb_mc_1xywh( h, x+1, y+1, 1, 1 );
-        }
-    }
+        x264_mb_mc_1xywh( h, x, y, 2, 2 );
 }
 
 void x264_mb_mc_8x8( x264_t *h, int i8 )
@@ -659,37 +587,9 @@ void x264_mb_mc_8x8( x264_t *h, int i8 )
         case D_L1_8x8:
             x264_mb_mc_1xywh( h, x, y, 2, 2 );
             break;
-        case D_L1_8x4:
-            x264_mb_mc_1xywh( h, x, y+0, 2, 1 );
-            x264_mb_mc_1xywh( h, x, y+1, 2, 1 );
-            break;
-        case D_L1_4x8:
-            x264_mb_mc_1xywh( h, x+0, y, 1, 2 );
-            x264_mb_mc_1xywh( h, x+1, y, 1, 2 );
-            break;
-        case D_L1_4x4:
-            x264_mb_mc_1xywh( h, x+0, y+0, 1, 1 );
-            x264_mb_mc_1xywh( h, x+1, y+0, 1, 1 );
-            x264_mb_mc_1xywh( h, x+0, y+1, 1, 1 );
-            x264_mb_mc_1xywh( h, x+1, y+1, 1, 1 );
-            break;
         case D_BI_8x8:
             x264_mb_mc_01xywh( h, x, y, 2, 2 );
             break;
-        case D_BI_8x4:
-            x264_mb_mc_01xywh( h, x, y+0, 2, 1 );
-            x264_mb_mc_01xywh( h, x, y+1, 2, 1 );
-            break;
-        case D_BI_4x8:
-            x264_mb_mc_01xywh( h, x+0, y, 1, 2 );
-            x264_mb_mc_01xywh( h, x+1, y, 1, 2 );
-            break;
-        case D_BI_4x4:
-            x264_mb_mc_01xywh( h, x+0, y+0, 1, 1 );
-            x264_mb_mc_01xywh( h, x+1, y+0, 1, 1 );
-            x264_mb_mc_01xywh( h, x+0, y+1, 1, 1 );
-            x264_mb_mc_01xywh( h, x+1, y+1, 1, 1 );
-            break;
         case D_DIRECT_8x8:
             x264_mb_mc_direct8x8( h, x, y );
             break;
@@ -730,17 +630,9 @@ void x264_mb_mc( x264_t *h )
     }
     else    /* B_*x* */
     {
-        int b_list0[2];
-        int b_list1[2];
+        const uint8_t *b_list0 = x264_mb_type_list_table[h->mb.i_type][0];
+        const uint8_t *b_list1 = x264_mb_type_list_table[h->mb.i_type][1];
 
-        int i;
-
-        /* init ref list utilisations */
-        for( i = 0; i < 2; i++ )
-        {
-            b_list0[i] = x264_mb_type_list0_table[h->mb.i_type][i];
-            b_list1[i] = x264_mb_type_list1_table[h->mb.i_type][i];
-        }
         if( h->mb.i_partition == D_16x16 )
         {
             if( b_list0[0] && b_list1[0] ) x264_mb_mc_01xywh( h, 0, 0, 4, 4 );
@@ -810,7 +702,8 @@ int x264_macroblock_cache_init( x264_t *h )
     for( i=0; i<=h->param.b_interlaced; i++ )
         for( j=0; j<3; j++ )
         {
-            CHECKED_MALLOC( h->mb.intra_border_backup[i][j], h->fdec->i_stride[j] );
+            /* shouldn't really be initialized, just silences a valgrind false-positive in predict_8x8_filter_mmx */
+            CHECKED_MALLOCZERO( h->mb.intra_border_backup[i][j], (h->sps->i_mb_width*16+32)>>!!j );
             h->mb.intra_border_backup[i][j] += 8;
         }
 
@@ -846,6 +739,14 @@ int x264_macroblock_cache_init( x264_t *h )
     h->mb.i_neighbour4[15] =
     h->mb.i_neighbour8[3] = MB_LEFT|MB_TOP|MB_TOPLEFT;
 
+    int buf_hpel = (h->param.i_width+48) * sizeof(int16_t);
+    int buf_ssim = h->param.analyse.b_ssim * 8 * (h->param.i_width/4+3) * sizeof(int);
+    int me_range = X264_MIN(h->param.analyse.i_me_range, h->param.analyse.i_mv_range);
+    int buf_tesa = (h->param.analyse.i_me_method >= X264_ME_ESA) *
+        ((me_range*2+18) * sizeof(int16_t) + (me_range+4) * (me_range+1) * 4 * sizeof(mvsad_t));
+    int buf_mbtree = h->param.rc.b_mb_tree * ((h->sps->i_mb_width+3)&~3) * sizeof(int);
+    CHECKED_MALLOC( h->scratch_buffer, X264_MAX4( buf_hpel, buf_ssim, buf_tesa, buf_mbtree ) );
+
     return 0;
 fail: return -1;
 }
@@ -871,6 +772,7 @@ void x264_macroblock_cache_end( x264_t *h )
     x264_free( h->mb.skipbp );
     x264_free( h->mb.cbp );
     x264_free( h->mb.qp );
+    x264_free( h->scratch_buffer );
 }
 void x264_macroblock_slice_init( x264_t *h )
 {
@@ -948,7 +850,7 @@ static void ALWAYS_INLINE x264_macroblock_load_pic_pointers( x264_t *h, int i_mb
     h->mc.copy[i?PIXEL_8x8:PIXEL_16x16]( h->mb.pic.p_fenc[i], FENC_STRIDE,
         h->mb.pic.p_fenc_plane[i], i_stride2, w );
     memcpy( &h->mb.pic.p_fdec[i][-1-FDEC_STRIDE], intra_fdec-1, w*3/2+1 );
-    if( h->mb.b_interlaced )
+    if( h->mb.b_interlaced || h->mb.b_reencode_mb )
     {
         const uint8_t *plane_fdec = &h->fdec->plane[i][i_pix_offset];
         for( j = 0; j < w; j++ )
@@ -1000,6 +902,7 @@ void x264_macroblock_cache_load( x264_t *h, int i_mb_x, int i_mb_y )
     {
         h->mb.i_mb_type_top =
         i_top_type= h->mb.type[i_top_xy];
+        h->mb.cache.i_cbp_top = h->mb.cbp[i_top_xy];
 
         h->mb.i_neighbour |= MB_TOP;
 
@@ -1015,6 +918,7 @@ void x264_macroblock_cache_load( x264_t *h, int i_mb_x, int i_mb_y )
     else
     {
         h->mb.i_mb_type_top = -1;
+        h->mb.cache.i_cbp_top = -1;
 
         /* load intra4x4 */
         h->mb.cache.intra4x4_pred_mode[x264_scan8[0] - 8] =
@@ -1038,6 +942,7 @@ void x264_macroblock_cache_load( x264_t *h, int i_mb_x, int i_mb_y )
         i_left_xy = i_mb_xy - 1;
         h->mb.i_mb_type_left =
         i_left_type = h->mb.type[i_left_xy];
+        h->mb.cache.i_cbp_left = h->mb.cbp[h->mb.i_mb_xy - 1];
 
         h->mb.i_neighbour |= MB_LEFT;
 
@@ -1062,6 +967,7 @@ void x264_macroblock_cache_load( x264_t *h, int i_mb_x, int i_mb_y )
     else
     {
         h->mb.i_mb_type_left = -1;
+        h->mb.cache.i_cbp_left = -1;
 
         h->mb.cache.intra4x4_pred_mode[x264_scan8[0 ] - 1] =
         h->mb.cache.intra4x4_pred_mode[x264_scan8[2 ] - 1] =
@@ -1110,7 +1016,7 @@ void x264_macroblock_cache_load( x264_t *h, int i_mb_x, int i_mb_y )
           + !!(h->mb.i_neighbour & MB_TOP);
     }
 
-    if( !h->mb.b_interlaced )
+    if( !h->mb.b_interlaced && !h->mb.b_reencode_mb )
     {
         copy_column8( h->mb.pic.p_fdec[0]-1+ 4*FDEC_STRIDE, h->mb.pic.p_fdec[0]+15+ 4*FDEC_STRIDE );
         copy_column8( h->mb.pic.p_fdec[0]-1+12*FDEC_STRIDE, h->mb.pic.p_fdec[0]+15+12*FDEC_STRIDE );
@@ -1457,9 +1363,10 @@ void x264_macroblock_cache_save( x264_t *h )
                 h->mb.skipbp[i_mb_xy] = 0xf;
             else if( i_mb_type == B_8x8 )
             {
-                int skipbp = 0;
-                for( i = 0; i < 4; i++ )
-                    skipbp |= ( h->mb.i_sub_partition[i] == D_DIRECT_8x8 ) << i;
+                int skipbp = ( h->mb.i_sub_partition[0] == D_DIRECT_8x8 ) << 0;
+                skipbp    |= ( h->mb.i_sub_partition[1] == D_DIRECT_8x8 ) << 1;
+                skipbp    |= ( h->mb.i_sub_partition[2] == D_DIRECT_8x8 ) << 2;
+                skipbp    |= ( h->mb.i_sub_partition[3] == D_DIRECT_8x8 ) << 3;
                 h->mb.skipbp[i_mb_xy] = skipbp;
             }
             else