Commit 91536acd authored by Loren Merritt's avatar Loren Merritt

New option: "B-frame pyramid" keeps the middle of 2+ consecutive B-frames as a...

New option: "B-frame pyramid" keeps the middle of 2+ consecutive B-frames as a reference, and reorders frame appropriately.


git-svn-id: svn://svn.videolan.org/x264/trunk@150 df754926-b1dd-0310-bc7b-ec298dee348c
parent 9591b038
...@@ -61,17 +61,18 @@ void x264_param_default( x264_param_t *param ) ...@@ -61,17 +61,18 @@ void x264_param_default( x264_param_t *param )
/* Encoder parameters */ /* Encoder parameters */
param->i_frame_reference = 1; param->i_frame_reference = 1;
param->i_keyint_max = 250; param->i_keyint_max = 250;
param->i_keyint_min = 100; param->i_keyint_min = 25;
param->i_bframe = 0; param->i_bframe = 0;
param->i_scenecut_threshold = 40; param->i_scenecut_threshold = 40;
param->b_bframe_adaptive = 1; param->b_bframe_adaptive = 1;
param->i_bframe_bias = 0; param->i_bframe_bias = 0;
param->b_bframe_pyramid = 0;
param->b_deblocking_filter = 1; param->b_deblocking_filter = 1;
param->i_deblocking_filter_alphac0 = 0; param->i_deblocking_filter_alphac0 = 0;
param->i_deblocking_filter_beta = 0; param->i_deblocking_filter_beta = 0;
param->b_cabac = 0; param->b_cabac = 1;
param->i_cabac_init_idc = -1; param->i_cabac_init_idc = -1;
param->rc.b_cbr = 0; param->rc.b_cbr = 0;
......
...@@ -140,6 +140,13 @@ typedef struct ...@@ -140,6 +140,13 @@ typedef struct
int i_num_ref_idx_l0_active; int i_num_ref_idx_l0_active;
int i_num_ref_idx_l1_active; int i_num_ref_idx_l1_active;
int b_ref_pic_list_reordering_l0;
int b_ref_pic_list_reordering_l1;
struct {
int idc;
int arg;
} ref_pic_list_order[2][16];
int i_cabac_init_idc; int i_cabac_init_idc;
int i_qp_delta; int i_qp_delta;
...@@ -237,13 +244,16 @@ struct x264_t ...@@ -237,13 +244,16 @@ struct x264_t
/* For adaptive B decision */ /* For adaptive B decision */
x264_frame_t *last_nonb; x264_frame_t *last_nonb;
/* frames used for reference +1 for decoding */ /* frames used for reference +1 for decoding +1 sentinel */
x264_frame_t *reference[16+1]; x264_frame_t *reference[16+2+1+1];
int i_last_idr; /* Frame number of the last IDR */ int i_last_idr; /* Frame number of the last IDR */
int i_input; /* Number of input frames already accepted */ int i_input; /* Number of input frames already accepted */
int i_max_dpb; /* Number of frames allocated in the decoded picture buffer */
int i_max_ref0;
int i_max_ref1;
int i_delay; /* Number of frames buffered for B reordering */ int i_delay; /* Number of frames buffered for B reordering */
} frames; } frames;
...@@ -258,6 +268,7 @@ struct x264_t ...@@ -258,6 +268,7 @@ struct x264_t
x264_frame_t *fref0[16]; /* ref list 0 */ x264_frame_t *fref0[16]; /* ref list 0 */
int i_ref1; int i_ref1;
x264_frame_t *fref1[16]; /* ref list 1 */ x264_frame_t *fref1[16]; /* ref list 1 */
int b_ref_reorder[2];
...@@ -371,6 +382,9 @@ struct x264_t ...@@ -371,6 +382,9 @@ struct x264_t
/* B_direct and weighted prediction */ /* B_direct and weighted prediction */
int dist_scale_factor[16][16]; int dist_scale_factor[16][16];
int bipred_weight[16][16]; int bipred_weight[16][16];
/* maps fref1[0]'s ref indices into the current list0 */
int map_col_to_list0_buf[2]; // for negative indices
int map_col_to_list0[16];
} mb; } mb;
/* rate control encoding only */ /* rate control encoding only */
......
...@@ -91,7 +91,9 @@ x264_frame_t *x264_frame_new( x264_t *h ) ...@@ -91,7 +91,9 @@ x264_frame_t *x264_frame_new( x264_t *h )
frame->i_qpplus1 = 0; frame->i_qpplus1 = 0;
frame->i_pts = -1; frame->i_pts = -1;
frame->i_frame = -1; frame->i_frame = -1;
frame->i_frame_num = -1;
frame->mb_type= x264_malloc( i_mb_count * sizeof( int8_t) );
frame->mv[0] = x264_malloc( 2*16 * i_mb_count * sizeof( int16_t ) ); frame->mv[0] = x264_malloc( 2*16 * i_mb_count * sizeof( int16_t ) );
frame->ref[0] = x264_malloc( 4 * i_mb_count * sizeof( int8_t ) ); frame->ref[0] = x264_malloc( 4 * i_mb_count * sizeof( int8_t ) );
if( h->param.i_bframe ) if( h->param.i_bframe )
...@@ -119,6 +121,7 @@ void x264_frame_delete( x264_frame_t *frame ) ...@@ -119,6 +121,7 @@ void x264_frame_delete( x264_frame_t *frame )
{ {
x264_free( frame->buffer[i] ); x264_free( frame->buffer[i] );
} }
x264_free( frame->mb_type );
x264_free( frame->mv[0] ); x264_free( frame->mv[0] );
x264_free( frame->mv[1] ); x264_free( frame->mv[1] );
x264_free( frame->ref[0] ); x264_free( frame->ref[0] );
......
...@@ -32,6 +32,8 @@ typedef struct ...@@ -32,6 +32,8 @@ typedef struct
int i_qpplus1; int i_qpplus1;
int64_t i_pts; int64_t i_pts;
int i_frame; /* Presentation frame number */ int i_frame; /* Presentation frame number */
int i_frame_num; /* Coded frame number */
int b_kept_as_ref;
/* YUV buffer */ /* YUV buffer */
int i_plane; int i_plane;
...@@ -48,6 +50,7 @@ typedef struct ...@@ -48,6 +50,7 @@ typedef struct
void *buffer[11]; void *buffer[11];
/* motion data */ /* motion data */
int8_t *mb_type;
int16_t (*mv[2])[2]; int16_t (*mv[2])[2];
int8_t *ref[2]; int8_t *ref[2];
int i_ref[2]; int i_ref[2];
......
...@@ -341,21 +341,23 @@ static int x264_mb_predict_mv_direct16x16_temporal( x264_t *h ) ...@@ -341,21 +341,23 @@ static int x264_mb_predict_mv_direct16x16_temporal( x264_t *h )
x264_macroblock_cache_ref( h, 0, 0, 4, 4, 1, 0 ); x264_macroblock_cache_ref( h, 0, 0, 4, 4, 1, 0 );
if( IS_INTRA( h->fref1[0]->mb_type[ h->mb.i_mb_xy ] ) )
{
x264_macroblock_cache_ref( h, 0, 0, 4, 4, 0, 0 );
x264_macroblock_cache_mv( h, 0, 0, 4, 4, 0, 0, 0 );
x264_macroblock_cache_mv( h, 0, 0, 4, 4, 1, 0, 0 );
return 1;
}
/* FIXME: optimize per block size */ /* FIXME: optimize per block size */
for( i = 0; i < 4; i++ ) for( i = 0; i < 4; i++ )
{ {
const int x8 = 2*(i%2); const int x8 = 2*(i%2);
const int y8 = 2*(i/2); const int y8 = 2*(i/2);
/* TODO: MapColToList0 */ const int i_part_8x8 = i_mb_8x8 + x8/2 + y8 * h->mb.i_mb_stride;
const int i_ref = h->fref1[0]->ref[0][ i_mb_8x8 + x8/2 + y8 * h->mb.i_mb_stride ]; const int i_ref = h->mb.map_col_to_list0[ h->fref1[0]->ref[0][ i_part_8x8 ] ];
if( i_ref == -1 ) if( i_ref >= 0 )
{
x264_macroblock_cache_ref( h, x8, y8, 2, 2, 0, 0 );
x264_macroblock_cache_mv( h, x8, y8, 2, 2, 0, 0, 0 );
x264_macroblock_cache_mv( h, x8, y8, 2, 2, 1, 0, 0 );
}
else
{ {
const int dist_scale_factor = h->mb.dist_scale_factor[i_ref][0]; const int dist_scale_factor = h->mb.dist_scale_factor[i_ref][0];
int x4, y4; int x4, y4;
...@@ -373,6 +375,12 @@ static int x264_mb_predict_mv_direct16x16_temporal( x264_t *h ) ...@@ -373,6 +375,12 @@ static int x264_mb_predict_mv_direct16x16_temporal( x264_t *h )
x264_macroblock_cache_mv( h, x4, y4, 1, 1, 1, mv_l0[0] - mv_col[0], mv_l0[1] - mv_col[1] ); x264_macroblock_cache_mv( h, x4, y4, 1, 1, 1, mv_l0[0] - mv_col[0], mv_l0[1] - mv_col[1] );
} }
} }
else
{
/* the colocated ref isn't in the current list0 */
/* FIXME: we might still be able to use direct_8x8 on some partitions */
return 0;
}
} }
return 1; return 1;
...@@ -821,7 +829,6 @@ void x264_macroblock_cache_init( x264_t *h ) ...@@ -821,7 +829,6 @@ void x264_macroblock_cache_init( x264_t *h )
h->mb.i_b8_stride = h->sps->i_mb_width * 2; h->mb.i_b8_stride = h->sps->i_mb_width * 2;
h->mb.i_b4_stride = h->sps->i_mb_width * 4; h->mb.i_b4_stride = h->sps->i_mb_width * 4;
h->mb.type= x264_malloc( i_mb_count * sizeof( int8_t) );
h->mb.qp = x264_malloc( i_mb_count * sizeof( int8_t) ); h->mb.qp = x264_malloc( i_mb_count * sizeof( int8_t) );
h->mb.cbp = x264_malloc( i_mb_count * sizeof( int16_t) ); h->mb.cbp = x264_malloc( i_mb_count * sizeof( int16_t) );
h->mb.skipbp = x264_malloc( i_mb_count * sizeof( int8_t) ); h->mb.skipbp = x264_malloc( i_mb_count * sizeof( int8_t) );
...@@ -840,8 +847,11 @@ void x264_macroblock_cache_init( x264_t *h ) ...@@ -840,8 +847,11 @@ void x264_macroblock_cache_init( x264_t *h )
} }
for( i=0; i<2; i++ ) for( i=0; i<2; i++ )
for( j=0; j < ( i ? 1 : h->param.i_frame_reference ); j++ ) {
int i_refs = i ? 1 + h->param.b_bframe_pyramid : h->param.i_frame_reference;
for( j=0; j < i_refs; j++ )
h->mb.mvr[i][j] = x264_malloc( 2 * i_mb_count * sizeof( int16_t ) ); h->mb.mvr[i][j] = x264_malloc( 2 * i_mb_count * sizeof( int16_t ) );
}
/* init with not avaiable (for top right idx=7,15) */ /* init with not avaiable (for top right idx=7,15) */
memset( h->mb.cache.ref[0], -2, X264_SCAN8_SIZE * sizeof( int8_t ) ); memset( h->mb.cache.ref[0], -2, X264_SCAN8_SIZE * sizeof( int8_t ) );
...@@ -851,8 +861,11 @@ void x264_macroblock_cache_end( x264_t *h ) ...@@ -851,8 +861,11 @@ void x264_macroblock_cache_end( x264_t *h )
{ {
int i, j; int i, j;
for( i=0; i<2; i++ ) for( i=0; i<2; i++ )
for( j=0; j < ( i ? 1 : h->param.i_frame_reference ); j++ ) {
int i_refs = i ? 1 + h->param.b_bframe_pyramid : h->param.i_frame_reference;
for( j=0; j < i_refs; j++ )
x264_free( h->mb.mvr[i][j] ); x264_free( h->mb.mvr[i][j] );
}
if( h->param.b_cabac ) if( h->param.b_cabac )
{ {
x264_free( h->mb.chroma_pred_mode ); x264_free( h->mb.chroma_pred_mode );
...@@ -864,16 +877,16 @@ void x264_macroblock_cache_end( x264_t *h ) ...@@ -864,16 +877,16 @@ void x264_macroblock_cache_end( x264_t *h )
x264_free( h->mb.skipbp ); x264_free( h->mb.skipbp );
x264_free( h->mb.cbp ); x264_free( h->mb.cbp );
x264_free( h->mb.qp ); x264_free( h->mb.qp );
x264_free( h->mb.type );
} }
void x264_macroblock_slice_init( x264_t *h ) void x264_macroblock_slice_init( x264_t *h )
{ {
int i; int i, j;
h->mb.mv[0] = h->fdec->mv[0]; h->mb.mv[0] = h->fdec->mv[0];
h->mb.mv[1] = h->fdec->mv[1]; h->mb.mv[1] = h->fdec->mv[1];
h->mb.ref[0] = h->fdec->ref[0]; h->mb.ref[0] = h->fdec->ref[0];
h->mb.ref[1] = h->fdec->ref[1]; h->mb.ref[1] = h->fdec->ref[1];
h->mb.type = h->fdec->mb_type;
h->fdec->i_ref[0] = h->i_ref0; h->fdec->i_ref[0] = h->i_ref0;
h->fdec->i_ref[1] = h->i_ref1; h->fdec->i_ref[1] = h->i_ref1;
...@@ -883,6 +896,20 @@ void x264_macroblock_slice_init( x264_t *h ) ...@@ -883,6 +896,20 @@ void x264_macroblock_slice_init( x264_t *h )
{ {
for( i = 0; i < h->i_ref1; i++ ) for( i = 0; i < h->i_ref1; i++ )
h->fdec->ref_poc[1][i] = h->fref1[i]->i_poc; h->fdec->ref_poc[1][i] = h->fref1[i]->i_poc;
h->mb.map_col_to_list0[-1] = -1;
h->mb.map_col_to_list0[-2] = -2;
for( i = 0; i < h->fref1[0]->i_ref[0]; i++ )
{
int poc = h->fref1[0]->ref_poc[0][i];
h->mb.map_col_to_list0[i] = -2;
for( j = 0; j < h->i_ref0; j++ )
if( h->fref0[j]->i_poc == poc )
{
h->mb.map_col_to_list0[i] = j;
break;
}
}
} }
} }
......
...@@ -874,7 +874,8 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a ) ...@@ -874,7 +874,8 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
a->l0.me16x16.cost -= a->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l0_active - 1, a->l0.i_ref ); a->l0.me16x16.cost -= a->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l0_active - 1, a->l0.i_ref );
/* ME for list 1 */ /* ME for list 1 */
/* not using fullpel_thresh since we don't yet do more than 1 list 1 ref */ i_fullpel_thresh = INT_MAX;
p_fullpel_thresh = h->i_ref1>1 ? &i_fullpel_thresh : NULL;
a->l1.me16x16.cost = INT_MAX; a->l1.me16x16.cost = INT_MAX;
for( i_ref = 0; i_ref < h->i_ref1; i_ref++ ) for( i_ref = 0; i_ref < h->i_ref1; i_ref++ )
{ {
...@@ -882,7 +883,7 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a ) ...@@ -882,7 +883,7 @@ static void x264_mb_analyse_inter_b16x16( x264_t *h, x264_mb_analysis_t *a )
LOAD_HPELS( m.p_fref, h->mb.pic.p_fref[1][i_ref], 0 ); LOAD_HPELS( m.p_fref, h->mb.pic.p_fref[1][i_ref], 0 );
x264_mb_predict_mv_16x16( h, 1, i_ref, m.mvp ); x264_mb_predict_mv_16x16( h, 1, i_ref, m.mvp );
x264_mb_predict_mv_ref16x16( h, 1, i_ref, mvc, &i_mvc ); x264_mb_predict_mv_ref16x16( h, 1, i_ref, mvc, &i_mvc );
x264_me_search( h, &m, mvc, i_mvc ); x264_me_search_ref( h, &m, mvc, i_mvc, p_fullpel_thresh );
/* add ref cost */ /* add ref cost */
m.cost += a->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l1_active - 1, i_ref ); m.cost += a->i_lambda * bs_size_te( h->sh.i_num_ref_idx_l1_active - 1, i_ref );
......
...@@ -1069,7 +1069,7 @@ void x264_macroblock_write_cabac( x264_t *h, bs_t *s ) ...@@ -1069,7 +1069,7 @@ void x264_macroblock_write_cabac( x264_t *h, bs_t *s )
continue; continue;
for( i = 0; i < 4; i++ ) for( i = 0; i < 4; i++ )
{ {
if( x264_mb_partition_listX_table[0][ h->mb.i_sub_partition[i] ] ) if( x264_mb_partition_listX_table[i_list][ h->mb.i_sub_partition[i] ] )
{ {
x264_cabac_mb_ref( h, i_list, 4*i ); x264_cabac_mb_ref( h, i_list, 4*i );
} }
......
...@@ -124,6 +124,7 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh, ...@@ -124,6 +124,7 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh,
int i_type, int i_idr_pic_id, int i_frame, int i_qp ) int i_type, int i_idr_pic_id, int i_frame, int i_qp )
{ {
x264_param_t *param = &h->param; x264_param_t *param = &h->param;
int i;
/* First we fill all field */ /* First we fill all field */
sh->sps = sps; sh->sps = sps;
...@@ -154,6 +155,25 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh, ...@@ -154,6 +155,25 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh,
sh->i_num_ref_idx_l0_active = 1; sh->i_num_ref_idx_l0_active = 1;
sh->i_num_ref_idx_l1_active = 1; sh->i_num_ref_idx_l1_active = 1;
sh->b_ref_pic_list_reordering_l0 = h->b_ref_reorder[0];
sh->b_ref_pic_list_reordering_l1 = h->b_ref_reorder[1];
/* If the ref list isn't in the default order, construct reordering header */
/* List1 reordering isn't needed yet */
if( sh->b_ref_pic_list_reordering_l0 )
{
int pred_frame_num = i_frame;
for( i = 0; i < h->i_ref0; i++ )
{
int diff = h->fref0[i]->i_frame_num - pred_frame_num;
if( diff == 0 )
x264_log( h, X264_LOG_ERROR, "diff frame num == 0\n" );
sh->ref_pic_list_order[0][i].idc = ( diff > 0 );
sh->ref_pic_list_order[0][i].arg = abs( diff ) - 1;
pred_frame_num = h->fref0[i]->i_frame_num;
}
}
sh->i_cabac_init_idc = param->i_cabac_init_idc; sh->i_cabac_init_idc = param->i_cabac_init_idc;
sh->i_qp_delta = i_qp - pps->i_pic_init_qp; sh->i_qp_delta = i_qp - pps->i_pic_init_qp;
...@@ -177,6 +197,8 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh, ...@@ -177,6 +197,8 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh,
static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal_ref_idc ) static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal_ref_idc )
{ {
int i;
bs_write_ue( s, sh->i_first_mb ); bs_write_ue( s, sh->i_first_mb );
bs_write_ue( s, sh->i_type + 5 ); /* same type things */ bs_write_ue( s, sh->i_type + 5 ); /* same type things */
bs_write_ue( s, sh->i_pps_id ); bs_write_ue( s, sh->i_pps_id );
...@@ -229,20 +251,29 @@ static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal ...@@ -229,20 +251,29 @@ static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal
/* ref pic list reordering */ /* ref pic list reordering */
if( sh->i_type != SLICE_TYPE_I ) if( sh->i_type != SLICE_TYPE_I )
{ {
int b_ref_pic_list_reordering_l0 = 0; bs_write1( s, sh->b_ref_pic_list_reordering_l0 );
bs_write1( s, b_ref_pic_list_reordering_l0 ); if( sh->b_ref_pic_list_reordering_l0 )
if( b_ref_pic_list_reordering_l0 )
{ {
/* FIXME */ for( i = 0; i < sh->i_num_ref_idx_l0_active; i++ )
{
bs_write_ue( s, sh->ref_pic_list_order[0][i].idc );
bs_write_ue( s, sh->ref_pic_list_order[0][i].arg );
}
bs_write_ue( s, 3 );
} }
} }
if( sh->i_type == SLICE_TYPE_B ) if( sh->i_type == SLICE_TYPE_B )
{ {
int b_ref_pic_list_reordering_l1 = 0; bs_write1( s, sh->b_ref_pic_list_reordering_l1 );
bs_write1( s, b_ref_pic_list_reordering_l1 ); if( sh->b_ref_pic_list_reordering_l1 )
if( b_ref_pic_list_reordering_l1 )
{ {
/* FIXME */ for( i = 0; i < sh->i_num_ref_idx_l1_active; i++ )
{
bs_write_ue( s, sh->ref_pic_list_order[1][i].idc );
bs_write_ue( s, sh->ref_pic_list_order[1][i].arg );
}
bs_write_ue( s, 3 );
} }
} }
...@@ -349,7 +380,12 @@ x264_t *x264_encoder_open ( x264_param_t *param ) ...@@ -349,7 +380,12 @@ x264_t *x264_encoder_open ( x264_param_t *param )
h->param.i_bframe = x264_clip3( h->param.i_bframe, 0, X264_BFRAME_MAX ); h->param.i_bframe = x264_clip3( h->param.i_bframe, 0, X264_BFRAME_MAX );
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;
h->frames.i_delay = h->param.i_bframe; h->frames.i_delay = h->param.i_bframe;
h->frames.i_max_ref0 = h->param.i_frame_reference;
h->frames.i_max_ref1 = h->param.b_bframe_pyramid ? 2
: h->param.i_bframe ? 1 : 0;
h->frames.i_max_dpb = h->frames.i_max_ref0 + h->frames.i_max_ref1 + 1;
h->param.i_deblocking_filter_alphac0 = x264_clip3( h->param.i_deblocking_filter_alphac0, -6, 6 ); h->param.i_deblocking_filter_alphac0 = x264_clip3( h->param.i_deblocking_filter_alphac0, -6, 6 );
h->param.i_deblocking_filter_beta = x264_clip3( h->param.i_deblocking_filter_beta, -6, 6 ); h->param.i_deblocking_filter_beta = x264_clip3( h->param.i_deblocking_filter_beta, -6, 6 );
...@@ -436,11 +472,11 @@ x264_t *x264_encoder_open ( x264_param_t *param ) ...@@ -436,11 +472,11 @@ x264_t *x264_encoder_open ( x264_param_t *param )
{ {
h->frames.unused[i] = x264_frame_new( h ); h->frames.unused[i] = x264_frame_new( h );
} }
for( i = 0; i < 2 + h->param.i_frame_reference; i++ ) for( i = 0; i < h->frames.i_max_dpb; i++ )
{ {
/* 2 = 1 backward ref + 1 fdec */
h->frames.reference[i] = x264_frame_new( h ); h->frames.reference[i] = x264_frame_new( h );
} }
h->frames.reference[h->frames.i_max_dpb] = NULL;
h->frames.i_last_idr = - h->param.i_keyint_max; h->frames.i_last_idr = - h->param.i_keyint_max;
h->frames.i_input = 0; h->frames.i_input = 0;
...@@ -560,35 +596,40 @@ int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal ) ...@@ -560,35 +596,40 @@ int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal )
static void x264_frame_put( x264_frame_t *list[X264_BFRAME_MAX], x264_frame_t *frame ) static void x264_frame_put( x264_frame_t *list[X264_BFRAME_MAX], x264_frame_t *frame )
{ {
int i = 0; int i = 0;
while( list[i] ) i++;
while( list[i] != NULL ) i++;
list[i] = frame; list[i] = frame;
} }
static void x264_frame_push( x264_frame_t *list[X264_BFRAME_MAX], x264_frame_t *frame )
{
int i = 0;
while( list[i] ) i++;
while( i-- )
list[i+1] = list[i];
list[0] = frame;
}
static x264_frame_t *x264_frame_get( x264_frame_t *list[X264_BFRAME_MAX+1] ) static x264_frame_t *x264_frame_get( x264_frame_t *list[X264_BFRAME_MAX+1] )
{ {
x264_frame_t *frame = list[0]; x264_frame_t *frame = list[0];
int i; int i;
for( i = 0; i < X264_BFRAME_MAX && list[i]; i++ )
for( i = 0; i < X264_BFRAME_MAX; i++ )
{
list[i] = list[i+1]; list[i] = list[i+1];
}
list[X264_BFRAME_MAX] = NULL;
return frame; return frame;
} }
/* Sort queued frames into input order */ static void x264_frame_sort( x264_frame_t *list[X264_BFRAME_MAX+1], int b_dts )
static void x264_frame_sort( x264_frame_t *list[X264_BFRAME_MAX+1] )
{ {
int i, b_ok; int i, b_ok;
do { do {
b_ok = 1; b_ok = 1;
for( i = 0; i < X264_BFRAME_MAX && list[i+1]; i++ ) for( i = 0; i < X264_BFRAME_MAX && list[i+1]; i++ )
{ {
if( list[i]->i_frame > list[i+1]->i_frame ) int dtype = list[i]->i_type - list[i+1]->i_type;
int dtime = list[i]->i_frame - list[i+1]->i_frame;
int swap = b_dts ? dtype > 0 || ( dtype == 0 && dtime > 0 )
: dtime > 0;
if( swap )
{ {
x264_frame_t *tmp = list[i+1]; x264_frame_t *tmp = list[i+1];
list[i+1] = list[i]; list[i+1] = list[i];
...@@ -598,8 +639,10 @@ static void x264_frame_sort( x264_frame_t *list[X264_BFRAME_MAX+1] ) ...@@ -598,8 +639,10 @@ static void x264_frame_sort( x264_frame_t *list[X264_BFRAME_MAX+1] )
} }
} while( !b_ok ); } while( !b_ok );
} }
#define x264_frame_sort_dts(list) x264_frame_sort(list, 1)
#define x264_frame_sort_pts(list) x264_frame_sort(list, 0)
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_slice_type )
{ {
int i; int i;
int b_ok; int b_ok;
...@@ -607,7 +650,7 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc ) ...@@ -607,7 +650,7 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
/* build ref list 0/1 */ /* build ref list 0/1 */
h->i_ref0 = 0; h->i_ref0 = 0;
h->i_ref1 = 0; h->i_ref1 = 0;
for( i = 1; i < h->param.i_frame_reference+2; i++ ) for( i = 1; i < h->frames.i_max_dpb; i++ )
{ {
if( h->frames.reference[i]->i_poc >= 0 ) if( h->frames.reference[i]->i_poc >= 0 )
{ {
...@@ -621,6 +664,7 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc ) ...@@ -621,6 +664,7 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
} }
} }
} }
/* Order ref0 from higher to lower poc */ /* Order ref0 from higher to lower poc */
do do
{ {
...@@ -656,14 +700,22 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc ) ...@@ -656,14 +700,22 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
} }
} while( !b_ok ); } while( !b_ok );
if( h->i_ref0 > h->param.i_frame_reference )