diff --git a/build/win32/libx264.vcproj b/build/win32/libx264.vcproj
index 8497a35..a0265fc 100644
diff --git a/build/win32/x264.sln b/build/win32/x264.sln
index 8fb518d..b4d5c5a 100644
diff --git a/build/win32/x264.vcproj b/build/win32/x264.vcproj
index c567265..48947c2 100644
diff --git a/common/bs.h b/common/bs.h
index eafa8f8..4f91bbd 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 9260c64..537aa6b 100644
--- a/common/common.c
+++ b/common/common.c
@@ -145,6 +145,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 )
@@ -372,7 +374,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" ) )
@@ -571,6 +589,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 1e46ae8..c7ba60f 100644
--- a/common/common.h
+++ b/common/common.h
@@ -288,7 +288,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 --git a/common/frame.c b/common/frame.c
index 23e6824..440d72b 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..4e9ab61 100644
--- a/common/frame.h
+++ b/common/frame.h
@@ -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 --git a/common/set.h b/common/set.h
index e1b9cd9..ce53101 100644
--- a/common/set.h
+++ b/common/set.h
@@ -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 --git a/encoder/encoder.c b/encoder/encoder.c
index fdcc957..ee4243a 100644
--- a/encoder/encoder.c
+++ b/encoder/encoder.c
@@ -403,6 +403,32 @@ 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" );
@@ -699,6 +725,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 );
@@ -902,11 +931,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 );
@@ -916,6 +940,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;
@@ -1357,7 +1386,7 @@ static int x264_slices_write( x264_t *h )
 #endif
 
     x264_stack_align( x264_slice_write, h );
-    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 )
@@ -1367,7 +1396,7 @@ static int x264_slices_write( x264_t *h )
     }
 #endif
 
-    h->out.i_frame_size = i_frame_size;
+    h->out.i_frame_size += i_frame_size;
     return 0;
 }
 
@@ -1389,11 +1418,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)
     {
@@ -1539,7 +1571,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                ----------------------------- */
@@ -1589,25 +1633,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 );
-            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 );
         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 */
@@ -1618,7 +1729,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;
 }
@@ -1668,7 +1779,9 @@ static void x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
 
     /* update rc */
     x264_emms();
-    x264_ratecontrol_end( h, h->out.i_frame_size * 8 );
+
+    int duration_this_frame = ((h->fenc->i_frame)&1) ? 2 : ( h->sps->vui.i_pulldown_type ? 3 : 2 );
+    x264_ratecontrol_end( h, (h->out.i_frame_size ) * 8, duration_this_frame );
 
     /* restore CPU state (before using float again) */
     x264_emms();
@@ -1680,7 +1793,7 @@ static void x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
 
     /* 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 --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c
index 2dd34d0..efbad6c 100644
--- a/encoder/ratecontrol.c
+++ b/encoder/ratecontrol.c
@@ -68,6 +68,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;
     int nmb;                    /* number of macroblocks in a frame */
@@ -87,6 +89,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 */
@@ -136,7 +140,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 );
@@ -282,6 +286,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;
 
     rc->bitrate = h->param.rc.i_bitrate * 1000.;
     rc->rate_tolerance = h->param.rc.f_rate_tolerance;
@@ -1062,7 +1089,7 @@ int x264_ratecontrol_slice_type( x264_t *h, int frame_num )
 }
 
 /* After encoding one frame, save stats and update ratecontrol state */
-void x264_ratecontrol_end( x264_t *h, int bits )
+void 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;
@@ -1144,7 +1171,7 @@ void x264_ratecontrol_end( x264_t *h, int bits )
         }
     }
 
-    update_vbv( h, bits );
+    update_vbv( h, bits, vfrlowhigh );
 }
 
 /****************************************************************************
@@ -1266,7 +1293,8 @@ static void update_predictor( predictor_t *p, double q, double var, double bits
 }
 
 // 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;
@@ -1277,10 +1305,13 @@ static void update_vbv( x264_t *h, int bits )
     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 progress
diff --git a/encoder/ratecontrol.h b/encoder/ratecontrol.h
index 3310d3c..849f6f0 100644
--- a/encoder/ratecontrol.h
+++ b/encoder/ratecontrol.h
@@ -34,7 +34,7 @@ void x264_ratecontrol_start( x264_t *, int i_force_qp );
 int  x264_ratecontrol_slice_type( x264_t *, int i_frame );
 void x264_ratecontrol_mb( x264_t *, int bits );
 int  x264_ratecontrol_qp( x264_t * );
-void x264_ratecontrol_end( x264_t *, int bits );
+void 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 --git a/encoder/set.c b/encoder/set.c
index 3103fcd..4727e71 100644
--- a/encoder/set.c
+++ b/encoder/set.c
@@ -208,8 +208,47 @@ 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 )
+    {
+        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 *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 +573,89 @@ 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;
+        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 --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 6e04edd..e4dc3f9 100644
--- a/x264.c
+++ b/x264.c
@@ -196,7 +196,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" );
@@ -352,6 +354,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" );
 }
 
@@ -393,6 +399,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' },
@@ -459,6 +467,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 --git a/x264.h b/x264.h
index e61040e..a757e5d 100644
--- a/x264.h
+++ b/x264.h
@@ -200,6 +200,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 */
@@ -265,6 +266,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;
 
@@ -290,6 +292,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 {
