]> git.sesse.net Git - x264/blobdiff - encoder/cabac.c
allow fractional CRF values with AQ.
[x264] / encoder / cabac.c
index d482c0666b0b2e18cdf06a0440aac5f2128aa3d2..93b26d8cf79e202dd4cce8856e929b1192d371fa 100644 (file)
@@ -304,6 +304,15 @@ static void x264_cabac_mb_qp_delta( x264_t *h, x264_cabac_t *cb )
     int i_dqp = h->mb.i_qp - h->mb.i_last_qp;
     int ctx;
 
+    /* Avoid writing a delta quant if we have an empty i16x16 block, e.g. in a completely flat background area */
+    if( h->mb.i_type == I_16x16 && !h->mb.cbp[h->mb.i_mb_xy] )
+    {
+#ifndef RD_SKIP_BS
+        h->mb.i_qp = h->mb.i_last_qp;
+#endif
+        i_dqp = 0;
+    }
+
     /* No need to test for PCM / SKIP */
     if( h->mb.i_last_dqp &&
         ( h->mb.type[i_mbn_xy] == I_16x16 || (h->mb.cbp[i_mbn_xy]&0x3f) ) )
@@ -332,18 +341,9 @@ static void x264_cabac_mb_qp_delta( x264_t *h, x264_cabac_t *cb )
 #ifndef RDO_SKIP_BS
 void x264_cabac_mb_skip( x264_t *h, int b_skip )
 {
-    int ctx = 0;
-
-    if( h->mb.i_mb_type_left >= 0 && !IS_SKIP( h->mb.i_mb_type_left ) )
-    {
-        ctx++;
-    }
-    if( h->mb.i_mb_type_top >= 0 && !IS_SKIP( h->mb.i_mb_type_top ) )
-    {
-        ctx++;
-    }
-
-    ctx += (h->sh.i_type == SLICE_TYPE_P) ? 11 : 24;
+    int ctx = (h->mb.i_mb_type_left >= 0 && !IS_SKIP( h->mb.i_mb_type_left ))
+            + (h->mb.i_mb_type_top >= 0 && !IS_SKIP( h->mb.i_mb_type_top ))
+            + (h->sh.i_type == SLICE_TYPE_P ? 11 : 24);
     x264_cabac_encode_decision( &h->cabac, ctx, b_skip );
 }
 #endif
@@ -373,42 +373,40 @@ static inline void x264_cabac_mb_sub_p_partition( x264_cabac_t *cb, int i_sub )
     }
 }
 
-static inline void x264_cabac_mb_sub_b_partition( x264_cabac_t *cb, int i_sub )
+static NOINLINE void x264_cabac_mb_sub_b_partition( x264_cabac_t *cb, int i_sub )
 {
-#define WRITE_SUB_3(a,b,c) {\
-        x264_cabac_encode_decision( cb, 36, a );\
-        x264_cabac_encode_decision( cb, 37, b );\
-        x264_cabac_encode_decision( cb, 39, c );\
-    }
-#define WRITE_SUB_5(a,b,c,d,e) {\
-        x264_cabac_encode_decision( cb, 36, a );\
-        x264_cabac_encode_decision( cb, 37, b );\
-        x264_cabac_encode_decision( cb, 38, c );\
-        x264_cabac_encode_decision( cb, 39, d );\
-        x264_cabac_encode_decision( cb, 39, e );\
-    }
-#define WRITE_SUB_6(a,b,c,d,e,f) {\
-        WRITE_SUB_5(a,b,c,d,e)\
-        x264_cabac_encode_decision( cb, 39, f );\
+    static const uint8_t part_bits[12][7] = {
+        {6,1,1,1,0,1,1}, // D_L0_4x4
+        {5,1,1,0,0,1},   // D_L0_8x4
+        {5,1,1,0,1,0},   // D_L0_4x8
+        {3,1,0,0},       // D_L0_8x8
+        {5,1,1,1,1,0},   // D_L1_4x4
+        {5,1,1,0,1,1},   // D_L1_8x4
+        {6,1,1,1,0,0,0}, // D_L1_4x8
+        {3,1,0,1},       // D_L1_8x8
+        {5,1,1,1,1,1},   // D_BI_4x4
+        {6,1,1,1,0,0,1}, // D_BI_8x4
+        {6,1,1,1,0,1,0}, // D_BI_4x8
+        {5,1,1,0,0,0},   // D_BI_8x8
+    };
+    int len;
+    if( i_sub == D_DIRECT_8x8 )
+    {
+        x264_cabac_encode_decision( cb, 36, 0 );
+        return;
     }
-
-    switch( i_sub )
+    len = part_bits[i_sub][0];
+    x264_cabac_encode_decision( cb, 36, part_bits[i_sub][1] );
+    x264_cabac_encode_decision( cb, 37, part_bits[i_sub][2] );
+    if( len == 3 )
+        x264_cabac_encode_decision( cb, 39, part_bits[i_sub][3] );
+    else
     {
-        case D_DIRECT_8x8:
-            x264_cabac_encode_decision( cb, 36, 0 );
-            break;
-        case D_L0_8x8: WRITE_SUB_3(1,0,0); break;
-        case D_L1_8x8: WRITE_SUB_3(1,0,1); break;
-        case D_BI_8x8: WRITE_SUB_5(1,1,0,0,0); break;
-        case D_L0_8x4: WRITE_SUB_5(1,1,0,0,1); break;
-        case D_L0_4x8: WRITE_SUB_5(1,1,0,1,0); break;
-        case D_L1_8x4: WRITE_SUB_5(1,1,0,1,1); break;
-        case D_L1_4x8: WRITE_SUB_6(1,1,1,0,0,0); break;
-        case D_BI_8x4: WRITE_SUB_6(1,1,1,0,0,1); break;
-        case D_BI_4x8: WRITE_SUB_6(1,1,1,0,1,0); break;
-        case D_L0_4x4: WRITE_SUB_6(1,1,1,0,1,1); break;
-        case D_L1_4x4: WRITE_SUB_5(1,1,1,1,0); break;
-        case D_BI_4x4: WRITE_SUB_5(1,1,1,1,1); break;
+        x264_cabac_encode_decision( cb, 38, part_bits[i_sub][3] );
+        x264_cabac_encode_decision( cb, 39, part_bits[i_sub][4] );
+        x264_cabac_encode_decision( cb, 39, part_bits[i_sub][5] );
+        if( len == 6 )
+            x264_cabac_encode_decision( cb, 39, part_bits[i_sub][6] );
     }
 }
 
@@ -448,29 +446,19 @@ static inline void x264_cabac_mb_ref( x264_t *h, x264_cabac_t *cb, int i_list, i
 
 static inline void x264_cabac_mb_mvd_cpn( x264_t *h, x264_cabac_t *cb, int i_list, int idx, int l, int mvd )
 {
+    static const uint8_t transition[7] = { 3,3,3,4,5,6,6 };
     const int amvd = abs( h->mb.cache.mvd[i_list][x264_scan8[idx] - 1][l] ) +
                      abs( h->mb.cache.mvd[i_list][x264_scan8[idx] - 8][l] );
     const int i_abs = abs( mvd );
     const int i_prefix = X264_MIN( i_abs, 9 );
-    const int ctxbase = (l == 0 ? 40 : 47);
-    int ctx;
+    const int ctxbase = l ? 47 : 40;
+    int ctx = (amvd>2) + (amvd>32);
     int i;
 
-
-    if( amvd < 3 )
-        ctx = 0;
-    else if( amvd > 32 )
-        ctx = 2;
-    else
-        ctx = 1;
-
     for( i = 0; i < i_prefix; i++ )
     {
         x264_cabac_encode_decision( cb, ctxbase + ctx, 1 );
-        if( ctx < 3 )
-            ctx = 3;
-        else if( ctx < 6 )
-            ctx++;
+        ctx = transition[ctx];
     }
     if( i_prefix < 9 )
         x264_cabac_encode_decision( cb, ctxbase + ctx, 0 );
@@ -537,11 +525,18 @@ static inline void x264_cabac_mb8x8_mvd( x264_t *h, x264_cabac_t *cb, int i_list
 
 static int x264_cabac_mb_cbf_ctxidxinc( x264_t *h, int i_cat, int i_idx )
 {
+    /* i_ctxBlockCat: 0-> DC 16x16  i_idx = 0
+     *                1-> AC 16x16  i_idx = luma4x4idx
+     *                2-> Luma4x4   i_idx = luma4x4idx
+     *                3-> DC Chroma i_idx = iCbCr
+     *                4-> AC Chroma i_idx = 4 * iCbCr + chroma4x4idx
+     *                5-> Luma8x8   i_idx = luma8x8idx
+     */
+
     int i_mba_xy = -1;
     int i_mbb_xy = -1;
     int i_nza = 0;
     int i_nzb = 0;
-    int ctx;
 
     if( i_cat == DCT_LUMA_DC )
     {
@@ -611,32 +606,25 @@ static int x264_cabac_mb_cbf_ctxidxinc( x264_t *h, int i_cat, int i_idx )
 
     if( IS_INTRA( h->mb.i_type ) )
     {
-        if( i_mba_xy < 0 )
-            i_nza = 1;
-        if( i_mbb_xy < 0 )
-            i_nzb = 1;
+        i_nza |= i_mba_xy < 0;
+        i_nzb |= i_mbb_xy < 0;
     }
 
-    ctx = 4 * i_cat;
-    if( i_nza )
-        ctx += 1;
-    if( i_nzb )
-        ctx += 2;
-    return ctx;
+    return 4*i_cat + 2*!!i_nzb + !!i_nza;
 }
 
 
-static const int significant_coeff_flag_offset[2][6] = {
+static const uint16_t significant_coeff_flag_offset[2][6] = {
     { 105, 120, 134, 149, 152, 402 },
     { 277, 292, 306, 321, 324, 436 }
 };
-static const int last_coeff_flag_offset[2][6] = {
+static const uint16_t last_coeff_flag_offset[2][6] = {
     { 166, 181, 195, 210, 213, 417 },
     { 338, 353, 367, 382, 385, 451 }
 };
-static const int coeff_abs_level_m1_offset[6] =
+static const uint16_t coeff_abs_level_m1_offset[6] =
     { 227, 237, 247, 257, 266, 426 };
-static const int significant_coeff_flag_offset_8x8[2][63] =
+static const uint8_t significant_coeff_flag_offset_8x8[2][63] =
 {{
     0, 1, 2, 3, 4, 5, 5, 4, 4, 3, 3, 4, 4, 4, 5, 5,
     4, 4, 4, 4, 3, 3, 6, 7, 7, 7, 8, 9,10, 9, 8, 7,
@@ -648,22 +636,22 @@ static const int significant_coeff_flag_offset_8x8[2][63] =
     9, 9,10,10, 8,11,12,11, 9, 9,10,10, 8,13,13, 9,
     9,10,10, 8,13,13, 9, 9,10,10,14,14,14,14,14
 }};
-static const int last_coeff_flag_offset_8x8[63] = {
+static const uint8_t last_coeff_flag_offset_8x8[63] = {
     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
     3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
     5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8
 };
-static const int identity[16] =
+static const uint8_t identity[16] =
     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
-    
+
 // node ctx: 0..3: abslevel1 (with abslevelgt1 == 0).
 //           4..7: abslevelgt1 + 3 (and abslevel1 doesn't matter).
 /* map node ctx => cabac ctx for level=1 */
 static const int coeff_abs_level1_ctx[8] = { 1, 2, 3, 4, 0, 0, 0, 0 };
 /* map node ctx => cabac ctx for level>1 */
 static const int coeff_abs_levelgt1_ctx[8] = { 5, 5, 5, 5, 6, 7, 8, 9 };
-static const int coeff_abs_level_transition[2][8] = {
+static const uint8_t coeff_abs_level_transition[2][8] = {
 /* update node ctx after coding a level=1 */
     { 1, 2, 3, 3, 4, 5, 6, 7 },
 /* update node ctx after coding a level>1 */
@@ -677,42 +665,32 @@ static void block_residual_write_cabac( x264_t *h, x264_cabac_t *cb, int i_ctxBl
     const int i_ctx_level = coeff_abs_level_m1_offset[i_ctxBlockCat];
 
     int i_coeff_abs_m1[64];
-    int i_coeff_sign[64];
+    int UNUSED i_coeff_sign[64];
     int i_coeff = 0;
     int i_last  = 0;
     int i_sigmap_size;
     int node_ctx = 0;
     int i, j;
 
-    const int *significant_coeff_flag_offset;
-    const int *last_coeff_flag_offset;
-
-    /* i_ctxBlockCat: 0-> DC 16x16  i_idx = 0
-     *                1-> AC 16x16  i_idx = luma4x4idx
-     *                2-> Luma4x4   i_idx = luma4x4idx
-     *                3-> DC Chroma i_idx = iCbCr
-     *                4-> AC Chroma i_idx = 4 * iCbCr + chroma4x4idx
-     *                5-> Luma8x8   i_idx = luma8x8idx
-     */
+    const uint8_t *significant_coeff_flag_offset;
+    const uint8_t *last_coeff_flag_offset;
 
-    for( j = i_count - 4; j >= 0; j -= 4 )
+    /* yes this is always aligned, and l[-1] exists in the cases where it's used (ac) */
+    for( j = i_count - 4; j >= -1; j -= 4 )
         if( *(uint64_t*)(l+j) )
             break;
-    for( i = 0; i < j+4; i++ )
-        if( l[i] != 0 )
-        {
-            i_coeff_abs_m1[i_coeff] = abs(l[i]) - 1;
-            i_coeff_sign[i_coeff]   = l[i] < 0;
-            i_coeff++;
-            i_last = i;
-        }
 
     if( i_count != 64 )
     {
         /* coded block flag */
-        x264_cabac_encode_decision( cb, 85 + x264_cabac_mb_cbf_ctxidxinc( h, i_ctxBlockCat, i_idx ), i_coeff != 0 );
-        if( i_coeff == 0 )
+        int ctx = 85 + x264_cabac_mb_cbf_ctxidxinc( h, i_ctxBlockCat, i_idx );
+        if( j >= -1 )
+            x264_cabac_encode_decision( cb, ctx, 1 );
+        else
+        {
+            x264_cabac_encode_decision( cb, ctx, 0 );
             return;
+        }
     }
 
     significant_coeff_flag_offset = (i_ctxBlockCat == DCT_LUMA_8x8)
@@ -721,33 +699,55 @@ static void block_residual_write_cabac( x264_t *h, x264_cabac_t *cb, int i_ctxBl
     last_coeff_flag_offset = (i_ctxBlockCat == DCT_LUMA_8x8)
                            ? last_coeff_flag_offset_8x8 : identity;
 
+    for( i = j; i < j+4; i++)
+        if( l[i] )
+            i_last = i;
+
     i_sigmap_size = X264_MIN( i_last+1, i_count-1 );
+
     for( i = 0; i < i_sigmap_size; i++ )
     {
-        x264_cabac_encode_decision( cb, i_ctx_sig + significant_coeff_flag_offset[i], l[i] != 0 );
-        if( l[i] != 0 )
+        if( l[i] )
+        {
+            i_coeff_abs_m1[i_coeff] = abs(l[i]) - 1;
+#ifndef RDO_SKIP_BS
+            i_coeff_sign[i_coeff]   = l[i] < 0;
+#endif
+            i_coeff++;
+            x264_cabac_encode_decision( cb, i_ctx_sig + significant_coeff_flag_offset[i], 1 );
             x264_cabac_encode_decision( cb, i_ctx_last + last_coeff_flag_offset[i], i == i_last );
+        }
+        else
+            x264_cabac_encode_decision( cb, i_ctx_sig + significant_coeff_flag_offset[i], 0 );
+    }
+
+    if( i == i_last )
+    {
+        i_coeff_abs_m1[i_coeff] = abs(l[i]) - 1;
+#ifndef RDO_SKIP_BS
+        i_coeff_sign[i_coeff]   = l[i] < 0;
+#endif
+        i_coeff++;
     }
 
     for( i = i_coeff - 1; i >= 0; i-- )
     {
         /* write coeff_abs - 1 */
-        const int i_prefix = X264_MIN( i_coeff_abs_m1[i], 14 );
-        const int i_ctxIdxInc = coeff_abs_level1_ctx[node_ctx] + i_ctx_level;
-        x264_cabac_encode_decision( cb, i_ctxIdxInc, i_prefix != 0 );
+        int i_prefix = X264_MIN( i_coeff_abs_m1[i], 14 );
+        int ctx = coeff_abs_level1_ctx[node_ctx] + i_ctx_level;
 
-        if( i_prefix != 0 )
+        if( i_prefix )
         {
-            const int i_ctxIdxInc = coeff_abs_levelgt1_ctx[node_ctx] + i_ctx_level;
+            x264_cabac_encode_decision( cb, ctx, 1 );
+            ctx = coeff_abs_levelgt1_ctx[node_ctx] + i_ctx_level;
 #ifdef RDO_SKIP_BS
-            cb->f8_bits_encoded += cabac_prefix_size[i_prefix][cb->state[i_ctxIdxInc]];
-            cb->state[i_ctxIdxInc] = cabac_prefix_transition[i_prefix][cb->state[i_ctxIdxInc]];
+            cb->f8_bits_encoded += cabac_prefix_size[i_prefix][cb->state[ctx]];
+            cb->state[ctx] = cabac_prefix_transition[i_prefix][cb->state[ctx]];
 #else
-            int j;
             for( j = 0; j < i_prefix - 1; j++ )
-                x264_cabac_encode_decision( cb, i_ctxIdxInc, 1 );
+                x264_cabac_encode_decision( cb, ctx, 1 );
             if( i_prefix < 14 )
-                x264_cabac_encode_decision( cb, i_ctxIdxInc, 0 );
+                x264_cabac_encode_decision( cb, ctx, 0 );
 #endif
             if( i_prefix >= 14 )
                 x264_cabac_encode_ue_bypass( cb, 0, i_coeff_abs_m1[i] - 14 );
@@ -755,13 +755,17 @@ static void block_residual_write_cabac( x264_t *h, x264_cabac_t *cb, int i_ctxBl
             node_ctx = coeff_abs_level_transition[1][node_ctx];
         }
         else
+        {
+            x264_cabac_encode_decision( cb, ctx, 0 );
             node_ctx = coeff_abs_level_transition[0][node_ctx];
-
-        /* write sign */
 #ifdef RDO_SKIP_BS
-        if( i_prefix == 0 )
+            x264_cabac_encode_bypass( cb, 0 ); // sign
 #endif
+        }
+
+#ifndef RDO_SKIP_BS
         x264_cabac_encode_bypass( cb, i_coeff_sign[i] );
+#endif
     }
 }