Constrained intra prediction support
authorJason Garrett-Glaser <darkshikari@gmail.com>
Mon, 5 Oct 2009 02:15:28 +0000 (19:15 -0700)
committerJason Garrett-Glaser <darkshikari@gmail.com>
Wed, 7 Oct 2009 00:33:59 +0000 (17:33 -0700)
Enable with --constrained-intra.  Significantly reduces compression, but required for the base layer of SVC encodes and maybe some other use-cases.

Commit sponsored by a media streaming company that wishes to remain anonymous.

common/common.c
common/common.h
common/macroblock.c
encoder/analyse.c
encoder/set.c
x264.c
x264.h

index 648c75a..fe02d65 100644 (file)
@@ -76,6 +76,8 @@ void    x264_param_default( x264_param_t *param )
     param->i_bframe_adaptive = X264_B_ADAPT_FAST;
     param->i_bframe_bias = 0;
     param->b_bframe_pyramid = 0;
+    param->b_interlaced = 0;
+    param->b_constrained_intra = 0;
 
     param->b_deblocking_filter = 1;
     param->i_deblocking_filter_alphac0 = 0;
@@ -394,6 +396,8 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
         p->i_cabac_init_idc = atoi(value);
     OPT("interlaced")
         p->b_interlaced = atobool(value);
+    OPT("constrained-intra")
+        p->b_constrained_intra = atobool(value);
     OPT("cqm")
     {
         if( strstr( value, "flat" ) )
@@ -890,6 +894,7 @@ char *x264_param2string( x264_param_t *p, int b_res )
     s += sprintf( s, " nr=%d", p->analyse.i_noise_reduction );
     s += sprintf( s, " decimate=%d", p->analyse.b_dct_decimate );
     s += sprintf( s, " mbaff=%d", p->b_interlaced );
+    s += sprintf( s, " constrained_intra=%d", p->b_constrained_intra );
 
     s += sprintf( s, " bframes=%d", p->i_bframe );
     if( p->i_bframe )
index 0498139..a0afeda 100644 (file)
@@ -461,6 +461,7 @@ struct x264_t
         unsigned int i_neighbour;
         unsigned int i_neighbour8[4];       /* neighbours of each 8x8 or 4x4 block that are available */
         unsigned int i_neighbour4[16];      /* at the time the block is coded */
+        unsigned int i_neighbour_intra;     /* for constrained intra pred */
         int     i_mb_type_top;
         int     i_mb_type_left;
         int     i_mb_type_topleft;
index 54a095d..7d014ab 100644 (file)
@@ -896,16 +896,20 @@ void x264_macroblock_cache_load( x264_t *h, int i_mb_x, int i_mb_y )
     h->mb.i_b4_xy = i_mb_4x4;
     h->mb.i_mb_top_xy = i_top_xy;
     h->mb.i_neighbour = 0;
+    h->mb.i_neighbour_intra = 0;
 
     /* load cache */
     if( i_top_xy >= h->sh.i_first_mb )
     {
         h->mb.i_mb_type_top =
-        i_top_type= h->mb.type[i_top_xy];
+        i_top_type = h->mb.type[i_top_xy];
         h->mb.cache.i_cbp_top = h->mb.cbp[i_top_xy];
 
         h->mb.i_neighbour |= MB_TOP;
 
+        if( !h->param.b_constrained_intra || IS_INTRA( i_top_type ) )
+            h->mb.i_neighbour_intra |= MB_TOP;
+
         /* load intra4x4 */
         *(uint32_t*)&h->mb.cache.intra4x4_pred_mode[x264_scan8[0] - 8] = *(uint32_t*)&h->mb.intra4x4_pred_mode[i_top_xy][0];
 
@@ -921,10 +925,7 @@ void x264_macroblock_cache_load( x264_t *h, int i_mb_x, int i_mb_y )
         h->mb.cache.i_cbp_top = -1;
 
         /* load intra4x4 */
-        h->mb.cache.intra4x4_pred_mode[x264_scan8[0] - 8] =
-        h->mb.cache.intra4x4_pred_mode[x264_scan8[1] - 8] =
-        h->mb.cache.intra4x4_pred_mode[x264_scan8[4] - 8] =
-        h->mb.cache.intra4x4_pred_mode[x264_scan8[5] - 8] = -1;
+        *(uint32_t*)&h->mb.cache.intra4x4_pred_mode[x264_scan8[0] - 8] = 0xFFFFFFFFU;
 
         /* load non_zero_count */
         h->mb.cache.non_zero_count[x264_scan8[0] - 8] =
@@ -946,6 +947,9 @@ void x264_macroblock_cache_load( x264_t *h, int i_mb_x, int i_mb_y )
 
         h->mb.i_neighbour |= MB_LEFT;
 
+        if( !h->param.b_constrained_intra || IS_INTRA( i_left_type ) )
+            h->mb.i_neighbour_intra |= MB_LEFT;
+
         /* load intra4x4 */
         h->mb.cache.intra4x4_pred_mode[x264_scan8[0 ] - 1] = h->mb.intra4x4_pred_mode[i_left_xy][4];
         h->mb.cache.intra4x4_pred_mode[x264_scan8[2 ] - 1] = h->mb.intra4x4_pred_mode[i_left_xy][5];
@@ -989,6 +993,8 @@ void x264_macroblock_cache_load( x264_t *h, int i_mb_x, int i_mb_y )
     {
         h->mb.i_neighbour |= MB_TOPRIGHT;
         h->mb.i_mb_type_topright = h->mb.type[ i_top_xy + 1 ];
+        if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_topright ) )
+            h->mb.i_neighbour_intra |= MB_TOPRIGHT;
     }
     else
         h->mb.i_mb_type_topright = -1;
@@ -996,6 +1002,8 @@ void x264_macroblock_cache_load( x264_t *h, int i_mb_x, int i_mb_y )
     {
         h->mb.i_neighbour |= MB_TOPLEFT;
         h->mb.i_mb_type_topleft = h->mb.type[ i_top_xy - 1 ];
+        if( !h->param.b_constrained_intra || IS_INTRA( h->mb.i_mb_type_topleft ) )
+            h->mb.i_neighbour_intra |= MB_TOPLEFT;
     }
     else
         h->mb.i_mb_type_topleft = -1;
@@ -1183,17 +1191,17 @@ void x264_macroblock_cache_load( x264_t *h, int i_mb_x, int i_mb_y )
     }
 
     h->mb.i_neighbour4[0] =
-    h->mb.i_neighbour8[0] = (h->mb.i_neighbour & (MB_TOP|MB_LEFT|MB_TOPLEFT))
-                            | ((h->mb.i_neighbour & MB_TOP) ? MB_TOPRIGHT : 0);
+    h->mb.i_neighbour8[0] = (h->mb.i_neighbour_intra & (MB_TOP|MB_LEFT|MB_TOPLEFT))
+                            | ((h->mb.i_neighbour_intra & MB_TOP) ? MB_TOPRIGHT : 0);
     h->mb.i_neighbour4[4] =
-    h->mb.i_neighbour4[1] = MB_LEFT | ((h->mb.i_neighbour & MB_TOP) ? (MB_TOP|MB_TOPLEFT|MB_TOPRIGHT) : 0);
+    h->mb.i_neighbour4[1] = MB_LEFT | ((h->mb.i_neighbour_intra & MB_TOP) ? (MB_TOP|MB_TOPLEFT|MB_TOPRIGHT) : 0);
     h->mb.i_neighbour4[2] =
     h->mb.i_neighbour4[8] =
     h->mb.i_neighbour4[10] =
-    h->mb.i_neighbour8[2] = MB_TOP|MB_TOPRIGHT | ((h->mb.i_neighbour & MB_LEFT) ? (MB_LEFT|MB_TOPLEFT) : 0);
+    h->mb.i_neighbour8[2] = MB_TOP|MB_TOPRIGHT | ((h->mb.i_neighbour_intra & MB_LEFT) ? (MB_LEFT|MB_TOPLEFT) : 0);
     h->mb.i_neighbour4[5] =
-    h->mb.i_neighbour8[1] = MB_LEFT | (h->mb.i_neighbour & MB_TOPRIGHT)
-                            | ((h->mb.i_neighbour & MB_TOP) ? MB_TOP|MB_TOPLEFT : 0);
+    h->mb.i_neighbour8[1] = MB_LEFT | (h->mb.i_neighbour_intra & MB_TOPRIGHT)
+                            | ((h->mb.i_neighbour_intra & MB_TOP) ? MB_TOP|MB_TOPLEFT : 0);
 }
 
 static void ALWAYS_INLINE x264_macroblock_store_pic( x264_t *h, int i )
@@ -1242,8 +1250,11 @@ void x264_macroblock_cache_save( x264_t *h )
                                                        h->mb.cache.intra4x4_pred_mode[x264_scan8[7] ],
                                                        h->mb.cache.intra4x4_pred_mode[x264_scan8[13] ], 0);
     }
-    else
+    else if( !h->param.b_constrained_intra || IS_INTRA(i_mb_type) )
         *(uint64_t*)intra4x4_pred_mode = I_PRED_4x4_DC * 0x0101010101010101ULL;
+    else
+        *(uint64_t*)intra4x4_pred_mode = (uint8_t)(-1) * 0x0101010101010101ULL;
+
 
     if( i_mb_type == I_PCM )
     {
index 242d6ba..8a8ead4 100644 (file)
@@ -662,7 +662,7 @@ static void x264_mb_analyse_intra_chroma( x264_t *h, x264_mb_analysis_t *a )
     p_srcc[0] = h->mb.pic.p_fenc[1];
     p_srcc[1] = h->mb.pic.p_fenc[2];
 
-    predict_8x8chroma_mode_available( h->mb.i_neighbour, predict_mode, &i_max );
+    predict_8x8chroma_mode_available( h->mb.i_neighbour_intra, predict_mode, &i_max );
     a->i_satd_i8x8chroma = COST_MAX;
     if( i_max == 4 && b_merged_satd )
     {
@@ -731,7 +731,7 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
     /*---------------- Try all mode and calculate their score ---------------*/
 
     /* 16x16 prediction selection */
-    predict_16x16_mode_available( h->mb.i_neighbour, predict_mode, &i_max );
+    predict_16x16_mode_available( h->mb.i_neighbour_intra, predict_mode, &i_max );
 
     if( b_merged_satd && i_max == 4 )
     {
@@ -996,7 +996,7 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
         int old_pred_mode = a->i_predict16x16;
         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 );
+        predict_16x16_mode_available( h->mb.i_neighbour_intra, predict_mode, &i_max );
         for( i = 0; i < i_max; i++ )
         {
             int i_mode = predict_mode[i];
@@ -1009,7 +1009,7 @@ static void x264_intra_rd_refine( x264_t *h, x264_mb_analysis_t *a )
     }
 
     /* RD selection for chroma prediction */
-    predict_8x8chroma_mode_available( h->mb.i_neighbour, predict_mode, &i_max );
+    predict_8x8chroma_mode_available( h->mb.i_neighbour_intra, predict_mode, &i_max );
     if( i_max > 1 )
     {
         i_thresh = a->i_satd_i8x8chroma * 5/4;
index 2f7e785..49ca340 100644 (file)
@@ -384,7 +384,7 @@ void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t *
 
     pps->i_chroma_qp_index_offset = param->analyse.i_chroma_qp_offset;
     pps->b_deblocking_filter_control = 1;
-    pps->b_constrained_intra_pred = 0;
+    pps->b_constrained_intra_pred = param->b_constrained_intra;
     pps->b_redundant_pic_cnt = 0;
 
     pps->b_transform_8x8_mode = param->analyse.b_transform_8x8 ? 1 : 0;
diff --git a/x264.c b/x264.c
index 87eef2e..ec4a378 100644 (file)
--- a/x264.c
+++ b/x264.c
@@ -222,6 +222,7 @@ static void Help( x264_param_t *defaults, int longhelp )
     H2( "      --slice-max-size <integer> Limit the size of each slice in bytes\n");
     H2( "      --slice-max-mbs <integer> Limit the size of each slice in macroblocks\n");
     H0( "      --interlaced            Enable pure-interlaced mode\n" );
+    H2( "      --constrained-intra     Enable constrained intra prediction.\n" );
     H0( "\n" );
     H0( "Ratecontrol:\n" );
     H0( "\n" );
@@ -428,6 +429,7 @@ static struct option long_options[] =
     { "filter",      required_argument, NULL, 0 },
     { "deblock",     required_argument, NULL, 'f' },
     { "interlaced",        no_argument, NULL, 0 },
+    { "constrained-intra", no_argument, NULL, 0 },
     { "cabac",             no_argument, NULL, 0 },
     { "no-cabac",          no_argument, NULL, 0 },
     { "qp",          required_argument, NULL, 'q' },
diff --git a/x264.h b/x264.h
index ec9321c..7bc2d36 100644 (file)
--- a/x264.h
+++ b/x264.h
@@ -35,7 +35,7 @@
 
 #include <stdarg.h>
 
-#define X264_BUILD 76
+#define X264_BUILD 77
 
 /* x264_t:
  *      opaque handler for encoder */
@@ -206,6 +206,7 @@ typedef struct x264_param_t
     int         i_cabac_init_idc;
 
     int         b_interlaced;
+    int         b_constrained_intra;
 
     int         i_cqm_preset;
     char        *psz_cqm_file;      /* JM format */