rendered paste bodydiff --git a/common/bs.h b/common/bs.h
index cf4befb..1668eb3 100644
--- a/common/bs.h
+++ b/common/bs.h
@@ -169,6 +169,13 @@ static inline void bs_align_1( bs_t *s )
bs_flush( s );
}
+static inline void bs_align_10( bs_t *s )
+{
+ if( s->i_left&7 )
+ bs_write1( s, 1 );
+ bs_flush( s );
+}
+
/* golomb functions */
static const uint8_t x264_ue_size_tab[256] =
diff --git a/common/common.c b/common/common.c
index d7d45d3..d0e0b1c 100644
--- a/common/common.c
+++ b/common/common.c
@@ -141,6 +141,8 @@ void x264_param_default( x264_param_t *param )
param->b_repeat_headers = 1;
param->b_aud = 0;
+ param->b_nal_hrd = 0;
+ param->i_pulldown = 0;
}
static int parse_enum( const char *arg, const char * const *names, int *dst )
@@ -368,7 +370,23 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
OPT("cabac-idc")
p->i_cabac_init_idc = atoi(value);
OPT("interlaced")
+ {
+ p->b_interlaced = atobool(value);
+ p->b_nal_hrd = atobool(value); // this is only a bool
+ p->b_tff = 1;
+ }
+ OPT("tff")
+ {
p->b_interlaced = atobool(value);
+ p->b_nal_hrd = atobool(value); // this is only a bool
+ p->b_tff = 1;
+ }
+ OPT("bff")
+ {
+ p->b_interlaced = atobool(value);
+ p->b_nal_hrd = atobool(value); // this is only a bool
+ p->b_tff = 0;
+ }
OPT("cqm")
{
if( strstr( value, "flat" ) )
@@ -567,6 +585,10 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
p->analyse.b_ssim = atobool(value);
OPT("aud")
p->b_aud = atobool(value);
+ OPT2("pulldown","pd")
+ p->i_pulldown = atoi(value);
+ OPT("nal-hrd")
+ p->b_nal_hrd = atobool(value);
OPT("sps-id")
p->i_sps_id = atoi(value);
OPT("global-header")
diff --git a/common/common.h b/common/common.h
index 5d1123c..ddf5ff3 100644
--- a/common/common.h
+++ b/common/common.h
@@ -279,6 +279,13 @@ struct x264_t
int i_poc_msb; /* decoding only */
int i_poc_lsb; /* decoding only */
int i_poc; /* decoding only */
+ int i_dframe;
+ int i_cpb_delay; /* Equal to number of fields preceding this field
+ * since last buffering_period SEI */
+ int64_t i_dts_last_key;
+ int64_t i_prev_dts_dur;
+ int64_t i_prev_dts;
+ int i_pic_struct_prev;
int i_thread_num; /* threads only */
int i_nal_type; /* threads only */
diff --git a/common/frame.c b/common/frame.c
index cc4b1b3..e74443f 100644
--- a/common/frame.c
+++ b/common/frame.c
@@ -109,6 +109,7 @@ x264_frame_t *x264_frame_new( x264_t *h )
frame->i_type = X264_TYPE_AUTO;
frame->i_qpplus1 = 0;
frame->i_pts = -1;
+ frame->i_dts = 0;
frame->i_frame = -1;
frame->i_frame_num = -1;
frame->i_lines_completed = -1;
diff --git a/common/frame.h b/common/frame.h
index aad77f5..f0cba3f 100644
--- a/common/frame.h
+++ b/common/frame.h
@@ -31,9 +31,10 @@
typedef struct
{
/* */
- int i_poc;
+ int i_poc;
int i_type;
- int i_qpplus1;
+ int i_qpplus1;
+ int64_t i_dts;
int64_t i_pts;
int i_frame; /* Presentation frame number */
int i_frame_num; /* Coded frame number */
diff --git a/common/set.h b/common/set.h
index e1b9cd9..ac56295 100644
--- a/common/set.h
+++ b/common/set.h
@@ -125,6 +125,20 @@ typedef struct
int i_num_reorder_frames;
int i_max_dec_frame_buffering;
+ int b_nal_hrd_parameters_present;
+ int i_pulldown_type;
+ int b_pic_struct_present_flag;
+ struct
+ {
+ int i_bit_rate;
+ int i_cpb_size;
+ int b_cbr;
+
+ int i_initial_cpb_removal_delay_length;
+ int i_cpb_removal_delay_length;
+ int i_dpb_output_delay_length;
+ } nal_hrd_parameters;
+
/* FIXME to complete */
} vui;
diff --git a/encoder/encoder.c b/encoder/encoder.c
index 8361369..0d08df3 100644
--- a/encoder/encoder.c
+++ b/encoder/encoder.c
@@ -383,6 +383,31 @@ static int x264_validate_parameters( x264_t *h )
}
}
+ if( h->param.b_nal_hrd )
+ {
+ if( h->param.rc.i_vbv_max_bitrate == 0 || h->param.rc.i_vbv_buffer_size == 0 )
+ {
+ x264_log( h, X264_LOG_WARNING, "NAL HRD parameters require VBV max bitrate and buffer size to be specified\n" );
+ h->param.b_nal_hrd = 0;
+ }
+ }
+
+ if( h->param.i_pulldown > 0 ) // 32 or 64
+ {
+ if( h->param.b_nal_hrd == 0 )
+ {
+ x264_log( h, X264_LOG_WARNING, "pulldown requires NAL HRD parameters setting\n" );
+ h->param.i_pulldown = 0;
+ }
+ else {
+ if( h->param.i_pulldown != 32 && h->param.i_pulldown != 64 )
+ {
+ x264_log( h, X264_LOG_WARNING, "32/64 only acceptable values for --pulldown. Forcing to 32 (3:2)" );
+ h->param.i_pulldown = 32;
+ }
+ }
+ }
+
if( h->param.rc.i_rc_method < 0 || h->param.rc.i_rc_method > 2 )
{
x264_log( h, X264_LOG_ERROR, "no ratecontrol method specified\n" );
@@ -677,6 +702,9 @@ x264_t *x264_encoder_open ( x264_param_t *param )
h->i_frame = 0;
h->i_frame_num = 0;
h->i_idr_pic_id = 0;
+ h->i_cpb_delay = 0;
+ h->i_dts_last_key = 0;
+ h->i_dframe = -1;
h->sps = &h->sps_array[0];
x264_sps_init( h->sps, h->param.i_sps_id, &h->param );
@@ -880,11 +908,6 @@ int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal )
/* Put SPS and PPS */
if( h->i_frame == 0 )
{
- /* identify ourself */
- x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
- x264_sei_version_write( h, &h->out.bs );
- x264_nal_end( h );
-
/* generate sequence parameters */
x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST );
x264_sps_write( &h->out.bs, h->sps );
@@ -894,6 +917,11 @@ int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal )
x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );
x264_pps_write( &h->out.bs, h->pps );
x264_nal_end( h );
+
+ /* identify ourself */
+ x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+ x264_sei_version_write( h, &h->out.bs );
+ x264_nal_end( h );
}
/* now set output*/
*pi_nal = h->out.i_nal;
@@ -1358,11 +1386,16 @@ int x264_encoder_encode( x264_t *h,
x264_picture_t *pic_in,
x264_picture_t *pic_out )
{
+
+ static const int tbt_pattern[] = { 5, 4, 6, 3 };
x264_t *thread_current, *thread_prev, *thread_oldest;
int i_nal_type;
int i_nal_ref_idc;
- int i_global_qp;
+ int i_global_qp;
+ int cpb_removal_delay;
+ int64_t i_ptsoffset = 0;
+ int64_t i_ptsreferenceoffset = 0;
if( h->param.i_threads > 1)
{
@@ -1461,7 +1494,7 @@ int x264_encoder_encode( x264_t *h,
pic_out->i_type = X264_TYPE_AUTO;
return 0;
}
-
+
if( h->fenc->i_type == X264_TYPE_IDR )
{
h->frames.i_last_idr = h->fenc->i_frame;
@@ -1477,6 +1510,7 @@ int x264_encoder_encode( x264_t *h,
i_nal_type = NAL_SLICE_IDR;
i_nal_ref_idc = NAL_PRIORITY_HIGHEST;
h->sh.i_type = SLICE_TYPE_I;
+
}
else if( h->fenc->i_type == X264_TYPE_I )
{
@@ -1509,8 +1543,18 @@ int x264_encoder_encode( x264_t *h,
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 && h->param.i_keyint_max > 1;
-
-
+ h->i_dframe++;
+ if( !h->sps->vui.i_pulldown_type ) {
+ i_ptsreferenceoffset = h->sps->vui.i_num_units_in_tick * (h->param.i_bframe ? ( h->param.b_bframe_pyramid ? 4 : 2 ) : 0 ) ;
+ }
+ else {
+ i_ptsreferenceoffset = h->sps->vui.i_num_reorder_frames * ( h->sps->vui.i_num_units_in_tick * 3 );
+ i_ptsoffset = ( ((h->fenc->i_frame)&1) ? (h->sps->vui.i_num_units_in_tick*((h->fenc->i_frame/2)+1)) :
+ (h->sps->vui.i_num_units_in_tick*((int64_t)(h->fenc->i_frame/2))) ) ;
+ } // pulldown > 0
+ h->fdec->i_dts = h->i_prev_dts + h->i_prev_dts_dur;
+ h->i_prev_dts = h->fdec->i_dts;
+ h->i_prev_dts_dur = h->sps->vui.i_num_units_in_tick * ( ((h->fenc->i_frame)&1) ? 2 : ( h->sps->vui.i_pulldown_type ? 3 : 2 ) );
/* ------------------- Init ----------------------------- */
/* build ref list 0/1 */
@@ -1561,14 +1605,6 @@ int x264_encoder_encode( x264_t *h,
/* Write SPS and PPS */
if( i_nal_type == NAL_SLICE_IDR && h->param.b_repeat_headers )
{
- if( h->fenc->i_frame == 0 )
- {
- /* identify ourself */
- x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
- x264_sei_version_write( h, &h->out.bs );
- x264_nal_end( h );
- }
-
/* generate sequence parameters */
x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST );
x264_sps_write( &h->out.bs, h->sps );
@@ -1578,6 +1614,70 @@ int x264_encoder_encode( x264_t *h,
x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );
x264_pps_write( &h->out.bs, h->pps );
x264_nal_end( h );
+
+ if( h->fenc->i_frame == 0 )
+ {
+ if( !h->param.b_nal_hrd ) { // only write here if !nal-hrd , else right in buffperiod nal
+ /* identify ourself */
+ x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+ x264_sei_version_write( h, &h->out.bs );
+ bs_rbsp_trailing(&h->out.bs);
+ x264_nal_end( h );
+ }
+ }
+ }
+
+ if( h->param.b_nal_hrd )
+ {
+ int dpb_output_delay, pic_struct;
+ pic_struct = 0;
+
+ x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+
+ // write bp sei then close and reopen nal to create separate nal from pt sei
+ if( i_nal_type == NAL_SLICE_IDR ) {
+ x264_sei_buffering_period_write( h, &h->param, &h->out.bs, h->sps );
+ if( h->fenc->i_frame == 0 ) // write identifying data after bp in same nal
+ {
+ /* identify ourself */
+ x264_sei_version_write( h, &h->out.bs );
+ bs_rbsp_trailing(&h->out.bs);
+ }
+ else bs_rbsp_trailing(&h->out.bs);
+ x264_nal_end( h );
+ x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+ }
+
+ // NEW CALC
+ if( !h->sh.b_field_pic ) {
+ //pic_struct
+ if( !h->param.b_interlaced ) {
+ if( h->sps->vui.i_pulldown_type == 32 )
+ pic_struct = tbt_pattern[(h->fenc->i_frame) & 3];
+ else if( h->sps->vui.i_pulldown_type == 64 )
+ pic_struct = (h->fenc->i_frame & 1) ? 7 : 8;
+ }
+ else {
+ // tff = 3, bff = 4
+ pic_struct = h->param.b_tff ? 3 : 4;
+ }
+ dpb_output_delay = (int)( h->fenc->i_pts*2 + i_ptsoffset + i_ptsreferenceoffset -
+ ( h->fdec->i_dts ) ) / h->sps->vui.i_num_units_in_tick ;
+ cpb_removal_delay = (h->fdec->i_dts - h->i_dts_last_key) / h->sps->vui.i_num_units_in_tick ;
+ if( h->sps->vui.i_pulldown_type == 64 ) {
+ cpb_removal_delay *= 2;
+ dpb_output_delay *=2;
+ }
+ x264_sei_picture_timing_write( &h->out.bs, h->sps, cpb_removal_delay, dpb_output_delay, pic_struct);
+ bs_rbsp_trailing(&h->out.bs);
+ cpb_removal_delay = h->i_cpb_delay;
+ if( i_nal_type == NAL_SLICE_IDR ) {
+ cpb_removal_delay = 0;
+ h->i_dts_last_key = h->fdec->i_dts ;
+ }
+ }
+ //bs_rbsp_trailing(&h->out.bs);
+ x264_nal_end( h );
}
/* Write frame */
@@ -1588,7 +1688,7 @@ int x264_encoder_encode( x264_t *h,
}
else
x264_slices_write( h );
-
+ h->i_cpb_delay = cpb_removal_delay;
x264_encoder_frame_end( thread_oldest, thread_current, pp_nal, pi_nal, pic_out );
return 0;
}
diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c
index 2dd34d0..effb193 100644
--- a/encoder/ratecontrol.c
+++ b/encoder/ratecontrol.c
@@ -1277,10 +1277,11 @@ static void update_vbv( x264_t *h, int bits )
if( !rcc->b_vbv )
return;
- rct->buffer_fill_final += rct->buffer_rate - bits;
+ rct->buffer_fill_final += rct->buffer_rate - bits;
if( rct->buffer_fill_final < 0 )
x264_log( h, X264_LOG_WARNING, "VBV underflow (%.0f bits)\n", rct->buffer_fill_final );
rct->buffer_fill_final = x264_clip3f( rct->buffer_fill_final, 0, rct->buffer_size );
+ h->param.rc.i_buffer_fill_final = x264_clip3f( rct->buffer_fill_final, 0, rct->buffer_size - 1000 );
}
// provisionally update VBV according to the planned size of all frames currently in progress
diff --git a/encoder/set.c b/encoder/set.c
index 552df80..b76e96e 100644
--- a/encoder/set.c
+++ b/encoder/set.c
@@ -208,6 +208,54 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
sps->vui.i_log2_max_mv_length_horizontal =
sps->vui.i_log2_max_mv_length_vertical = (int)(log(param->analyse.i_mv_range*4-1)/log(2)) + 1;
}
+
+ sps->vui.b_nal_hrd_parameters_present = param->b_nal_hrd;
+ if( sps->vui.b_nal_hrd_parameters_present )
+ {
+
+ int cpbBrVclFactor = 1000;
+ //int cpbBrNalFactor = 1000;
+
+
+ sps->vui.nal_hrd_parameters.i_bit_rate = param->rc.i_vbv_max_bitrate * cpbBrVclFactor;
+ sps->vui.nal_hrd_parameters.i_cpb_size = param->rc.i_vbv_buffer_size * cpbBrVclFactor;
+
+ sps->vui.nal_hrd_parameters.i_initial_cpb_removal_delay_length = 0;
+ while( (1 << ++sps->vui.nal_hrd_parameters.i_initial_cpb_removal_delay_length) <
+ (param->rc.i_vbv_buffer_size * 90000.0 / param->rc.i_vbv_max_bitrate) );
+ /*FIX ME*/sps->vui.nal_hrd_parameters.i_initial_cpb_removal_delay_length = 32;
+
+ sps->vui.nal_hrd_parameters.i_cpb_removal_delay_length = 0;
+ while( (1 << ++sps->vui.nal_hrd_parameters.i_cpb_removal_delay_length) <
+ (param->i_keyint_max * 8) ); //amped up to *3 for higher cpb values
+ /*FIX ME*/ //if( sps->vui.nal_hrd_parameters.i_cpb_removal_delay_length > 22 )
+ sps->vui.nal_hrd_parameters.i_cpb_removal_delay_length = 22;
+
+
+ sps->vui.nal_hrd_parameters.i_dpb_output_delay_length = 0;
+ while( (1 << ++sps->vui.nal_hrd_parameters.i_dpb_output_delay_length) <
+ ((sps->vui.i_num_reorder_frames + sps->i_num_ref_frames) * 8) ); //amped up to *3 for higher dpb values
+ /*FIX ME*///if( sps->vui.nal_hrd_parameters.i_dpb_output_delay_length > 22 )
+ sps->vui.nal_hrd_parameters.i_dpb_output_delay_length = 22;
+}
+
+ sps->vui.b_pic_struct_present_flag = 0;
+ sps->vui.i_pulldown_type = param->i_pulldown;
+ if( !param->b_interlaced ) {
+ if( sps->vui.i_pulldown_type > 0 ) {
+ if( sps->vui.b_nal_hrd_parameters_present ) { // pulldown and hrd go together
+ sps->vui.b_pic_struct_present_flag = 1;
+ sps->vui.i_num_units_in_tick = 1001;
+ if( sps->vui.i_pulldown_type == 64 ) sps->vui.i_time_scale = 60000*2;
+ else sps->vui.i_time_scale = 30000*2;
+ }
+ }
+ }
+ else {
+ if( sps->vui.b_nal_hrd_parameters_present ) {
+ sps->vui.b_pic_struct_present_flag = 1;
+ }
+ }
}
@@ -345,9 +393,45 @@ void x264_sps_write( bs_t *s, x264_sps_t *sps )
bs_write1( s, sps->vui.b_fixed_frame_rate );
}
- bs_write1( s, 0 ); /* nal_hrd_parameters_present_flag */
+ bs_write1( s, sps->vui.b_nal_hrd_parameters_present );
+ if( sps->vui.b_nal_hrd_parameters_present )
+ {
+ int bit_rate_scale = 0, cpb_size_scale = 0;
+ unsigned int bit_rate_tmp, cpb_size_tmp;
+
+ bs_write_ue( s, 0 ); /* cpb_cnt_minus1 */
+
+ bit_rate_tmp = ( sps->vui.nal_hrd_parameters.i_bit_rate + (1 << 5) ) >> 6;
+ while( ( bit_rate_tmp & 1) == 0 )
+ {
+ bit_rate_tmp >>= 1;
+ bit_rate_scale++;
+ if (bit_rate_scale == 15)
+ break;
+ }
+ cpb_size_tmp = ( sps->vui.nal_hrd_parameters.i_cpb_size + (1 << 3) ) >> 4;
+ while( ( cpb_size_tmp & 1) == 0 )
+ {
+ cpb_size_tmp >>= 1;
+ cpb_size_scale++;
+ if (cpb_size_scale == 15)
+ break;
+ }
+ bs_write( s, 4, bit_rate_scale );
+ bs_write( s, 4, cpb_size_scale );
+ bs_write_ue_big( s, bit_rate_tmp - 1 );
+ bs_write_ue_big( s, cpb_size_tmp - 1 );
+ bs_write1( s, 0 );
+ bs_write( s, 5, sps->vui.nal_hrd_parameters.i_initial_cpb_removal_delay_length - 1 );
+ bs_write( s, 5, sps->vui.nal_hrd_parameters.i_cpb_removal_delay_length - 1 );
+ bs_write( s, 5, sps->vui.nal_hrd_parameters.i_dpb_output_delay_length - 1 );
+ bs_write( s, 5, 24 ); // time_offset_length
+ }
+
bs_write1( s, 0 ); /* vcl_hrd_parameters_present_flag */
- bs_write1( s, 0 ); /* pic_struct_present_flag */
+ if( sps->vui.b_nal_hrd_parameters_present ) /* or VCL HRD */
+ bs_write1( s, 0); /* low_delay_hrd_flag */
+ bs_write1( s, sps->vui.b_pic_struct_present_flag ); /* pic_struct_present_flag */
bs_write1( s, sps->vui.b_bitstream_restriction );
if( sps->vui.b_bitstream_restriction )
{
@@ -498,12 +582,84 @@ void x264_sei_version_write( x264_t *h, bs_t *s )
for( i = 0; i < length-16; i++ )
bs_write( s, 8, version[i] );
- bs_rbsp_trailing( s );
+ bs_align_10( s ); // does nothing here.. but dangit it belongs
x264_free( opts );
x264_free( version );
}
+void x264_sei_buffering_period_write( x264_t *h, x264_param_t *param, bs_t *s, x264_sps_t *sps )
+{
+ int payload_size;
+
+ bs_write( s, 8, 0x0 ); // payload_type = buffering_period
+ payload_size = bs_size_ue( sps->i_id );
+ if( sps->vui.b_nal_hrd_parameters_present )
+ payload_size += sps->vui.nal_hrd_parameters.i_initial_cpb_removal_delay_length * 2;
+
+ bs_write( s, 8, (payload_size + 7) / 8);
+ bs_write_ue( s, sps->i_id );
+
+ if ( sps->vui.b_nal_hrd_parameters_present )
+ {
+ /* NOTE: This should be a loop for each CPB, but we currently only support one */
+
+ double buffer_rate = param->rc.i_vbv_max_bitrate;
+ double buffer_size = param->rc.i_vbv_buffer_size;
+ double buffer_fill_final;
+ if( h->param.rc.i_buffer_fill_final > 0 )
+ buffer_fill_final = h->param.rc.i_buffer_fill_final / 1000;
+ else
+ buffer_fill_final = buffer_size * param->rc.f_vbv_buffer_init;
+ bs_write( s, sps->vui.nal_hrd_parameters.i_initial_cpb_removal_delay_length,
+ buffer_fill_final * 90000. / ( buffer_rate ) );
+ bs_write( s, sps->vui.nal_hrd_parameters.i_initial_cpb_removal_delay_length,
+ ( buffer_size - buffer_fill_final ) * 90000. / ( buffer_rate ) );
+ }
+
+ /* VCL HRD parameters should go here */
+ //bs_rbsp_trailing( s );
+ bs_align_10( s );
+}
+
+void x264_sei_picture_timing_write( bs_t *s, x264_sps_t *sps, int cpb_removal_delay, int dpb_output_delay, int pic_struct )
+{
+ int payload_size;
+
+ static const int num_clockts[] = { 1, 1, 1, 2, 2, 3, 3, 2, 3 };
+ bs_write( s, 8, 0x1 ); // payload_type = pic_timing
+
+ payload_size = 0;
+ if( sps->vui.b_nal_hrd_parameters_present ) {
+ payload_size += sps->vui.nal_hrd_parameters.i_cpb_removal_delay_length
+ + sps->vui.nal_hrd_parameters.i_dpb_output_delay_length;
+ if( sps->vui.b_pic_struct_present_flag ) {
+ payload_size += 4;
+ payload_size += num_clockts[pic_struct]; // pad #num_clockts bytes for 0 (no time code)
+ }
+ }
+
+ bs_write( s, 8, (payload_size + 7) / 8);
+
+ if( sps->vui.b_nal_hrd_parameters_present )
+ {
+ /* NOTE: This should be a loop for each CPB, but we currently only support one */
+
+ bs_write( s, sps->vui.nal_hrd_parameters.i_cpb_removal_delay_length,
+ cpb_removal_delay);
+ bs_write( s, sps->vui.nal_hrd_parameters.i_dpb_output_delay_length,
+ dpb_output_delay);
+ if( sps->vui.b_pic_struct_present_flag ) {
+ bs_write( s, 4, pic_struct );
+ bs_write( s, num_clockts[ pic_struct ], 0 );
+ }
+ }
+
+ /* VCL HRD parameters should go here */
+ //bs_rbsp_trailing( s );
+ bs_align_10( s );
+}
+
const x264_level_t x264_levels[] =
{
{ 10, 1485, 99, 152064, 64, 175, 64, 64, 0, 0, 0, 1 },
diff --git a/encoder/set.h b/encoder/set.h
index 3611c9a..767acbc 100644
--- a/encoder/set.h
+++ b/encoder/set.h
@@ -29,6 +29,8 @@ void x264_sps_write( bs_t *s, x264_sps_t *sps );
void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t *sps );
void x264_pps_write( bs_t *s, x264_pps_t *pps );
void x264_sei_version_write( x264_t *h, bs_t *s );
+void x264_sei_buffering_period_write( x264_t *h, x264_param_t *param, bs_t *s, x264_sps_t *sps );
+void x264_sei_picture_timing_write( bs_t *s, x264_sps_t *sps, int cpb_removal_delay, int dpb_output_delay, int pic_struct );
int x264_validate_levels( x264_t *h, int verbose );
#endif
diff --git a/x264.c b/x264.c
index 9aafc35..0df9f0e 100644
--- a/x264.c
+++ b/x264.c
@@ -180,7 +180,9 @@ static void Help( x264_param_t *defaults, int b_longhelp )
H1( " --no-deblock Disable loop filter\n" );
H0( " -f, --deblock <alpha:beta> Loop filter AlphaC0 and Beta parameters [%d:%d]\n",
defaults->i_deblocking_filter_alphac0, defaults->i_deblocking_filter_beta );
- H0( " --interlaced Enable pure-interlaced mode\n" );
+ H0( " --interlaced Enable pure-interlaced mode (tff)\n" );
+ H0( " --tff Alias for --interlaced\n" );
+ H0( " --bff Enable pure-interlaced mode (bff)\n" );
H0( "\n" );
H0( "Ratecontrol:\n" );
H0( "\n" );
@@ -336,6 +338,10 @@ static void Help( x264_param_t *defaults, int b_longhelp )
H1( " --dump-yuv <string> Save reconstructed frames\n" );
H1( " --sps-id <integer> Set SPS and PPS id numbers [%d]\n", defaults->i_sps_id );
H1( " --aud Use access unit delimiters\n" );
+ H1( " --nal-hrd Use NAL HRD parameters\n" );
+ H1( " --pulldown <integer> Use 3:2 pulldown\n"
+ " - 32: TBT,BT,BTB,TB pattern\n"
+ " - 64: triple,double *recommended for 720p\n" );
H0( "\n" );
}
@@ -402,6 +408,8 @@ static int Parse( int argc, char **argv,
{ "filter", required_argument, NULL, 0 },
{ "deblock", required_argument, NULL, 'f' },
{ "interlaced", no_argument, NULL, 0 },
+ { "tff", no_argument, NULL, 0 },
+ { "bff", no_argument, NULL, 0 },
{ "no-cabac",no_argument, NULL, 0 },
{ "qp", required_argument, NULL, 'q' },
{ "qpmin", required_argument, NULL, 0 },
@@ -463,6 +471,9 @@ static int Parse( int argc, char **argv,
{ "dump-yuv",required_argument, NULL, 0 },
{ "sps-id", required_argument, NULL, 0 },
{ "aud", no_argument, NULL, 0 },
+ { "nal-hrd", no_argument, NULL, 0 },
+ { "pulldown", required_argument,NULL, 0 },
+ { "pd", required_argument, NULL, 0 },
{ "nr", required_argument, NULL, 0 },
{ "cqm", required_argument, NULL, 0 },
{ "cqmfile", required_argument, NULL, 0 },
@@ -828,7 +839,10 @@ static int Encode( x264_param_t *param, cli_opt_t *opt )
if( p_read_frame( &pic, opt->hin, i_frame + opt->i_seek ) )
break;
- pic.i_pts = (int64_t)i_frame * param->i_fps_den;
+ //if( !h->sps->vui.i_pulldown_type )
+ pic.i_pts = (int64_t)i_frame * param->i_fps_den;
+ //else
+ // pic.i_pts = (int64_t)((double)i_frame * (double)param->i_fps_den * ((((i_frame)+1)&1) ? 1.5 : 1.0 ) );
if( opt->qpfile )
parse_qpfile( opt, &pic, i_frame + opt->i_seek );
diff --git a/x264.h b/x264.h
index 3971992..8eb0304 100644
--- a/x264.h
+++ b/x264.h
@@ -201,6 +201,7 @@ typedef struct x264_param_t
int i_cabac_init_idc;
int b_interlaced;
+ int b_tff;
int i_cqm_preset;
char *psz_cqm_file; /* JM format */
@@ -266,6 +267,7 @@ typedef struct x264_param_t
int i_vbv_max_bitrate;
int i_vbv_buffer_size;
float f_vbv_buffer_init; /* <=1: fraction of buffer_size. >1: kbit */
+ int64_t i_buffer_fill_final;
float f_ip_factor;
float f_pb_factor;
@@ -291,6 +293,8 @@ typedef struct x264_param_t
int b_aud; /* generate access unit delimiters */
int b_repeat_headers; /* put SPS/PPS before each keyframe */
int i_sps_id; /* SPS and PPS id number */
+ int b_nal_hrd; /* Add NAL HRD parameters to bitstream */
+ int i_pulldown; /* 3:2 pulldown */
} x264_param_t;
typedef struct {