]> granicus.if.org Git - libx264/commitdiff
rd refinement of intra chroma direction (enabled in --subme 7)
authorLoren Merritt <pengvado@videolan.org>
Sun, 29 Oct 2006 01:17:33 +0000 (01:17 +0000)
committerLoren Merritt <pengvado@videolan.org>
Sun, 29 Oct 2006 01:17:33 +0000 (01:17 +0000)
patch by Alex Wright.

git-svn-id: svn://svn.videolan.org/x264/trunk@595 df754926-b1dd-0310-bc7b-ec298dee348c

common/macroblock.h
encoder/analyse.c
encoder/cabac.c
encoder/cavlc.c
encoder/macroblock.c
encoder/macroblock.h
encoder/rdo.c

index 6a9e733dd998ad83c12d2c03b54653aa4e495836..d1825ffcb92b868a7ccacf1c6171b13afa0e6cf0 100644 (file)
@@ -290,9 +290,6 @@ int  x264_mb_predict_non_zero_code( x264_t *h, int idx );
  *      doesn't check for intra or cbp */
 int  x264_mb_transform_8x8_allowed( x264_t *h );
 
-void x264_mb_encode_i4x4( x264_t *h, int idx, int i_qscale );
-void x264_mb_encode_i8x8( x264_t *h, int idx, int i_qscale );
-
 void x264_mb_mc( x264_t *h );
 void x264_mb_mc_8x8( x264_t *h, int i8 );
 
index fcf3a66d51a80ebdb2d855fadbc31d88b1ec756c..b5d9ea01a38f73b261d826e72881eec8c6fa47c4 100644 (file)
@@ -98,6 +98,7 @@ typedef struct
 
     /* Chroma part */
     int i_satd_i8x8chroma;
+    int i_satd_i8x8chroma_dir[4];
     int i_predict8x8chroma;
 
     /* II: Inter part P/B frame */
@@ -456,6 +457,8 @@ static void x264_mb_analyse_intra_chroma( x264_t *h, x264_mb_analysis_t *a )
             int i_mode = predict_mode[i];
             int i_satd = satdu[i_mode] + satdv[i_mode]
                        + a->i_lambda * bs_size_ue(i_mode);
+
+            a->i_satd_i8x8chroma_dir[i] = i_satd;
             COPY2_IF_LT( a->i_satd_i8x8chroma, i_satd, a->i_predict8x8chroma, i_mode );
         }
     }
@@ -477,6 +480,7 @@ static void x264_mb_analyse_intra_chroma( x264_t *h, x264_mb_analysis_t *a )
                                                p_srcc[1], FENC_STRIDE ) +
                      a->i_lambda * bs_size_ue( x264_mb_pred_mode8x8c_fix[i_mode] );
 
+            a->i_satd_i8x8chroma_dir[i] = i_satd;
             COPY2_IF_LT( a->i_satd_i8x8chroma, i_satd, a->i_predict8x8chroma, i_mode );
         }
     }
@@ -718,15 +722,15 @@ 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];
 
     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++ )
@@ -799,7 +803,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 );
@@ -843,6 +847,43 @@ 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_qp_chroma = i_chroma_qp_table[x264_clip3( h->mb.i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )];
+            int i_chroma_lambda = i_qp0_cost2_table[i_qp_chroma];
+            /* 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) \
index b0964bc6b93135ed945b1e15eab04489b1befd63..7b0223896e67bd25f8dcc12e25e7d1f878478a34 100644 (file)
@@ -1144,4 +1144,21 @@ static void x264_partition_i4x4_size_cabac( x264_t *h, x264_cabac_t *cb, int i4,
     x264_cabac_mb_intra4x4_pred_mode( cb, i_pred, i_mode );
     block_residual_write_cabac( h, cb, DCT_LUMA_4x4, i4, h->dct.block[i4].luma4x4, 16 );
 }
+
+static void x264_i8x8_chroma_size_cabac( x264_t *h, x264_cabac_t *cb )
+{
+    x264_cabac_mb_intra_chroma_pred_mode( h, cb );
+    if( h->mb.i_cbp_chroma > 0 )
+    {
+        block_residual_write_cabac( h, cb, DCT_CHROMA_DC, 0, h->dct.chroma_dc[0], 4 );
+        block_residual_write_cabac( h, cb, DCT_CHROMA_DC, 1, h->dct.chroma_dc[1], 4 );
+
+        if( h->mb.i_cbp_chroma == 2 )
+        {
+            int i;
+            for( i = 0; i < 8; i++ )
+                block_residual_write_cabac( h, cb, DCT_CHROMA_AC, i, h->dct.block[16+i].residual_ac, 15 );
+        }
+    }
+}
 #endif
index 0589f9cadf5d487a31d887b3fde4202389642f70..6176001c686e34f16bb62556ac651e10dfbb07be 100644 (file)
@@ -801,4 +801,22 @@ static int x264_partition_i4x4_size_cavlc( x264_t *h, int i4, int i_mode )
     block_residual_write_cavlc( h, &h->out.bs, i4, h->dct.block[i4].luma4x4, 16 );
     return h->out.bs.i_bits_encoded;
 }
+
+static int x264_i8x8_chroma_size_cavlc( x264_t *h )
+{
+    h->out.bs.i_bits_encoded = bs_size_ue( x264_mb_pred_mode8x8c_fix[ h->mb.i_chroma_pred_mode ] );
+    if( h->mb.i_cbp_chroma != 0 )
+    {
+        block_residual_write_cavlc( h, &h->out.bs, BLOCK_INDEX_CHROMA_DC, h->dct.chroma_dc[0], 4 );
+        block_residual_write_cavlc( h, &h->out.bs, BLOCK_INDEX_CHROMA_DC, h->dct.chroma_dc[1], 4 );
+
+        if( h->mb.i_cbp_chroma == 2 )
+        {
+            int i;
+            for( i = 0; i < 8; i++ )
+                block_residual_write_cavlc( h, &h->out.bs, 16 + i, h->dct.block[16+i].residual_ac, 15 );
+        }
+    }
+    return h->out.bs.i_bits_encoded;
+}
 #endif
index 3a60d2d057bde6d9bec5d047619025ac74e05058..f970983a06cbe246c2a46369a461afba4c311c53 100644 (file)
@@ -242,7 +242,7 @@ static void x264_mb_encode_i16x16( x264_t *h, int i_qscale )
     h->dctf.add16x16_idct( p_dst, &dct4x4[1] );
 }
 
-static void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qscale )
+void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qscale )
 {
     int i, ch;
     int b_decimate = b_inter && (h->sh.i_type == SLICE_TYPE_B || h->param.analyse.b_dct_decimate);
@@ -312,6 +312,19 @@ static void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qscale )
             dct4x4[i][0][0] = dct2x2[0][i];
         h->dctf.add8x8_idct( p_dst, dct4x4 );
     }
+
+    /* coded block pattern */
+    h->mb.i_cbp_chroma = 0;
+    for( i = 0; i < 8; i++ )
+    {
+        int nz = array_non_zero_count( h->dct.block[16+i].residual_ac, 15 );
+        h->mb.cache.non_zero_count[x264_scan8[16+i]] = nz;
+        h->mb.i_cbp_chroma |= nz;
+    }
+    if( h->mb.i_cbp_chroma )
+        h->mb.i_cbp_chroma = 2;    /* dc+ac (we can't do only ac) */
+    else if( array_non_zero( h->dct.chroma_dc[0], 8 ) )
+        h->mb.i_cbp_chroma = 1;    /* dc only */
 }
 
 static void x264_macroblock_encode_skip( x264_t *h )
@@ -569,7 +582,7 @@ void x264_macroblock_encode( x264_t *h )
     /* encode the 8x8 blocks */
     x264_mb_encode_8x8_chroma( h, !IS_INTRA( h->mb.i_type ), i_qp );
 
-    /* Calculate the Luma/Chroma pattern and non_zero_count */
+    /* coded block pattern and non_zero_count */
     h->mb.i_cbp_luma = 0x00;
     if( h->mb.i_type == I_16x16 )
     {
@@ -606,22 +619,6 @@ void x264_macroblock_encode( x264_t *h )
         }
     }
 
-    /* Calculate the chroma pattern */
-    h->mb.i_cbp_chroma = 0x00;
-    for( i = 0; i < 8; i++ )
-    {
-        const int nz = array_non_zero_count( h->dct.block[16+i].residual_ac, 15 );
-        h->mb.cache.non_zero_count[x264_scan8[16+i]] = nz;
-        if( nz > 0 )
-        {
-            h->mb.i_cbp_chroma = 0x02;    /* dc+ac (we can't do only ac) */
-        }
-    }
-    if( h->mb.i_cbp_chroma == 0x00 && array_non_zero( h->dct.chroma_dc[0], 8 ) )
-    {
-        h->mb.i_cbp_chroma = 0x01;    /* dc only */
-    }
-
     if( h->param.b_cabac )
     {
         i_cbp_dc = ( h->mb.i_type == I_16x16 && array_non_zero( h->dct.luma16x16_dc, 16 ) )
index e324bbb03e78b430e01d3d76c981888ae5df8a29..ac87c8b106cfa21145ea49ccea9b3e74fb4596f7 100644 (file)
@@ -40,6 +40,9 @@ void x264_macroblock_write_cabac ( x264_t *h, x264_cabac_t *cb );
 void x264_macroblock_write_cavlc ( x264_t *h, bs_t *s );
 
 void x264_macroblock_encode_p8x8( x264_t *h, int i8 );
+void x264_mb_encode_i4x4( x264_t *h, int idx, int i_qscale );
+void x264_mb_encode_i8x8( x264_t *h, int idx, int i_qscale );
+void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qscale );
 
 void x264_cabac_mb_skip( x264_t *h, int b_skip );
 
index a108d6437abbd5718aa1bb4fb5cfa14fe82d6462..36326dac37a01cc18245f0a5f1fb9131f1c4ccc8 100644 (file)
@@ -178,6 +178,31 @@ int x264_rd_cost_i4x4( x264_t *h, int i_lambda2, int i4, int i_mode )
     return i_ssd + i_bits;
 }
 
+int x264_rd_cost_i8x8_chroma( x264_t *h, int i_lambda2, int i_mode, int b_dct )
+{
+    int i_ssd, i_bits;
+
+    if( b_dct )
+        x264_mb_encode_8x8_chroma( h, 0, h->mb.i_qp );
+    i_ssd = ssd_plane( h, PIXEL_8x8, 1, 0, 0 ) +
+            ssd_plane( h, PIXEL_8x8, 2, 0, 0 );
+
+    h->mb.i_chroma_pred_mode = i_mode;
+
+    if( h->param.b_cabac )
+    {
+        x264_cabac_t cabac_tmp = h->cabac;
+        cabac_tmp.f8_bits_encoded = 0;
+        x264_i8x8_chroma_size_cabac( h, &cabac_tmp );
+        i_bits = ( cabac_tmp.f8_bits_encoded * i_lambda2 + 128 ) >> 8;
+    }
+    else
+    {
+        i_bits = x264_i8x8_chroma_size_cavlc( h ) * i_lambda2;
+    }
+
+    return i_ssd + i_bits;
+}
 /****************************************************************************
  * Trellis RD quantization
  ****************************************************************************/