All pastes #1391682 Raw Edit

x264_hrd_pulldown.11_interlace.d

public text v1 · immutable
#1391682 ·published 2009-04-14 13:30 UTC
rendered paste body
diff --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 {