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 )
/* Encoder parameters */
param->i_frame_reference = 1;
param->i_keyint_max = 250;
param->i_keyint_min = 100;
param->i_keyint_min = 25;
param->i_bframe = 0;
param->i_scenecut_threshold = 40;
param->b_bframe_adaptive = 1;
param->i_bframe_bias = 0;
param->b_bframe_pyramid = 0;
param->b_deblocking_filter = 1;
param->i_deblocking_filter_alphac0 = 0;
param->i_deblocking_filter_beta = 0;
param->b_cabac = 0;
param->b_cabac = 1;
param->i_cabac_init_idc = -1;
param->rc.b_cbr = 0;
......
......@@ -140,6 +140,13 @@ typedef struct
int i_num_ref_idx_l0_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_qp_delta;
......@@ -237,13 +244,16 @@ struct x264_t
/* For adaptive B decision */
x264_frame_t *last_nonb;
/* frames used for reference +1 for decoding */
x264_frame_t *reference[16+1];
/* frames used for reference +1 for decoding +1 sentinel */
x264_frame_t *reference[16+2+1+1];
int i_last_idr; /* Frame number of the last IDR */
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 */
} frames;
......@@ -258,6 +268,7 @@ struct x264_t
x264_frame_t *fref0[16]; /* ref list 0 */
int i_ref1;
x264_frame_t *fref1[16]; /* ref list 1 */
int b_ref_reorder[2];
......@@ -371,6 +382,9 @@ struct x264_t
/* B_direct and weighted prediction */
int dist_scale_factor[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;
/* rate control encoding only */
......
......@@ -91,7 +91,9 @@ x264_frame_t *x264_frame_new( x264_t *h )
frame->i_qpplus1 = 0;
frame->i_pts = -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->ref[0] = x264_malloc( 4 * i_mb_count * sizeof( int8_t ) );
if( h->param.i_bframe )
......@@ -119,6 +121,7 @@ void x264_frame_delete( x264_frame_t *frame )
{
x264_free( frame->buffer[i] );
}
x264_free( frame->mb_type );
x264_free( frame->mv[0] );
x264_free( frame->mv[1] );
x264_free( frame->ref[0] );
......
......@@ -32,6 +32,8 @@ typedef struct
int i_qpplus1;
int64_t i_pts;
int i_frame; /* Presentation frame number */
int i_frame_num; /* Coded frame number */
int b_kept_as_ref;
/* YUV buffer */
int i_plane;
......@@ -48,6 +50,7 @@ typedef struct
void *buffer[11];
/* motion data */
int8_t *mb_type;
int16_t (*mv[2])[2];
int8_t *ref[2];
int i_ref[2];
......
......@@ -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 );
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 */
for( i = 0; i < 4; i++ )
{
const int x8 = 2*(i%2);
const int y8 = 2*(i/2);
/* TODO: MapColToList0 */
const int i_ref = h->fref1[0]->ref[0][ i_mb_8x8 + x8/2 + y8 * h->mb.i_mb_stride ];
const int i_part_8x8 = 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 )
{
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
if( i_ref >= 0 )
{
const int dist_scale_factor = h->mb.dist_scale_factor[i_ref][0];
int x4, y4;
......@@ -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] );
}
}
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;
......@@ -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_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.cbp = x264_malloc( i_mb_count * sizeof( int16_t) );
h->mb.skipbp = x264_malloc( i_mb_count * sizeof( int8_t) );
......@@ -840,8 +847,11 @@ void x264_macroblock_cache_init( x264_t *h )
}
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 ) );
}
/* init with not avaiable (for top right idx=7,15) */
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 )
{
int i, j;
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] );
}
if( h->param.b_cabac )
{
x264_free( h->mb.chroma_pred_mode );
......@@ -864,16 +877,16 @@ void x264_macroblock_cache_end( x264_t *h )
x264_free( h->mb.skipbp );
x264_free( h->mb.cbp );
x264_free( h->mb.qp );
x264_free( h->mb.type );
}
void x264_macroblock_slice_init( x264_t *h )
{
int i;
int i, j;
h->mb.mv[0] = h->fdec->mv[0];
h->mb.mv[1] = h->fdec->mv[1];
h->mb.ref[0] = h->fdec->ref[0];
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[1] = h->i_ref1;
......@@ -883,6 +896,20 @@ void x264_macroblock_slice_init( x264_t *h )
{
for( i = 0; i < h->i_ref1; i++ )
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 )
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 */
/* 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;
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 )
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_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 */
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 )
continue;
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 );
}
......
......@@ -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 )
{
x264_param_t *param = &h->param;
int i;
/* First we fill all field */
sh->sps = sps;
......@@ -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_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_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,
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_type + 5 ); /* same type things */
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
/* ref pic list reordering */
if( sh->i_type != SLICE_TYPE_I )
{
int b_ref_pic_list_reordering_l0 = 0;
bs_write1( s, b_ref_pic_list_reordering_l0 );
if( b_ref_pic_list_reordering_l0 )
bs_write1( s, sh->b_ref_pic_list_reordering_l0 );
if( sh->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 )
{
int b_ref_pic_list_reordering_l1 = 0;
bs_write1( s, b_ref_pic_list_reordering_l1 );
if( b_ref_pic_list_reordering_l1 )
bs_write1( s, sh->b_ref_pic_list_reordering_l1 );
if( sh->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 )
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.b_bframe_pyramid = h->param.b_bframe_pyramid && 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_beta = x264_clip3( h->param.i_deblocking_filter_beta, -6, 6 );
......@@ -436,11 +472,11 @@ x264_t *x264_encoder_open ( x264_param_t *param )
{
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[h->frames.i_max_dpb] = NULL;
h->frames.i_last_idr = - h->param.i_keyint_max;
h->frames.i_input = 0;
......@@ -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 )
{
int i = 0;
while( list[i] != NULL ) i++;
while( list[i] ) i++;
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] )
{
x264_frame_t *frame = list[0];
int i;
for( i = 0; i < X264_BFRAME_MAX; i++ )
{
for( i = 0; i < X264_BFRAME_MAX && list[i]; i++ )
list[i] = list[i+1];
}
list[X264_BFRAME_MAX] = NULL;
return frame;
}
/* Sort queued frames into input order */
static void x264_frame_sort( x264_frame_t *list[X264_BFRAME_MAX+1] )
static void x264_frame_sort( x264_frame_t *list[X264_BFRAME_MAX+1], int b_dts )
{
int i, b_ok;
do {
b_ok = 1;
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];
list[i+1] = list[i];
......@@ -598,8 +639,10 @@ static void x264_frame_sort( x264_frame_t *list[X264_BFRAME_MAX+1] )
}
} 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 b_ok;
......@@ -607,7 +650,7 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
/* build ref list 0/1 */
h->i_ref0 = 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 )
{
......@@ -621,6 +664,7 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
}
}
}
/* Order ref0 from higher to lower poc */
do
{
......@@ -656,14 +700,22 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
}
} while( !b_ok );
if( h->i_ref0 > h->param.i_frame_reference )
{
h->i_ref0 = h->param.i_frame_reference;
}
if( h->i_ref1 > 1 )
/* In the standard, a P-frame's ref list is sorted by frame_num.
* We use POC, but check whether explicit reordering is needed */
h->b_ref_reorder[0] =
h->b_ref_reorder[1] = 0;
if( i_slice_type == SLICE_TYPE_P )
{
h->i_ref1 = 1;
for( i = 0; i < h->i_ref0 - 1; i++ )
if( h->fref0[i]->i_frame_num < h->fref0[i+1]->i_frame_num )
{
h->b_ref_reorder[0] = 1;
break;
}
}
h->i_ref0 = X264_MIN( h->i_ref0, h->frames.i_max_ref0 );
h->i_ref1 = X264_MIN( h->i_ref1, h->frames.i_max_ref1 );
}
static inline void x264_reference_update( x264_t *h )
......@@ -699,8 +751,9 @@ static inline void x264_reference_update( x264_t *h )
h->frames.last_nonb = h->fdec;
/* move frame in the buffer */
h->fdec = h->frames.reference[h->param.i_frame_reference+1];
for( i = h->param.i_frame_reference+1; i > 0; i-- )
/* FIXME: override to forget earliest pts, not earliest dts */
h->fdec = h->frames.reference[h->frames.i_max_dpb-1];
for( i = h->frames.i_max_dpb-1; i > 0; i-- )
{
h->frames.reference[i] = h->frames.reference[i-1];
}
......@@ -712,7 +765,7 @@ static inline void x264_reference_reset( x264_t *h )
int i;
/* reset ref pictures */
for( i = 1; i < h->param.i_frame_reference+2; i++ )
for( i = 1; i < h->frames.i_max_dpb; i++ )
{
h->frames.reference[i]->i_poc = -1;
}
......@@ -739,6 +792,8 @@ static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_slice_type,
h->sh.i_num_ref_idx_l1_active = h->i_ref1 <= 0 ? 1 : h->i_ref1;
}
h->fdec->i_frame_num = h->sh.i_frame_num;
if( h->sps->i_poc_type == 0 )
{
h->sh.i_poc_lsb = h->fdec->i_poc & ( (1 << h->sps->i_log2_max_poc_lsb) - 1 );
......@@ -982,12 +1037,19 @@ int x264_encoder_encode( x264_t *h,
x264_slicetype_decide( h );
/* 3: move some B-frames and 1 non-B to encode queue */
while( h->frames.next[bframes]->i_type == X264_TYPE_B )
while( IS_X264_TYPE_B( h->frames.next[bframes]->i_type ) )
bframes++;
x264_frame_put( h->frames.current, h->frames.next[bframes] );
x264_frame_put( h->frames.current, x264_frame_get( &h->frames.next[bframes] ) );
/* FIXME: when max B-frames > 3, BREF may no longer be centered after GOP closing */
if( h->param.b_bframe_pyramid && bframes > 1 )
{
x264_frame_t *mid = x264_frame_get( &h->frames.next[bframes/2] );
mid->i_type = X264_TYPE_BREF;
x264_frame_put( h->frames.current, mid );
bframes--;
}
while( bframes-- )
x264_frame_put( h->frames.current, x264_frame_get( h->frames.next ) );
x264_frame_get( h->frames.next );
}
TIMER_STOP( i_mtime_encode_frame );
......@@ -1033,6 +1095,12 @@ do_encode:
i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/
i_slice_type = SLICE_TYPE_P;
}
else if( h->fenc->i_type == X264_TYPE_BREF )
{
i_nal_type = NAL_SLICE;
i_nal_ref_idc = NAL_PRIORITY_HIGH; /* maybe add MMCO to forget it? -> low */
i_slice_type = SLICE_TYPE_B;
}
else /* B frame */
{
i_nal_type = NAL_SLICE;
......@@ -1043,6 +1111,8 @@ do_encode:
h->fdec->i_type = h->fenc->i_type;
h->fdec->i_poc = h->fenc->i_poc;
h->fdec->i_frame = h->fenc->i_frame;
h->fenc->b_kept_as_ref =
h->fdec->b_kept_as_ref = i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE;
......@@ -1054,7 +1124,7 @@ do_encode:
h->fdec->i_qpplus1 = i_global_qp + 1;
/* build ref list 0/1 */
x264_reference_build_list( h, h->fdec->i_poc );
x264_reference_build_list( h, h->fdec->i_poc, i_slice_type );
if( i_slice_type == SLICE_TYPE_B )
x264_macroblock_bipred_init( h );
......@@ -1101,7 +1171,6 @@ do_encode:
/* restore CPU state (before using float again) */
x264_cpu_restore( h->param.cpu );
/* XXX: this scene cut won't work with B frame (it may never create IDR -> bad) */
if( i_slice_type == SLICE_TYPE_P && !h->param.rc.b_stat_read
&& h->param.i_scenecut_threshold >= 0 )
{
......@@ -1150,6 +1219,7 @@ do_encode:
h->out.nal[h->out.i_nal-1].i_payload > 2 * h->i_last_inter_size &&
h->frames.i_last_i > 4)*/
{
int b;
x264_log( h, X264_LOG_DEBUG, "scene cut at %d size=%d Icost:%.0f Pcost:%.0f ratio:%.3f bias=%.3f lastIDR:%d (I:%d P:%d Skip:%d)\n",
h->fenc->i_frame,
......@@ -1162,8 +1232,8 @@ do_encode:
/* Restore frame num */
h->i_frame_num--;
for( i = 0; h->frames.current[i] && h->frames.current[i]->i_type == X264_TYPE_B; i++ );
if( i > 0 )
for( b = 0; h->frames.current[b] && IS_X264_TYPE_B( h->frames.current[b]->i_type ); b++ );
if( b > 0 )
{
/* If using B-frames, force GOP to be closed.
* Even if this frame is going to be I and not IDR, forcing a
......@@ -1173,10 +1243,14 @@ do_encode:
* we can't assign an I-frame. Instead, change the previous
* B-frame to P, and rearrange coding order. */
x264_frame_t *tmp = h->frames.current[i-1];
h->frames.current[i-1] = h->fenc;
h->fenc = tmp;
if( h->param.b_bframe_adaptive || b > 1 )
h->fenc->i_type = X264_TYPE_AUTO;
x264_frame_sort_pts( h->frames.current );
x264_frame_push( h->frames.next, h->fenc );
h->fenc = h->frames.current[b-1];
h->frames.current[b-1] = NULL;
h->fenc->i_type = X264_TYPE_P;
x264_frame_sort_dts( h->frames.current );
}
/* Do IDR if needed */
else if( i_gop_size >= h->param.i_keyint_min )
......@@ -1197,7 +1271,7 @@ do_encode:
/* Put enqueued frames back in the pool */
while( (tmp = x264_frame_get( h->frames.current ) ) != NULL )
x264_frame_put( h->frames.next, tmp );
x264_frame_sort( h->frames.next );
x264_frame_sort_pts( h->frames.next );
}
else
{
......@@ -1465,7 +1539,7 @@ void x264_encoder_close ( x264_t *h )
if( h->frames.unused[i] ) x264_frame_delete( h->frames.unused[i] );
}
/* ref frames */
for( i = 0; i < h->param.i_frame_reference+2; i++ )
for( i = 0; i < h->frames.i_max_dpb; i++ )
{
x264_frame_delete( h->frames.reference[i] );
}
......
......@@ -53,7 +53,7 @@
typedef struct
{
int pict_type;
int idr;
int kept_as_ref;
float qscale;
int mv_bits;
int i_tex_bits;
......@@ -313,10 +313,11 @@ int x264_ratecontrol_new( x264_t *h )
&rce->mv_bits, &rce->misc_bits, &rce->i_count, &rce->p_count, &rce->s_count);
switch(pict_type){
case 'I': rce->idr = 1;
case 'I': rce->kept_as_ref = 1;
case 'i': rce->pict_type = SLICE_TYPE_I; break;
case 'P': rce->pict_type = SLICE_TYPE_P; break;
case 'B': rce->pict_type = SLICE_TYPE_B; break;
case 'B': rce->kept_as_ref = 1;
case 'b': rce->pict_type = SLICE_TYPE_B; break;
default: e = -1; break;
}
if(e != 10){
......@@ -392,8 +393,12 @@ void x264_ratecontrol_start( x264_t *h, int i_slice_type )
if( !h->param.rc.b_cbr )
{
rc->qpm = rc->qpa = rc->qp =
rc->qp_constant[ i_slice_type ];
int q;
if( i_slice_type == SLICE_TYPE_B && h->fdec->b_kept_as_ref )
q = ( rc->qp_constant[ SLICE_TYPE_B ] + rc->qp_constant[ SLICE_TYPE_P ] ) / 2;
else
q = rc->qp_constant[ i_slice_type ];
rc->qpm = rc->qpa = rc->qp = q;
return;
}
else if( h->param.rc.b_stat_read )
......@@ -579,10 +584,10 @@ int x264_ratecontrol_slice_type( x264_t *h, int frame_num )
switch( h->rc->entry[frame_num].pict_type )
{
case SLICE_TYPE_I:
return h->rc->entry[frame_num].idr ? X264_TYPE_IDR : X264_TYPE_I;
return h->rc->entry[frame_num].kept_as_ref ? X264_TYPE_IDR : X264_TYPE_I;
case SLICE_TYPE_B:
return X264_TYPE_B;
return h->rc->entry[frame_num].kept_as_ref ? X264_TYPE_BREF : X264_TYPE_B;
case SLICE_TYPE_P:
default:
......@@ -610,7 +615,8 @@ void x264_ratecontrol_end( x264_t *h, int bits )
if( h->param.rc.b_stat_write )
{
char c_type = rc->slice_type==SLICE_TYPE_I ? (h->fenc->i_poc==0 ? 'I' : 'i')
: rc->slice_type==SLICE_TYPE_P ? 'P' : 'B';
: rc->slice_type==SLICE_TYPE_P ? 'P'
: h->fenc->b_kept_as_ref ? 'B' : 'b';
fprintf( rc->p_stat_file_out,
"in:%d out:%d type:%c q:%.3f itex:%d ptex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d;\n",
h->fenc->i_frame, h->i_frame-1,
......@@ -763,7 +769,8 @@ static double get_diff_limited_q(x264_t *h, ratecontrol_entry_t *rce, double q)
{
if( h->param.rc.f_pb_factor > 0 )
q = last_non_b_q;
q *= fabs( h->param.rc.f_pb_factor );
if( !rce->kept_as_ref )
q *= fabs( h->param.rc.f_pb_factor );
}
else if( pict_type == SLICE_TYPE_P
&& rcc->last_non_b_pict_type == SLICE_TYPE_P
......@@ -845,7 +852,10 @@ static float rate_estimate_qscale(x264_t *h, int pict_type)
if(rce->pict_type == SLICE_TYPE_B)
{
return rcc->last_qscale * h->param.rc.f_pb_factor;
if(rce->kept_as_ref)
return rcc->last_qscale * sqrtf(h->param.rc.f_pb_factor);
else
return rcc->last_qscale * h->param.rc.f_pb_factor;
}
else
{
......
......@@ -79,7 +79,9 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
sps->i_num_ref_frames = param->i_frame_reference;
if( param->i_bframe )
sps->i_num_ref_frames++; /* for 2 ref in B */
sps->i_num_ref_frames++; /* for backwards ref in B */
if( param->b_bframe_pyramid )
sps->i_num_ref_frames++; /* for 2nd backwards ref */
sps->b_gaps_in_frame_num_value_allowed = 0;
sps->i_mb_width = ( param->i_width + 15 ) / 16;
sps->i_mb_height= ( param->i_height + 15 )/ 16;
......
......@@ -377,31 +377,33 @@ void x264_slicetype_decide( x264_t *h )
}
if( frm->i_type == X264_TYPE_IDR )
{
h->i_poc = 0;
h->i_frame_num = 0;
/* Close GOP */
if( bframes > 0 )
{
bframes--;
h->frames.next[bframes]->i_type = X264_TYPE_P;
}
else
{