rendered paste bodydiff -uNrp a/common/bs.h b/common/bs.h--- a/common/bs.h 2009-07-07 21:27:03 +0300+++ b/common/bs.h 2009-08-09 20:15:34 +0300@@ -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 -uNrp a/common/common.c b/common/common.c--- a/common/common.c 2009-08-09 19:51:37 +0300+++ b/common/common.c 2009-08-09 20:15:34 +0300@@ -148,6 +148,8 @@ void x264_param_default( x264_param_t 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 )@@ -375,7 +377,23 @@ int x264_param_parse( x264_param_t *p, c 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" ) )@@ -580,6 +598,10 @@ int x264_param_parse( x264_param_t *p, c 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 -uNrp a/common/common.h b/common/common.h--- a/common/common.h 2009-08-09 19:51:37 +0300+++ b/common/common.h 2009-08-09 20:15:34 +0300@@ -333,7 +333,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 */ int i_nal_ref_idc; /* threads only */diff -uNrp a/common/frame.c b/common/frame.c--- a/common/frame.c 2009-08-09 19:51:37 +0300+++ b/common/frame.c 2009-08-09 20:15:34 +0300@@ -115,6 +115,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 -uNrp a/common/frame.h b/common/frame.h--- a/common/frame.h 2009-08-09 19:51:37 +0300+++ b/common/frame.h 2009-08-09 20:15:34 +0300@@ -34,6 +34,7 @@ typedef struct int i_poc; int i_type; 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 -uNrp a/common/set.h b/common/set.h--- a/common/set.h 2009-07-07 21:27:03 +0300+++ b/common/set.h 2009-08-09 20:15:34 +0300@@ -125,6 +125,18 @@ 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 -uNrp a/encoder/encoder.c b/encoder/encoder.c--- a/encoder/encoder.c 2009-08-09 19:51:37 +0300+++ b/encoder/encoder.c 2009-08-09 20:24:56 +0300@@ -409,6 +409,32 @@ static int x264_validate_parameters( x26 } } + 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" );@@ -728,6 +754,9 @@ x264_t *x264_encoder_open ( x264_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 );@@ -941,12 +970,6 @@ int x264_encoder_headers( x264_t *h, x26 /* Put SPS and PPS */ if( h->i_frame == 0 ) {- /* identify ourself */- x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );- if( x264_sei_version_write( h, &h->out.bs ) )- return -1;- x264_nal_end( h );- /* generate sequence parameters */ x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST ); x264_sps_write( &h->out.bs, h->sps );@@ -956,6 +979,12 @@ int x264_encoder_headers( x264_t *h, x26 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 );+ if( x264_sei_version_write( h, &h->out.bs ) )+ return -1;+ x264_nal_end( h ); } /* now set output*/ *pi_nal = h->out.i_nal;@@ -1407,7 +1436,7 @@ static void *x264_slices_write( x264_t * if( x264_stack_align( x264_slice_write, h ) ) return (void *)-1;- i_frame_size = h->out.nal[h->out.i_nal-1].i_payload;+ i_frame_size = h->out.nal[h->out.i_nal-1].i_payload + ( NALU_OVERHEAD * (int)h->param.b_nal_hrd ); #if VISUALIZE if( h->param.b_visualize )@@ -1417,7 +1446,7 @@ static void *x264_slices_write( x264_t * } #endif - h->out.i_frame_size = i_frame_size;+ h->out.i_frame_size += i_frame_size; return (void *)0; } @@ -1439,11 +1468,14 @@ 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) {@@ -1598,7 +1630,19 @@ 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 ----------------------------- */@@ -1648,26 +1692,92 @@ int x264_encoder_encode( x264_t *h, h->i_nal_ref_idc = i_nal_ref_idc; /* Write SPS and PPS */+ //clear payload tracking -- start here so we can add non VCL-NAL payload size+ //to bring to type II conformance+ h->out.i_frame_size = (NALU_OVERHEAD + 1 ) * (int)h->param.b_aud * (int)h->param.b_nal_hrd; 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 );- if( x264_sei_version_write( h, &h->out.bs ) )- return -1;- x264_nal_end( h );- }- /* generate sequence parameters */ x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST ); x264_sps_write( &h->out.bs, h->sps ); x264_nal_end( h );+ h->out.i_frame_size += (h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD ) * (int)h->param.b_nal_hrd ; /* generate picture parameters */ x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST ); x264_pps_write( &h->out.bs, h->pps ); x264_nal_end( h );+ h->out.i_frame_size += ( h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD ) * (int)h->param.b_nal_hrd;++ if( h->fenc->i_frame == 0 )+ {+ if( !h->param.b_nal_hrd )+ {+ /* 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 );+ h->out.i_frame_size += ( h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD )+ * (int)h->param.b_nal_hrd;+ }+ }+ }++ if( h->param.b_nal_hrd )+ {+ int dpb_output_delay = 0;+ int 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);+ x264_nal_end( h );+ h->out.i_frame_size += (h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD ) * (int)h->param.b_nal_hrd;+ x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );+ }+ if( !h->sh.b_field_pic )+ {+ //pic_struct+ 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->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;+ cpb_removal_delay *= 2;+ dpb_output_delay *=2;+ }+ }+ else+ {+ // tff = 3, bff = 4+ pic_struct = h->param.b_tff ? 3 : 4;+ }+ 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 ;+ }+ }+ x264_nal_end( h );+ h->out.i_frame_size += ( h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD ) * (int)h->param.b_nal_hrd; } /* Write frame */@@ -1681,6 +1791,7 @@ int x264_encoder_encode( x264_t *h, if( (intptr_t)x264_slices_write( h ) ) return -1; + h->i_cpb_delay = cpb_removal_delay; return x264_encoder_frame_end( thread_oldest, thread_current, pp_nal, pi_nal, pic_out ); } @@ -1732,7 +1843,9 @@ static int x264_encoder_frame_end( x264_ /* update rc */ x264_emms();- if( x264_ratecontrol_end( h, h->out.i_frame_size * 8 ) < 0 )++ int duration_this_frame = ((h->fenc->i_frame)&1) ? 2 : ( h->sps->vui.i_pulldown_type ? 3 : 2 );+ if( x264_ratecontrol_end( h, (h->out.i_frame_size ) * 8, duration_this_frame ) < 0 ) return -1; /* restore CPU state (before using float again) */@@ -1745,7 +1858,7 @@ static int x264_encoder_frame_end( x264_ /* Slice stat */ h->stat.i_slice_count[h->sh.i_type]++;- h->stat.i_slice_size[h->sh.i_type] += h->out.i_frame_size + NALU_OVERHEAD;+ h->stat.i_slice_size[h->sh.i_type] += h->out.i_frame_size + ( NALU_OVERHEAD * (int)!h->param.b_nal_hrd ); h->stat.f_slice_qp[h->sh.i_type] += h->fdec->f_qp_avg_aq; for( i = 0; i < X264_MBTYPE_MAX; i++ )diff -uNrp a/encoder/ratecontrol.c b/encoder/ratecontrol.c--- a/encoder/ratecontrol.c 2009-08-09 19:51:37 +0300+++ b/encoder/ratecontrol.c 2009-08-09 20:15:41 +0300@@ -69,6 +69,8 @@ struct x264_ratecontrol_t int b_vbv; int b_vbv_min_rate; double fps;+ double fps_vfr_low;+ double fps_vfr_high; /* variable frame rate support (final side only)*/ double bitrate; double rate_tolerance; double qcompress;@@ -89,6 +91,8 @@ struct x264_ratecontrol_t double buffer_fill_final; /* real buffer as of the last finished frame */ double buffer_fill; /* planned buffer, if all in-progress frames hit their bit budget */ double buffer_rate; /* # of bits added to buffer_fill after each frame */+ double buffer_rate_vfr_low; /* # bits added to buffer on a long frame time */+ double buffer_rate_vfr_high;/* # bits added to buffer on a short frame time */ predictor_t *pred; /* predict frame size from satd */ /* ABR stuff */@@ -143,7 +147,7 @@ struct x264_ratecontrol_t static int parse_zones( x264_t *h ); static int init_pass2(x264_t *); static float rate_estimate_qscale( x264_t *h );-static void update_vbv( x264_t *h, int bits );+static void update_vbv( x264_t *h, int bits, int vfrlowhigh ); //high = 3 static void update_vbv_plan( x264_t *h ); static double predict_size( predictor_t *p, double q, double var ); static void update_predictor( predictor_t *p, double q, double var, double bits );@@ -327,6 +331,29 @@ int x264_ratecontrol_new( x264_t *h ) rc->fps = (float) h->param.i_fps_num / h->param.i_fps_den; else rc->fps = 25.0;+ rc->fps_vfr_low =+ rc->fps_vfr_high =+ rc->fps;+ if( !h->param.b_interlaced )+ {+ if( h->sps->vui.i_pulldown_type > 0 && h->sps->vui.b_nal_hrd_parameters_present )+ {+ if( h->sps->vui.i_pulldown_type == 32 )+ {+ rc->fps_vfr_low = 19.98;+ rc->fps = 23.976; // fps average for prediction+ rc->fps_vfr_high = 29.97;+ }+ else+ {+ rc->fps_vfr_low = 19.98; // 39.96;+ rc->fps = 23.976; // fps average for prediction // 47.952;+ rc->fps_vfr_high = 29.97; // 59.94;+ }+ }+ }+ rc->buffer_rate_vfr_low = h->param.rc.i_vbv_max_bitrate * 1000 / rc->fps_vfr_low;+ rc->buffer_rate_vfr_high= h->param.rc.i_vbv_max_bitrate * 1000 / rc->fps_vfr_high; if( h->param.rc.b_mb_tree ) {@@ -1166,7 +1193,7 @@ int x264_ratecontrol_slice_type( x264_t } /* After encoding one frame, save stats and update ratecontrol state */-int x264_ratecontrol_end( x264_t *h, int bits )+int x264_ratecontrol_end( x264_t *h, int bits, int vfrlowhigh ) { x264_ratecontrol_t *rc = h->rc; const int *mbs = h->stat.frame.i_mb_count;@@ -1256,7 +1283,7 @@ int x264_ratecontrol_end( x264_t *h, int } } - update_vbv( h, bits );+ update_vbv( h, bits, vfrlowhigh ); return 0; fail: x264_log(h, X264_LOG_ERROR, "ratecontrol_end: stats file could not be written to\n");@@ -1393,7 +1420,8 @@ static void update_predictor( predictor_ } // update VBV after encoding a frame-static void update_vbv( x264_t *h, int bits )+// vfrlowhigh 2 == high default == low when non vfr stream low == avg+static void update_vbv( x264_t *h, int bits, int vfrlowhigh ) { x264_ratecontrol_t *rcc = h->rc; x264_ratecontrol_t *rct = h->thread[0]->rc;@@ -1404,10 +1432,13 @@ static void update_vbv( x264_t *h, int b if( !rcc->b_vbv ) return; - rct->buffer_fill_final += rct->buffer_rate - bits;+ // we will honor vfr (when applicable) for the final buffer while prediction routines+ // will continue to use the average frame rate+ rct->buffer_fill_final += ( vfrlowhigh == 3 ? rcc->buffer_rate_vfr_high : rcc->buffer_rate_vfr_low ) - 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 progressdiff -uNrp a/encoder/ratecontrol.h b/encoder/ratecontrol.h--- a/encoder/ratecontrol.h 2009-08-07 18:50:22 +0300+++ b/encoder/ratecontrol.h 2009-08-09 20:15:41 +0300@@ -35,7 +35,7 @@ void x264_ratecontrol_start( x264_t *, i int x264_ratecontrol_slice_type( x264_t *, int i_frame ); void x264_ratecontrol_mb( x264_t *, int bits ); int x264_ratecontrol_qp( x264_t * );-int x264_ratecontrol_end( x264_t *, int bits );+int x264_ratecontrol_end( x264_t *, int bits, int vfrlowhigh ); void x264_ratecontrol_summary( x264_t * ); void x264_ratecontrol_set_estimated_size( x264_t *, int bits ); int x264_ratecontrol_get_estimated_size( x264_t const *);diff -uNrp a/encoder/set.c b/encoder/set.c--- a/encoder/set.c 2009-08-09 19:51:37 +0300+++ b/encoder/set.c 2009-08-09 20:28:45 +0300@@ -208,8 +208,47 @@ void x264_sps_init( x264_sps_t *sps, int 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 )+ {+ sps->vui.nal_hrd_parameters.i_bit_rate = param->rc.i_vbv_max_bitrate * 1000;+ sps->vui.nal_hrd_parameters.i_cpb_size = param->rc.i_vbv_buffer_size * 1000;++ 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 ) );++ sps->vui.nal_hrd_parameters.i_cpb_removal_delay_length = 0;+ while( (1 << ++sps->vui.nal_hrd_parameters.i_cpb_removal_delay_length) <+ (2 * (param->i_keyint_max * ((param->i_pulldown/32)+1) )));++ sps->vui.nal_hrd_parameters.i_dpb_output_delay_length = 0;+ while( (1 << ++sps->vui.nal_hrd_parameters.i_dpb_output_delay_length) <+ ( ( 2 * (sps->i_num_ref_frames + X264_MAX(sps->vui.i_num_reorder_frames, param->i_bframe) ) *+ ( ( param->i_pulldown/32) + 1 ) ) ) );+ }++ 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 && 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;+ }+} void x264_sps_write( bs_t *s, x264_sps_t *sps ) {@@ -345,9 +384,45 @@ void x264_sps_write( bs_t *s, x264_sps_t 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 ) {@@ -502,7 +577,7 @@ int x264_sei_version_write( x264_t *h, b 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 );@@ -512,6 +587,83 @@ fail: return -1; } +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;+ assert( ( buffer_fill_final * 90000. / ( buffer_rate ) ) <+ pow( 2, sps->vui.nal_hrd_parameters.i_initial_cpb_removal_delay_length ) );+ 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_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 */++ assert( cpb_removal_delay < pow( 2, sps->vui.nal_hrd_parameters.i_cpb_removal_delay_length ) );+ bs_write( s, sps->vui.nal_hrd_parameters.i_cpb_removal_delay_length,+ cpb_removal_delay);+ assert( dpb_output_delay < pow( 2, sps->vui.nal_hrd_parameters.i_dpb_output_delay_length ) );+ 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 -uNrp a/encoder/set.h b/encoder/set.h--- a/encoder/set.h 2009-08-09 19:51:37 +0300+++ b/encoder/set.h 2009-08-09 20:29:12 +0300@@ -29,6 +29,8 @@ void x264_sps_write( bs_t *s, x264_sps_t 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 ); int 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 ); #endifdiff -uNrp a/x264.c b/x264.c--- a/x264.c 2009-08-09 19:51:37 +0300+++ b/x264.c 2009-08-09 20:15:48 +0300@@ -196,7 +196,9 @@ static void Help( x264_param_t *defaults 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" );@@ -358,6 +360,10 @@ static void Help( x264_param_t *defaults 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" ); } @@ -399,6 +405,8 @@ static struct option long_options[] = { "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 }, { "cabac", no_argument, NULL, 0 }, { "no-cabac", no_argument, NULL, 0 }, { "qp", required_argument, NULL, 'q' },@@ -470,6 +478,9 @@ static struct option long_options[] = { "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 },diff -uNrp a/x264.h b/x264.h--- a/x264.h 2009-08-09 19:51:37 +0300+++ b/x264.h 2009-08-09 20:15:48 +0300@@ -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 */@@ -267,6 +268,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; @@ -294,6 +296,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 */ /* Optional callback for freeing this x264_param_t when it is done being used. * Only used when the x264_param_t sits in memory for an indefinite period of time,