Commit cf5ba813 authored by Lamont Alston's avatar Lamont Alston Committed by Fiona Glaser

Make B-pyramid spec-compliant

The rules of the specification with regard to picture buffering for pyramid coding are widely ignored.
x264's b-pyramid implementation, despite being practically identical to that proposed by the original paper, was technically not compliant.
Now it is.
Two modes are now available:
1) strict b-pyramid, while worse for compression, follows the rule mandated by Blu-ray (no P-frames can reference B-frames)
2) normal b-pyramid, which is like the old mode except fully compliant.
This patch also adds MMCO support (necessary for compliant pyramid in some cases).
MB-tree still doesn't support b-pyramid (but will soon).
parent e691cc0e
...@@ -75,7 +75,7 @@ void x264_param_default( x264_param_t *param ) ...@@ -75,7 +75,7 @@ void x264_param_default( x264_param_t *param )
param->i_scenecut_threshold = 40; param->i_scenecut_threshold = 40;
param->i_bframe_adaptive = X264_B_ADAPT_FAST; param->i_bframe_adaptive = X264_B_ADAPT_FAST;
param->i_bframe_bias = 0; param->i_bframe_bias = 0;
param->b_bframe_pyramid = 0; param->i_bframe_pyramid = 0;
param->b_interlaced = 0; param->b_interlaced = 0;
param->b_constrained_intra = 0; param->b_constrained_intra = 0;
...@@ -366,7 +366,7 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) ...@@ -366,7 +366,7 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
OPT("b-bias") OPT("b-bias")
p->i_bframe_bias = atoi(value); p->i_bframe_bias = atoi(value);
OPT("b-pyramid") OPT("b-pyramid")
p->b_bframe_pyramid = atobool(value); b_error |= parse_enum( value, x264_b_pyramid_names, &p->i_bframe_pyramid );
OPT("nf") OPT("nf")
p->b_deblocking_filter = !atobool(value); p->b_deblocking_filter = !atobool(value);
OPT2("filter", "deblock") OPT2("filter", "deblock")
...@@ -900,7 +900,7 @@ char *x264_param2string( x264_param_t *p, int b_res ) ...@@ -900,7 +900,7 @@ char *x264_param2string( x264_param_t *p, int b_res )
if( p->i_bframe ) if( p->i_bframe )
{ {
s += sprintf( s, " b_pyramid=%d b_adapt=%d b_bias=%d direct=%d wpredb=%d", s += sprintf( s, " b_pyramid=%d b_adapt=%d b_bias=%d direct=%d wpredb=%d",
p->b_bframe_pyramid, p->i_bframe_adaptive, p->i_bframe_bias, p->i_bframe_pyramid, p->i_bframe_adaptive, p->i_bframe_bias,
p->analyse.i_direct_mv_pred, p->analyse.b_weighted_bipred ); p->analyse.i_direct_mv_pred, p->analyse.b_weighted_bipred );
} }
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#define X264_MIN4(a,b,c,d) X264_MIN((a),X264_MIN3((b),(c),(d))) #define X264_MIN4(a,b,c,d) X264_MIN((a),X264_MIN3((b),(c),(d)))
#define X264_MAX4(a,b,c,d) X264_MAX((a),X264_MAX3((b),(c),(d))) #define X264_MAX4(a,b,c,d) X264_MAX((a),X264_MAX3((b),(c),(d)))
#define XCHG(type,a,b) do{ type t = a; a = b; b = t; } while(0) #define XCHG(type,a,b) do{ type t = a; a = b; b = t; } while(0)
#define IS_DISPOSABLE(type) ( type == X264_TYPE_B )
#define FIX8(f) ((int)(f*(1<<8)+.5)) #define FIX8(f) ((int)(f*(1<<8)+.5))
#define CHECKED_MALLOC( var, size )\ #define CHECKED_MALLOC( var, size )\
...@@ -224,11 +225,20 @@ typedef struct ...@@ -224,11 +225,20 @@ typedef struct
int b_ref_pic_list_reordering_l0; int b_ref_pic_list_reordering_l0;
int b_ref_pic_list_reordering_l1; int b_ref_pic_list_reordering_l1;
struct { struct
{
int idc; int idc;
int arg; int arg;
} ref_pic_list_order[2][16]; } ref_pic_list_order[2][16];
int i_mmco_remove_from_end;
int i_mmco_command_count;
struct /* struct for future expansion */
{
int i_difference_of_pic_nums;
int i_poc;
} mmco[16];
int i_cabac_init_idc; int i_cabac_init_idc;
int i_qp; int i_qp;
......
...@@ -38,7 +38,8 @@ typedef struct ...@@ -38,7 +38,8 @@ typedef struct
x264_param_t *param; x264_param_t *param;
int i_frame; /* Presentation frame number */ int i_frame; /* Presentation frame number */
int i_frame_num; /* Coded frame number */ int i_dts; /* Coded frame number */
int i_frame_num; /* 7.4.3 frame_num */
int b_kept_as_ref; int b_kept_as_ref;
uint8_t b_fdec; uint8_t b_fdec;
uint8_t b_last_minigop_bframe; /* this frame is the last b in a sequence of bframes */ uint8_t b_last_minigop_bframe; /* this frame is the last b in a sequence of bframes */
......
...@@ -694,7 +694,7 @@ int x264_macroblock_cache_init( x264_t *h ) ...@@ -694,7 +694,7 @@ int x264_macroblock_cache_init( x264_t *h )
for( i=0; i<2; i++ ) for( i=0; i<2; i++ )
{ {
int i_refs = X264_MIN(16, (i ? 1 : h->param.i_frame_reference) + h->param.b_bframe_pyramid) << h->param.b_interlaced; int i_refs = X264_MIN(16, (i ? 1 + !!h->param.i_bframe_pyramid : h->param.i_frame_reference) ) << h->param.b_interlaced;
for( j=0; j < i_refs; j++ ) for( j=0; j < i_refs; j++ )
CHECKED_MALLOC( h->mb.mvr[i][j], 2 * i_mb_count * sizeof(int16_t) ); CHECKED_MALLOC( h->mb.mvr[i][j], 2 * i_mb_count * sizeof(int16_t) );
} }
......
...@@ -272,7 +272,17 @@ static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal ...@@ -272,7 +272,17 @@ static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal
} }
else else
{ {
bs_write1( s, 0 ); /* adaptive_ref_pic_marking_mode_flag */ bs_write1( s, sh->i_mmco_command_count > 0 ); /* adaptive_ref_pic_marking_mode_flag */
if( sh->i_mmco_command_count > 0 )
{
int i;
for( i = 0; i < sh->i_mmco_command_count; i++ )
{
bs_write_ue( s, 1 ); /* mark short term ref as unused */
bs_write_ue( s, sh->mmco[i].i_difference_of_pic_nums - 1 );
}
bs_write_ue( s, 0 ); /* end command list */
}
} }
} }
...@@ -498,7 +508,9 @@ static int x264_validate_parameters( x264_t *h ) ...@@ -498,7 +508,9 @@ static int x264_validate_parameters( x264_t *h )
if( h->param.i_keyint_max == 1 ) if( h->param.i_keyint_max == 1 )
h->param.i_bframe = 0; h->param.i_bframe = 0;
h->param.i_bframe_bias = x264_clip3( h->param.i_bframe_bias, -90, 100 ); h->param.i_bframe_bias = x264_clip3( h->param.i_bframe_bias, -90, 100 );
h->param.b_bframe_pyramid = h->param.b_bframe_pyramid && h->param.i_bframe > 1; if( h->param.i_bframe <= 1 )
h->param.i_bframe_pyramid = X264_B_PYRAMID_NONE;
h->param.i_bframe_pyramid = x264_clip3( h->param.i_bframe_pyramid, X264_B_PYRAMID_NONE, X264_B_PYRAMID_NORMAL );
if( !h->param.i_bframe ) if( !h->param.i_bframe )
{ {
h->param.i_bframe_adaptive = X264_B_ADAPT_NONE; h->param.i_bframe_adaptive = X264_B_ADAPT_NONE;
...@@ -602,10 +614,10 @@ static int x264_validate_parameters( x264_t *h ) ...@@ -602,10 +614,10 @@ static int x264_validate_parameters( x264_t *h )
h->param.rc.i_aq_mode = 1; h->param.rc.i_aq_mode = 1;
h->param.rc.f_aq_strength = 0; h->param.rc.f_aq_strength = 0;
} }
if( h->param.rc.b_mb_tree && h->param.b_bframe_pyramid ) if( h->param.rc.b_mb_tree && h->param.i_bframe_pyramid )
{ {
x264_log( h, X264_LOG_WARNING, "b-pyramid + mb-tree is not supported\n" ); x264_log( h, X264_LOG_WARNING, "b-pyramid + mb-tree is not supported\n" );
h->param.b_bframe_pyramid = 0; h->param.i_bframe_pyramid = X264_B_PYRAMID_NONE;
} }
h->param.analyse.i_noise_reduction = x264_clip3( h->param.analyse.i_noise_reduction, 0, 1<<16 ); h->param.analyse.i_noise_reduction = x264_clip3( h->param.analyse.i_noise_reduction, 0, 1<<16 );
if( h->param.analyse.i_subpel_refine == 10 && (h->param.analyse.i_trellis != 2 || !h->param.rc.i_aq_mode) ) if( h->param.analyse.i_subpel_refine == 10 && (h->param.analyse.i_trellis != 2 || !h->param.rc.i_aq_mode) )
...@@ -980,7 +992,7 @@ int x264_encoder_reconfig( x264_t *h, x264_param_t *param ) ...@@ -980,7 +992,7 @@ int x264_encoder_reconfig( x264_t *h, x264_param_t *param )
if( h->pps->b_transform_8x8_mode ) if( h->pps->b_transform_8x8_mode )
COPY( analyse.b_transform_8x8 ); COPY( analyse.b_transform_8x8 );
if( h->frames.i_max_ref1 > 1 ) if( h->frames.i_max_ref1 > 1 )
COPY( b_bframe_pyramid ); COPY( i_bframe_pyramid );
COPY( i_slice_max_size ); COPY( i_slice_max_size );
COPY( i_slice_max_mbs ); COPY( i_slice_max_mbs );
COPY( i_slice_count ); COPY( i_slice_count );
...@@ -1091,6 +1103,21 @@ int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal ) ...@@ -1091,6 +1103,21 @@ int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal )
return frame_size; return frame_size;
} }
/* Check to see whether we have chosen a reference list ordering different
* from the standard's default. */
static inline void x264_reference_check_reorder( x264_t *h )
{
int i;
for( i = 0; i < h->i_ref0 - 1; i++ )
/* P and B-frames use different default orders. */
if( h->sh.i_type == SLICE_TYPE_P ? h->fref0[i]->i_frame_num < h->fref0[i+1]->i_frame_num
: h->fref0[i]->i_poc < h->fref0[i+1]->i_poc )
{
h->b_ref_reorder[0] = 1;
break;
}
}
static inline void x264_reference_build_list( x264_t *h, int i_poc ) static inline void x264_reference_build_list( x264_t *h, int i_poc )
{ {
int i; int i;
...@@ -1125,6 +1152,15 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc ) ...@@ -1125,6 +1152,15 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
} }
} }
} while( !b_ok ); } while( !b_ok );
if( h->sh.i_mmco_remove_from_end )
for( i = h->i_ref0-1; i >= h->i_ref0 - h->sh.i_mmco_remove_from_end; i-- )
{
int diff = h->i_frame_num - h->fref0[i]->i_frame_num;
h->sh.mmco[h->sh.i_mmco_command_count].i_poc = h->fref0[i]->i_poc;
h->sh.mmco[h->sh.i_mmco_command_count++].i_difference_of_pic_nums = diff;
}
/* Order ref1 from lower to higher poc (bubble sort) for B-frame */ /* Order ref1 from lower to higher poc (bubble sort) for B-frame */
do do
{ {
...@@ -1140,6 +1176,8 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc ) ...@@ -1140,6 +1176,8 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
} }
} while( !b_ok ); } while( !b_ok );
x264_reference_check_reorder( h );
h->i_ref1 = X264_MIN( h->i_ref1, h->frames.i_max_ref1 ); h->i_ref1 = X264_MIN( h->i_ref1, h->frames.i_max_ref1 );
h->i_ref0 = X264_MIN( h->i_ref0, h->frames.i_max_ref0 ); h->i_ref0 = X264_MIN( h->i_ref0, h->frames.i_max_ref0 );
h->i_ref0 = X264_MIN( h->i_ref0, h->param.i_frame_reference ); // if reconfig() has lowered the limit h->i_ref0 = X264_MIN( h->i_ref0, h->param.i_frame_reference ); // if reconfig() has lowered the limit
...@@ -1226,6 +1264,7 @@ static void x264_fdec_filter_row( x264_t *h, int mb_y ) ...@@ -1226,6 +1264,7 @@ static void x264_fdec_filter_row( x264_t *h, int mb_y )
static inline int x264_reference_update( x264_t *h ) static inline int x264_reference_update( x264_t *h )
{ {
int i, j;
if( !h->fdec->b_kept_as_ref ) if( !h->fdec->b_kept_as_ref )
{ {
if( h->param.i_threads > 1 ) if( h->param.i_threads > 1 )
...@@ -1238,9 +1277,15 @@ static inline int x264_reference_update( x264_t *h ) ...@@ -1238,9 +1277,15 @@ static inline int x264_reference_update( x264_t *h )
return 0; return 0;
} }
/* apply mmco from previous frame. */
for( i = 0; i < h->sh.i_mmco_command_count; i++ )
for( j = 0; h->frames.reference[j]; j++ )
if( h->frames.reference[j]->i_poc == h->sh.mmco[i].i_poc )
x264_frame_push_unused( h, x264_frame_shift( &h->frames.reference[j] ) );
/* move frame in the buffer */ /* move frame in the buffer */
x264_frame_push( h->frames.reference, h->fdec ); x264_frame_push( h->frames.reference, h->fdec );
if( h->frames.reference[h->frames.i_max_dpb] ) if( h->frames.reference[h->sps->i_num_ref_frames] )
x264_frame_push_unused( h, x264_frame_shift( h->frames.reference ) ); x264_frame_push_unused( h, x264_frame_shift( h->frames.reference ) );
h->fdec = x264_frame_pop_unused( h, 1 ); h->fdec = x264_frame_pop_unused( h, 1 );
if( !h->fdec ) if( !h->fdec )
...@@ -1256,6 +1301,40 @@ static inline void x264_reference_reset( x264_t *h ) ...@@ -1256,6 +1301,40 @@ static inline void x264_reference_reset( x264_t *h )
h->fenc->i_poc = 0; h->fenc->i_poc = 0;
} }
static inline void x264_reference_hierarchy_reset( x264_t *h )
{
int i, ref;
int b_hasdelayframe = 0;
if( !h->param.i_bframe_pyramid )
return;
/* look for delay frames -- chain must only contain frames that are disposable */
for( i = 0; h->frames.current[i] && IS_DISPOSABLE( h->frames.current[i]->i_type ); i++ )
b_hasdelayframe |= h->frames.current[i]->i_dts
!= h->frames.current[i]->i_frame + h->sps->vui.i_num_reorder_frames;
if( h->param.i_bframe_pyramid != X264_B_PYRAMID_STRICT && !b_hasdelayframe )
return;
/* Remove last BREF. There will never be old BREFs in the
* dpb during a BREF decode when pyramid == STRICT */
for( ref = 0; h->frames.reference[ref]; ref++ )
{
if( h->param.i_bframe_pyramid == X264_B_PYRAMID_STRICT
&& h->frames.reference[ref]->i_type == X264_TYPE_BREF )
{
int diff = h->i_frame_num - h->frames.reference[ref]->i_frame_num;
h->sh.mmco[h->sh.i_mmco_command_count++].i_difference_of_pic_nums = diff;
x264_frame_push_unused( h, x264_frame_pop( h->frames.reference ) );
h->b_ref_reorder[0] = 1;
break;
}
}
/* Prepare to room in the dpb for the delayed display time of the later b-frame's */
h->sh.i_mmco_remove_from_end = X264_MAX( ref + 2 - h->frames.i_max_dpb, 0 );
}
static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp ) static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp )
{ {
/* ------------------------ Create slice header ----------------------- */ /* ------------------------ Create slice header ----------------------- */
...@@ -1622,7 +1701,7 @@ int x264_encoder_encode( x264_t *h, ...@@ -1622,7 +1701,7 @@ int x264_encoder_encode( x264_t *h,
x264_picture_t *pic_out ) x264_picture_t *pic_out )
{ {
x264_t *thread_current, *thread_prev, *thread_oldest; x264_t *thread_current, *thread_prev, *thread_oldest;
int i_nal_type, i; int i_nal_type;
int i_nal_ref_idc; int i_nal_ref_idc;
int i_global_qp; int i_global_qp;
...@@ -1721,35 +1800,41 @@ int x264_encoder_encode( x264_t *h, ...@@ -1721,35 +1800,41 @@ int x264_encoder_encode( x264_t *h,
h->frames.i_last_idr = h->fenc->i_frame; h->frames.i_last_idr = h->fenc->i_frame;
h->i_frame_num = 0; h->i_frame_num = 0;
} }
h->sh.i_mmco_command_count = 0;
h->sh.i_mmco_remove_from_end = 0;
h->b_ref_reorder[0] =
h->b_ref_reorder[1] = 0;
/* ------------------- Setup frame context ----------------------------- */ /* ------------------- Setup frame context ----------------------------- */
/* 5: Init data dependent of frame type */ /* 5: Init data dependent of frame type */
if( h->fenc->i_type == X264_TYPE_IDR ) if( h->fenc->i_type == X264_TYPE_IDR )
{ {
/* reset ref pictures */ /* reset ref pictures */
x264_reference_reset( h );
i_nal_type = NAL_SLICE_IDR; i_nal_type = NAL_SLICE_IDR;
i_nal_ref_idc = NAL_PRIORITY_HIGHEST; i_nal_ref_idc = NAL_PRIORITY_HIGHEST;
h->sh.i_type = SLICE_TYPE_I; h->sh.i_type = SLICE_TYPE_I;
x264_reference_reset( h );
} }
else if( h->fenc->i_type == X264_TYPE_I ) else if( h->fenc->i_type == X264_TYPE_I )
{ {
i_nal_type = NAL_SLICE; i_nal_type = NAL_SLICE;
i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/ i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/
h->sh.i_type = SLICE_TYPE_I; h->sh.i_type = SLICE_TYPE_I;
x264_reference_hierarchy_reset( h );
} }
else if( h->fenc->i_type == X264_TYPE_P ) else if( h->fenc->i_type == X264_TYPE_P )
{ {
i_nal_type = NAL_SLICE; i_nal_type = NAL_SLICE;
i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/ i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/
h->sh.i_type = SLICE_TYPE_P; h->sh.i_type = SLICE_TYPE_P;
x264_reference_hierarchy_reset( h );
} }
else if( h->fenc->i_type == X264_TYPE_BREF ) else if( h->fenc->i_type == X264_TYPE_BREF )
{ {
i_nal_type = NAL_SLICE; i_nal_type = NAL_SLICE;
i_nal_ref_idc = NAL_PRIORITY_HIGH; /* maybe add MMCO to forget it? -> low */ i_nal_ref_idc = h->param.i_bframe_pyramid == X264_B_PYRAMID_STRICT ? NAL_PRIORITY_LOW : NAL_PRIORITY_HIGH;
h->sh.i_type = SLICE_TYPE_B; h->sh.i_type = SLICE_TYPE_B;
x264_reference_hierarchy_reset( h );
} }
else /* B frame */ else /* B frame */
{ {
...@@ -1839,20 +1924,10 @@ int x264_encoder_encode( x264_t *h, ...@@ -1839,20 +1924,10 @@ int x264_encoder_encode( x264_t *h,
h->fdec->i_qpplus1 = i_global_qp + 1; h->fdec->i_qpplus1 = i_global_qp + 1;
if( h->param.rc.b_stat_read && h->sh.i_type != SLICE_TYPE_I ) if( h->param.rc.b_stat_read && h->sh.i_type != SLICE_TYPE_I )
{
x264_reference_build_list_optimal( h ); x264_reference_build_list_optimal( h );
x264_reference_check_reorder( h );
/* Check to see whether we have chosen a reference list ordering different }
* from the standard's default. */
h->b_ref_reorder[0] =
h->b_ref_reorder[1] = 0;
for( i = 0; i < h->i_ref0 - 1; i++ )
/* P and B-frames use different default orders. */
if( h->sh.i_type == SLICE_TYPE_P ? h->fref0[i]->i_frame_num < h->fref0[i+1]->i_frame_num
: h->fref0[i]->i_poc < h->fref0[i+1]->i_poc )
{
h->b_ref_reorder[0] = 1;
break;
}
if( h->sh.i_type == SLICE_TYPE_B ) if( h->sh.i_type == SLICE_TYPE_B )
x264_macroblock_bipred_init( h ); x264_macroblock_bipred_init( h );
......
...@@ -217,18 +217,22 @@ static void x264_lookahead_encoder_shift( x264_t *h ) ...@@ -217,18 +217,22 @@ static void x264_lookahead_encoder_shift( x264_t *h )
} }
if( h->lookahead->ofbuf.list[i_frames] ) if( h->lookahead->ofbuf.list[i_frames] )
{ {
int i_dts = h->lookahead->ofbuf.list[0]->i_frame;
h->lookahead->ofbuf.list[bframes]->i_dts = i_dts;
x264_frame_push( h->frames.current, x264_frame_shift( &h->lookahead->ofbuf.list[bframes] ) ); x264_frame_push( h->frames.current, x264_frame_shift( &h->lookahead->ofbuf.list[bframes] ) );
h->lookahead->ofbuf.i_size--; h->lookahead->ofbuf.i_size--;
if( h->param.b_bframe_pyramid && bframes > 1 ) if( h->param.i_bframe_pyramid && bframes > 1 )
{ {
x264_frame_t *mid = x264_frame_shift( &h->lookahead->ofbuf.list[bframes/2] ); x264_frame_t *mid = x264_frame_shift( &h->lookahead->ofbuf.list[bframes/2] );
h->lookahead->ofbuf.i_size--; h->lookahead->ofbuf.i_size--;
mid->i_type = X264_TYPE_BREF; mid->i_type = X264_TYPE_BREF;
mid->i_dts = ++i_dts;
x264_frame_push( h->frames.current, mid ); x264_frame_push( h->frames.current, mid );
bframes--; bframes--;
} }
while( bframes-- ) while( bframes-- )
{ {
h->lookahead->ofbuf.list[0]->i_dts = ++i_dts;
x264_frame_push( h->frames.current, x264_frame_shift( h->lookahead->ofbuf.list ) ); x264_frame_push( h->frames.current, x264_frame_shift( h->lookahead->ofbuf.list ) );
h->lookahead->ofbuf.i_size--; h->lookahead->ofbuf.i_size--;
} }
......
...@@ -525,6 +525,7 @@ int x264_ratecontrol_new( x264_t *h ) ...@@ -525,6 +525,7 @@ int x264_ratecontrol_new( x264_t *h )
{ {
int i; int i;
char *opts = stats_buf; char *opts = stats_buf;
char buf[12];
stats_in = strchr( stats_buf, '\n' ); stats_in = strchr( stats_buf, '\n' );
if( !stats_in ) if( !stats_in )
return -1; return -1;
...@@ -541,8 +542,9 @@ int x264_ratecontrol_new( x264_t *h ) ...@@ -541,8 +542,9 @@ int x264_ratecontrol_new( x264_t *h )
/* since B-adapt doesn't (yet) take into account B-pyramid, /* since B-adapt doesn't (yet) take into account B-pyramid,
* the converse is not a problem */ * the converse is not a problem */
if( strstr( opts, "b_pyramid=1" ) && !h->param.b_bframe_pyramid ) sprintf( buf, "b_pyramid=%d", h->param.i_bframe_pyramid );
x264_log( h, X264_LOG_WARNING, "1st pass used B-pyramid, 2nd doesn't\n" ); if( !strstr( opts, buf ) )
x264_log( h, X264_LOG_WARNING, "different B-pyramid setting than 1st pass\n" );
if( ( p = strstr( opts, "keyint=" ) ) && sscanf( p, "keyint=%d", &i ) if( ( p = strstr( opts, "keyint=" ) ) && sscanf( p, "keyint=%d", &i )
&& h->param.i_keyint_max != i ) && h->param.i_keyint_max != i )
......
...@@ -189,11 +189,13 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) ...@@ -189,11 +189,13 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
sps->vui.b_fixed_frame_rate = 1; sps->vui.b_fixed_frame_rate = 1;
} }
sps->vui.i_num_reorder_frames = param->b_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0; sps->vui.i_num_reorder_frames = param->i_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0;
/* extra slot with pyramid so that we don't have to override the /* extra slot with pyramid so that we don't have to override the
* order of forgetting old pictures */ * order of forgetting old pictures */
sps->vui.i_max_dec_frame_buffering = sps->vui.i_max_dec_frame_buffering =
sps->i_num_ref_frames = X264_MIN(16, X264_MAX(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames)); sps->i_num_ref_frames = X264_MIN(16, X264_MAX3(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames,
param->i_bframe_pyramid ? 4 : 1 ));
sps->i_num_ref_frames -= param->i_bframe_pyramid == X264_B_PYRAMID_STRICT;
sps->vui.b_bitstream_restriction = 1; sps->vui.b_bitstream_restriction = 1;
if( sps->vui.b_bitstream_restriction ) if( sps->vui.b_bitstream_restriction )
...@@ -540,7 +542,7 @@ int x264_validate_levels( x264_t *h, int verbose ) ...@@ -540,7 +542,7 @@ int x264_validate_levels( x264_t *h, int verbose )
{ {
int ret = 0; int ret = 0;
int mbs = h->sps->i_mb_width * h->sps->i_mb_height; int mbs = h->sps->i_mb_width * h->sps->i_mb_height;
int dpb = mbs * 384 * h->sps->i_num_ref_frames; int dpb = mbs * 384 * h->sps->vui.i_max_dec_frame_buffering;
int cbp_factor = h->sps->i_profile_idc==PROFILE_HIGH ? 5 : 4; int cbp_factor = h->sps->i_profile_idc==PROFILE_HIGH ? 5 : 4;
const x264_level_t *l = x264_levels; const x264_level_t *l = x264_levels;
...@@ -554,7 +556,7 @@ int x264_validate_levels( x264_t *h, int verbose ) ...@@ -554,7 +556,7 @@ int x264_validate_levels( x264_t *h, int verbose )
h->sps->i_mb_width, h->sps->i_mb_height, l->frame_size ); h->sps->i_mb_width, h->sps->i_mb_height, l->frame_size );
if( dpb > l->dpb ) if( dpb > l->dpb )
ERROR( "DPB size (%d frames, %d bytes) > level limit (%d frames, %d bytes)\n", ERROR( "DPB size (%d frames, %d bytes) > level limit (%d frames, %d bytes)\n",
h->sps->i_num_ref_frames, dpb, (int)(l->dpb / (384*mbs)), l->dpb ); h->sps->vui.i_max_dec_frame_buffering, dpb, (int)(l->dpb / (384*mbs)), l->dpb );
#define CHECK( name, limit, val ) \ #define CHECK( name, limit, val ) \
if( (val) > (limit) ) \ if( (val) > (limit) ) \
......
...@@ -937,6 +937,13 @@ void x264_slicetype_decide( x264_t *h ) ...@@ -937,6 +937,13 @@ void x264_slicetype_decide( x264_t *h )
for( bframes = 0;; bframes++ ) for( bframes = 0;; bframes++ )
{ {
frm = h->lookahead->next.list[bframes]; frm = h->lookahead->next.list[bframes];
if( h->param.i_bframe_pyramid < X264_B_PYRAMID_NORMAL && !h->param.rc.b_stat_read
&& frm->i_type == X264_TYPE_BREF )
{
frm->i_type = X264_TYPE_B;
x264_log( h, X264_LOG_WARNING, "Externally supplied B-ref at frame %d incompatible with B-pyramid %s\n",
frm->i_frame, x264_b_pyramid_names[h->param.i_bframe_pyramid] );
}
/* Limit GOP size */ /* Limit GOP size */
if( frm->i_frame - h->lookahead->i_last_idr >= h->param.i_keyint_max ) if( frm->i_frame - h->lookahead->i_last_idr >= h->param.i_keyint_max )
......
...@@ -726,7 +726,7 @@ int set_param_mp4( hnd_t handle, x264_param_t *p_param ) ...@@ -726,7 +726,7 @@ int set_param_mp4( hnd_t handle, x264_param_t *p_param )
p_mp4->i_time_res = p_param->i_fps_num; p_mp4->i_time_res = p_param->i_fps_num;
p_mp4->i_time_inc = p_param->i_fps_den; p_mp4->i_time_inc = p_param->i_fps_den;
p_mp4->i_init_delay = p_param->i_bframe ? (p_param->b_bframe_pyramid ? 2 : 1) : 0; p_mp4->i_init_delay = p_param->i_bframe ? (p_param->i_bframe_pyramid ? 2 : 1) : 0;
p_mp4->i_init_delay *= p_mp4->i_time_inc; p_mp4->i_init_delay *= p_mp4->i_time_inc;
fprintf( stderr, "mp4 [info]: initial delay %d (scale %d)\n", fprintf( stderr, "mp4 [info]: initial delay %d (scale %d)\n",
p_mp4->i_init_delay, p_mp4->i_time_res ); p_mp4->i_init_delay, p_mp4->i_time_res );
......
...@@ -207,7 +207,11 @@ static void Help( x264_param_t *defaults, int longhelp ) ...@@ -207,7 +207,11 @@ static void Help( x264_param_t *defaults, int longhelp )
" - 1: Fast\n" " - 1: Fast\n"
" - 2: Optimal (slow with high --bframes)\n", defaults->i_bframe_adaptive ); " - 2: Optimal (slow with high --bframes)\n", defaults->i_bframe_adaptive );
H2( " --b-bias <integer> Influences how often B-frames are used [%d]\n", defaults->i_bframe_bias ); H2( " --b-bias <integer> Influences how often B-frames are used [%d]\n", defaults->i_bframe_bias );
H1( " --b-pyramid Keep some B-frames as references\n" ); H1( " --b-pyramid <string> Keep some B-frames as references [%s]\n"
" - none: Disabled\n"
" - strict: Strictly heirarchical pyramid\n"
" - normal: Non-strict (not Blu-ray compatible)\n",
strtable_lookup( x264_b_pyramid_names, defaults->i_bframe_pyramid ) );
H1( " --no-cabac Disable CABAC\n" ); H1( " --no-cabac Disable CABAC\n" );
H1( " -r, --ref <integer> Number of reference frames [%d]\n", defaults->i_frame_reference ); H1( " -r, --ref <integer> Number of reference frames [%d]\n", defaults->i_frame_reference );
H1( " --no-deblock Disable loop filter\n" ); H1( " --no-deblock Disable loop filter\n" );
...@@ -416,7 +420,7 @@ static struct option long_options[] = ...@@ -416,7 +420,7 @@ static struct option long_options[] =
{ "b-adapt", required_argument, NULL, 0 }, { "b-adapt", required_argument, NULL, 0 },
{ "no-b-adapt", no_argument, NULL, 0 }, { "no-b-adapt", no_argument, NULL, 0 },
{ "b-bias", required_argument, NULL, 0 }, { "b-bias", required_argument, NULL, 0 },
{ "b-pyramid", no_argument, NULL, 0 }, { "b-pyramid", required_argument, NULL, 0 },
{ "min-keyint", required_argument, NULL, 'i' }, { "min-keyint", required_argument, NULL, 'i' },
{ "keyint", required_argument, NULL, 'I' }, { "keyint", required_argument, NULL, 'I' },
{ "scenecut", required_argument, NULL, 0 }, { "scenecut", required_argument, NULL, 0 },
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include <stdarg.h> #include <stdarg.h>
#define X264_BUILD 77 #define X264_BUILD 78
/* x264_t: /* x264_t:
* opaque handler for encoder */ * opaque handler for encoder */
...@@ -95,9 +95,13 @@ typedef struct x264_t x264_t; ...@@ -95,9 +95,13 @@ typedef struct x264_t x264_t;
#define X264_B_ADAPT_NONE 0 #define X264_B_ADAPT_NONE 0
#define X264_B_ADAPT_FAST 1 #define X264_B_ADAPT_FAST 1
#define X264_B_ADAPT_TRELLIS 2 #define X264_B_ADAPT_TRELLIS 2
#define X264_B_PYRAMID_NONE 0
#define X264_B_PYRAMID_STRICT 1
#define X264_B_PYRAMID_NORMAL 2
static const char * const x264_direct_pred_names[] = { "none", "spatial", "temporal", "auto", 0 }; static const char * const x264_direct_pred_names[] = { "none", "spatial", "temporal", "auto", 0 };
static const char * const x264_motion_est_names[] = { "dia", "hex", "umh", "esa", "tesa", 0 }; static const char * const x264_motion_est_names[] = { "dia", "hex", "umh", "esa", "tesa", 0 };
static const char * const x264_b_pyramid_names[] = { "none", "strict", "normal", 0 };
static const char * const x264_overscan_names[] = { "undef", "show", "crop", 0 }; static const char * const x264_overscan_names[] = { "undef", "show", "crop", 0 };
static const char * const x264_vidformat_names[] = { "component", "pal", "ntsc", "secam", "mac", "undef", 0 }; static const char * const x264_vidformat_names[] = { "component", "pal", "ntsc", "secam", "mac", "undef", 0 };
static const char * const x264_fullrange_names[] = { "off", "on", 0 }; static const char * const x264_fullrange_names[] = { "off", "on", 0 };
...@@ -196,7 +200,7 @@ typedef struct x264_param_t ...@@ -196,7 +200,7 @@ typedef struct x264_param_t
int i_bframe; /* how many b-frame between 2 references pictures */ int i_bframe; /* how many b-frame between 2 references pictures */
int i_bframe_adaptive; int i_bframe_adaptive;
int i_bframe_bias; int i_bframe_bias;
int b_bframe_pyramid; /* Keep some B-frames as references */ int i_bframe_pyramid; /* Keep some B-frames as references: 0=off, 1=strict heirarchical, 2=normal */
int b_deblocking_filter; int b_deblocking_filter;
int i_deblocking_filter_alphac0; /* [-6, 6] -6 light filter, 6 strong */ int i_deblocking_filter_alphac0; /* [-6, 6] -6 light filter, 6 strong */
......
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