Deblock-aware RD
authorJason Garrett-Glaser <darkshikari@gmail.com>
Tue, 10 Aug 2010 23:55:05 +0000 (16:55 -0700)
committerJason Garrett-Glaser <darkshikari@gmail.com>
Mon, 16 Aug 2010 09:53:55 +0000 (02:53 -0700)
Small quality gain (~0.5%) at lower bitrates, potentially larger with QPRD.
May help more with psy, maybe not.
Enabled at subme >= 9.  Small speed cost (a few %).

common/common.h
common/deblock.c
common/frame.h
encoder/analyse.c
encoder/rdo.c

index 161f053..72fc1d8 100644 (file)
@@ -637,6 +637,7 @@ struct x264_t
         /* set to true if we are re-encoding a macroblock. */
         int b_reencode_mb;
         int ip_offset; /* Used by PIR to offset the quantizer of intra-refresh blocks. */
+        int b_deblock_rdo;
 
         struct
         {
index 55039b5..0b61248 100644 (file)
@@ -383,9 +383,55 @@ void x264_frame_deblock_row( x264_t *h, int mb_y )
                                  FILTER( , 1, 2, qp, qpc );
             if( !transform_8x8 ) FILTER( , 1, 3, qp, qpc );
         }
+
+        #undef FILTER
     }
 }
 
+/* For deblock-aware RD.
+ * TODO:
+ *  deblock macroblock edges
+ *  support analysis partitions smaller than 16x16
+ *  deblock chroma
+ *  handle duplicate refs correctly
+ *  handle cavlc+8x8dct correctly
+ */
+void x264_macroblock_deblock( x264_t *h )
+{
+    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 qp = h->mb.i_qp;
+    if( qp <= qp_thresh || h->mb.i_type == P_SKIP )
+        return;
+
+    uint8_t (*bs)[4][4] = h->deblock_strength[h->mb.i_mb_y&h->sh.b_mbaff][h->mb.i_mb_x];
+    if( IS_INTRA( h->mb.i_type ) )
+        memset( bs, 3, 2*4*4*sizeof(uint8_t) );
+    else
+        h->loopf.deblock_strength( h->mb.cache.non_zero_count, h->mb.cache.ref, h->mb.cache.mv,
+                                   bs, 4 >> h->sh.b_mbaff, h->sh.i_type == SLICE_TYPE_B );
+
+    int transform_8x8 = h->mb.b_transform_8x8;
+    pixel *fdec = h->mb.pic.p_fdec[0];
+
+    #define FILTER( dir, edge )\
+    do\
+    {\
+        deblock_edge( h, fdec + 4*edge*(dir?FDEC_STRIDE:1),\
+                      FDEC_STRIDE, bs[dir][edge], qp, 0,\
+                      h->loopf.deblock_luma[dir] );\
+    } while(0)
+
+    if( !transform_8x8 ) FILTER( 0, 1 );
+                         FILTER( 0, 2 );
+    if( !transform_8x8 ) FILTER( 0, 3 );
+
+    if( !transform_8x8 ) FILTER( 1, 1 );
+                         FILTER( 1, 2 );
+    if( !transform_8x8 ) FILTER( 1, 3 );
+
+    #undef FILTER
+}
+
 #if HAVE_MMX
 void x264_deblock_v_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
 void x264_deblock_h_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
index 1e00fc5..fcc28d7 100644 (file)
@@ -184,6 +184,7 @@ void          x264_frame_expand_border_lowres( x264_frame_t *frame );
 void          x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame );
 
 void          x264_frame_deblock_row( x264_t *h, int mb_y );
+void          x264_macroblock_deblock( x264_t *h );
 
 void          x264_frame_filter( x264_t *h, x264_frame_t *frame, int mb_y, int b_end );
 void          x264_frame_init_lowres( x264_t *h, x264_frame_t *frame );
index f93a9e0..fdc2498 100644 (file)
@@ -357,6 +357,7 @@ static void x264_mb_analyse_init( x264_t *h, x264_mb_analysis_t *a, int i_qp )
     /* mbrd == 2 -> RD refinement */
     /* mbrd == 3 -> QPRD */
     a->i_mbrd = (subme>=6) + (subme>=8) + (h->param.analyse.i_subpel_refine>=10);
+    h->mb.b_deblock_rdo = h->param.analyse.i_subpel_refine >= 9;
 
     x264_mb_analyse_init_qp( h, a, i_qp );
 
index 4fae811..d4e6b0c 100644 (file)
@@ -157,6 +157,9 @@ static int x264_rd_cost_mb( x264_t *h, int i_lambda2 )
 
     x264_macroblock_encode( h );
 
+    if( h->mb.b_deblock_rdo )
+        x264_macroblock_deblock( h );
+
     i_ssd = ssd_mb( h );
 
     if( IS_SKIP( h->mb.i_type ) )