]> git.sesse.net Git - x264/blobdiff - common/frame.c
rm gtk, avc2avi.
[x264] / common / frame.c
index 2be8c7a024e8aa6e0e2cf62518f9fd36d738499f..dc447a72af3b2514e857616d526e1471addce918 100644 (file)
@@ -77,6 +77,14 @@ x264_frame_t *x264_frame_new( x264_t *h )
         CHECKED_MALLOC( frame->buffer_lowres[0], 4 * luma_plane_size );
         for( i = 0; i < 4; i++ )
             frame->lowres[i] = frame->buffer_lowres[0] + (frame->i_stride_lowres * i_padv + PADH) + i * luma_plane_size;
+
+        for( j = 0; j <= !!h->param.i_bframe; j++ )
+            for( i = 0; i <= h->param.i_bframe; i++ )
+            {
+                CHECKED_MALLOC( frame->lowres_mvs[j][i], 2*h->mb.i_mb_count*sizeof(int16_t) );
+                memset( frame->lowres_mvs[j][i], 0, 2*h->mb.i_mb_count*sizeof(int16_t) );
+                CHECKED_MALLOC( frame->lowres_mv_costs[j][i], h->mb.i_mb_count*sizeof(int) );
+            }
     }
 
     if( h->param.analyse.i_me_method >= X264_ME_ESA )
@@ -97,6 +105,7 @@ x264_frame_t *x264_frame_new( x264_t *h )
     CHECKED_MALLOC( frame->mb_type, i_mb_count * sizeof(int8_t));
     CHECKED_MALLOC( frame->mv[0], 2*16 * i_mb_count * sizeof(int16_t) );
     CHECKED_MALLOC( frame->ref[0], 4 * i_mb_count * sizeof(int8_t) );
+    CHECKED_MALLOC( frame->i_intra_cost, i_mb_count * sizeof(uint16_t) );
     if( h->param.i_bframe )
     {
         CHECKED_MALLOC( frame->mv[1], 2*16 * i_mb_count * sizeof(int16_t) );
@@ -114,6 +123,9 @@ x264_frame_t *x264_frame_new( x264_t *h )
         for( j = 0; j < h->param.i_bframe + 2; j++ )
             CHECKED_MALLOC( frame->i_row_satds[i][j], i_lines/16 * sizeof(int) );
 
+    if( h->param.rc.i_aq_mode )
+        CHECKED_MALLOC( frame->f_qp_offset, h->mb.i_mb_count * sizeof(float) );
+
     x264_pthread_mutex_init( &frame->mutex, NULL );
     x264_pthread_cond_init( &frame->cv, NULL );
 
@@ -134,6 +146,14 @@ void x264_frame_delete( x264_frame_t *frame )
     for( i = 0; i < X264_BFRAME_MAX+2; i++ )
         for( j = 0; j < X264_BFRAME_MAX+2; j++ )
             x264_free( frame->i_row_satds[i][j] );
+    for( j = 0; j < 2; j++ )
+        for( i = 0; i <= X264_BFRAME_MAX; i++ )
+        {
+            x264_free( frame->lowres_mvs[j][i] );
+            x264_free( frame->lowres_mv_costs[j][i] );
+        }
+    x264_free( frame->f_qp_offset );
+    x264_free( frame->i_intra_cost );
     x264_free( frame->i_row_bits );
     x264_free( frame->i_row_qp );
     x264_free( frame->mb_type );
@@ -233,7 +253,7 @@ void x264_frame_expand_border( x264_t *h, x264_frame_t *frame, int mb_y, int b_e
 void x264_frame_expand_border_filtered( x264_t *h, x264_frame_t *frame, int mb_y, int b_end )
 {
     /* during filtering, 8 extra pixels were filtered on each edge,
-     * but up to 3 of the horizontal ones may be wrong. 
+     * but up to 3 of the horizontal ones may be wrong.
        we want to expand border from the last filtered pixel */
     int b_start = !mb_y;
     int stride = frame->i_stride[0];
@@ -297,7 +317,7 @@ void x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame )
 
 /* cavlc + 8x8 transform stores nnz per 16 coeffs for the purpose of
  * entropy coding, but per 64 coeffs for the purpose of deblocking */
-void munge_cavlc_nnz_row( x264_t *h, int mb_y, uint8_t (*buf)[16] )
+static void munge_cavlc_nnz_row( x264_t *h, int mb_y, uint8_t (*buf)[16] )
 {
     uint32_t (*src)[6] = (uint32_t(*)[6])h->mb.non_zero_count + mb_y * h->sps->i_mb_width;
     int8_t *transform = h->mb.mb_transform_size + mb_y * h->sps->i_mb_width;
@@ -338,28 +358,32 @@ static void munge_cavlc_nnz( x264_t *h, int mb_y, uint8_t (*buf)[16], void (*fun
 
 
 /* Deblocking filter */
-
-static const int i_alpha_table[52] =
+static const uint8_t i_alpha_table[52+12*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,  0,  0,  0,  4,  4,  5,  6,
      7,  8,  9, 10, 12, 13, 15, 17, 20, 22,
     25, 28, 32, 36, 40, 45, 50, 56, 63, 71,
     80, 90,101,113,127,144,162,182,203,226,
-    255, 255
+   255,255,
+   255,255,255,255,255,255,255,255,255,255,255,255,
 };
-static const int i_beta_table[52] =
+static const uint8_t i_beta_table[52+12*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,  0,  0,  0,  2,  2,  2,  3,
      3,  3,  3,  4,  4,  4,  6,  6,  7,  7,
      8,  8,  9,  9, 10, 10, 11, 11, 12, 12,
     13, 13, 14, 14, 15, 15, 16, 16, 17, 17,
-    18, 18
+    18, 18,
+    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
 };
-
-static const int8_t i_tc0_table[52][4] =
+static const int8_t i_tc0_table[52+12*2][4] =
 {
+    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
+    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
     {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
     {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
     {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 1 },
@@ -368,53 +392,52 @@ static const int8_t i_tc0_table[52][4] =
     {-1, 1, 1, 2 }, {-1, 1, 2, 3 }, {-1, 1, 2, 3 }, {-1, 2, 2, 3 }, {-1, 2, 2, 4 }, {-1, 2, 3, 4 },
     {-1, 2, 3, 4 }, {-1, 3, 3, 5 }, {-1, 3, 4, 6 }, {-1, 3, 4, 6 }, {-1, 4, 5, 7 }, {-1, 4, 5, 8 },
     {-1, 4, 6, 9 }, {-1, 5, 7,10 }, {-1, 6, 8,11 }, {-1, 6, 8,13 }, {-1, 7,10,14 }, {-1, 8,11,16 },
-    {-1, 9,12,18 }, {-1,10,13,20 }, {-1,11,15,23 }, {-1,13,17,25 }
+    {-1, 9,12,18 }, {-1,10,13,20 }, {-1,11,15,23 }, {-1,13,17,25 },
+    {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
+    {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
 };
+#define alpha_table(x) i_alpha_table[(x)+12]
+#define beta_table(x)  i_beta_table[(x)+12]
+#define tc0_table(x)   i_tc0_table[(x)+12]
 
 /* From ffmpeg */
-static inline int clip_uint8( int a )
-{
-    if (a&(~255))
-        return (-a)>>31;
-    else
-        return a;
-}
-
 static inline void deblock_luma_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0 )
 {
     int i, d;
-    for( i = 0; i < 4; i++ ) {
-        if( tc0[i] < 0 ) {
+    for( i = 0; i < 4; i++ )
+    {
+        if( tc0[i] < 0 )
+        {
             pix += 4*ystride;
             continue;
         }
-        for( d = 0; d < 4; d++ ) {
+        for( d = 0; d < 4; d++ )
+        {
             const int p2 = pix[-3*xstride];
             const int p1 = pix[-2*xstride];
             const int p0 = pix[-1*xstride];
             const int q0 = pix[ 0*xstride];
             const int q1 = pix[ 1*xstride];
             const int q2 = pix[ 2*xstride];
-   
-            if( abs( p0 - q0 ) < alpha &&
-                abs( p1 - p0 ) < beta &&
-                abs( q1 - q0 ) < beta ) {
-   
+
+            if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta )
+            {
                 int tc = tc0[i];
                 int delta;
-   
-                if( abs( p2 - p0 ) < beta ) {
+                if( abs( p2 - p0 ) < beta )
+                {
                     pix[-2*xstride] = p1 + x264_clip3( (( p2 + ((p0 + q0 + 1) >> 1)) >> 1) - p1, -tc0[i], tc0[i] );
                     tc++;
                 }
-                if( abs( q2 - q0 ) < beta ) {
+                if( abs( q2 - q0 ) < beta )
+                {
                     pix[ 1*xstride] = q1 + x264_clip3( (( q2 + ((p0 + q0 + 1) >> 1)) >> 1) - q1, -tc0[i], tc0[i] );
                     tc++;
                 }
-    
+
                 delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
-                pix[-1*xstride] = clip_uint8( p0 + delta );    /* p0' */
-                pix[ 0*xstride] = clip_uint8( q0 - delta );    /* q0' */
+                pix[-1*xstride] = x264_clip_uint8( p0 + delta );    /* p0' */
+                pix[ 0*xstride] = x264_clip_uint8( q0 - delta );    /* q0' */
             }
             pix += ystride;
         }
@@ -422,7 +445,7 @@ static inline void deblock_luma_c( uint8_t *pix, int xstride, int ystride, int a
 }
 static void deblock_v_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
 {
-    deblock_luma_c( pix, stride, 1, alpha, beta, tc0 ); 
+    deblock_luma_c( pix, stride, 1, alpha, beta, tc0 );
 }
 static void deblock_h_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
 {
@@ -432,43 +455,45 @@ static void deblock_h_luma_c( uint8_t *pix, int stride, int alpha, int beta, int
 static inline void deblock_chroma_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0 )
 {
     int i, d;
-    for( i = 0; i < 4; i++ ) {
+    for( i = 0; i < 4; i++ )
+    {
         const int tc = tc0[i];
-        if( tc <= 0 ) {
+        if( tc <= 0 )
+        {
             pix += 2*ystride;
             continue;
         }
-        for( d = 0; d < 2; d++ ) {
+        for( d = 0; d < 2; d++ )
+        {
             const int p1 = pix[-2*xstride];
             const int p0 = pix[-1*xstride];
             const int q0 = pix[ 0*xstride];
             const int q1 = pix[ 1*xstride];
 
-            if( abs( p0 - q0 ) < alpha &&
-                abs( p1 - p0 ) < beta &&
-                abs( q1 - q0 ) < beta ) {
-
+            if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta )
+            {
                 int delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
-                pix[-1*xstride] = clip_uint8( p0 + delta );    /* p0' */
-                pix[ 0*xstride] = clip_uint8( q0 - delta );    /* q0' */
+                pix[-1*xstride] = x264_clip_uint8( p0 + delta );    /* p0' */
+                pix[ 0*xstride] = x264_clip_uint8( q0 - delta );    /* q0' */
             }
             pix += ystride;
         }
     }
 }
 static void deblock_v_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
-{   
+{
     deblock_chroma_c( pix, stride, 1, alpha, beta, tc0 );
 }
 static void deblock_h_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
-{   
+{
     deblock_chroma_c( pix, 1, stride, alpha, beta, tc0 );
 }
 
 static inline void deblock_luma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta )
 {
     int d;
-    for( d = 0; d < 16; d++ ) {
+    for( d = 0; d < 16; d++ )
+    {
         const int p2 = pix[-3*xstride];
         const int p1 = pix[-2*xstride];
         const int p0 = pix[-1*xstride];
@@ -476,35 +501,31 @@ static inline void deblock_luma_intra_c( uint8_t *pix, int xstride, int ystride,
         const int q1 = pix[ 1*xstride];
         const int q2 = pix[ 2*xstride];
 
-        if( abs( p0 - q0 ) < alpha &&
-            abs( p1 - p0 ) < beta &&
-            abs( q1 - q0 ) < beta ) {
-
-            if(abs( p0 - q0 ) < ((alpha >> 2) + 2) ){
-                if( abs( p2 - p0 ) < beta)
+        if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta )
+        {
+            if(abs( p0 - q0 ) < ((alpha >> 2) + 2) )
+            {
+                if( abs( p2 - p0 ) < beta ) /* p0', p1', p2' */
                 {
                     const int p3 = pix[-4*xstride];
-                    /* p0', p1', p2' */
                     pix[-1*xstride] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3;
                     pix[-2*xstride] = ( p2 + p1 + p0 + q0 + 2 ) >> 2;
                     pix[-3*xstride] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3;
-                } else {
-                    /* p0' */
-                    pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
                 }
-                if( abs( q2 - q0 ) < beta)
+                else /* p0' */
+                    pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
+                if( abs( q2 - q0 ) < beta ) /* q0', q1', q2' */
                 {
                     const int q3 = pix[3*xstride];
-                    /* q0', q1', q2' */
                     pix[0*xstride] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3;
                     pix[1*xstride] = ( p0 + q0 + q1 + q2 + 2 ) >> 2;
                     pix[2*xstride] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3;
-                } else {
-                    /* q0' */
-                    pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
                 }
-            }else{
-                /* p0', q0' */
+                else /* q0' */
+                    pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
+            }
+            else /* p0', q0' */
+            {
                 pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
                 pix[ 0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
             }
@@ -513,83 +534,72 @@ static inline void deblock_luma_intra_c( uint8_t *pix, int xstride, int ystride,
     }
 }
 static void deblock_v_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
-{   
+{
     deblock_luma_intra_c( pix, stride, 1, alpha, beta );
 }
 static void deblock_h_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
-{   
+{
     deblock_luma_intra_c( pix, 1, stride, alpha, beta );
 }
 
 static inline void deblock_chroma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta )
-{   
-    int d; 
-    for( d = 0; d < 8; d++ ) {
+{
+    int d;
+    for( d = 0; d < 8; d++ )
+    {
         const int p1 = pix[-2*xstride];
         const int p0 = pix[-1*xstride];
         const int q0 = pix[ 0*xstride];
         const int q1 = pix[ 1*xstride];
 
-        if( abs( p0 - q0 ) < alpha &&
-            abs( p1 - p0 ) < beta &&
-            abs( q1 - q0 ) < beta ) {
-
+        if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta )
+        {
             pix[-1*xstride] = (2*p1 + p0 + q1 + 2) >> 2;   /* p0' */
             pix[ 0*xstride] = (2*q1 + q0 + p1 + 2) >> 2;   /* q0' */
         }
-
         pix += ystride;
     }
 }
 static void deblock_v_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
-{   
+{
     deblock_chroma_intra_c( pix, stride, 1, alpha, beta );
 }
 static void deblock_h_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
-{   
+{
     deblock_chroma_intra_c( pix, 1, stride, alpha, beta );
 }
 
 static inline void deblock_edge( x264_t *h, uint8_t *pix1, uint8_t *pix2, int i_stride, uint8_t bS[4], int i_qp, int b_chroma, x264_deblock_inter_t pf_inter )
 {
-    const int index_a = x264_clip3( i_qp + h->sh.i_alpha_c0_offset, 0, 51 );
-    const int alpha = i_alpha_table[index_a];
-    const int beta  = i_beta_table[x264_clip3( i_qp + h->sh.i_beta_offset, 0, 51 )];
+    const int index_a = i_qp + h->sh.i_alpha_c0_offset;
+    const int alpha = alpha_table(index_a);
+    const int beta  = beta_table(i_qp + h->sh.i_beta_offset);
     int8_t tc[4];
 
     if( !alpha || !beta )
         return;
 
-    tc[0] = i_tc0_table[index_a][bS[0]] + b_chroma;
-    tc[1] = i_tc0_table[index_a][bS[1]] + b_chroma;
-    tc[2] = i_tc0_table[index_a][bS[2]] + b_chroma;
-    tc[3] = i_tc0_table[index_a][bS[3]] + b_chroma;
+    tc[0] = tc0_table(index_a)[bS[0]] + b_chroma;
+    tc[1] = tc0_table(index_a)[bS[1]] + b_chroma;
+    tc[2] = tc0_table(index_a)[bS[2]] + b_chroma;
+    tc[3] = tc0_table(index_a)[bS[3]] + b_chroma;
 
-    if(b_chroma)
-    {
-        pf_inter( pix1, i_stride, alpha, beta, tc );
+    pf_inter( pix1, i_stride, alpha, beta, tc );
+    if( b_chroma )
         pf_inter( pix2, i_stride, alpha, beta, tc );
-    }
-    else
-        pf_inter( pix1, i_stride, alpha, beta, tc );
 }
 
 static inline void deblock_edge_intra( x264_t *h, uint8_t *pix1, uint8_t *pix2, int i_stride, uint8_t bS[4], int i_qp, int b_chroma, x264_deblock_intra_t pf_intra )
 {
-    const int index_a = x264_clip3( i_qp + h->sh.i_alpha_c0_offset, 0, 51 );
-    const int alpha = i_alpha_table[index_a];
-    const int beta  = i_beta_table[x264_clip3( i_qp + h->sh.i_beta_offset, 0, 51 )];
+    const int alpha = alpha_table(i_qp + h->sh.i_alpha_c0_offset);
+    const int beta  = beta_table(i_qp + h->sh.i_beta_offset);
 
     if( !alpha || !beta )
         return;
 
-    if(b_chroma)
-    {
-        pf_intra( pix1, i_stride, alpha, beta );
+    pf_intra( pix1, i_stride, alpha, beta );
+    if( b_chroma )
         pf_intra( pix2, i_stride, alpha, beta );
-    }
-    else
-        pf_intra( pix1, i_stride, alpha, beta );
 }
 
 void x264_frame_deblock_row( x264_t *h, int mb_y )
@@ -598,90 +608,124 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
     const int s4x4 = 4 * h->mb.i_mb_stride;
     const int b_interlaced = h->sh.b_mbaff;
     const int mvy_limit = 4 >> b_interlaced;
+    const int qp_thresh = 15 - X264_MIN(h->sh.i_alpha_c0_offset, h->sh.i_beta_offset) - X264_MAX(0, h->param.analyse.i_chroma_qp_offset);
     int mb_x;
-
-    int i_stride2[3] = { h->fdec->i_stride[0] << b_interlaced,
-                         h->fdec->i_stride[1] << b_interlaced,
-                         h->fdec->i_stride[2] << b_interlaced };
+    int stridey   = h->fdec->i_stride[0];
+    int stride2y  = stridey << b_interlaced;
+    int strideuv  = h->fdec->i_stride[1];
+    int stride2uv = strideuv << b_interlaced;
 
     if( !h->pps->b_cabac && h->pps->b_transform_8x8_mode )
         munge_cavlc_nnz( h, mb_y, h->mb.nnz_backup, munge_cavlc_nnz_row );
 
-    for( mb_x = 0; mb_x < h->sps->i_mb_width; )
+    for( mb_x = 0; mb_x < h->sps->i_mb_width; mb_x += (~b_interlaced | mb_y)&1, mb_y ^= b_interlaced )
     {
         const int mb_xy  = mb_y * h->mb.i_mb_stride + mb_x;
         const int mb_8x8 = 2 * s8x8 * mb_y + 2 * mb_x;
         const int mb_4x4 = 4 * s4x4 * mb_y + 4 * mb_x;
         const int b_8x8_transform = h->mb.mb_transform_size[mb_xy];
-        const int i_edge_end = (h->mb.type[mb_xy] == P_SKIP) ? 1 : 4;
-
-        int i_pix_y[3] = { 16*mb_y*h->fdec->i_stride[0] + 16*mb_x,
-                            8*mb_y*h->fdec->i_stride[1] +  8*mb_x,
-                            8*mb_y*h->fdec->i_stride[2] +  8*mb_x };
+        const int i_qp = h->mb.qp[mb_xy];
+        int i_edge_end = (h->mb.type[mb_xy] == P_SKIP) ? 1 : 4;
+        uint8_t *pixy = h->fdec->plane[0] + 16*mb_y*stridey  + 16*mb_x;
+        uint8_t *pixu = h->fdec->plane[1] +  8*mb_y*strideuv +  8*mb_x;
+        uint8_t *pixv = h->fdec->plane[2] +  8*mb_y*strideuv +  8*mb_x;
         if( b_interlaced && (mb_y&1) )
         {
-            i_pix_y[0] -= 15*h->fdec->i_stride[0];
-            i_pix_y[1] -=  7*h->fdec->i_stride[1];
-            i_pix_y[2] -=  7*h->fdec->i_stride[2];
+            pixy -= 15*stridey;
+            pixu -=  7*strideuv;
+            pixv -=  7*strideuv;
         }
 
         x264_prefetch_fenc( h, h->fdec, mb_x, mb_y );
 
+        if( i_qp <= qp_thresh )
+            i_edge_end = 1;
+
         #define FILTER_DIR(intra, i_dir)\
         {\
             /* Y plane */\
-            i_qp = h->mb.qp[mb_xy];\
             i_qpn= h->mb.qp[mbn_xy];\
             if( i_dir == 0 )\
             {\
                 /* vertical edge */\
-                deblock_edge##intra( h, &h->fdec->plane[0][i_pix_y[0] + 4*i_edge], NULL,\
-                              i_stride2[0], bS, (i_qp+i_qpn+1) >> 1, 0,\
+                deblock_edge##intra( h, pixy + 4*i_edge, NULL,\
+                              stride2y, bS, (i_qp+i_qpn+1) >> 1, 0,\
                               h->loopf.deblock_h_luma##intra );\
                 if( !(i_edge & 1) )\
                 {\
                     /* U/V planes */\
-                    int i_qpc = ( i_chroma_qp_table[x264_clip3( i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )] +\
-                                  i_chroma_qp_table[x264_clip3( i_qpn + h->pps->i_chroma_qp_index_offset, 0, 51 )] + 1 ) >> 1;\
-                    deblock_edge##intra( h, &h->fdec->plane[1][i_pix_y[1] + 2*i_edge],\
-                                  &h->fdec->plane[2][i_pix_y[2] + 2*i_edge],\
-                                  i_stride2[1], bS, i_qpc, 1,\
+                    int i_qpc = (h->chroma_qp_table[i_qp] + h->chroma_qp_table[i_qpn] + 1) >> 1;\
+                    deblock_edge##intra( h, pixu + 2*i_edge, pixv + 2*i_edge,\
+                                  stride2uv, bS, i_qpc, 1,\
                                   h->loopf.deblock_h_chroma##intra );\
                 }\
             }\
             else\
             {\
                 /* horizontal edge */\
-                deblock_edge##intra( h, &h->fdec->plane[0][i_pix_y[0] + 4*i_edge*i_stride2[0]], NULL,\
-                              i_stride2[0], bS, (i_qp+i_qpn+1) >> 1, 0,\
+                deblock_edge##intra( h, pixy + 4*i_edge*stride2y, NULL,\
+                              stride2y, bS, (i_qp+i_qpn+1) >> 1, 0,\
                               h->loopf.deblock_v_luma##intra );\
                 /* U/V planes */\
                 if( !(i_edge & 1) )\
                 {\
-                    int i_qpc = ( i_chroma_qp_table[x264_clip3( i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )] +\
-                                  i_chroma_qp_table[x264_clip3( i_qpn + h->pps->i_chroma_qp_index_offset, 0, 51 )] + 1 ) >> 1;\
-                    deblock_edge##intra( h, &h->fdec->plane[1][i_pix_y[1] + 2*i_edge*i_stride2[1]],\
-                                  &h->fdec->plane[2][i_pix_y[2] + 2*i_edge*i_stride2[2]],\
-                                  i_stride2[1], bS, i_qpc, 1,\
+                    int i_qpc = (h->chroma_qp_table[i_qp] + h->chroma_qp_table[i_qpn] + 1) >> 1;\
+                    deblock_edge##intra( h, pixu + 2*i_edge*stride2uv, pixv + 2*i_edge*stride2uv,\
+                                  stride2uv, bS, i_qpc, 1,\
                                   h->loopf.deblock_v_chroma##intra );\
                 }\
             }\
         }
 
+        #define DEBLOCK_STRENGTH(i_dir)\
+        {\
+            /* *** Get bS for each 4px for the current edge *** */\
+            if( IS_INTRA( h->mb.type[mb_xy] ) || IS_INTRA( h->mb.type[mbn_xy]) )\
+                *(uint32_t*)bS = 0x03030303;\
+            else\
+            {\
+                *(uint32_t*)bS = 0x00000000;\
+                for( i = 0; i < 4; i++ )\
+                {\
+                    int x  = i_dir == 0 ? i_edge : i;\
+                    int y  = i_dir == 0 ? i      : i_edge;\
+                    int xn = i_dir == 0 ? (x - 1)&0x03 : x;\
+                    int yn = i_dir == 0 ? y : (y - 1)&0x03;\
+                    if( h->mb.non_zero_count[mb_xy][x+y*4] != 0 ||\
+                        h->mb.non_zero_count[mbn_xy][xn+yn*4] != 0 )\
+                        bS[i] = 2;\
+                    else\
+                    {\
+                        /* FIXME: A given frame may occupy more than one position in\
+                         * the reference list. So we should compare the frame numbers,\
+                         * not the indices in the ref list.\
+                         * No harm yet, as we don't generate that case.*/\
+                        int i8p= mb_8x8+(x>>1)+(y>>1)*s8x8;\
+                        int i8q= mbn_8x8+(xn>>1)+(yn>>1)*s8x8;\
+                        int i4p= mb_4x4+x+y*s4x4;\
+                        int i4q= mbn_4x4+xn+yn*s4x4;\
+                        for( l = 0; l < 1 + (h->sh.i_type == SLICE_TYPE_B); l++ )\
+                            if( h->mb.ref[l][i8p] != h->mb.ref[l][i8q] ||\
+                                abs( h->mb.mv[l][i4p][0] - h->mb.mv[l][i4q][0] ) >= 4 ||\
+                                abs( h->mb.mv[l][i4p][1] - h->mb.mv[l][i4q][1] ) >= mvy_limit )\
+                            {\
+                                bS[i] = 1;\
+                                break;\
+                            }\
+                    }\
+                }\
+            }\
+        }
+
         /* i_dir == 0 -> vertical edge
          * i_dir == 1 -> horizontal edge */
-        #define deblock_dir(i_dir)\
+        #define DEBLOCK_DIR(i_dir)\
         {\
             int i_edge = (i_dir ? (mb_y <= b_interlaced) : (mb_x == 0));\
-            int i_qp, i_qpn, i, l, mbn_xy, mbn_8x8, mbn_4x4;\
+            int i_qpn, i, l, mbn_xy, mbn_8x8, mbn_4x4;\
             DECLARE_ALIGNED_4( uint8_t bS[4] );  /* filtering strength */\
             if( i_edge )\
-            {\
                 i_edge+= b_8x8_transform;\
-                mbn_xy  = mb_xy;\
-                mbn_8x8 = mb_8x8;\
-                mbn_4x4 = mb_4x4;\
-            }\
             else\
             {\
                 mbn_xy  = i_dir == 0 ? mb_xy  - 1 : mb_xy - h->mb.i_mb_stride;\
@@ -696,65 +740,27 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
                 else if( IS_INTRA( h->mb.type[mb_xy] ) || IS_INTRA( h->mb.type[mbn_xy]) )\
                 {\
                     FILTER_DIR( _intra, i_dir );\
-                    i_edge += b_8x8_transform+1;\
-                    mbn_xy  = mb_xy;\
-                    mbn_8x8 = mb_8x8;\
-                    mbn_4x4 = mb_4x4;\
+                    goto end##i_dir;\
                 }\
+                DEBLOCK_STRENGTH(i_dir);\
+                if( *(uint32_t*)bS )\
+                    FILTER_DIR( , i_dir);\
+                end##i_dir:\
+                i_edge += b_8x8_transform+1;\
             }\
+            mbn_xy  = mb_xy;\
+            mbn_8x8 = mb_8x8;\
+            mbn_4x4 = mb_4x4;\
             for( ; i_edge < i_edge_end; i_edge+=b_8x8_transform+1 )\
             {\
-                /* *** Get bS for each 4px for the current edge *** */\
-                if( IS_INTRA( h->mb.type[mb_xy] ) || IS_INTRA( h->mb.type[mbn_xy] ) )\
-                    *(uint32_t*)bS = 0x03030303;\
-                else\
-                {\
-                    *(uint32_t*)bS = 0x00000000;\
-                    for( i = 0; i < 4; i++ )\
-                    {\
-                        int x  = i_dir == 0 ? i_edge : i;\
-                        int y  = i_dir == 0 ? i      : i_edge;\
-                        int xn = (x - (i_dir == 0 ? 1 : 0 ))&0x03;\
-                        int yn = (y - (i_dir == 0 ? 0 : 1 ))&0x03;\
-                        if( h->mb.non_zero_count[mb_xy][x+y*4] != 0 ||\
-                            h->mb.non_zero_count[mbn_xy][xn+yn*4] != 0 )\
-                            bS[i] = 2;\
-                        else\
-                        {\
-                            /* FIXME: A given frame may occupy more than one position in\
-                             * the reference list. So we should compare the frame numbers,\
-                             * not the indices in the ref list.\
-                             * No harm yet, as we don't generate that case.*/\
-                            int i8p= mb_8x8+(x>>1)+(y>>1)*s8x8;\
-                            int i8q= mbn_8x8+(xn>>1)+(yn>>1)*s8x8;\
-                            int i4p= mb_4x4+x+y*s4x4;\
-                            int i4q= mbn_4x4+xn+yn*s4x4;\
-                            for( l = 0; l < 1 + (h->sh.i_type == SLICE_TYPE_B); l++ )\
-                                if( h->mb.ref[l][i8p] != h->mb.ref[l][i8q] ||\
-                                    abs( h->mb.mv[l][i4p][0] - h->mb.mv[l][i4q][0] ) >= 4 ||\
-                                    abs( h->mb.mv[l][i4p][1] - h->mb.mv[l][i4q][1] ) >= mvy_limit )\
-                                {\
-                                    bS[i] = 1;\
-                                    break;\
-                                }\
-                        }\
-                    }\
-                }\
+                DEBLOCK_STRENGTH(i_dir);\
                 if( *(uint32_t*)bS )\
                     FILTER_DIR( , i_dir);\
-                mbn_xy  = mb_xy;\
-                mbn_8x8 = mb_8x8;\
-                mbn_4x4 = mb_4x4;\
             }\
         }
 
-        deblock_dir(0);
-        deblock_dir(1);
-
-        /* next mb */
-        if( !b_interlaced || (mb_y&1) )
-            mb_x++;
-        mb_y ^= b_interlaced;
+        DEBLOCK_DIR(0);
+        DEBLOCK_DIR(1);
     }
 
     if( !h->pps->b_cabac && h->pps->b_transform_8x8_mode )
@@ -784,12 +790,12 @@ void x264_deblock_v8_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta,
 void x264_deblock_h_luma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta );
 void x264_deblock_v8_luma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta );
 
-void x264_deblock_v_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
+static void x264_deblock_v_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
 {
     x264_deblock_v8_luma_mmxext( pix,   stride, alpha, beta, tc0   );
     x264_deblock_v8_luma_mmxext( pix+8, stride, alpha, beta, tc0+2 );
 }
-void x264_deblock_v_luma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta )
+static void x264_deblock_v_luma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta )
 {
     x264_deblock_v8_luma_intra_mmxext( pix,   stride, alpha, beta );
     x264_deblock_v8_luma_intra_mmxext( pix+8, stride, alpha, beta );
@@ -920,6 +926,7 @@ x264_frame_t *x264_frame_pop_unused( x264_t *h )
         frame = x264_frame_new( h );
     assert( frame->i_reference_count == 0 );
     frame->i_reference_count = 1;
+    frame->b_intra_calculated = 0;
     return frame;
 }