diff --git a/common/common.c b/common/common.c
index 6d1d7f0..ef401cb 100644
--- a/common/common.c
+++ b/common/common.c
@@ -60,6 +60,9 @@ void    x264_param_default( x264_param_t *param )
     param->vui.i_transfer  = 2;  /* undef */
     param->vui.i_colmatrix = 2;  /* undef */
     param->vui.i_chroma_loc= 0;  /* left center */
+
+    param->b_nal_hrd = 0;
+
     param->i_fps_num       = 25;
     param->i_fps_den       = 1;
     param->i_level_idc     = -1;
@@ -158,6 +161,12 @@ void    x264_param_default( x264_param_t *param )
     param->b_aud = 0;
     param->b_vfr_input = 1;
     param->b_dts_compress = 0;
+    param->b_nal_hrd = 0;
+    param->b_cbr_hrd = 0;
+    param->b_tff = 1;
+    param->b_pic_struct = 0;
+    param->b_pulldown = 0;
+    param->i_pulldown_delay = 0;
 }
 
 static int parse_enum( const char *arg, const char * const *names, int *dst )
@@ -403,6 +412,13 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
         p->i_cabac_init_idc = atoi(value);
     OPT("interlaced")
         p->b_interlaced = atobool(value);
+    OPT("tff")
+        p->b_interlaced = atobool(value);
+    OPT("bff")
+    {
+        p->b_interlaced = atobool(value);
+        p->b_tff = !p->b_interlaced;
+    }
     OPT("constrained-intra")
         p->b_constrained_intra = atobool(value);
     OPT("cqm")
@@ -621,6 +637,13 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
         p->b_annexb = atobool(value);
     OPT("force-cfr")
         p->b_vfr_input = !atobool(value);
+    OPT("nal-hrd")
+    {
+        p->b_cbr_hrd = !strcasecmp( value, "cbr" );
+        p->b_nal_hrd = p->b_cbr_hrd || !strcasecmp( value, "vbr" );
+    }
+    OPT("pic-struct")
+        p->b_pic_struct = atobool(value);
     else
         return X264_PARAM_BAD_NAME;
 #undef OPT
@@ -696,6 +719,7 @@ int x264_picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_heigh
     pic->img.i_stride[1] = i_width / 2;
     pic->img.i_stride[2] = i_width / 2;
     pic->param = NULL;
+    pic->i_pic_struct = PIC_STRUCT_AUTO;
     return 0;
 }
 
@@ -906,7 +930,8 @@ char *x264_param2string( x264_param_t *p, int b_res )
         s += sprintf( s, " slice_max_mbs=%d", p->i_slice_max_mbs );
     s += sprintf( s, " nr=%d", p->analyse.i_noise_reduction );
     s += sprintf( s, " decimate=%d", p->analyse.b_dct_decimate );
-    s += sprintf( s, " mbaff=%d", p->b_interlaced );
+    s += sprintf( s, " interlaced=%s", p->b_interlaced ? p->b_tff ? "tff" : "bff" : "0" );
+
     s += sprintf( s, " constrained_intra=%d", p->b_constrained_intra );
 
     s += sprintf( s, " bframes=%d", p->i_bframe );
@@ -959,6 +984,9 @@ char *x264_param2string( x264_param_t *p, int b_res )
             s += sprintf( s, " zones" );
     }
 
+    s += sprintf( s, " pulldown=%d", p->b_pulldown );
+    if( p->rc.i_vbv_buffer_size )
+        s += sprintf( s, " nal_hrd=%d", p->b_nal_hrd );
     return buf;
 }
 
diff --git a/common/common.h b/common/common.h
index 950f48f..72cef45 100644
--- a/common/common.h
+++ b/common/common.h
@@ -67,6 +67,9 @@ do {\
 
 #define X264_WEIGHTP_FAKE (-1)
 
+#define NALU_OVERHEAD 5 // startcode + NAL type costs 5 bytes per frame
+#define FILLER_OVERHEAD (NALU_OVERHEAD+1)
+
 /****************************************************************************
  * Includes
  ****************************************************************************/
@@ -214,6 +217,17 @@ enum slice_type_e
 
 static const char slice_type_to_char[] = { 'P', 'B', 'I', 'S', 'S' };
 
+enum sei_payload_type_e
+{
+    SEI_BUFFERING_PERIOD    = 0,
+    SEI_PIC_TIMING          = 1,
+    SEI_PAN_SCAN_RECT       = 2,
+    SEI_FILLER              = 3,
+    SEI_USER_DATA_REGISTERED_ITU_T_T35 = 4,
+    SEI_USER_DATA_UNREGISTERED = 5,
+    SEI_RECOVERY_POINT      = 6,
+};
+
 typedef struct
 {
     x264_sps_t *sps;
@@ -367,6 +381,12 @@ struct x264_t
     int             i_nal_type;
     int             i_nal_ref_idc;
 
+    int             i_disp_fields;  /* Number of displayed fields (both coded and implied via pic_struct) */
+    int             i_coded_fields; /* Number of coded fields (both coded and implied via pic_struct) */
+
+    int             i_cpb_delay;    /* Equal to number of fields preceding this field
+                                     * since last buffering_period SEI */
+
     /* We use only one SPS and one PPS */
     x264_sps_t      sps_array[1];
     x264_sps_t      *sps;
@@ -449,7 +469,10 @@ struct x264_t
     x264_frame_t    *fref1[16+3];     /* ref list 1 */
     int             b_ref_reorder[2];
 
-
+    /* hrd */
+    int initial_cpb_removal_delay;
+    int current_cpb_delay;
+    int dpb_output_delay;
 
     /* Current MB DCT coeffs */
     struct
@@ -720,7 +743,6 @@ struct x264_t
         int     i_direct_frames[2];
         /* num p-frames weighted */
         int     i_wpred[3];
-
     } stat;
 
     void *scratch_buffer; /* for any temporary storage that doesn't want repeated malloc */
diff --git a/common/frame.c b/common/frame.c
index 40cc78f..8e54e52 100644
--- a/common/frame.c
+++ b/common/frame.c
@@ -73,6 +73,10 @@ x264_frame_t *x264_frame_new( x264_t *h, int b_fdec )
     frame->i_frame_num = -1;
     frame->i_lines_completed = -1;
     frame->b_fdec = b_fdec;
+
+    frame->i_pic_struct = PIC_STRUCT_AUTO;
+    frame->i_field_cnt = -1;
+
     frame->orig = frame;
 
     /* all 4 luma planes allocated together, since the cacheline split code
@@ -225,6 +229,7 @@ int x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src )
     dst->i_qpplus1  = src->i_qpplus1;
     dst->i_pts      = dst->i_reordered_pts = src->i_pts;
     dst->param      = src->param;
+    dst->i_pic_struct = src->i_pic_struct;
 
     for( i=0; i<3; i++ )
     {
diff --git a/common/frame.h b/common/frame.h
index b1852b3..dbdae9d 100644
--- a/common/frame.h
+++ b/common/frame.h
@@ -40,8 +40,11 @@ typedef struct x264_frame
 
     int     i_frame;     /* Presentation frame number */
     int     i_coded;     /* Coded frame number */
+    int     i_field_cnt; /* Presentation field count */
     int     i_frame_num; /* 7.4.3 frame_num */
     int     b_kept_as_ref;
+    int     i_pic_struct;
+    int     b_top_field_first;
     int     b_keyframe;
     uint8_t b_fdec;
     uint8_t b_last_minigop_bframe; /* this frame is the last b in a sequence of bframes */
@@ -107,6 +110,9 @@ typedef struct x264_frame
     uint32_t i_pixel_sum;
     uint64_t i_pixel_ssd;
 
+    /* hrd */
+    x264_hrd_t hrd_timing;
+
     /* vbv */
     uint8_t i_planned_type[X264_LOOKAHEAD_MAX+1];
     int i_planned_satd[X264_LOOKAHEAD_MAX+1];
diff --git a/common/osdep.h b/common/osdep.h
index 7f680ed..7610f73 100644
--- a/common/osdep.h
+++ b/common/osdep.h
@@ -221,10 +221,13 @@ static ALWAYS_INLINE uint16_t endian_fix16( uint16_t x )
 
 #if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 3)
 #define x264_clz(x) __builtin_clz(x)
+#define x264_ctz(x) __builtin_ctz(x)
 #else
 static int ALWAYS_INLINE x264_clz( uint32_t x )
 {
     static uint8_t lut[16] = {4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0};
+    if( !x )
+        return 0; // just to be consistent with __builtin_clz
     int y, z = (((x >> 16) - 1) >> 27) & 16;
     x >>= z^16;
     z += y = ((x - 0x100) >> 28) & 8;
@@ -233,6 +236,20 @@ static int ALWAYS_INLINE x264_clz( uint32_t x )
     x >>= y^4;
     return z + lut[x];
 }
+
+static int ALWAYS_INLINE x264_ctz( uint32_t x )
+{
+    static uint8_t lut[16] = {4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
+    if( !x )
+        return 0; // just to be consistent with __builtin_ctz
+    int y, z = (((x & 0xffff) - 1) >> 27) & 16;
+    x >>= z;
+    z += y = (((x & 0xff) - 1) >> 28) & 8;
+    x >>= y;
+    z += y = (((x & 0xf) - 1) >> 29) & 4;
+    x >>= y;
+    return z + lut[x&0xf];
+}
 #endif
 
 #ifdef USE_REAL_PTHREAD
diff --git a/common/set.h b/common/set.h
index e1b9cd9..f55e6e3 100644
--- a/common/set.h
+++ b/common/set.h
@@ -116,6 +116,27 @@ typedef struct
         int i_time_scale;
         int b_fixed_frame_rate;
 
+        int b_nal_hrd_parameters_present;
+        int b_vcl_hrd_parameters_present;
+
+        struct
+        {
+            int i_cpb_cnt;
+            int i_bit_rate_scale;
+            int i_cpb_size_scale;
+            int i_bit_rate_value;
+            int i_cpb_size_value;
+            int i_bit_rate_unscaled;
+            int i_cpb_size_unscaled;
+            int b_cbr_hrd;
+
+            int i_initial_cpb_removal_delay_length;
+            int i_cpb_removal_delay_length;
+            int i_dpb_output_delay_length;
+            int i_time_offset_length;
+        } hrd;
+
+        int b_pic_struct_present;
         int b_bitstream_restriction;
         int b_motion_vectors_over_pic_boundaries;
         int i_max_bytes_per_pic_denom;
diff --git a/encoder/encoder.c b/encoder/encoder.c
index d873cd0..d9d1a2d 100644
--- a/encoder/encoder.c
+++ b/encoder/encoder.c
@@ -39,14 +39,14 @@
 
 //#define DEBUG_MB_TYPE
 
-#define NALU_OVERHEAD 5 // startcode + NAL type costs 5 bytes per frame
-
 #define bs_write_ue bs_write_ue_big
 
 static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
                                    x264_nal_t **pp_nal, int *pi_nal,
                                    x264_picture_t *pic_out );
 
+static int delta_tfi_divisor[10] = { 0, 2, 1, 1, 2, 2, 3, 3, 4, 6 }; // Number of coded/displayed fields (indexed by i_pic_struct)
+
 /****************************************************************************
  *
  ******************************* x264 libs **********************************
@@ -505,6 +505,35 @@ static int x264_validate_parameters( x264_t *h )
         h->param.rc.i_aq_mode = 0;
         h->param.rc.b_mb_tree = 0;
     }
+
+    if( h->param.rc.i_rc_method == X264_RC_CRF && h->param.rc.b_stat_read )
+    {
+        x264_log(h, X264_LOG_ERROR, "constant rate-factor is incompatible with 2pass.\n");
+        return -1;
+    }
+    if( h->param.rc.i_vbv_buffer_size )
+    {
+        if( h->param.rc.i_rc_method == X264_RC_CQP )
+        {
+            x264_log(h, X264_LOG_WARNING, "VBV is incompatible with constant QP, ignored.\n");
+            h->param.rc.i_vbv_max_bitrate = 0;
+            h->param.rc.i_vbv_buffer_size = 0;
+        }
+        else if( h->param.rc.i_vbv_max_bitrate == 0 )
+        {
+            if( h->param.rc.i_rc_method == X264_RC_ABR )
+            {
+                x264_log( h, X264_LOG_INFO, "VBV maxrate unspecified, assuming CBR\n" );
+                h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate;
+            }
+            else
+            {
+                x264_log( h, X264_LOG_INFO, "VBV bufsize set but maxrate unspecified, ignored\n" );
+                h->param.rc.i_vbv_buffer_size = 0;
+            }
+        }
+    }
+
     h->param.rc.i_qp_max = x264_clip3( h->param.rc.i_qp_max, 0, 51 );
     h->param.rc.i_qp_min = x264_clip3( h->param.rc.i_qp_min, 0, h->param.rc.i_qp_max );
 
@@ -745,6 +774,34 @@ static int x264_validate_parameters( x264_t *h )
         h->param.analyse.b_ssim = 0;
     }
 
+    if( h->param.b_pulldown && !h->param.i_pulldown_delay )
+    {
+        x264_log( h, X264_LOG_WARNING, "Pulldown requires delay\n" );
+        h->param.b_pulldown = 0;
+    }
+
+    if( h->param.b_pulldown && h->param.b_vfr_input )
+    {
+        x264_log( h, X264_LOG_WARNING, "Pulldown not compatible with variable framerate\n" );
+        h->param.b_pulldown = 0;
+    }
+
+    if( h->param.b_pulldown || h->param.b_interlaced )
+        h->param.b_pic_struct = 1;
+
+    if( h->param.b_nal_hrd && !h->param.rc.i_vbv_buffer_size )
+    {
+        x264_log( h, X264_LOG_WARNING, "NAL HRD parameters require VBV parameters \n" );
+        h->param.b_nal_hrd = 0;
+    }
+
+    if( h->param.b_cbr_hrd && ( h->param.rc.i_bitrate != h->param.rc.i_vbv_max_bitrate ||
+			      ( h->param.rc.i_vbv_max_bitrate && !h->param.rc.i_bitrate ) ) )
+    {
+        x264_log( h, X264_LOG_WARNING, "CBR HRD requires constant bitrate \n" );
+        h->param.b_cbr_hrd = 0;
+    }
+
     /* ensure the booleans are 0 or 1 so they can be used in math */
 #define BOOLIFY(x) h->param.x = !!h->param.x
     BOOLIFY( b_cabac );
@@ -770,6 +827,8 @@ static int x264_validate_parameters( x264_t *h )
     BOOLIFY( rc.b_stat_write );
     BOOLIFY( rc.b_stat_read );
     BOOLIFY( rc.b_mb_tree );
+    BOOLIFY( b_nal_hrd );
+    BOOLIFY( b_cbr_hrd );
 #undef BOOLIFY
 
     return 0;
@@ -875,6 +934,7 @@ x264_t *x264_encoder_open( x264_param_t *param )
     }
     else
         h->i_dts_compress_multiplier = 1;
+    h->i_cpb_delay = 0;
 
     h->sps = &h->sps_array[0];
     x264_sps_init( h->sps, h->param.i_sps_id, &h->param );
@@ -929,7 +989,7 @@ x264_t *x264_encoder_open( x264_param_t *param )
         CHECKED_MALLOCZERO( h->frames.blank_unused, h->i_thread_frames * 4 * sizeof(x264_frame_t *) );
     h->i_ref0 = 0;
     h->i_ref1 = 0;
-
+    h->i_coded_fields = h->i_disp_fields = 0;
     x264_rdo_init();
 
     /* init CPU functions */
@@ -1037,6 +1097,12 @@ x264_t *x264_encoder_open( x264_param_t *param )
     if( x264_ratecontrol_new( h ) < 0 )
         goto fail;
 
+    if( h->param.b_nal_hrd )
+    {
+        x264_log( h, X264_LOG_INFO, "HRD bitrate: %ld bits/sec\n", h->sps->vui.hrd.i_bit_rate_unscaled );
+        x264_log( h, X264_LOG_INFO, "CPB size: %lld bits\n", h->sps->vui.hrd.i_cpb_size_unscaled );
+    }
+
     if( h->param.psz_dump_yuv )
     {
         /* create or truncate the reconstructed video file */
@@ -1110,6 +1176,17 @@ int x264_encoder_reconfig( x264_t *h, x264_param_t *param )
     COPY( i_slice_max_size );
     COPY( i_slice_max_mbs );
     COPY( i_slice_count );
+
+    COPY( b_nal_hrd );
+    COPY( b_cbr_hrd );
+    COPY( b_pic_struct );
+
+    if( h->param.b_pulldown != param->b_pulldown )
+    {
+        COPY( b_pulldown );
+        COPY( i_pulldown_delay );
+    }
+
 #undef COPY
 
     mbcmp_init( h );
@@ -1160,10 +1237,14 @@ static int x264_nal_end( x264_t *h )
     return x264_nal_check_buffer( h );
 }
 
-static int x264_encoder_encapsulate_nals( x264_t *h )
+static int x264_encoder_encapsulate_nals( x264_t *h, int start )
 {
-    int nal_size = 0, i;
-    for( i = 0; i < h->out.i_nal; i++ )
+    int nal_size = 0, previous_nal_size = 0, i;
+
+    for( i = 0; i < start; i++ )
+        previous_nal_size += h->out.nal[i].i_payload;
+
+    for( i = start; i < h->out.i_nal; i++ )
         nal_size += h->out.nal[i].i_payload;
 
     /* Worst-case NAL unit escaping: reallocate the buffer if it's too small. */
@@ -1172,13 +1253,15 @@ static int x264_encoder_encapsulate_nals( x264_t *h )
         uint8_t *buf = x264_malloc( nal_size * 2 + h->out.i_nal * 4 );
         if( !buf )
             return -1;
+        if( previous_nal_size )
+            memcpy( buf, h->nal_buffer, previous_nal_size );
         x264_free( h->nal_buffer );
         h->nal_buffer = buf;
     }
 
-    uint8_t *nal_buffer = h->nal_buffer;
+    uint8_t *nal_buffer = h->nal_buffer + previous_nal_size;
 
-    for( i = 0; i < h->out.i_nal; i++ )
+    for( i = start; i < h->out.i_nal; i++ )
     {
         int size = x264_nal_encode( nal_buffer, h->param.b_annexb, &h->out.nal[i] );
         h->out.nal[i].i_payload = size;
@@ -1186,7 +1269,7 @@ static int x264_encoder_encapsulate_nals( x264_t *h )
         nal_buffer += size;
     }
 
-    return nal_buffer - h->nal_buffer;
+    return nal_buffer - (h->nal_buffer + previous_nal_size);
 }
 
 /****************************************************************************
@@ -1200,11 +1283,6 @@ int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal )
     bs_init( &h->out.bs, h->out.p_bitstream, h->out.i_bitstream );
 
     /* Write SEI, SPS and PPS. */
-    x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
-    if( x264_sei_version_write( h, &h->out.bs ) )
-        return -1;
-    if( x264_nal_end( h ) )
-        return -1;
 
     /* generate sequence parameters */
     x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST );
@@ -1218,7 +1296,14 @@ int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal )
     if( x264_nal_end( h ) )
         return -1;
 
-    frame_size = x264_encoder_encapsulate_nals( h );
+    /* identify ourselves */
+    x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+    if( x264_sei_version_write( h, &h->out.bs ) )
+        return -1;
+    if( x264_nal_end( h ) )
+        return -1;
+
+    frame_size = x264_encoder_encapsulate_nals( h, 0 );
 
     /* now set output*/
     *pi_nal = h->out.i_nal;
@@ -1642,7 +1727,14 @@ static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp )
     if( h->sps->i_poc_type == 0 )
     {
         h->sh.i_poc_lsb = h->fdec->i_poc & ( (1 << h->sps->i_log2_max_poc_lsb) - 1 );
-        h->sh.i_delta_poc_bottom = 0;
+        if( h->param.b_interlaced )
+        {
+            h->sh.i_delta_poc_bottom = h->fenc->b_top_field_first ? 1 : -1;
+            if( h->sh.i_delta_poc_bottom == -1 )
+                h->sh.i_poc_lsb = ( h->fdec->i_poc + 1 ) & ( (1 << h->sps->i_log2_max_poc_lsb) - 1 );
+        }
+        else
+            h->sh.i_delta_poc_bottom = 0;
     }
     else if( h->sps->i_poc_type == 1 )
     {
@@ -2050,6 +2142,7 @@ int     x264_encoder_encode( x264_t *h,
 {
     x264_t *thread_current, *thread_prev, *thread_oldest;
     int i_nal_type, i_nal_ref_idc, i_global_qp, i;
+    int overhead = NALU_OVERHEAD;
 
     if( h->i_thread_frames > 1 )
     {
@@ -2097,6 +2190,21 @@ int     x264_encoder_encode( x264_t *h,
         if( h->frames.i_bframe_delay && fenc->i_frame == h->frames.i_bframe_delay )
             h->frames.i_bframe_delay_time = fenc->i_pts;
 
+        if( fenc->i_pic_struct == PIC_STRUCT_AUTO )
+        {
+            if( h->param.b_interlaced )
+                fenc->i_pic_struct = fenc->b_top_field_first ? PIC_STRUCT_TOP_BOTTOM : PIC_STRUCT_BOTTOM_TOP;
+            else
+                fenc->i_pic_struct = PIC_STRUCT_PROGRESSIVE;
+        }
+        else if( ( fenc->i_pic_struct < PIC_STRUCT_AUTO ) || ( fenc->i_pic_struct > PIC_STRUCT_TRIPLE ) )
+            fenc->i_pic_struct = PIC_STRUCT_PROGRESSIVE;
+
+        // add number of "displayed" fields
+        fenc->i_field_cnt = h->i_disp_fields;
+
+        h->i_disp_fields += delta_tfi_divisor[fenc->i_pic_struct];
+
         if( h->frames.b_have_lowres )
         {
             if( h->param.analyse.i_weighted_pred == X264_WEIGHTP_FAKE || h->param.analyse.i_weighted_pred == X264_WEIGHTP_SMART )
@@ -2245,13 +2353,12 @@ int     x264_encoder_encode( x264_t *h,
         bs_rbsp_trailing( &h->out.bs );
         if( x264_nal_end( h ) )
             return -1;
+        overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
     }
 
     h->i_nal_type = i_nal_type;
     h->i_nal_ref_idc = i_nal_ref_idc;
 
-    int overhead = NALU_OVERHEAD;
-
     if( h->param.b_intra_refresh && h->fenc->i_type == X264_TYPE_P )
     {
         int pocdiff = (h->fdec->i_poc - h->fref0[0]->i_poc)/2;
@@ -2273,22 +2380,11 @@ int     x264_encoder_encode( x264_t *h,
         h->fdec->i_pir_end_col = X264_MIN( h->fdec->f_pir_position+0.5, h->sps->i_mb_width-1 );
     }
 
-    /* Write SPS and PPS */
     if( h->fenc->b_keyframe )
     {
+        /* Write SPS and PPS */
         if( 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;
-                if( x264_nal_end( h ) )
-                    return -1;
-                overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
-            }
-
             /* generate sequence parameters */
             x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST );
             x264_sps_write( &h->out.bs, h->sps );
@@ -2304,6 +2400,32 @@ int     x264_encoder_encode( x264_t *h,
             overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
         }
 
+        /* generate sei buffering period */
+        if( h->sps->vui.b_nal_hrd_parameters_present )
+        {
+            h->initial_cpb_removal_delay = x264_hrd_fullness( h, 8*overhead );
+
+            x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+            x264_sei_buffering_period_write( h, &h->out.bs, h->initial_cpb_removal_delay );
+            if( x264_nal_end( h ) )
+               return -1;
+            overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
+        }
+
+        if( 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;
+                if( x264_nal_end( h ) )
+                    return -1;
+                overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
+            }
+        }
+
         if( h->fenc->i_type != X264_TYPE_IDR )
         {
             x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
@@ -2313,6 +2435,40 @@ int     x264_encoder_encode( x264_t *h,
         }
     }
 
+    /* FIXME support VFR */
+    /* generate sei pic timing */
+    if( h->sps->vui.b_pic_struct_present || h->sps->vui.b_nal_hrd_parameters_present )
+    {
+        h->dpb_output_delay = h->fenc->i_field_cnt - h->i_coded_fields;
+
+        // add a correction term for pulldown
+        h->dpb_output_delay += h->param.i_pulldown_delay;
+
+        // add a correction term for frame reordering
+        h->dpb_output_delay += h->sps->vui.i_num_reorder_frames*2;
+
+        // fix possible negative dpb_output_delay because of pulldown changes
+        if( h->dpb_output_delay < 0 )
+        {
+            h->i_cpb_delay += h->dpb_output_delay;
+            h->dpb_output_delay = 0;
+        }
+
+        x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+        x264_sei_pic_timing_write( h, &h->out.bs, h->i_cpb_delay, h->dpb_output_delay, h->fenc->i_pic_struct );
+        if( x264_nal_end( h ) )
+            return -1;
+        overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
+    }
+
+    h->current_cpb_delay = h->i_cpb_delay;
+
+    if( h->fenc->b_keyframe )
+        h->i_cpb_delay = 0;
+
+    h->i_cpb_delay += delta_tfi_divisor[h->fenc->i_pic_struct];
+    h->i_coded_fields += delta_tfi_divisor[h->fenc->i_pic_struct];
+
     /* Init the rate control */
     /* FIXME: Include slice header bit cost. */
     x264_ratecontrol_start( h, h->fenc->i_qpplus1, overhead*8 );
@@ -2383,13 +2539,7 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
 
     x264_frame_push_unused( thread_current, h->fenc );
 
-    /* End bitstream, set output  */
-    *pi_nal = h->out.i_nal;
-    *pp_nal = h->out.nal;
-
-    frame_size = x264_encoder_encapsulate_nals( h );
-
-    h->out.i_nal = 0;
+    frame_size = x264_encoder_encapsulate_nals( h, 0 );
 
     /* Set output picture properties */
     if( h->sh.i_type == SLICE_TYPE_I )
@@ -2436,9 +2586,27 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
 
     /* update rc */
     x264_emms();
-    if( x264_ratecontrol_end( h, frame_size * 8 ) < 0 )
+    int filler = 0;
+    if( x264_ratecontrol_end( h, frame_size * 8, &filler ) < 0 )
         return -1;
 
+    pic_out->hrd_timing = h->fenc->hrd_timing;
+
+    if( filler )
+    {
+        x264_nal_start( h, NAL_FILLER, NAL_PRIORITY_DISPOSABLE );
+        x264_filler_write( h, &h->out.bs, filler );
+        if( x264_nal_end( h ) )
+            return -1;
+        frame_size += x264_encoder_encapsulate_nals( h, h->out.i_nal-1 );
+    }
+
+    /* End bitstream, set output  */
+    *pi_nal = h->out.i_nal;
+    *pp_nal = h->out.nal;
+
+    h->out.i_nal = 0;
+
     x264_noise_reduction_update( thread_current );
 
     /* ---------------------- Compute/Print statistics --------------------- */
diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c
index 63b3be6..71391d8 100644
--- a/encoder/ratecontrol.c
+++ b/encoder/ratecontrol.c
@@ -146,13 +146,19 @@ struct x264_ratecontrol_t
     int i_zones;
     x264_zone_t *zones;
     x264_zone_t *prev_zone;
+
+    /* hrd stuff */
+    int initial_cpb_removal_delay;
+    int current_cpb_delay;
+    double nrt_first_access_unit;
+    double previous_cpb_final_arrival_time;
 };
 
 
 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 int update_vbv( x264_t *h, int bits, int *filler_sei_size );
 static void update_vbv_plan( x264_t *h, int overhead );
 static double predict_size( predictor_t *p, double q, double var );
 static void update_predictor( predictor_t *p, double q, double var, double bits );
@@ -421,33 +427,6 @@ int x264_ratecontrol_new( x264_t *h )
     rc->last_non_b_pict_type = -1;
     rc->cbr_decay = 1.0;
 
-    if( h->param.rc.i_rc_method == X264_RC_CRF && h->param.rc.b_stat_read )
-    {
-        x264_log(h, X264_LOG_ERROR, "constant rate-factor is incompatible with 2pass.\n");
-        return -1;
-    }
-    if( h->param.rc.i_vbv_buffer_size )
-    {
-        if( h->param.rc.i_rc_method == X264_RC_CQP )
-        {
-            x264_log(h, X264_LOG_WARNING, "VBV is incompatible with constant QP, ignored.\n");
-            h->param.rc.i_vbv_max_bitrate = 0;
-            h->param.rc.i_vbv_buffer_size = 0;
-        }
-        else if( h->param.rc.i_vbv_max_bitrate == 0 )
-        {
-            if( h->param.rc.i_rc_method == X264_RC_ABR )
-            {
-                x264_log( h, X264_LOG_INFO, "VBV maxrate unspecified, assuming CBR\n" );
-                h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate;
-            }
-            else
-            {
-                x264_log( h, X264_LOG_INFO, "VBV bufsize set but maxrate unspecified, ignored\n" );
-                h->param.rc.i_vbv_buffer_size = 0;
-            }
-        }
-    }
     if( h->param.rc.i_vbv_max_bitrate < h->param.rc.i_bitrate &&
         h->param.rc.i_vbv_max_bitrate > 0)
         x264_log(h, X264_LOG_WARNING, "max bitrate less than average bitrate, ignored.\n");
@@ -462,8 +441,49 @@ int x264_ratecontrol_new( x264_t *h )
         }
         if( h->param.rc.f_vbv_buffer_init > 1. )
             h->param.rc.f_vbv_buffer_init = x264_clip3f( h->param.rc.f_vbv_buffer_init / h->param.rc.i_vbv_buffer_size, 0, 1 );
-        rc->buffer_rate = h->param.rc.i_vbv_max_bitrate * 1000. / rc->fps;
-        rc->buffer_size = h->param.rc.i_vbv_buffer_size * 1000.;
+
+        int vbv_buffer_size = h->param.rc.i_vbv_buffer_size * 1000;
+        int vbv_max_bitrate = h->param.rc.i_vbv_max_bitrate * 1000;
+
+        /* Init HRD */
+        if( h->param.b_nal_hrd )
+        {
+            h->sps->vui.hrd.i_cpb_cnt = 1;
+            h->sps->vui.hrd.b_cbr_hrd = h->param.b_cbr_hrd;
+            h->sps->vui.hrd.i_time_offset_length = 0;
+
+            #define BR_SHIFT  6
+            #define CPB_SHIFT 4
+
+            int bitrate = 1000*h->param.rc.i_vbv_max_bitrate;
+            int bufsize = 1000*h->param.rc.i_vbv_buffer_size;
+
+            // normalize HRD size and rate to the value / scale notation
+            h->sps->vui.hrd.i_bit_rate_scale = x264_clip3( x264_ctz( bitrate ) - BR_SHIFT, 0, 15 );
+            h->sps->vui.hrd.i_bit_rate_value = bitrate >> ( h->sps->vui.hrd.i_bit_rate_scale + BR_SHIFT );
+            h->sps->vui.hrd.i_bit_rate_unscaled = h->sps->vui.hrd.i_bit_rate_value << ( h->sps->vui.hrd.i_bit_rate_scale + BR_SHIFT );
+            h->sps->vui.hrd.i_cpb_size_scale = x264_clip3( x264_ctz( bufsize ) - CPB_SHIFT, 0, 15 );
+            h->sps->vui.hrd.i_cpb_size_value = bufsize >> ( h->sps->vui.hrd.i_cpb_size_scale + CPB_SHIFT );
+            h->sps->vui.hrd.i_cpb_size_unscaled = h->sps->vui.hrd.i_cpb_size_value << ( h->sps->vui.hrd.i_cpb_size_scale + CPB_SHIFT );
+
+            #undef CPB_SHIFT
+            #undef BR_SHIFT
+
+            // FIXME should we use the maximums from the levels
+            int max_cpb = 2*h->param.i_keyint_max + 1;
+            int max_dpb = 2 + 2*h->sps->vui.i_max_dec_frame_buffering + 1;
+            int max_delay = (int)(90000.0 * (double)h->sps->vui.hrd.i_cpb_size_unscaled / h->sps->vui.hrd.i_bit_rate_unscaled + 0.5);
+
+            h->sps->vui.hrd.i_initial_cpb_removal_delay_length = 2 + x264_clip3( 32 - x264_clz( max_delay ), 4, 22);
+            h->sps->vui.hrd.i_cpb_removal_delay_length = x264_clip3( 32 - x264_clz( max_cpb ), 4, 24 );
+            h->sps->vui.hrd.i_dpb_output_delay_length  = x264_clip3( 32 - x264_clz( max_dpb ), 4, 24 );
+
+            vbv_buffer_size = X264_MIN( vbv_buffer_size, h->sps->vui.hrd.i_cpb_size_unscaled );
+            vbv_max_bitrate = X264_MIN( vbv_max_bitrate, h->sps->vui.hrd.i_bit_rate_unscaled );
+        }
+
+        rc->buffer_rate = (double)vbv_max_bitrate / rc->fps;
+        rc->buffer_size = vbv_buffer_size;
         rc->single_frame_vbv = rc->buffer_rate * 1.1 > rc->buffer_size;
         h->param.rc.f_vbv_buffer_init = X264_MAX( h->param.rc.f_vbv_buffer_init, rc->buffer_rate / rc->buffer_size );
         rc->buffer_fill_final = rc->buffer_size * h->param.rc.f_vbv_buffer_init;
@@ -1314,11 +1334,11 @@ void x264_ratecontrol_set_weights( x264_t *h, x264_frame_t *frm )
 }
 
 /* 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 *filler )
 {
     x264_ratecontrol_t *rc = h->rc;
     const int *mbs = h->stat.frame.i_mb_count;
-    int i;
+    int i, filler_sei_size = 0;
 
     x264_emms();
 
@@ -1425,7 +1445,57 @@ int x264_ratecontrol_end( x264_t *h, int bits )
         }
     }
 
-    update_vbv( h, bits );
+    *filler = update_vbv( h, bits, &filler_sei_size );
+
+    if( h->sps->vui.b_nal_hrd_parameters_present )
+    {
+        double cpb_nominal_removal_time;
+        rc->current_cpb_delay = h->current_cpb_delay;
+
+        if( h->fenc->i_frame == 0 )
+        {
+            // access unit initialises the HRD
+            h->fenc->hrd_timing.cpb_initial_arrival_time = 0;
+            rc->initial_cpb_removal_delay = h->initial_cpb_removal_delay;
+            cpb_nominal_removal_time = rc->nrt_first_access_unit = (double)rc->initial_cpb_removal_delay / 90000;
+        }
+        else
+        {
+            cpb_nominal_removal_time = rc->nrt_first_access_unit +
+                (double)rc->current_cpb_delay * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
+            if( h->fenc->b_keyframe )
+            {
+                 rc->nrt_first_access_unit = cpb_nominal_removal_time;
+                 rc->initial_cpb_removal_delay = h->initial_cpb_removal_delay;
+            }
+
+            if( h->sps->vui.hrd.b_cbr_hrd )
+                h->fenc->hrd_timing.cpb_initial_arrival_time = rc->previous_cpb_final_arrival_time;
+            else
+            {
+                // NOTE: Equation C-4 has initial_cpb_removal_delay_offset which is hardcoded to zero in x264.
+                double cpb_earliest_arrival_time = cpb_nominal_removal_time - (double)rc->initial_cpb_removal_delay / 90000;
+                h->fenc->hrd_timing.cpb_initial_arrival_time = X264_MAX( rc->previous_cpb_final_arrival_time, cpb_earliest_arrival_time );
+            }
+        }
+        // Equation C-6
+        h->fenc->hrd_timing.cpb_final_arrival_time = rc->previous_cpb_final_arrival_time =
+            h->fenc->hrd_timing.cpb_initial_arrival_time + (double)(bits + filler_sei_size*8) / h->sps->vui.hrd.i_bit_rate_unscaled;
+
+        if( cpb_nominal_removal_time >= h->fenc->hrd_timing.cpb_final_arrival_time )
+            h->fenc->hrd_timing.cpb_removal_time = cpb_nominal_removal_time;
+        else
+        {
+            // access unit is so large it cannot be removed at the nominal cpb removal time
+            h->fenc->hrd_timing.cpb_removal_time = cpb_nominal_removal_time +
+                ceil( (h->fenc->hrd_timing.cpb_final_arrival_time - cpb_nominal_removal_time) *
+                    (double)h->sps->vui.i_time_scale / h->sps->vui.i_num_units_in_tick );
+        }
+
+        h->fenc->hrd_timing.dpb_output_time = (double)h->dpb_output_delay * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale +
+                                              h->fenc->hrd_timing.cpb_removal_time;
+    }
+
     return 0;
 fail:
     x264_log(h, X264_LOG_ERROR, "ratecontrol_end: stats file could not be written to\n");
@@ -1562,8 +1632,10 @@ 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 )
+static int update_vbv( x264_t *h, int bits, int *filler_sei_size )
 {
+    int filler = 0;
+
     x264_ratecontrol_t *rcc = h->rc;
     x264_ratecontrol_t *rct = h->thread[0]->rc;
 
@@ -1571,14 +1643,41 @@ static void update_vbv( x264_t *h, int bits )
         update_predictor( &rct->pred[h->sh.i_type], qp2qscale(rcc->qpa_rc), rcc->last_satd, bits );
 
     if( !rcc->b_vbv )
-        return;
+        return filler;
 
     rct->buffer_fill_final -= bits;
     if( rct->buffer_fill_final < 0 )
         x264_log( h, X264_LOG_WARNING, "VBV underflow (frame %d, %.0f bits)\n", h->i_frame, rct->buffer_fill_final );
     rct->buffer_fill_final = X264_MAX( rct->buffer_fill_final, 0 );
     rct->buffer_fill_final += rct->buffer_rate;
-    rct->buffer_fill_final = X264_MIN( rct->buffer_fill_final, rct->buffer_size );
+
+    if( h->sps->vui.hrd.b_cbr_hrd && rct->buffer_fill_final >= rct->buffer_size )
+    {
+        filler = (rct->buffer_fill_final - rct->buffer_size) / 8;
+        *filler_sei_size = filler + FILLER_OVERHEAD;
+        rct->buffer_fill_final -= *filler_sei_size * 8;
+    }
+    else
+        rct->buffer_fill_final = X264_MIN( rct->buffer_fill_final, rct->buffer_size );
+
+    return filler;
+}
+
+int x264_hrd_fullness( x264_t *h, int overhead )
+{
+    x264_ratecontrol_t *rct = h->thread[0]->rc;
+    double cpb_bits = rct->buffer_fill_final - overhead;
+    double bps = h->sps->vui.hrd.i_bit_rate_unscaled;
+    double cpb_size = h->sps->vui.hrd.i_cpb_size_unscaled;
+    double cpb_fullness = 90000.0*cpb_bits/bps;
+
+    if( cpb_fullness < 0 || cpb_fullness > cpb_size ) // why?
+    {
+         x264_log( h, X264_LOG_WARNING, "CPB %s: %.0lf bits in a %.0lf-bit buffer\n",
+                   cpb_fullness < 0 ? "underflow" : "overflow", cpb_bits, cpb_size );
+    }
+
+    return x264_clip3f( cpb_fullness + 0.5, 0, cpb_size ); // just lie if we are in a weird state
 }
 
 // provisionally update VBV according to the planned size of all frames currently in progress
@@ -2053,6 +2152,10 @@ void x264_thread_sync_ratecontrol( x264_t *cur, x264_t *prev, x264_t *next )
         COPY(expected_bits_sum);
         COPY(wanted_bits_window);
         COPY(bframe_bits);
+        COPY(initial_cpb_removal_delay);
+        COPY(current_cpb_delay);
+        COPY(nrt_first_access_unit);
+        COPY(previous_cpb_final_arrival_time);
 #undef COPY
     }
     //FIXME row_preds[] (not strictly necessary, but would improve prediction)
diff --git a/encoder/ratecontrol.h b/encoder/ratecontrol.h
index 5a8d088..e76f74d 100644
--- a/encoder/ratecontrol.h
+++ b/encoder/ratecontrol.h
@@ -37,7 +37,7 @@ int  x264_ratecontrol_slice_type( x264_t *, int i_frame );
 void x264_ratecontrol_set_weights( x264_t *h, x264_frame_t *frm );
 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 *filler );
 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 *);
@@ -45,6 +45,6 @@ int  x264_rc_analyse_slice( x264_t *h );
 int x264_weighted_reference_duplicate( x264_t *h, int i_ref, const x264_weight_t *w );
 void x264_threads_distribute_ratecontrol( x264_t *h );
 void x264_threads_merge_ratecontrol( x264_t *h );
-
+int x264_hrd_fullness( x264_t *h, int overhead );
 #endif
 
diff --git a/encoder/set.c b/encoder/set.c
index f79919b..b216141 100644
--- a/encoder/set.c
+++ b/encoder/set.c
@@ -28,6 +28,8 @@
 
 #define bs_write_ue bs_write_ue_big
 
+static int num_clock_ts[10] = { 0, 1, 1, 1, 2, 2, 3, 3, 2, 3 }; // Indexed by pic_struct values
+
 static void transpose( uint8_t *buf, int w )
 {
     int i, j;
@@ -179,15 +181,21 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
         sps->vui.i_chroma_loc_bottom = param->vui.i_chroma_loc;
     }
 
-    sps->vui.b_timing_info_present = 0;
-    if( param->i_timebase_num > 0 && param->i_timebase_den > 0 )
+    sps->vui.b_timing_info_present = !!(param->i_timebase_num && param->i_timebase_den > 0);
+
+    if( sps->vui.b_timing_info_present )
     {
-        sps->vui.b_timing_info_present = 1;
         sps->vui.i_num_units_in_tick = param->i_timebase_num;
         sps->vui.i_time_scale = param->i_timebase_den * 2;
         sps->vui.b_fixed_frame_rate = !param->b_vfr_input;
     }
 
+    sps->vui.b_vcl_hrd_parameters_present = 0; // we don't support VCL HRD
+    sps->vui.b_nal_hrd_parameters_present = param->b_nal_hrd;
+    sps->vui.b_pic_struct_present = !!param->b_pic_struct;
+
+    // NOTE: HRD related parts of the SPS are initialised in ratecontrol_new
+
     sps->vui.i_num_reorder_frames = param->i_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0;
     /* extra slot with pyramid so that we don't have to override the
      * order of forgetting old pictures */
@@ -203,11 +211,10 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
         sps->vui.i_max_bytes_per_pic_denom = 0;
         sps->vui.i_max_bits_per_mb_denom = 0;
         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.i_log2_max_mv_length_vertical = (int)log2( param->analyse.i_mv_range*4-1 ) + 1;
     }
 }
 
-
 void x264_sps_write( bs_t *s, x264_sps_t *sps )
 {
     bs_realign( s );
@@ -343,9 +350,30 @@ 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, 0 );      /* vcl_hrd_parameters_present_flag */
-        bs_write1( s, 0 );      /* pic_struct_present_flag */
+        bs_write1( s, sps->vui.b_nal_hrd_parameters_present );
+        if( sps->vui.b_nal_hrd_parameters_present )
+        {
+            bs_write_ue( s, sps->vui.hrd.i_cpb_cnt - 1 );
+            bs_write( s, 4, sps->vui.hrd.i_bit_rate_scale );
+            bs_write( s, 4, sps->vui.hrd.i_cpb_size_scale );
+
+            bs_write_ue( s, sps->vui.hrd.i_bit_rate_value - 1 );
+            bs_write_ue( s, sps->vui.hrd.i_cpb_size_value - 1 );
+
+            bs_write1( s, sps->vui.hrd.b_cbr_hrd );
+
+            bs_write( s, 5, sps->vui.hrd.i_initial_cpb_removal_delay_length - 1 );
+            bs_write( s, 5, sps->vui.hrd.i_cpb_removal_delay_length - 1 );
+            bs_write( s, 5, sps->vui.hrd.i_dpb_output_delay_length - 1 );
+            bs_write( s, 5, sps->vui.hrd.i_time_offset_length );
+        }
+
+        bs_write1( s, sps->vui.b_vcl_hrd_parameters_present );
+
+        if( sps->vui.b_nal_hrd_parameters_present || sps->vui.b_vcl_hrd_parameters_present )
+            bs_write1( s, 0 );   /* low_delay_hrd_flag */
+
+        bs_write1( s, sps->vui.b_pic_struct_present );
         bs_write1( s, sps->vui.b_bitstream_restriction );
         if( sps->vui.b_bitstream_restriction )
         {
@@ -476,7 +504,7 @@ void x264_sei_recovery_point_write( x264_t *h, bs_t *s, int recovery_frame_cnt )
     int payload_size;
 
     bs_realign( s );
-    bs_write( s, 8, 0x06 ); // payload_type = Recovery Point
+    bs_write( s, 8, SEI_USER_DATA_UNREGISTERED );
     payload_size = bs_size_ue( recovery_frame_cnt ) + 4;
 
     bs_write( s, 8, (payload_size + 7) / 8);
@@ -512,7 +540,7 @@ int x264_sei_version_write( x264_t *h, bs_t *s )
     length = strlen(version)+1+16;
 
     bs_realign( s );
-    bs_write( s, 8, 0x5 ); // payload_type = user_data_unregistered
+    bs_write( s, 8, SEI_USER_DATA_UNREGISTERED );
     // payload_size
     for( i = 0; i <= length-255; i += 255 )
         bs_write( s, 8, 255 );
@@ -534,6 +562,95 @@ fail:
     return -1;
 }
 
+void x264_sei_buffering_period_write( x264_t *h, bs_t *s, int initial_cpb_removal_delay )
+{
+    x264_sps_t *sps = h->sps;
+
+    int payload_size; // in bits
+
+    payload_size = bs_size_ue( sps->i_id );
+    if( sps->vui.b_nal_hrd_parameters_present )
+        payload_size += sps->vui.hrd.i_initial_cpb_removal_delay_length * 2;
+
+    bs_realign( s );
+    bs_write( s, 8, SEI_BUFFERING_PERIOD );
+    bs_write( s, 8, (payload_size + 7) / 8);
+
+    bs_write_ue( s, sps->i_id );
+
+    if( sps->vui.b_nal_hrd_parameters_present )
+    {
+        bs_write( s, sps->vui.hrd.i_initial_cpb_removal_delay_length, initial_cpb_removal_delay );
+        bs_write( s, sps->vui.hrd.i_initial_cpb_removal_delay_length, 0 ); /* initial_cpb_removal_delay_offset */
+    }
+
+    if( s->i_left&7 )
+        bs_write1( s, 1 );
+    if( s->i_left&7 )
+        bs_align_0( s );
+
+    bs_rbsp_trailing( s );
+    bs_flush( s );
+}
+
+void x264_sei_pic_timing_write( x264_t *h, bs_t *s, int cpb_removal_delay, int dpb_output_delay, int pic_struct )
+{
+    x264_sps_t *sps = h->sps;
+
+    int payload_size = 0; // in bits
+
+    if( sps->vui.b_nal_hrd_parameters_present || sps->vui.b_vcl_hrd_parameters_present ) // if CpbDpbDelaysPresentFlag
+        payload_size += sps->vui.hrd.i_cpb_removal_delay_length + sps->vui.hrd.i_dpb_output_delay_length;
+
+    if( sps->vui.b_pic_struct_present )
+    {
+        payload_size += 4; // size of (pic_struct)
+        payload_size += num_clock_ts[pic_struct];
+    }
+
+    bs_realign( s );
+    bs_write( s, 8, SEI_PIC_TIMING );
+    bs_write( s, 8, (payload_size + 7) / 8 );
+
+    if( sps->vui.b_nal_hrd_parameters_present || sps->vui.b_vcl_hrd_parameters_present )
+    {
+        bs_write( s, sps->vui.hrd.i_cpb_removal_delay_length, cpb_removal_delay );
+        bs_write( s, sps->vui.hrd.i_dpb_output_delay_length, dpb_output_delay );
+    }
+
+    if( sps->vui.b_pic_struct_present )
+    {
+        int i = 0;
+
+        bs_write( s, 4, pic_struct-1 ); // We use index 0 for "Auto"
+
+        // FIXME: is the use of num_clock_ts standardised
+        for( i = 0; i < num_clock_ts[pic_struct]; i++ )
+            bs_write1( s, 0 );
+    }
+
+    if( s->i_left&7 )
+        bs_write1( s, 1 );
+    if( s->i_left&7 )
+        bs_align_0( s );
+
+    bs_rbsp_trailing( s );
+    bs_flush( s );
+}
+
+void x264_filler_write( x264_t *h, bs_t *s, int filler )
+{
+    int i;
+
+    bs_realign( s );
+
+    for( i = 0; i < filler; i++ )
+        bs_write( s, 8, 0xff );
+
+    bs_rbsp_trailing( s );
+    bs_flush( 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 125f7e1..b3ed234 100644
--- a/encoder/set.h
+++ b/encoder/set.h
@@ -31,5 +31,8 @@ void x264_pps_write( bs_t *s, x264_pps_t *pps );
 void x264_sei_recovery_point_write( x264_t *h, bs_t *s, int recovery_frame_cnt );
 int  x264_sei_version_write( x264_t *h, bs_t *s );
 int  x264_validate_levels( x264_t *h, int verbose );
+void x264_sei_buffering_period_write( x264_t *h, bs_t *s, int initial_cpb_removal_delay );
+void x264_sei_pic_timing_write( x264_t *h, bs_t *s, int cpb_removal_delay, int dpb_output_delay, int pic_struct );
+void x264_filler_write( x264_t *h, bs_t *s, int filler );
 
 #endif
diff --git a/input/avs.c b/input/avs.c
index 522f8fe..b69c710 100644
--- a/input/avs.c
+++ b/input/avs.c
@@ -263,6 +263,7 @@ static int picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_hei
     pic->img.i_csp = i_csp;
     pic->img.i_plane = 3;
     pic->param = NULL;
+    pic->i_pic_struct = PIC_STRUCT_AUTO;
     return 0;
 }
 
diff --git a/output/flv.c b/output/flv.c
index b3e5d16..03501e4 100644
--- a/output/flv.c
+++ b/output/flv.c
@@ -154,9 +154,9 @@ static int write_headers( hnd_t handle, x264_nal_t *p_nal )
     flv_hnd_t *p_flv = handle;
     flv_buffer *c = p_flv->c;
 
-    int sei_size = p_nal[0].i_payload;
-    int sps_size = p_nal[1].i_payload;
-    int pps_size = p_nal[2].i_payload;
+    int sps_size = p_nal[0].i_payload;
+    int pps_size = p_nal[1].i_payload;
+    int sei_size = p_nal[2].i_payload;
 
     // SEI
     /* It is within the spec to write this as-is but for
@@ -167,10 +167,10 @@ static int write_headers( hnd_t handle, x264_nal_t *p_nal )
         return -1;
     p_flv->sei_len = sei_size;
 
-    memcpy( p_flv->sei, p_nal[0].p_payload, sei_size );
+    memcpy( p_flv->sei, p_nal[2].p_payload, sei_size );
 
     // SPS
-    uint8_t *sps = p_nal[1].p_payload + 4;
+    uint8_t *sps = p_nal[0].p_payload + 4;
 
     x264_put_byte( c, FLV_TAG_TYPE_VIDEO );
     x264_put_be24( c, 0 ); // rewrite later
@@ -196,7 +196,7 @@ static int write_headers( hnd_t handle, x264_nal_t *p_nal )
     // PPS
     x264_put_byte( c, 1 ); // number of pps
     x264_put_be16( c, pps_size - 4 );
-    flv_append_data( c, p_nal[2].p_payload + 4, pps_size - 4 );
+    flv_append_data( c, p_nal[1].p_payload + 4, pps_size - 4 );
 
     // rewrite data length info
     unsigned length = c->d_cur - p_flv->start;
diff --git a/output/matroska.c b/output/matroska.c
index 8e84f52..af11a36 100644
--- a/output/matroska.c
+++ b/output/matroska.c
@@ -107,13 +107,13 @@ static int write_headers( hnd_t handle, x264_nal_t *p_nal )
 {
     mkv_hnd_t *p_mkv = handle;
 
-    int sei_size = p_nal[0].i_payload;
-    int sps_size = p_nal[1].i_payload - 4;
-    int pps_size = p_nal[2].i_payload - 4;
+    int sps_size = p_nal[0].i_payload - 4;
+    int pps_size = p_nal[1].i_payload - 4;
+    int sei_size = p_nal[2].i_payload;
 
-    uint8_t *sei = p_nal[0].p_payload;
-    uint8_t *sps = p_nal[1].p_payload + 4;
-    uint8_t *pps = p_nal[2].p_payload + 4;
+    uint8_t *sps = p_nal[0].p_payload + 4;
+    uint8_t *pps = p_nal[1].p_payload + 4;
+    uint8_t *sei = p_nal[2].p_payload;
 
     int ret;
     uint8_t *avcC;
diff --git a/output/mp4.c b/output/mp4.c
index e3ad9c6..b3bb702 100644
--- a/output/mp4.c
+++ b/output/mp4.c
@@ -227,13 +227,13 @@ static int write_headers( hnd_t handle, x264_nal_t *p_nal )
     mp4_hnd_t *p_mp4 = handle;
     GF_AVCConfigSlot *p_slot;
 
-    int sei_size = p_nal[0].i_payload;
-    int sps_size = p_nal[1].i_payload - 4;
-    int pps_size = p_nal[2].i_payload - 4;
+    int sps_size = p_nal[0].i_payload - 4;
+    int pps_size = p_nal[1].i_payload - 4;
+    int sei_size = p_nal[2].i_payload;
 
-    uint8_t *sei = p_nal[0].p_payload;
-    uint8_t *sps = p_nal[1].p_payload + 4;
-    uint8_t *pps = p_nal[2].p_payload + 4;
+    uint8_t *sps = p_nal[0].p_payload + 4;
+    uint8_t *pps = p_nal[1].p_payload + 4;
+    uint8_t *sei = p_nal[2].p_payload;
 
     // SPS
 
diff --git a/x264.c b/x264.c
index 58bc1f4..f934949 100644
--- a/x264.c
+++ b/x264.c
@@ -57,6 +57,7 @@ typedef struct {
     hnd_t hin;
     hnd_t hout;
     FILE *qpfile;
+    int i_pulldown;
 } cli_opt_t;
 
 /* i/o file operation function pointer structs */
@@ -92,10 +93,27 @@ static const char * const muxer_names[] =
     0
 };
 
+static const char * const pulldown_names[] = { "", "32", "64", "double", "triple", "euro", 0 };
+
+typedef struct{
+    int mod;
+    int *pattern;
+    int i_delay;
+} cli_pulldown_t;
+
+enum pulldown_type_e
+{
+    X264_PULLDOWN_32     = 1,
+    X264_PULLDOWN_64     = 2,
+    X264_PULLDOWN_DOUBLE = 3,
+    X264_PULLDOWN_TRIPLE = 4,
+    X264_PULLDOWN_EURO   = 5,
+};
+
 static void Help( x264_param_t *defaults, int longhelp );
 static int  Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt );
 static int  Encode( x264_param_t *param, cli_opt_t *opt );
-
+static int  set_pulldown( cli_pulldown_t *pulldown, int i_pulldown );
 /****************************************************************************
  * main:
  ****************************************************************************/
@@ -339,7 +357,8 @@ static void Help( x264_param_t *defaults, int longhelp )
     else H1( "      --slices <integer>      Number of slices per frame\n" );
     H2( "      --slice-max-size <integer> Limit the size of each slice in bytes\n");
     H2( "      --slice-max-mbs <integer> Limit the size of each slice in macroblocks\n");
-    H0( "      --interlaced            Enable pure-interlaced mode\n" );
+    H0( "      --interlaced, --tff     Enable pure-interlaced mode (top field first)\n" );
+    H0( "      --bff                   Enable pure-interlaced mode (bottom field first)\n" );
     H2( "      --constrained-intra     Enable constrained intra prediction.\n" );
     H0( "\n" );
     H0( "Ratecontrol:\n" );
@@ -481,6 +500,11 @@ static void Help( x264_param_t *defaults, int longhelp )
                                        strtable_lookup( x264_colmatrix_names, defaults->vui.i_colmatrix ) );
     H2( "      --chromaloc <integer>   Specify chroma sample location (0 to 5) [%d]\n",
                                        defaults->vui.i_chroma_loc );
+
+    H0( "      --nal-hrd <string>      Signal HRD information (needed e.g. for Blu-Ray compliance)\n"
+        "                                  - vbr, cbr. (requires vbv-bufsize; cbr-hrd not allowed in .mp4)\n" );
+    H2( "      --pic-struct            Send pic_struct in Picture Timing SEI (on for pulldown or interlaced) \n" );
+
     H0( "\n" );
     H0( "Input/Output:\n" );
     H0( "\n" );
@@ -513,6 +537,8 @@ static void Help( x264_param_t *defaults, int longhelp )
     H2( "      --sps-id <integer>      Set SPS and PPS id numbers [%d]\n", defaults->i_sps_id );
     H2( "      --aud                   Use access unit delimiters\n" );
     H2( "      --force-cfr             Force constant framerate timestamp generation\n" );
+    H0( "      --pulldown <string>     Use soft pulldown and Timing SEI to change frame rate\n"
+        "                                  - 32, 64, double, triple, euro\n" );
     H0( "\n" );
 }
 
@@ -534,6 +560,7 @@ static void Help( x264_param_t *defaults, int longhelp )
 #define OPT_DEMUXER 271
 #define OPT_INDEX 272
 #define OPT_INTERLACED 273
+#define OPT_PULLDOWN 274
 
 static char short_options[] = "8A:B:b:f:hI:i:m:o:p:q:r:t:Vvw";
 static struct option long_options[] =
@@ -562,6 +589,8 @@ static struct option long_options[] =
     { "filter",      required_argument, NULL, 0 },
     { "deblock",     required_argument, NULL, 'f' },
     { "interlaced",        no_argument, NULL, OPT_INTERLACED },
+    { "tff",               no_argument, NULL, 0 },
+    { "bff",               no_argument, NULL, 0 },
     { "no-interlaced",     no_argument, NULL, OPT_INTERLACED },
     { "constrained-intra", no_argument, NULL, 0 },
     { "cabac",             no_argument, NULL, 0 },
@@ -668,6 +697,9 @@ static struct option long_options[] =
     { "colormatrix", required_argument, NULL, 0 },
     { "chromaloc",   required_argument, NULL, 0 },
     { "force-cfr",         no_argument, NULL, 0 },
+    { "pic-struct",        no_argument, NULL, 0 },
+    { "nal-hrd",     required_argument, NULL, 0 },
+    { "pulldown",    required_argument, NULL, OPT_PULLDOWN },
     {0, 0, 0, 0}
 };
 
@@ -682,9 +714,13 @@ static int select_output( const char *muxer, char *filename, x264_param_t *param
 #ifdef MP4_OUTPUT
         output = mp4_output;
         param->b_annexb = 0;
-        param->b_aud = 0;
         param->b_dts_compress = 0;
         param->b_repeat_headers = 0;
+        if( param->b_cbr_hrd )
+        {
+            fprintf( stderr, "x264 [warning]: cbr-hrd is not compatible with mp4\n" );
+            param->b_cbr_hrd = 0;
+        }
 #else
         fprintf( stderr, "x264 [error]: not compiled with MP4 output support\n" );
         return -1;
@@ -694,7 +730,6 @@ static int select_output( const char *muxer, char *filename, x264_param_t *param
     {
         output = mkv_output;
         param->b_annexb = 0;
-        param->b_aud = 0;
         param->b_dts_compress = 0;
         param->b_repeat_headers = 0;
     }
@@ -702,7 +737,6 @@ static int select_output( const char *muxer, char *filename, x264_param_t *param
     {
         output = flv_output;
         param->b_annexb = 0;
-        param->b_aud = 0;
         param->b_dts_compress = 1;
         param->b_repeat_headers = 0;
     }
@@ -791,6 +825,71 @@ static int select_input( const char *demuxer, char *used_demuxer, char *filename
     return 0;
 }
 
+static int set_pulldown( cli_pulldown_t *pulldown, int i_pulldown )
+{
+    switch( i_pulldown )
+    {
+        case X264_PULLDOWN_32:
+            pulldown->mod = 4;
+            pulldown->pattern = malloc( pulldown->mod*sizeof(int) );
+            if( !pulldown->pattern )
+                return -1;
+            pulldown->pattern[0] = PIC_STRUCT_TOP_BOTTOM_TOP;
+            pulldown->pattern[1] = PIC_STRUCT_BOTTOM_TOP;
+            pulldown->pattern[2] = PIC_STRUCT_BOTTOM_TOP_BOTTOM;
+            pulldown->pattern[3] = PIC_STRUCT_TOP_BOTTOM;
+            pulldown->i_delay = 1;
+            break;
+
+        case X264_PULLDOWN_64:
+            pulldown->mod = 2;
+            pulldown->pattern = malloc( pulldown->mod*sizeof(int) );
+            if( !pulldown->pattern )
+                return -1;
+            pulldown->pattern[0] = PIC_STRUCT_DOUBLE;
+            pulldown->pattern[1] = PIC_STRUCT_TRIPLE;
+            pulldown->i_delay = 4;
+            break;
+
+        case X264_PULLDOWN_DOUBLE:
+            pulldown->mod = 1;
+            pulldown->pattern = malloc( pulldown->mod*sizeof(int) );
+            if( !pulldown->pattern )
+                return -1;
+            pulldown->pattern[0] = PIC_STRUCT_DOUBLE;
+            pulldown->i_delay = 2;
+            break;
+
+        case X264_PULLDOWN_TRIPLE:
+            pulldown->mod = 1;
+            pulldown->i_delay = 4;
+            pulldown->pattern = malloc( pulldown->mod*sizeof(int) );
+            if( !pulldown->pattern )
+                return -1;
+            pulldown->pattern[0] = PIC_STRUCT_TRIPLE;
+            break;
+
+        case X264_PULLDOWN_EURO:
+            pulldown->mod = 24;
+            pulldown->i_delay = 1;
+            pulldown->pattern = malloc( pulldown->mod*sizeof(int) );
+            if( !pulldown->pattern )
+                return -1;
+
+            int j;
+            for( j = 0; j < 11; j++ )
+            {
+                pulldown->pattern[j+1] = PIC_STRUCT_BOTTOM_TOP;
+                pulldown->pattern[j+13] = PIC_STRUCT_TOP_BOTTOM;
+            }
+            pulldown->pattern[0] = PIC_STRUCT_TOP_BOTTOM_TOP;
+            pulldown->pattern[12] = PIC_STRUCT_BOTTOM_TOP_BOTTOM;
+            break;
+    }
+
+    return 0;
+}
+
 /*****************************************************************************
  * Parse:
  *****************************************************************************/
@@ -1159,6 +1258,16 @@ psy_failure:
             case OPT_INTERLACED:
                 b_user_interlaced = 1;
                 goto generic_option;
+            case OPT_PULLDOWN:
+                for( i = 0; pulldown_names[i] && strcasecmp( pulldown_names[i], optarg ); )
+                    i++;
+                if( !pulldown_names[i] )
+                {
+                    fprintf( stderr, "x264 [error]: invalid pulldown '%s'\n", optarg );
+                    return -1;
+                }
+                opt->i_pulldown = i;
+                break;
             default:
 generic_option:
             {
@@ -1445,6 +1554,7 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
 {
     x264_t *h;
     x264_picture_t pic;
+    cli_pulldown_t p_pulldown;
 
     int     i_frame, i_frame_total, i_frame_output;
     int64_t i_start, i_end;
@@ -1470,6 +1580,15 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
     param->i_frame_total = i_frame_total;
     i_update_interval = i_frame_total ? x264_clip3( i_frame_total / 1000, 1, 10 ) : 10;
 
+    /* set up pulldown */
+    if( opt->i_pulldown )
+    {
+        param->b_pulldown = 1;
+        if( set_pulldown( &p_pulldown, opt->i_pulldown ) < 0 )
+            return -1;
+        param->i_pulldown_delay = p_pulldown.i_delay;
+    }
+
     if( ( h = x264_encoder_open( param ) ) == NULL )
     {
         fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );
@@ -1554,6 +1673,9 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
             pic.i_qpplus1 = 0;
         }
 
+        if( opt->i_pulldown )
+            pic.i_pic_struct = p_pulldown.pattern[ i_frame % p_pulldown.mod ];
+
         i_frame_size = Encode_frame( h, opt->hout, &pic, &last_pts );
         if( i_frame_size < 0 )
             return -1;
@@ -1615,5 +1737,8 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
                  (double) i_file * 8 / ( 1000 * duration ) );
     }
 
+    if( opt->i_pulldown )
+        free(p_pulldown.pattern);
+
     return 0;
 }
diff --git a/x264.h b/x264.h
index 2550864..b97bcaa 100644
--- a/x264.h
+++ b/x264.h
@@ -176,6 +176,9 @@ typedef struct x264_param_t
     int         i_level_idc;
     int         i_frame_total; /* number of frames to encode if known, else 0 */
 
+    int         b_nal_hrd;       /* Use Buffering and Picture Timing SEI's to signal HRD */
+    int         b_cbr_hrd;       /* Use CBR-HRD mode with filler bytes */
+
     struct
     {
         /* they will be reduced to be 0 < x <= 65535 and prime */
@@ -320,6 +323,26 @@ typedef struct x264_param_t
                                  * by compressing them to be less than the second PTS.
                                  * Warning: this will change the timebase! */
 
+    int b_tff;
+
+    /* Custom Pulldown:
+     * Set b_pulldown to use pulldown and pass the correct pic_struct with the frame
+     *
+     * i_pulldown_delay is the number of effective extra frames added to the sequence as a result of pulldown (mandatory)
+     * i_pulldown_delay is added to each frame's dpb output delay
+     * timebase must also be appropriate for the pulldown changes that could be made
+     *
+     * Pulldown changes are not clearly defined in H.264. Therefore, it is the calling app's responsibility to manage this.
+     * Correct timestamps must also be input.
+     *
+     * Use the frame-exact x264_picture_t->param instead of the frame-inexact x264_encoder_reconfig to change pulldown on the fly.
+     */
+
+    int b_pulldown;
+    int i_pulldown_delay;
+
+    int b_pic_struct;
+
     /* Slicing parameters */
     int i_slice_max_size;    /* Max size per slice in bytes; includes estimated NAL overhead. */
     int i_slice_max_mbs;     /* Max number of MBs per slice; overrides i_slice_count. */
@@ -368,6 +391,29 @@ int x264_param_parse( x264_param_t *, const char *name, const char *value );
 /****************************************************************************
  * Picture structures and functions.
  ****************************************************************************/
+
+enum pic_struct_e
+{
+    PIC_STRUCT_AUTO         = 0,   // automatically decide (default)
+    PIC_STRUCT_PROGRESSIVE  = 1,   // progressive frame
+    // "TOP" and "BOTTOM" are not supported in x264 (PAFF only)
+    PIC_STRUCT_TOP_BOTTOM   = 4,   // top field followed by bottom
+    PIC_STRUCT_BOTTOM_TOP   = 5,   // bottom field followed by top
+    PIC_STRUCT_TOP_BOTTOM_TOP = 6, // top field, bottom field, top field repeated
+    PIC_STRUCT_BOTTOM_TOP_BOTTOM = 7, // bottom field, top field, bottom field repeated
+    PIC_STRUCT_DOUBLE       = 8,   // double frame
+    PIC_STRUCT_TRIPLE       = 9    // triple frame
+};
+
+typedef struct
+{
+    double cpb_initial_arrival_time;
+    double cpb_final_arrival_time;
+    double cpb_removal_time;
+
+    double dpb_output_time;
+} x264_hrd_t;
+
 typedef struct
 {
     int     i_csp;
@@ -388,6 +434,9 @@ typedef struct
     int     i_type;
     /* In: force quantizer for > 0 */
     int     i_qpplus1;
+    /* In: pic_struct, for pulldown/doubling/etc...used only if b_pic_timing_sei=1.
+     *     pic_struct_e for pic_struct inputs */
+    int     i_pic_struct;
     /* Out: whether this frame is a keyframe.  Important when using modes that result in
      * SEI recovery points being used instead of IDR frames. */
     int     b_keyframe;
@@ -405,6 +454,8 @@ typedef struct
     x264_param_t *param;
     /* In: raw data */
     x264_image_t img;
+    /* Out: HRD timing information. Output only when b_nal_hrd is set. */
+    x264_hrd_t hrd_timing;
     /* private user data. libx264 doesn't touch this,
        not even copy it from input to output frames. */
     void *opaque;
@@ -436,6 +487,7 @@ enum nal_unit_type_e
     NAL_SPS         = 7,
     NAL_PPS         = 8,
     NAL_AUD         = 9,
+    NAL_FILLER      = 12,    
     /* ref_idc == 0 for 6,9,10,11,12 */
 };
 enum nal_priority_e
