Commit 7639d496 authored by Fiona Glaser's avatar Fiona Glaser

Constrained intra prediction support

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.
parent 8270136f
......@@ -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 )
......
......@@ -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;
......
......@@ -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 )
{
......
......@@ -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;
......
......@@ -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;
......
......@@ -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' },
......
......@@ -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 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment