[x264-devel] commit: skip intra pred+dct+quant in cases where it's redundant ( analyse vs encode) (Jason Garrett-Glaser )

git version control git at videolan.org
Thu Mar 20 02:11:18 CET 2008


x264 | branch: master | Jason Garrett-Glaser <darkshikari at gmail.com> | Wed Mar 19 15:01:05 2008 -0600| [f46c3bc88be70eb4ab798cba5e0da75b13038ffc]

skip intra pred+dct+quant in cases where it's redundant (analyse vs encode)
large speedup with trellis=2, small speedup with trellis=0 and/or subme>=6

> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=f46c3bc88be70eb4ab798cba5e0da75b13038ffc
---

 common/common.h      |   12 ++++++++++++
 encoder/analyse.c    |   23 +++++++++++++++++++++++
 encoder/macroblock.c |   20 ++++++++++++++++++--
 3 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/common/common.h b/common/common.h
index 584bcd7..7c4be09 100644
--- a/common/common.h
+++ b/common/common.h
@@ -424,6 +424,12 @@ struct x264_t
         int     i_intra16x16_pred_mode;
         int     i_chroma_pred_mode;
 
+        /* skip flags for i4x4 and i8x8
+         * 0 = encode as normal.
+         * 1 (non-RD only) = the DCT is still in h->dct, restore fdec and skip reconstruction.
+         * 2 (RD only) = the DCT has since been overwritten by RD; restore that too. */
+        int i_skip_intra;
+
         struct
         {
             /* space for p_fenc and p_fdec */
@@ -432,6 +438,12 @@ struct x264_t
             DECLARE_ALIGNED( uint8_t, fenc_buf[24*FENC_STRIDE], 16 );
             DECLARE_ALIGNED( uint8_t, fdec_buf[27*FDEC_STRIDE], 16 );
 
+            /* i4x4 and i8x8 backup data, for skipping the encode stage when possible */            
+            DECLARE_ALIGNED( uint8_t, i4x4_fdec_buf[16*16], 16 );
+            DECLARE_ALIGNED( uint8_t, i8x8_fdec_buf[16*16], 16 );
+            DECLARE_ALIGNED( int, i8x8_dct_buf[3][64], 16 );
+            DECLARE_ALIGNED( int, i4x4_dct_buf[15][16], 16 );
+
             /* pointer over mb of the frame to be compressed */
             uint8_t *p_fenc[3];
 
diff --git a/encoder/analyse.c b/encoder/analyse.c
index 741ab1e..0264621 100644
--- a/encoder/analyse.c
+++ b/encoder/analyse.c
@@ -229,6 +229,10 @@ 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 )
@@ -646,7 +650,15 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
         }
 
         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;
@@ -723,7 +735,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.block, sizeof(h->mb.pic.i4x4_dct_buf) );
+            }
+        }
         else
             a->i_satd_i4x4 = COST_MAX;
     }
@@ -768,6 +788,7 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
     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 )
     {
@@ -2569,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 ----------------------*/
diff --git a/encoder/macroblock.c b/encoder/macroblock.c
index 67bc2d8..d095b7c 100644
--- a/encoder/macroblock.c
+++ b/encoder/macroblock.c
@@ -368,7 +368,15 @@ void x264_macroblock_encode( x264_t *h )
     {
         DECLARE_ALIGNED( uint8_t, edge[33], 16 );
         h->mb.b_transform_8x8 = 1;
-        for( i = 0; i < 4; i++ )
+        /* If we already encoded 3 of the 4 i8x8 blocks, we don't have to do them again. */
+        if( h->mb.i_skip_intra )
+        {
+            h->mc.copy[PIXEL_16x16]( h->mb.pic.p_fdec[0], FDEC_STRIDE, h->mb.pic.i8x8_fdec_buf, 16, 16 );
+            /* In RD mode, restore the now-overwritten DCT data. */
+            if( h->mb.i_skip_intra == 2 )
+                h->mc.memcpy_aligned( h->dct.luma8x8, h->mb.pic.i8x8_dct_buf, sizeof(h->mb.pic.i8x8_dct_buf) );
+        }
+        for( i = h->mb.i_skip_intra ? 3 : 0 ; i < 4; i++ )
         {
             uint8_t  *p_dst = &h->mb.pic.p_fdec[0][8 * (i&1) + 8 * (i>>1) * FDEC_STRIDE];
             int      i_mode = h->mb.cache.intra4x4_pred_mode[x264_scan8[4*i]];
@@ -381,7 +389,15 @@ void x264_macroblock_encode( x264_t *h )
     else if( h->mb.i_type == I_4x4 )
     {
         h->mb.b_transform_8x8 = 0;
-        for( i = 0; i < 16; i++ )
+        /* If we already encoded 15 of the 16 i4x4 blocks, we don't have to do them again. */
+        if( h->mb.i_skip_intra )
+        {
+            h->mc.copy[PIXEL_16x16]( h->mb.pic.p_fdec[0], FDEC_STRIDE, h->mb.pic.i4x4_fdec_buf, 16, 16 );
+            /* In RD mode, restore the now-overwritten DCT data. */
+            if( h->mb.i_skip_intra == 2 )
+                h->mc.memcpy_aligned( h->dct.block, h->mb.pic.i4x4_dct_buf, sizeof(h->mb.pic.i4x4_dct_buf) );
+        }
+        for( i = h->mb.i_skip_intra ? 15 : 0 ; i < 16; i++ )
         {
             uint8_t  *p_dst = &h->mb.pic.p_fdec[0][4 * block_idx_x[i] + 4 * block_idx_y[i] * FDEC_STRIDE];
             int      i_mode = h->mb.cache.intra4x4_pred_mode[x264_scan8[i]];



More information about the x264-devel mailing list