]> git.sesse.net Git - x264/commitdiff
Blu-ray support: NAL-HRD, VFR ratecontrol, filler, pulldown
authorKieran Kunhya <kieran@kunhya.com>
Tue, 2 Mar 2010 08:57:10 +0000 (00:57 -0800)
committerFiona Glaser <fiona@x264.com>
Sat, 27 Mar 2010 19:47:01 +0000 (12:47 -0700)
x264 can now generate Blu-ray-compliant streams for authoring Blu-ray Discs!
Compliance tested using Sony BD-ROM Verifier 1.21.
Thanks to The Criterion Collection for sponsoring compliance testing!

An example command, using constant quality mode, for 1080p24 content:
x264 --crf 16 --preset veryslow --tune film --weightp 0 --bframes 3 --nal-hrd vbr --vbv-maxrate 40000 --vbv-bufsize 30000 --level 4.1 --keyint 24 --b-pyramid strict --slices 4 --aud --colorprim "bt709" --transfer "bt709" --colormatrix "bt709" --sar 1:1 <input> -o <output>

This command is much more complicated than usual due to the very complicated restrictions the Blu-ray spec has.
Most options after "tune" are required by the spec.
--weightp 0 is not, but there are known bugged Blu-ray player chipsets (Mediatek, notably) that will decode video with --weightp 1 or 2 incorrectly.
Furthermore, note the Blu-ray spec has very strict limitations on allowed resolution/fps combinations.
Examples include 1080p @ 24000/1001fps (NTSC FILM) and 720p @ 60000/1001fps.

Detailed features introduced in this patch:

Full NAL-HRD compliance, with both VBR (no filler) and CBR (filler) modes.
Can be enabled with --nal-hrd vbr/cbr.
libx264 now returns HRD timing information to the caller in the form of an x264_hrd_t.
x264cli doesn't currently use it, but this information is critical for compliant TS muxing.

Full VFR ratecontrol support: VBV, 1-pass ABR, and 2-pass modes.
This means that, even without knowing the average framerate, x264 can achieve a correct bitrate in target bitrate modes.
Note that this changes the statsfile format; first pass encodes make before this patch will have to be re-run.

Pulldown support: libx264 allows the calling application to specify a pulldown mode for each frame.
This is similar to the way that RFFs (Repeat Field Flags) work in MPEG-2.
Note that libx264 does not modify timestamps: it assumes the calling application has set timestamps correctly for pulldown!
x264cli contains an example implementation of caller-side pulldown code.

Pic_struct support: necessary for pulldown and allows interlaced signalling.
Also signal TFF vs BFF with delta_poc_bottom: should significantly improve interlaced compression.
--tff and --bff should be preferred to the old --interlaced in order to tell x264 what field order to use.

Huge thanks to Alex Giladi and Lamont Alston for their work on code that eventually became part of this patch.

18 files changed:
common/common.c
common/common.h
common/frame.c
common/frame.h
common/osdep.h
common/set.h
encoder/encoder.c
encoder/ratecontrol.c
encoder/ratecontrol.h
encoder/set.c
encoder/set.h
encoder/slicetype.c
input/avs.c
output/flv.c
output/matroska.c
output/mp4.c
x264.c
x264.h

index 923b4e994dd885a683439e631534149ea8033f0f..a4ec2bb4b4624fa66df4a9ca0f7b702aa87fbc9c 100644 (file)
@@ -158,6 +158,9 @@ void x264_param_default( x264_param_t *param )
     param->b_aud = 0;
     param->b_vfr_input = 1;
     param->b_dts_compress = 0;
+    param->i_nal_hrd = X264_NAL_HRD_NONE;
+    param->b_tff = 1;
+    param->b_pic_struct = 0;
 }
 
 static int x264_param_apply_preset( x264_param_t *param, const char *preset )
@@ -331,6 +334,7 @@ static int x264_param_apply_tune( x264_param_t *param, const char *tune )
             param->i_sync_lookahead = 0;
             param->i_bframe = 0;
             param->b_sliced_threads = 1;
+            param->b_vfr_input = 0;
         }
         else if( !strncasecmp( s, "touhou", 6 ) )
         {
@@ -676,6 +680,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 = p->b_tff = 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")
@@ -895,6 +906,10 @@ 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")
+        b_error |= parse_enum( value, x264_nal_hrd_names, &p->i_nal_hrd );
+    OPT("pic-struct")
+        p->b_pic_struct = atobool(value);
     else
         return X264_PARAM_BAD_NAME;
 #undef OPT
@@ -970,6 +985,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;
 }
 
@@ -1149,6 +1165,7 @@ char *x264_param2string( x264_param_t *p, int b_res )
     {
         s += sprintf( s, "%dx%d ", p->i_width, p->i_height );
         s += sprintf( s, "fps=%d/%d ", p->i_fps_num, p->i_fps_den );
+        s += sprintf( s, "timebase=%d/%d ", p->i_timebase_num, p->i_timebase_den );
     }
 
     s += sprintf( s, "cabac=%d", p->b_cabac );
@@ -1180,7 +1197,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 );
@@ -1233,6 +1251,8 @@ char *x264_param2string( x264_param_t *p, int b_res )
             s += sprintf( s, " zones" );
     }
 
+    if( p->rc.i_vbv_buffer_size )
+        s += sprintf( s, " nal_hrd=%s", x264_nal_hrd_names[p->i_nal_hrd] );
     return buf;
 }
 
index 878eee24aee2722ed49a95ccfe1543ba579586a1..8b79e92aaa5b1c56ae1a85e6855c045d69e4fa3c 100644 (file)
@@ -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   = 4,
+    SEI_USER_DATA_UNREGISTERED = 5,
+    SEI_RECOVERY_POINT         = 6,
+};
+
 typedef struct
 {
     x264_sps_t *sps;
@@ -233,7 +247,7 @@ typedef struct
 
     int i_idr_pic_id;   /* -1 if nal_type != 5 */
 
-    int i_poc_lsb;
+    int i_poc;
     int i_delta_poc_bottom;
 
     int i_delta_poc[2];
@@ -367,6 +381,15 @@ 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_disp_fields_last_frame;
+    int             i_prev_duration; /* Duration of previous frame */
+    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 */
+    int             i_coded_fields_lookahead; /* Use separate counters for lookahead */
+    int             i_cpb_delay_lookahead;
+
     /* We use only one SPS and one PPS */
     x264_sps_t      sps_array[1];
     x264_sps_t      *sps;
@@ -432,6 +455,8 @@ struct x264_t
         int64_t i_bframe_delay_time;
         int64_t i_init_delta;
         int64_t i_prev_reordered_pts[2];
+        int64_t i_largest_pts;
+        int64_t i_second_largest_pts;
         int b_have_lowres;  /* Whether 1/2 resolution luma planes are being used */
         int b_have_sub8x8_esa;
     } frames;
@@ -449,7 +474,9 @@ struct x264_t
     x264_frame_t    *fref1[16+3];     /* ref list 1 */
     int             b_ref_reorder[2];
 
-
+    /* hrd */
+    int initial_cpb_removal_delay;
+    int64_t first_pts;
 
     /* Current MB DCT coeffs */
     struct
index 03e7c3d414fd1aab7011c0577f981ba0ecc10a69..a81ef4480eed288e6715b1181574aa20f6536a65 100644 (file)
@@ -73,6 +73,15 @@ 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->i_duration =
+    frame->i_cpb_duration =
+    frame->i_dpb_output_delay =
+    frame->i_cpb_delay = 0;
+    frame->i_coded_fields_lookahead =
+    frame->i_cpb_delay_lookahead = -1;
+
     frame->orig = frame;
 
     /* all 4 luma planes allocated together, since the cacheline split code
@@ -227,6 +236,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++ )
     {
index 0566b1ea50f930ab7dedb720d903ac4dc807482f..419da0890f30a019744b477c7978ed85e78a4e94 100644 (file)
@@ -36,12 +36,18 @@ typedef struct x264_frame
     int     i_qpplus1;
     int64_t i_pts;
     int64_t i_reordered_pts;
+    int     i_duration;  /* in SPS time_scale units (i.e 2 * timebase units) used for vfr */
+    int     i_cpb_duration;
+    int     i_cpb_delay; /* in SPS time_scale units (i.e 2 * timebase units) */
+    int     i_dpb_output_delay;
     x264_param_t *param;
 
     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_keyframe;
     uint8_t b_fdec;
     uint8_t b_last_minigop_bframe; /* this frame is the last b in a sequence of bframes */
@@ -109,9 +115,15 @@ 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];
+    double f_planned_cpb_duration[X264_LOOKAHEAD_MAX+1];
+    int i_coded_fields_lookahead;
+    int i_cpb_delay_lookahead;
 
     /* threading */
     int     i_lines_completed; /* in pixels */
index 7f680ed039ad2ba269f28559467d7894c3e60de8..5223ef5f463cdbbda1253f16eb4dd5f1df0fc763 100644 (file)
@@ -221,6 +221,7 @@ 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 )
 {
@@ -233,6 +234,18 @@ 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};
+    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
index e1b9cd908efe14fc65f3333ebbf79eb45941230b..f55e6e347fb8232af5ec9d6ec1c9a8e1042edad6 100644 (file)
@@ -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;
index fa6fe0bdd779f392a908c5e5ce9b828eba12323d..11a3bf5f7e14ac1fde6c00ce93d2fa357c1d6337 100644 (file)
@@ -39,8 +39,6 @@
 
 //#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,
@@ -101,7 +99,7 @@ static void x264_slice_header_init( x264_t *h, x264_slice_header_t *sh,
     sh->i_idr_pic_id = i_idr_pic_id;
 
     /* poc stuff, fixed later */
-    sh->i_poc_lsb = 0;
+    sh->i_poc = 0;
     sh->i_delta_poc_bottom = 0;
     sh->i_delta_poc[0] = 0;
     sh->i_delta_poc[1] = 0;
@@ -204,7 +202,7 @@ static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal
 
     if( sh->sps->i_poc_type == 0 )
     {
-        bs_write( s, sh->sps->i_log2_max_poc_lsb, sh->i_poc_lsb & ((1<<sh->sps->i_log2_max_poc_lsb)-1) );
+        bs_write( s, sh->sps->i_log2_max_poc_lsb, sh->i_poc & ((1<<sh->sps->i_log2_max_poc_lsb)-1) );
         if( sh->pps->b_pic_order && !sh->b_field_pic )
         {
             bs_write_se( s, sh->i_delta_poc_bottom );
@@ -777,6 +775,22 @@ static int x264_validate_parameters( x264_t *h )
         h->param.analyse.b_ssim = 0;
     }
 
+    if( h->param.b_interlaced )
+        h->param.b_pic_struct = 1;
+
+    if( h->param.i_nal_hrd && !h->param.rc.i_vbv_buffer_size )
+    {
+        x264_log( h, X264_LOG_WARNING, "NAL HRD parameters require VBV parameters\n" );
+        h->param.i_nal_hrd = X264_NAL_HRD_NONE;
+    }
+
+    if( h->param.i_nal_hrd == X264_NAL_HRD_CBR &&
+       (h->param.rc.i_bitrate != h->param.rc.i_vbv_max_bitrate || !h->param.rc.i_vbv_max_bitrate) )
+    {
+        x264_log( h, X264_LOG_WARNING, "CBR HRD requires constant bitrate\n" );
+        h->param.i_nal_hrd = X264_NAL_HRD_VBR;
+    }
+
     /* 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 );
@@ -790,6 +804,8 @@ static int x264_validate_parameters( x264_t *h )
     BOOLIFY( b_aud );
     BOOLIFY( b_repeat_headers );
     BOOLIFY( b_annexb );
+    BOOLIFY( b_vfr_input );
+    BOOLIFY( b_pic_struct );
     BOOLIFY( analyse.b_transform_8x8 );
     BOOLIFY( analyse.b_weighted_bipred );
     BOOLIFY( analyse.b_chroma_me );
@@ -936,6 +952,8 @@ x264_t *x264_encoder_open( x264_param_t *param )
     h->frames.i_delay += h->i_thread_frames - 1;
     h->frames.i_delay = X264_MIN( h->frames.i_delay, X264_LOOKAHEAD_MAX );
     h->frames.i_delay += h->param.i_sync_lookahead;
+    h->frames.i_delay += h->param.b_vfr_input && (h->param.rc.i_rc_method == X264_RC_ABR || h->param.rc.b_stat_write
+                                                 || h->param.rc.i_vbv_buffer_size);
     h->frames.i_bframe_delay = h->param.i_bframe ? (h->param.i_bframe_pyramid ? 2 : 1) : 0;
 
     h->frames.i_max_ref0 = h->param.i_frame_reference;
@@ -953,6 +971,7 @@ x264_t *x264_encoder_open( x264_param_t *param )
 
     h->frames.i_last_keyframe = - h->param.i_keyint_max;
     h->frames.i_input    = 0;
+    h->frames.i_largest_pts = h->frames.i_second_largest_pts = -1;
 
     CHECKED_MALLOCZERO( h->frames.unused[0], (h->frames.i_delay + 3) * sizeof(x264_frame_t *) );
     /* Allocate room for max refs plus a few extra just in case. */
@@ -963,7 +982,8 @@ 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_cpb_delay = h->i_coded_fields = h->i_disp_fields = h->i_prev_duration = 0;
+    h->i_disp_fields_last_frame = -1;
     x264_rdo_init();
 
     /* init CPU functions */
@@ -1071,6 +1091,12 @@ x264_t *x264_encoder_open( x264_param_t *param )
     if( x264_ratecontrol_new( h ) < 0 )
         goto fail;
 
+    if( h->param.i_nal_hrd )
+    {
+        x264_log( h, X264_LOG_DEBUG, "HRD bitrate: %i bits/sec\n", h->sps->vui.hrd.i_bit_rate_unscaled );
+        x264_log( h, X264_LOG_DEBUG, "CPB size: %i bits\n", h->sps->vui.hrd.i_cpb_size_unscaled );
+    }
+
     if( h->param.psz_dump_yuv )
     {
         /* create or truncate the reconstructed video file */
@@ -1105,6 +1131,7 @@ fail:
  ****************************************************************************/
 int x264_encoder_reconfig( x264_t *h, x264_param_t *param )
 {
+    int rc_reconfig = 0;
     h = h->thread[h->thread[0]->i_thread_phase];
     x264_set_aspect_ratio( h, param, 0 );
 #define COPY(var) h->param.var = param->var
@@ -1144,6 +1171,7 @@ 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 );
+
     /* VBV can't be turned on if it wasn't on to begin with */
     if( h->param.rc.i_vbv_max_bitrate > 0 && h->param.rc.i_vbv_buffer_size > 0 &&
           param->rc.i_vbv_max_bitrate > 0 &&   param->rc.i_vbv_buffer_size > 0 )
@@ -1151,8 +1179,14 @@ int x264_encoder_reconfig( x264_t *h, x264_param_t *param )
         COPY( rc.i_vbv_max_bitrate );
         COPY( rc.i_vbv_buffer_size );
         COPY( rc.i_bitrate );
+        rc_reconfig = 1;
+    }
+    if( h->param.rc.f_rf_constant != param->rc.f_rf_constant )
+    {
+        COPY( rc.f_rf_constant );
+        rc_reconfig = 1;
     }
-    COPY( rc.f_rf_constant );
+
 #undef COPY
 
     mbcmp_init( h );
@@ -1164,7 +1198,7 @@ int x264_encoder_reconfig( x264_t *h, x264_param_t *param )
      * vbv-bufsize
      * crf
      * bitrate (CBR only) */
-    if( !ret )
+    if( !ret && rc_reconfig )
         x264_ratecontrol_init_reconfigurable( h, 0 );
 
     return ret;
@@ -1213,10 +1247,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. */
@@ -1225,13 +1263,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 long_startcode = !i || h->out.nal[i].i_type == NAL_SPS || h->out.nal[i].i_type == NAL_PPS;
         int size = x264_nal_encode( nal_buffer, &h->out.nal[i], h->param.b_annexb, long_startcode );
@@ -1240,7 +1280,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);
 }
 
 /****************************************************************************
@@ -1254,11 +1294,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 );
@@ -1272,7 +1307,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;
@@ -1695,8 +1737,15 @@ 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;
+        h->sh.i_poc = h->fdec->i_poc;
+        if( h->param.b_interlaced )
+        {
+            h->sh.i_delta_poc_bottom = h->param.b_tff ? 1 : -1;
+            if( h->sh.i_delta_poc_bottom == -1 )
+                h->sh.i_poc = h->fdec->i_poc + 1;
+        }
+        else
+            h->sh.i_delta_poc_bottom = 0;
     }
     else if( h->sps->i_poc_type == 1 )
     {
@@ -2106,6 +2155,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 )
     {
@@ -2153,6 +2203,27 @@ 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( h->param.b_vfr_input && fenc->i_pts <= h->frames.i_largest_pts )
+            x264_log( h, X264_LOG_WARNING, "non-strictly-monotonic PTS\n" );
+
+        h->frames.i_second_largest_pts = h->frames.i_largest_pts;
+        h->frames.i_largest_pts = fenc->i_pts;
+
+        if( (fenc->i_pic_struct < PIC_STRUCT_AUTO) || (fenc->i_pic_struct > PIC_STRUCT_TRIPLE) )
+            fenc->i_pic_struct = PIC_STRUCT_AUTO;
+
+        if( fenc->i_pic_struct == PIC_STRUCT_AUTO )
+        {
+            int b_interlaced = fenc->param ? fenc->param->b_interlaced : h->param.b_interlaced;
+            if( b_interlaced )
+            {
+                int b_tff = fenc->param ? fenc->param->b_tff : h->param.b_tff;
+                fenc->i_pic_struct = b_tff ? PIC_STRUCT_TOP_BOTTOM : PIC_STRUCT_BOTTOM_TOP;
+            }
+            else
+                fenc->i_pic_struct = PIC_STRUCT_PROGRESSIVE;
+        }
+
         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 )
@@ -2198,6 +2269,8 @@ int     x264_encoder_encode( x264_t *h,
     /* ------------------- Get frame to be encoded ------------------------- */
     /* 4: get picture to encode */
     h->fenc = x264_frame_shift( h->frames.current );
+    if( h->i_frame == 0 )
+        h->first_pts = h->fenc->i_reordered_pts;
     if( h->fenc->param )
     {
         x264_encoder_reconfig( h, h->fenc->param );
@@ -2301,13 +2374,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->param.b_annexb && h->out.i_nal-1);
     }
 
     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;
@@ -2329,22 +2401,11 @@ int     x264_encoder_encode( x264_t *h,
         h->fdec->i_pir_end_col = h->fdec->f_pir_position+0.5;
     }
 
-    /* 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 );
@@ -2360,16 +2421,49 @@ 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, overhead*8 );
+
+            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 - (h->param.b_annexb && h->out.i_nal-1);
+        }
+
+        if( h->param.b_repeat_headers && 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 - (h->param.b_annexb && h->out.i_nal-1);
+        }
+
         if( h->fenc->i_type != X264_TYPE_IDR )
         {
             int time_to_recovery = X264_MIN( h->sps->i_mb_width - 1, h->param.i_keyint_max ) + h->param.i_bframe;
             x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
             x264_sei_recovery_point_write( h, &h->out.bs, time_to_recovery );
             x264_nal_end( h );
-            overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
+            overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
         }
     }
 
+    /* generate sei pic timing */
+    if( h->sps->vui.b_pic_struct_present || h->sps->vui.b_nal_hrd_parameters_present )
+    {
+        x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+        x264_sei_pic_timing_write( h, &h->out.bs, h->fenc->i_cpb_delay, h->fenc->i_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->param.b_annexb && h->out.i_nal-1);
+    }
+
     /* Init the rate control */
     /* FIXME: Include slice header bit cost. */
     x264_ratecontrol_start( h, h->fenc->i_qpplus1, overhead*8 );
@@ -2443,13 +2537,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 )
@@ -2483,7 +2571,8 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
     }
     else
         pic_out->i_dts = h->fenc->i_reordered_pts;
-    assert( pic_out->i_pts >= pic_out->i_dts );
+    if( pic_out->i_pts < pic_out->i_dts )
+        x264_log( h, X264_LOG_WARNING, "invalid DTS: PTS is less than DTS\n" );
 
     pic_out->img.i_plane = h->fdec->i_plane;
     for(i = 0; i < 3; i++)
@@ -2496,9 +2585,40 @@ 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;
+
+    while( filler > 0 )
+    {
+        int f, overhead;
+        overhead = (FILLER_OVERHEAD - h->param.b_annexb);
+        if( h->param.i_slice_max_size && filler > h->param.i_slice_max_size )
+        {
+            int next_size = filler - h->param.i_slice_max_size;
+            int overflow = X264_MAX( overhead - next_size, 0 );
+            f = h->param.i_slice_max_size - overhead - overflow;
+        }
+        else
+            f = X264_MAX( 0, filler - overhead );
+
+        x264_nal_start( h, NAL_FILLER, NAL_PRIORITY_DISPOSABLE );
+        x264_filler_write( h, &h->out.bs, f );
+        if( x264_nal_end( h ) )
+            return -1;
+        int total_size = x264_encoder_encapsulate_nals( h, h->out.i_nal-1 );
+        frame_size += total_size;
+        filler -= total_size;
+    }
+
+    /* 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 --------------------- */
@@ -2812,7 +2932,15 @@ void    x264_encoder_close  ( x264_t *h )
                             h->stat.i_frame_count[SLICE_TYPE_B];
         int64_t i_mb_count = i_count * h->mb.i_mb_count;
         float fps = (float) h->param.i_fps_num / h->param.i_fps_den;
-        float f_bitrate = fps * SUM3(h->stat.i_frame_size) / i_count / 125;
+        float f_bitrate;
+        /* duration algorithm fails with one frame */
+        if( i_count == 1 )
+            f_bitrate = fps * SUM3(h->stat.i_frame_size) / i_count / 125;
+        else
+        {
+            float duration = (float)(2 * h->frames.i_largest_pts - h->frames.i_second_largest_pts) * h->param.i_timebase_num / h->param.i_timebase_den;
+            f_bitrate = SUM3(h->stat.i_frame_size) / duration / 125;
+        }
 
         if( h->pps->b_transform_8x8_mode )
         {
index bf27936e9517523580e78a6419d135148958f9db..c95bbaf42c41bd85b7c0993538605af64ca4bcdb 100644 (file)
@@ -55,6 +55,8 @@ typedef struct
     int16_t i_weight_denom;
     int refcount[16];
     int refs;
+    int i_duration;
+    int i_cpb_duration;
 } ratecontrol_entry_t;
 
 typedef struct
@@ -94,6 +96,7 @@ 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 vbv_max_rate;        /* # of bits added to buffer_fill per second */
     predictor_t *pred;          /* predict frame size from satd */
     int single_frame_vbv;
 
@@ -149,13 +152,18 @@ struct x264_ratecontrol_t
     int i_zones;
     x264_zone_t *zones;
     x264_zone_t *prev_zone;
+
+    /* hrd stuff */
+    int initial_cpb_removal_delay;
+    double nrt_first_access_unit; /* nominal removal time */
+    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 );
 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 );
@@ -400,6 +408,16 @@ void x264_ratecontrol_init_reconfigurable( x264_t *h, int b_init )
     if( !b_init && rc->b_2pass )
         return;
 
+    if( h->param.rc.i_rc_method == X264_RC_CRF )
+    {
+        /* Arbitrary rescaling to make CRF somewhat similar to QP.
+         * Try to compensate for MB-tree's effects as well. */
+        double base_cplx = h->mb.i_mb_count * (h->param.i_bframe ? 120 : 80);
+        double mbtree_offset = h->param.rc.b_mb_tree ? (1.0-h->param.rc.f_qcompress)*13.5 : 0;
+        rc->rate_factor_constant = pow( base_cplx, 1 - rc->qcompress )
+                                 / qp2qscale( h->param.rc.f_rf_constant + mbtree_offset );
+    }
+
     if( h->param.rc.i_vbv_max_bitrate > 0 && h->param.rc.i_vbv_buffer_size > 0 )
     {
         if( h->param.rc.i_vbv_buffer_size < (int)(h->param.rc.i_vbv_max_bitrate / rc->fps) )
@@ -413,8 +431,59 @@ void x264_ratecontrol_init_reconfigurable( x264_t *h, int b_init )
            so if the stream starts as CBR, keep it CBR. */
         if( rc->b_vbv_min_rate )
             h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate;
-        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.i_nal_hrd && b_init )
+        {
+            h->sps->vui.hrd.i_cpb_cnt = 1;
+            h->sps->vui.hrd.b_cbr_hrd = h->param.i_nal_hrd == X264_NAL_HRD_CBR;
+            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
+
+            // arbitrary
+            #define MAX_DURATION 0.5
+
+            int max_cpb_output_delay = h->param.i_keyint_max * MAX_DURATION * h->sps->vui.i_time_scale / h->sps->vui.i_num_units_in_tick;
+            int max_dpb_output_delay = h->sps->vui.i_max_dec_frame_buffering * MAX_DURATION * h->sps->vui.i_time_scale / h->sps->vui.i_num_units_in_tick;
+            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_output_delay ), 4, 32 );
+            h->sps->vui.hrd.i_dpb_output_delay_length  = x264_clip3( 32 - x264_clz( max_dpb_output_delay ), 4, 32 );
+
+            #undef MAX_DURATION
+
+            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 );
+        }
+        else if( h->param.i_nal_hrd && !b_init )
+        {
+            x264_log( h, X264_LOG_WARNING, "VBV parameters cannot be changed when NAL HRD is in use\n" );
+            return;
+        }
+
+        rc->buffer_rate = vbv_max_bitrate / rc->fps;
+        rc->vbv_max_rate = vbv_max_bitrate;
+        rc->buffer_size = vbv_buffer_size;
         rc->single_frame_vbv = rc->buffer_rate * 1.1 > rc->buffer_size;
         rc->cbr_decay = 1.0 - rc->buffer_rate / rc->buffer_size
                       * 0.5 * X264_MAX(0, 1.5 - rc->buffer_rate * rc->fps / rc->bitrate);
@@ -430,15 +499,6 @@ void x264_ratecontrol_init_reconfigurable( x264_t *h, int b_init )
                           && h->param.rc.i_vbv_max_bitrate <= h->param.rc.i_bitrate;
         }
     }
-    if( h->param.rc.i_rc_method == X264_RC_CRF )
-    {
-        /* Arbitrary rescaling to make CRF somewhat similar to QP.
-         * Try to compensate for MB-tree's effects as well. */
-        double base_cplx = h->mb.i_mb_count * (h->param.i_bframe ? 120 : 80);
-        double mbtree_offset = h->param.rc.b_mb_tree ? (1.0-h->param.rc.f_qcompress)*13.5 : 0;
-        rc->rate_factor_constant = pow( base_cplx, 1 - rc->qcompress )
-                                 / qp2qscale( h->param.rc.f_rf_constant + mbtree_offset );
-    }
 }
 
 int x264_ratecontrol_new( x264_t *h )
@@ -591,6 +651,18 @@ int x264_ratecontrol_new( x264_t *h )
                 return -1;
             }
 
+            if( ( p = strstr( opts, "timebase=" ) ) && sscanf( p, "timebase=%d/%d", &i, &j ) != 2 )
+            {
+                x264_log( h, X264_LOG_ERROR, "timebase specified in stats file not valid\n" );
+                return -1;
+            }
+            if( i != h->param.i_timebase_num || j != h->param.i_timebase_den )
+            {
+                x264_log( h, X264_LOG_ERROR, "timebase mismatch with 1st pass (%d/%d vs %d/%d)\n",
+                          h->param.i_timebase_num, h->param.i_timebase_den, i, j );
+                return -1;
+            }
+
             CMP_OPT_FIRST_PASS( "wpredp", X264_MAX( 0, h->param.analyse.i_weighted_pred ) );
             CMP_OPT_FIRST_PASS( "bframes", h->param.i_bframe );
             CMP_OPT_FIRST_PASS( "b_pyramid", h->param.i_bframe_pyramid );
@@ -681,8 +753,8 @@ int x264_ratecontrol_new( x264_t *h )
             rce = &rc->entry[frame_number];
             rce->direct_mode = 0;
 
-            e += sscanf(p, " in:%*d out:%*d type:%c q:%f tex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d d:%c",
-                   &pict_type, &qp, &rce->tex_bits,
+            e += sscanf(p, " in:%*d out:%*d type:%c dur:%d cpbdur:%d q:%f tex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d d:%c",
+                   &pict_type, &rce->i_duration, &rce->i_cpb_duration, &qp, &rce->tex_bits,
                    &rce->mv_bits, &rce->misc_bits, &rce->i_count, &rce->p_count,
                    &rce->s_count, &rce->direct_mode);
 
@@ -733,7 +805,7 @@ int x264_ratecontrol_new( x264_t *h )
                     break;
                 default:  e = -1; break;
             }
-            if(e < 10)
+            if(e < 12)
             {
 parse_error:
                 x264_log(h, X264_LOG_ERROR, "statistics are damaged at line %d, parser out=%d\n", i, e);
@@ -1042,24 +1114,31 @@ void x264_ratecontrol_start( x264_t *h, int i_force_qp, int overhead )
     {
         memset( h->fdec->i_row_bits, 0, h->sps->i_mb_height * sizeof(int) );
         rc->row_pred = &rc->row_preds[h->sh.i_type];
+        rc->buffer_rate = h->fenc->i_cpb_duration * rc->vbv_max_rate * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
         update_vbv_plan( h, overhead );
 
         const x264_level_t *l = x264_levels;
         while( l->level_idc != 0 && l->level_idc != h->param.i_level_idc )
             l++;
 
+        int mincr = l->mincr;
+
+        /* Blu-ray requires this */
+        if( l->level_idc == 41 && h->param.i_nal_hrd )
+            mincr = 4;
+
         /* The spec has a bizarre special case for the first frame. */
         if( h->i_frame == 0 )
         {
             //384 * ( Max( PicSizeInMbs, fR * MaxMBPS ) + MaxMBPS * ( tr( 0 ) - tr,n( 0 ) ) ) / MinCR
             double fr = 1. / 172;
             int pic_size_in_mbs = h->sps->i_mb_width * h->sps->i_mb_height;
-            rc->frame_size_maximum = 384 * 8 * X264_MAX( pic_size_in_mbs, fr*l->mbps ) / l->mincr;
+            rc->frame_size_maximum = 384 * 8 * X264_MAX( pic_size_in_mbs, fr*l->mbps ) / mincr;
         }
         else
         {
             //384 * MaxMBPS * ( tr( n ) - tr( n - 1 ) ) / MinCR
-            rc->frame_size_maximum = 384 * 8 * (1 / rc->fps) * l->mbps / l->mincr;
+            rc->frame_size_maximum = 384 * 8 * ((double)h->fenc->i_cpb_duration * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale) * l->mbps / mincr;
         }
     }
 
@@ -1317,7 +1396,7 @@ 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;
@@ -1346,9 +1425,10 @@ int x264_ratecontrol_end( x264_t *h, int bits )
                           dir_avg>0 ? 's' : dir_avg<0 ? 't' : '-' )
                         : '-';
         if( fprintf( rc->p_stat_file_out,
-                 "in:%d out:%d type:%c q:%.2f tex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d d:%c ref:",
+                 "in:%d out:%d type:%c dur:%d cpbdur:%d q:%.2f tex:%d mv:%d misc:%d imb:%d pmb:%d smb:%d d:%c ref:",
                  h->fenc->i_frame, h->i_frame,
-                 c_type, rc->qpa_rc,
+                 c_type, h->fenc->i_duration,
+                 h->fenc->i_cpb_duration, rc->qpa_rc,
                  h->stat.frame.i_tex_bits,
                  h->stat.frame.i_mv_bits,
                  h->stat.frame.i_misc_bits,
@@ -1405,7 +1485,9 @@ int x264_ratecontrol_end( x264_t *h, int bits )
             rc->cplxr_sum += bits * qp2qscale(rc->qpa_rc) / (rc->last_rceq * fabs(h->param.rc.f_pb_factor));
         }
         rc->cplxr_sum *= rc->cbr_decay;
-        rc->wanted_bits_window += rc->bitrate / rc->fps;
+        double frame_duration = (double)h->fenc->i_duration * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
+
+        rc->wanted_bits_window += frame_duration * rc->bitrate;
         rc->wanted_bits_window *= rc->cbr_decay;
     }
 
@@ -1428,7 +1510,45 @@ int x264_ratecontrol_end( x264_t *h, int bits )
         }
     }
 
-    update_vbv( h, bits );
+    *filler = update_vbv( h, bits );
+
+    if( h->sps->vui.b_nal_hrd_parameters_present )
+    {
+        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;
+            h->fenc->hrd_timing.cpb_removal_time = rc->nrt_first_access_unit = (double)rc->initial_cpb_removal_delay / 90000;
+        }
+        else
+        {
+            h->fenc->hrd_timing.cpb_removal_time = rc->nrt_first_access_unit + (double)h->fenc->i_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 = h->fenc->hrd_timing.cpb_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 = h->fenc->hrd_timing.cpb_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 );
+            }
+        }
+        int filler_bits = *filler ? X264_MAX( (FILLER_OVERHEAD - h->param.b_annexb), *filler )*8 : 0;
+        // 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_bits) / h->sps->vui.hrd.i_bit_rate_unscaled;
+
+        h->fenc->hrd_timing.dpb_output_time = (double)h->fenc->i_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");
@@ -1565,8 +1685,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 = 0;
+
     x264_ratecontrol_t *rcc = h->rc;
     x264_ratecontrol_t *rct = h->thread[0]->rc;
 
@@ -1574,14 +1696,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 += rcc->buffer_rate;
-    rct->buffer_fill_final = X264_MIN( rct->buffer_fill_final, rcc->buffer_size );
+
+    if( h->sps->vui.hrd.b_cbr_hrd && rct->buffer_fill_final > rcc->buffer_size )
+    {
+        filler = ceil( (rct->buffer_fill_final - rcc->buffer_size) / 8 );
+        rct->buffer_fill_final -= X264_MAX( (FILLER_OVERHEAD - h->param.b_annexb), filler ) * 8;
+    }
+    else
+        rct->buffer_fill_final = X264_MIN( rct->buffer_fill_final, rcc->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_bits < 0 || cpb_bits > cpb_size )
+    {
+         x264_log( h, X264_LOG_WARNING, "CPB %s: %.0lf bits in a %.0lf-bit buffer\n",
+                   cpb_bits < 0 ? "underflow" : "overflow", cpb_bits, cpb_size );
+    }
+
+    return x264_clip3f( cpb_fullness + 0.5, 0, 90000.0*cpb_size/bps ); // just lie if we are in a weird state
 }
 
 // provisionally update VBV according to the planned size of all frames currently in progress
@@ -1602,7 +1751,7 @@ static void update_vbv_plan( x264_t *h, int overhead )
             bits  = X264_MAX(bits, t->rc->frame_size_estimated);
             rcc->buffer_fill -= bits;
             rcc->buffer_fill = X264_MAX( rcc->buffer_fill, 0 );
-            rcc->buffer_fill += rcc->buffer_rate;
+            rcc->buffer_fill += t->rc->buffer_rate;
             rcc->buffer_fill = X264_MIN( rcc->buffer_fill, rcc->buffer_size );
         }
     }
@@ -1637,6 +1786,7 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
                 double cur_bits = predict_size( &rcc->pred[h->sh.i_type], q, rcc->last_satd );
                 double buffer_fill_cur = rcc->buffer_fill - cur_bits;
                 double target_fill;
+                double total_duration = 0;
                 frame_q[0] = h->sh.i_type == SLICE_TYPE_I ? q * h->param.rc.f_ip_factor : q;
                 frame_q[1] = frame_q[0] * h->param.rc.f_pb_factor;
                 frame_q[2] = frame_q[0] / h->param.rc.f_ip_factor;
@@ -1644,7 +1794,8 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
                 /* Loop over the planned future frames. */
                 for( j = 0; buffer_fill_cur >= 0 && buffer_fill_cur <= rcc->buffer_size; j++ )
                 {
-                    buffer_fill_cur += rcc->buffer_rate;
+                    total_duration += h->fenc->f_planned_cpb_duration[j];
+                    buffer_fill_cur += rcc->vbv_max_rate * h->fenc->f_planned_cpb_duration[j];
                     int i_type = h->fenc->i_planned_type[j];
                     int i_satd = h->fenc->i_planned_satd[j];
                     if( i_type == X264_TYPE_AUTO )
@@ -1654,7 +1805,7 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
                     buffer_fill_cur -= cur_bits;
                 }
                 /* Try to get to get the buffer at least 50% filled, but don't set an impossible goal. */
-                target_fill = X264_MIN( rcc->buffer_fill + j * rcc->buffer_rate * 0.5, rcc->buffer_size * 0.5 );
+                target_fill = X264_MIN( rcc->buffer_fill + total_duration * rcc->vbv_max_rate * 0.5, rcc->buffer_size * 0.5 );
                 if( buffer_fill_cur < target_fill )
                 {
                     q *= 1.01;
@@ -1662,7 +1813,7 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
                     continue;
                 }
                 /* Try to get the buffer no more than 80% filled, but don't set an impossible goal. */
-                target_fill = x264_clip3f( rcc->buffer_fill - j * rcc->buffer_rate * 0.5, rcc->buffer_size * 0.8, rcc->buffer_size );
+                target_fill = x264_clip3f( rcc->buffer_fill - total_duration * rcc->vbv_max_rate * 0.5, rcc->buffer_size * 0.8, rcc->buffer_size );
                 if( rcc->b_vbv_min_rate && buffer_fill_cur > target_fill )
                 {
                     q /= 1.01;
@@ -1714,11 +1865,17 @@ static double clip_qscale( x264_t *h, int pict_type, double q )
             double pbbits = bits;
             double bbits = predict_size( rcc->pred_b_from_p, q * h->param.rc.f_pb_factor, rcc->last_satd );
             double space;
-            if( bbits > rcc->buffer_rate  )
+            double bframe_cpb_duration = 0;
+            double minigop_cpb_duration;
+            for( int i = 0; i < nb; i++ )
+                bframe_cpb_duration += h->fenc->f_planned_cpb_duration[1+i];
+
+            if( bbits * nb > bframe_cpb_duration * rcc->vbv_max_rate )
                 nb = 0;
             pbbits += nb * bbits;
 
-            space = rcc->buffer_fill + (1+nb)*rcc->buffer_rate - rcc->buffer_size;
+            minigop_cpb_duration = bframe_cpb_duration + h->fenc->f_planned_cpb_duration[0];
+            space = rcc->buffer_fill + minigop_cpb_duration*rcc->vbv_max_rate - rcc->buffer_size;
             if( pbbits < space )
             {
                 q *= X264_MAX( pbbits / space, bits / (0.5 * rcc->buffer_size) );
@@ -1919,6 +2076,9 @@ static float rate_estimate_qscale( x264_t *h )
             else
             {
                 int i_frame_done = h->fenc->i_frame + 1 - h->i_thread_frames;
+                double i_time_done = i_frame_done / rcc->fps;
+                if( h->param.b_vfr_input )
+                    i_time_done = ((double)(h->fenc->i_reordered_pts - h->first_pts)) * h->param.i_timebase_num / h->param.i_timebase_den;
 
                 q = get_qscale( h, &rce, rcc->wanted_bits_window / rcc->cplxr_sum, h->fenc->i_frame );
 
@@ -1927,10 +2087,10 @@ static float rate_estimate_qscale( x264_t *h )
                 if( !rcc->b_vbv_min_rate && rcc->last_satd )
                 {
                     // FIXME is it simpler to keep track of wanted_bits in ratecontrol_end?
-                    wanted_bits = i_frame_done * rcc->bitrate / rcc->fps;
+                    wanted_bits = i_time_done * rcc->bitrate;
                     if( wanted_bits > 0 )
                     {
-                        abr_buffer *= X264_MAX( 1, sqrt(i_frame_done/25) );
+                        abr_buffer *= X264_MAX( 1, sqrt(i_time_done) );
                         overflow = x264_clip3f( 1.0 + (total_bits - wanted_bits) / abr_buffer, .5, 2 );
                         q *= overflow;
                     }
@@ -2112,6 +2272,9 @@ 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(nrt_first_access_unit);
+        COPY(previous_cpb_final_arrival_time);
 #undef COPY
     }
     //FIXME row_preds[] (not strictly necessary, but would improve prediction)
@@ -2131,7 +2294,8 @@ static int find_underflow( x264_t *h, double *fills, int *t0, int *t1, int over
     int i, start=-1, end=-1;
     for(i = *t0; i < rcc->num_entries; i++)
     {
-        fill += (rcc->buffer_rate - qscale2bits(&rcc->entry[i], rcc->entry[i].new_qscale)) * parity;
+        fill += (rcc->entry[i].i_cpb_duration * rcc->vbv_max_rate * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale -
+                 qscale2bits(&rcc->entry[i], rcc->entry[i].new_qscale)) * parity;
         fill = x264_clip3f(fill, 0, rcc->buffer_size);
         fills[i] = fill;
         if(fill <= buffer_min || i == 0)
@@ -2182,7 +2346,7 @@ static double count_expected_bits( x264_t *h )
     return expected_bits;
 }
 
-static int vbv_pass2( x264_t *h )
+static int vbv_pass2( x264_t *h, double all_available_bits )
 {
     /* for each interval of buffer_full .. underflow, uniformly increase the qp of all
      * frames in the interval until either buffer is full at some intermediate frame or the
@@ -2191,7 +2355,6 @@ static int vbv_pass2( x264_t *h )
 
     x264_ratecontrol_t *rcc = h->rc;
     double *fills;
-    double all_available_bits = h->param.rc.i_bitrate * 1000. * rcc->num_entries / rcc->fps;
     double expected_bits = 0;
     double adjustment;
     double prev_bits = 0;
@@ -2251,14 +2414,18 @@ static int init_pass2( x264_t *h )
 {
     x264_ratecontrol_t *rcc = h->rc;
     uint64_t all_const_bits = 0;
-    uint64_t all_available_bits = (uint64_t)(h->param.rc.i_bitrate * 1000. * rcc->num_entries / rcc->fps);
+    int i;
+    double duration = 0;
+    for( i = 0; i < rcc->num_entries; i++ )
+        duration += rcc->entry[i].i_duration;
+    duration *= (double)h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
+    uint64_t all_available_bits = h->param.rc.i_bitrate * 1000. * duration;
     double rate_factor, step, step_mult;
     double qblur = h->param.rc.f_qblur;
     double cplxblur = h->param.rc.f_complexity_blur;
     const int filter_size = (int)(qblur*4) | 1;
     double expected_bits;
     double *qscale, *blurred_qscale;
-    int i;
 
     /* find total/average complexity & const_bits */
     for(i=0; i<rcc->num_entries; i++)
@@ -2401,7 +2568,7 @@ static int init_pass2( x264_t *h )
         x264_free(blurred_qscale);
 
     if(rcc->b_vbv)
-        if( vbv_pass2( h ) )
+        if( vbv_pass2( h, all_available_bits ) )
             return -1;
     expected_bits = count_expected_bits(h);
 
index 2767866452d64b76be894973c8ae9749c1597da3..f070a9ccb1cee90a9c9515f8e31bca1481ac2ecc 100644 (file)
@@ -39,7 +39,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 *);
@@ -47,6 +47,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
 
index 03a6dee79d59d208fa56d5f52f4e6fb8a7b0e62d..974fb53de72177d1cca60be820440b2718e9ec04 100644 (file)
@@ -28,6 +28,9 @@
 
 #define bs_write_ue bs_write_ue_big
 
+// Indexed by pic_struct values
+static const uint8_t num_clock_ts[10] = { 0, 1, 1, 1, 2, 2, 3, 3, 2, 3 };
+
 static void transpose( uint8_t *buf, int w )
 {
     int i, j;
@@ -71,6 +74,29 @@ static void scaling_list_write( bs_t *s, x264_pps_t *pps, int idx )
     }
 }
 
+static uint8_t *x264_sei_write_header( bs_t *s, int payload_type )
+{
+    bs_write( s, 8, payload_type );
+
+    bs_flush( s );
+    uint8_t *p_start = s->p;
+    bs_realign( s );
+
+    bs_write( s, 8, 0 );
+    return p_start;
+}
+
+static void x264_sei_write( bs_t *s, uint8_t *p_start )
+{
+    bs_align_10( s );
+    bs_flush( s );
+
+    p_start[0] = s->p - p_start - 1; // -1 for the length byte
+    bs_realign( s );
+
+    bs_rbsp_trailing( s );
+}
+
 void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
 {
     sps->i_id = i_id;
@@ -179,15 +205,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 > 0 && 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->i_nal_hrd;
+    sps->vui.b_pic_struct_present = param->b_pic_struct;
+
+    // NOTE: HRD related parts of the SPS are initialised in x264_ratecontrol_init_reconfigurable
+
     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 +235,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)log2f( param->analyse.i_mv_range*4-1 ) + 1;
     }
 }
 
-
 void x264_sps_write( bs_t *s, x264_sps_t *sps )
 {
     bs_realign( s );
@@ -343,9 +374,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 )
         {
@@ -473,20 +525,15 @@ 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 payload_size;
-
     bs_realign( s );
-    bs_write( s, 8, 0x06 ); // payload_type = Recovery Point
-    payload_size = bs_size_ue( recovery_frame_cnt ) + 4;
+    uint8_t *p_start = x264_sei_write_header( s, SEI_RECOVERY_POINT );
 
-    bs_write( s, 8, (payload_size + 7) / 8);
     bs_write_ue( s, recovery_frame_cnt ); // recovery_frame_cnt
     bs_write( s, 1, 1 ); //exact_match_flag 1
     bs_write( s, 1, 0 ); //broken_link_flag 0
     bs_write( s, 2, 0 ); //changing_slice_group 0
 
-    bs_align_10( s );
-    bs_rbsp_trailing( s );
+    x264_sei_write( s, p_start );
     bs_flush( s );
 }
 
@@ -512,7 +559,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 +581,63 @@ 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;
+    bs_realign( s );
+    uint8_t *p_start = x264_sei_write_header( s, SEI_BUFFERING_PERIOD );
+
+    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 */
+    }
+
+    x264_sei_write( s, p_start );
+    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;
+    bs_realign( s );
+    uint8_t *p_start = x264_sei_write_header( s, SEI_PIC_TIMING );
+
+    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 )
+    {
+        bs_write( s, 4, pic_struct-1 ); // We use index 0 for "Auto"
+
+        // These clock timestamps are not standardised so we don't set them
+        // They could be time of origin, capture or alternative ideal display
+        for( int i = 0; i < num_clock_ts[pic_struct]; i++ )
+            bs_write1( s, 0 ); // clock_timestamp_flag
+    }
+
+    x264_sei_write( s, p_start );
+    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, 2, 0, 0, 1 },
index 125f7e14f3cd767c501c815beecc2aea076b3532..b3ed2348dcfe4ca7abf258aec66d4c49c5ed904d 100644 (file)
@@ -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
index f69880247a83f79e1ccfe63f99e71cbc43de099e..dc39bb082d3f4644fa91dab32a9feb455c0896af 100644 (file)
@@ -29,6 +29,9 @@
 #include "macroblock.h"
 #include "me.h"
 
+// Indexed by pic_struct values
+static const uint8_t delta_tfi_divisor[10] = { 0, 2, 1, 1, 2, 2, 3, 3, 4, 6 };
+
 static int x264_slicetype_frame_cost( x264_t *h, x264_mb_analysis_t *a,
                                       x264_frame_t **frames, int p0, int p1, int b,
                                       int b_intra_penalty );
@@ -821,14 +824,47 @@ static int x264_vbv_frame_cost( x264_t *h, x264_mb_analysis_t *a, x264_frame_t *
     return cost;
 }
 
+static void x264_calculate_durations( x264_t *h, x264_frame_t *cur_frame, x264_frame_t *prev_frame, int *i_cpb_delay, int *i_coded_fields )
+{
+    cur_frame->i_cpb_delay = *i_cpb_delay;
+    cur_frame->i_dpb_output_delay = cur_frame->i_field_cnt - *i_coded_fields;
+
+    // add a correction term for frame reordering
+    cur_frame->i_dpb_output_delay += h->sps->vui.i_num_reorder_frames*2;
+
+    // fix possible negative dpb_output_delay because of pulldown changes and reordering
+    if( cur_frame->i_dpb_output_delay < 0 )
+    {
+        cur_frame->i_cpb_delay += cur_frame->i_dpb_output_delay;
+        cur_frame->i_dpb_output_delay = 0;
+        if( prev_frame )
+            prev_frame->i_cpb_duration += cur_frame->i_dpb_output_delay;
+    }
+
+    if( cur_frame->b_keyframe )
+        *i_cpb_delay = 0;
+
+    *i_cpb_delay += cur_frame->i_duration;
+    *i_coded_fields += cur_frame->i_duration;
+    cur_frame->i_cpb_duration = cur_frame->i_duration;
+}
+
 static void x264_vbv_lookahead( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **frames, int num_frames, int keyframe )
 {
     int last_nonb = 0, cur_nonb = 1, next_nonb, i, idx = 0;
+    x264_frame_t *prev_frame = NULL;
+    int prev_frame_idx = 0;
     while( cur_nonb < num_frames && frames[cur_nonb]->i_type == X264_TYPE_B )
         cur_nonb++;
     next_nonb = keyframe ? last_nonb : cur_nonb;
 
-    while( cur_nonb <= num_frames )
+    if( frames[0]->i_coded_fields_lookahead >= 0 )
+    {
+        h->i_coded_fields_lookahead = frames[0]->i_coded_fields_lookahead;
+        h->i_cpb_delay_lookahead = frames[0]->i_cpb_delay_lookahead;
+    }
+
+    while( cur_nonb < num_frames )
     {
         /* P/I cost: This shouldn't include the cost of next_nonb */
         if( next_nonb != cur_nonb )
@@ -836,6 +872,18 @@ static void x264_vbv_lookahead( x264_t *h, x264_mb_analysis_t *a, x264_frame_t *
             int p0 = IS_X264_TYPE_I( frames[cur_nonb]->i_type ) ? cur_nonb : last_nonb;
             frames[next_nonb]->i_planned_satd[idx] = x264_vbv_frame_cost( h, a, frames, p0, cur_nonb, cur_nonb );
             frames[next_nonb]->i_planned_type[idx] = frames[cur_nonb]->i_type;
+            frames[cur_nonb]->i_coded_fields_lookahead = h->i_coded_fields_lookahead;
+            frames[cur_nonb]->i_cpb_delay_lookahead = h->i_cpb_delay_lookahead;
+            x264_calculate_durations( h, frames[cur_nonb], prev_frame, &h->i_cpb_delay_lookahead, &h->i_coded_fields_lookahead );
+            if( prev_frame )
+            {
+                frames[next_nonb]->f_planned_cpb_duration[prev_frame_idx] = (double)prev_frame->i_cpb_duration *
+                                                                            h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
+            }
+            frames[next_nonb]->f_planned_cpb_duration[idx] = (double)frames[cur_nonb]->i_cpb_duration *
+                                                             h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
+            prev_frame = frames[cur_nonb];
+            prev_frame_idx = idx;
             idx++;
         }
         /* Handle the B-frames: coded order */
@@ -843,6 +891,18 @@ static void x264_vbv_lookahead( x264_t *h, x264_mb_analysis_t *a, x264_frame_t *
         {
             frames[next_nonb]->i_planned_satd[idx] = x264_vbv_frame_cost( h, a, frames, last_nonb, cur_nonb, i );
             frames[next_nonb]->i_planned_type[idx] = X264_TYPE_B;
+            frames[i]->i_coded_fields_lookahead = h->i_coded_fields_lookahead;
+            frames[i]->i_cpb_delay_lookahead = h->i_cpb_delay_lookahead;
+            x264_calculate_durations( h, frames[i], prev_frame, &h->i_cpb_delay_lookahead, &h->i_coded_fields_lookahead );
+            if( prev_frame )
+            {
+                frames[next_nonb]->f_planned_cpb_duration[prev_frame_idx] = (double)prev_frame->i_cpb_duration *
+                                                                            h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
+            }
+            frames[next_nonb]->f_planned_cpb_duration[idx] = (double)frames[i]->i_cpb_duration *
+                                                             h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
+            prev_frame = frames[i];
+            prev_frame_idx = idx;
         }
         last_nonb = cur_nonb;
         cur_nonb++;
@@ -1196,6 +1256,37 @@ void x264_slicetype_decide( x264_t *h )
     if( !h->lookahead->next.i_size )
         return;
 
+    int lookahead_size = h->lookahead->next.i_size;
+
+    if( h->param.rc.i_rc_method == X264_RC_ABR || h->param.rc.b_stat_write || h->param.rc.i_vbv_buffer_size )
+    {
+        for( i = 0; i < h->lookahead->next.i_size; i++ )
+        {
+            if( h->param.b_vfr_input )
+            {
+                if( lookahead_size-- > 1 )
+                    h->lookahead->next.list[i]->i_duration = 2 * (h->lookahead->next.list[i+1]->i_pts - h->lookahead->next.list[i]->i_pts);
+                else
+                    h->lookahead->next.list[i]->i_duration = h->i_prev_duration;
+            }
+            else
+                h->lookahead->next.list[i]->i_duration = delta_tfi_divisor[h->lookahead->next.list[i]->i_pic_struct];
+            h->i_prev_duration = h->lookahead->next.list[i]->i_duration;
+
+            if( h->lookahead->next.list[i]->i_frame > h->i_disp_fields_last_frame && lookahead_size > 0 )
+            {
+                h->lookahead->next.list[i]->i_field_cnt = h->i_disp_fields;
+                h->i_disp_fields += h->lookahead->next.list[i]->i_duration;
+                h->i_disp_fields_last_frame = h->lookahead->next.list[i]->i_frame;
+            }
+            else if( lookahead_size == 0 )
+            {
+                h->lookahead->next.list[i]->i_field_cnt = h->i_disp_fields;
+                h->lookahead->next.list[i]->i_duration = h->i_prev_duration;
+            }
+        }
+    }
+
     if( h->param.rc.b_stat_read )
     {
         /* Use the frame types from the first pass */
@@ -1342,8 +1433,25 @@ void x264_slicetype_decide( x264_t *h )
         frames[0]->i_reordered_pts = h->lookahead->next.list[0]->i_pts;
         memcpy( h->lookahead->next.list, frames, (bframes+1) * sizeof(x264_frame_t*) );
     }
+
     for( i = 0; i <= bframes; i++ )
-         h->lookahead->next.list[i]->i_coded = i_coded++;
+    {
+        h->lookahead->next.list[i]->i_coded = i_coded++;
+        if( h->param.rc.i_rc_method == X264_RC_ABR || h->param.rc.b_stat_write || h->param.rc.i_vbv_buffer_size )
+        {
+            if( i )
+            {
+                x264_calculate_durations( h, h->lookahead->next.list[i], h->lookahead->next.list[i-1], &h->i_cpb_delay, &h->i_coded_fields );
+                h->lookahead->next.list[0]->f_planned_cpb_duration[i-1] = (double)h->lookahead->next.list[i-1]->i_cpb_duration *
+                                                                          h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
+            }
+            else
+                x264_calculate_durations( h, h->lookahead->next.list[i], NULL, &h->i_cpb_delay, &h->i_coded_fields );
+
+            h->lookahead->next.list[0]->f_planned_cpb_duration[i] = (double)h->lookahead->next.list[i]->i_cpb_duration *
+                                                                    h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
+        }
+    }
 }
 
 int x264_rc_analyse_slice( x264_t *h )
index 79b5c80a00ab19eaa902244ee42813ecbef5a200..e4653aa6f3efbe628f202eeb4479623285cec236 100644 (file)
@@ -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;
 }
 
index 2e0a0e47a8d2e54faf2a385147a3ab08509486ed..04f44283508aaaa9209aeb5def8d193a6a4f2152 100644 (file)
@@ -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;
index fb39ced035df7cba432272b8060192f7dc7624c7..25e91d583456efdfa02e18648cbf35b896c7c30d 100644 (file)
@@ -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;
index bb3484513d948ec1e7b0ce658606dd1daab62c72..c5e19887f909e69248b33bb5f2f06cbbedb1e5b5 100644 (file)
@@ -225,13 +225,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 45b1248c4efbee3f8a8af6c01a0f8be3b789cec2..4712473e2e1bdbe0ba1f6b6ff1990c5c10cde602 100644 (file)
--- a/x264.c
+++ b/x264.c
@@ -59,6 +59,7 @@ typedef struct {
     FILE *qpfile;
     FILE *tcfile_out;
     double timebase_convert_multiplier;
+    int i_pulldown;
 } cli_opt_t;
 
 /* i/o file operation function pointer structs */
@@ -94,6 +95,48 @@ static const char * const muxer_names[] =
     0
 };
 
+static const char * const pulldown_names[] = { "none", "22", "32", "64", "double", "triple", "euro", 0 };
+
+typedef struct{
+    int mod;
+    uint8_t pattern[24];
+    float fps_factor;
+} cli_pulldown_t;
+
+enum pulldown_type_e
+{
+    X264_PULLDOWN_22 = 1,
+    X264_PULLDOWN_32,
+    X264_PULLDOWN_64,
+    X264_PULLDOWN_DOUBLE,
+    X264_PULLDOWN_TRIPLE,
+    X264_PULLDOWN_EURO
+};
+
+#define TB  PIC_STRUCT_TOP_BOTTOM
+#define BT  PIC_STRUCT_BOTTOM_TOP
+#define TBT PIC_STRUCT_TOP_BOTTOM_TOP
+#define BTB PIC_STRUCT_BOTTOM_TOP_BOTTOM
+
+static const cli_pulldown_t pulldown_values[] =
+{
+    [X264_PULLDOWN_22]     = {1,  {TB},                                   2.0},
+    [X264_PULLDOWN_32]     = {4,  {TBT, BT, BTB, TB},                     1.25},
+    [X264_PULLDOWN_64]     = {2,  {PIC_STRUCT_DOUBLE, PIC_STRUCT_TRIPLE}, 1.0},
+    [X264_PULLDOWN_DOUBLE] = {1,  {PIC_STRUCT_DOUBLE},                    2.0},
+    [X264_PULLDOWN_TRIPLE] = {1,  {PIC_STRUCT_TRIPLE},                    3.0},
+    [X264_PULLDOWN_EURO]   = {24, {TBT, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT,
+                                   BTB, TB, TB, TB, TB, TB, TB, TB, TB, TB, TB, TB}, 25.0/24.0}
+};
+
+#undef TB
+#undef BT
+#undef TBT
+#undef BTB
+
+// indexed by pic_struct enum
+static const float pulldown_frame_duration[10] = { 0.0, 1, 0.5, 0.5, 1, 1, 1.5, 1.5, 2, 3 };
+
 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 );
@@ -299,7 +342,7 @@ static void Help( x264_param_t *defaults, int longhelp )
         "                                    --no-cabac --no-deblock --no-weightb\n"
         "                                    --weightp 0\n"
         "                                  - zerolatency:\n"
-        "                                    --bframes 0 --rc-lookahead 0\n"
+        "                                    --bframes 0 --force-cfr --rc-lookahead 0\n"
         "                                    --sync-lookahead 0 --sliced-threads\n" );
     else H0( "                                  - psy tunings: film,animation,grain,psnr,ssim\n"
              "                                  - other tunings: fastdecode,zerolatency\n" );
@@ -334,7 +377,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( "      --tff                   Enable interlaced mode (top field first)\n" );
+    H0( "      --bff                   Enable interlaced mode (bottom field first)\n" );
     H2( "      --constrained-intra     Enable constrained intra prediction.\n" );
     H0( "\n" );
     H0( "Ratecontrol:\n" );
@@ -476,6 +520,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 );
+
+    H2( "      --nal-hrd <string>      Signal HRD information (requires vbv-bufsize)\n"
+        "                                  - none, vbr, cbr (cbr not allowed in .mp4)\n" );
+    H2( "      --pic-struct            Force pic_struct in Picture Timing SEI\n" );
+
     H0( "\n" );
     H0( "Input/Output:\n" );
     H0( "\n" );
@@ -513,6 +562,8 @@ static void Help( x264_param_t *defaults, int longhelp )
     H2( "      --timebase <int/int>    Specify timebase numerator and denominator\n"
         "                 <integer>    Specify timebase numerator for input timecode file\n"
         "                              or specify timebase denominator for other input\n" );
+    H0( "      --pulldown <string>     Use soft pulldown to change frame rate\n"
+        "                                  - none, 22, 32, 64, double, triple, euro (requires cfr input)\n" );
     H0( "\n" );
 }
 
@@ -537,6 +588,7 @@ static void Help( x264_param_t *defaults, int longhelp )
 #define OPT_TCFILE_IN 274
 #define OPT_TCFILE_OUT 275
 #define OPT_TIMEBASE 276
+#define OPT_PULLDOWN 277
 
 static char short_options[] = "8A:B:b:f:hI:i:m:o:p:q:r:t:Vvw";
 static struct option long_options[] =
@@ -565,6 +617,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, OPT_INTERLACED },
+    { "bff",               no_argument, NULL, OPT_INTERLACED },
     { "no-interlaced",     no_argument, NULL, OPT_INTERLACED },
     { "constrained-intra", no_argument, NULL, 0 },
     { "cabac",             no_argument, NULL, 0 },
@@ -674,6 +728,9 @@ static struct option long_options[] =
     { "tcfile-in",   required_argument, NULL, OPT_TCFILE_IN },
     { "tcfile-out",  required_argument, NULL, OPT_TCFILE_OUT },
     { "timebase",    required_argument, NULL, OPT_TIMEBASE },
+    { "pic-struct",        no_argument, NULL, 0 },
+    { "nal-hrd",     required_argument, NULL, 0 },
+    { "pulldown",    required_argument, NULL, OPT_PULLDOWN },
     {0, 0, 0, 0}
 };
 
@@ -688,9 +745,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->i_nal_hrd == X264_NAL_HRD_CBR )
+        {
+            fprintf( stderr, "x264 [warning]: cbr nal-hrd is not compatible with mp4\n" );
+            param->i_nal_hrd = X264_NAL_HRD_VBR;
+        }
 #else
         fprintf( stderr, "x264 [error]: not compiled with MP4 output support\n" );
         return -1;
@@ -700,7 +761,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;
     }
@@ -708,7 +768,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;
     }
@@ -981,6 +1040,16 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
             case OPT_TIMEBASE:
                 input_opt.timebase = optarg;
                 break;
+            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:
             {
@@ -1274,6 +1343,7 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
 {
     x264_t *h;
     x264_picture_t pic;
+    const cli_pulldown_t *pulldown = NULL; // shut up gcc
 
     int     i_frame, i_frame_total, i_frame_output;
     int64_t i_start, i_end;
@@ -1289,6 +1359,7 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
     double  duration;
     int     prev_timebase_den = param->i_timebase_den / gcd( param->i_timebase_num, param->i_timebase_den );
     int     dts_compress_multiplier;
+    double  pulldown_pts = 0;
 
     opt->b_progress &= param->i_log_level < X264_LOG_DEBUG;
     i_frame_total = input.get_frame_total( opt->hin );
@@ -1299,6 +1370,20 @@ 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_vfr_input )
+    {
+        param->b_pic_struct = 1;
+        pulldown = &pulldown_values[opt->i_pulldown];
+        param->i_timebase_num = param->i_fps_den;
+        if( fmod( param->i_fps_num * pulldown->fps_factor, 1 ) )
+        {
+            fprintf( stderr, "x264 [error]: unsupported framerate for chosen pulldown\n" );
+            return -1;
+        }
+        param->i_timebase_den = param->i_fps_num * pulldown->fps_factor;
+    }
+
     if( ( h = x264_encoder_open( param ) ) == NULL )
     {
         fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );
@@ -1361,7 +1446,14 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
 
         if( !param->b_vfr_input )
             pic.i_pts = i_frame;
-        if( opt->timebase_convert_multiplier )
+
+        if( opt->i_pulldown && !param->b_vfr_input )
+        {
+            pic.i_pic_struct = pulldown->pattern[ i_frame % pulldown->mod ];
+            pic.i_pts = (int64_t)( pulldown_pts + 0.5 );
+            pulldown_pts += pulldown_frame_duration[pic.i_pic_struct];
+        }
+        else if( opt->timebase_convert_multiplier )
             pic.i_pts = (int64_t)( pic.i_pts * opt->timebase_convert_multiplier + 0.5 );
 
         int64_t output_pts = pic.i_pts * dts_compress_multiplier;   /* pts libx264 returns */
@@ -1380,6 +1472,7 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
             pic.i_pts = largest_pts + ticks_per_frame;
             output_pts = pic.i_pts * dts_compress_multiplier;
         }
+
         second_largest_pts = largest_pts;
         largest_pts = pic.i_pts;
         if( opt->tcfile_out )
@@ -1430,7 +1523,8 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
         duration = (double)param->i_fps_den / param->i_fps_num;
     else
         duration = (double)(2 * largest_pts - second_largest_pts) * param->i_timebase_num / param->i_timebase_den;
-    duration *= dts_compress_multiplier;
+    if( !(opt->i_pulldown && !param->b_vfr_input) )
+        duration *= dts_compress_multiplier;
 
     i_end = x264_mdate();
     input.picture_clean( &pic );
diff --git a/x264.h b/x264.h
index b93c6660a55ecb3ffebc754eafc228462d5adb60..77313c72e3cf93e1571f73281fb8a7d8ea980f8b 100644 (file)
--- a/x264.h
+++ b/x264.h
@@ -35,7 +35,7 @@
 
 #include <stdarg.h>
 
-#define X264_BUILD 88
+#define X264_BUILD 89
 
 /* x264_t:
  *      opaque handler for encoder */
@@ -111,6 +111,7 @@ static const char * const x264_fullrange_names[] = { "off", "on", 0 };
 static const char * const x264_colorprim_names[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "film", 0 };
 static const char * const x264_transfer_names[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "linear", "log100", "log316", 0 };
 static const char * const x264_colmatrix_names[] = { "GBR", "bt709", "undef", "", "fcc", "bt470bg", "smpte170m", "smpte240m", "YCgCo", 0 };
+static const char * const x264_nal_hrd_names[] = { "none", "vbr", "cbr", 0 };
 
 /* Colorspace type
  * legacy only; nothing other than I420 is really supported. */
@@ -148,6 +149,11 @@ static const char * const x264_colmatrix_names[] = { "GBR", "bt709", "undef", ""
 #define X264_THREADS_AUTO 0 /* Automatically select optimal number of threads */
 #define X264_SYNC_LOOKAHEAD_AUTO (-1) /* Automatically select optimal lookahead thread buffer size */
 
+/* HRD */
+#define X264_NAL_HRD_NONE            0
+#define X264_NAL_HRD_VBR             1
+#define X264_NAL_HRD_CBR             2
+
 /* Zones: override ratecontrol or other options for specific sections of the video.
  * See x264_encoder_reconfig() for which options can be changed.
  * If zones overlap, whichever comes later in the list takes precedence. */
@@ -176,6 +182,14 @@ typedef struct x264_param_t
     int         i_level_idc;
     int         i_frame_total; /* number of frames to encode if known, else 0 */
 
+    /* NAL HRD
+     * Uses Buffering and Picture Timing SEIs to signal HRD
+     * The HRD in H.264 was not designed with VFR in mind.
+     * It is therefore not recommendeded to use NAL HRD with VFR.
+     * Furthermore, reconfiguring the VBV (via x264_encoder_reconfig)
+     * will currently generate invalid HRD. */
+    int         i_nal_hrd;
+
     struct
     {
         /* they will be reduced to be 0 < x <= 65535 and prime */
@@ -320,6 +334,20 @@ typedef struct x264_param_t
                                  * by compressing them to be less than the second PTS.
                                  * Warning: this will change the timebase! */
 
+    int b_tff;
+
+    /* Pulldown:
+     * The correct pic_struct must be passed with each input frame.
+     * The input timebase should be the timebase corresponding to the output framerate. This should be constant.
+     * e.g. for 3:2 pulldown timebase should be 1001/30000
+     * The PTS passed with each frame must be the PTS of the frame after pulldown is applied.
+     * Frame doubling and tripling require b_vfr_input set to zero (see H.264 Table D-1)
+     *
+     * Pulldown changes are not clearly defined in H.264. Therefore, it is the calling app's responsibility to manage this.
+     */
+
+    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. */
@@ -436,6 +464,29 @@ int     x264_param_apply_profile( x264_param_t *, const char *profile );
 /****************************************************************************
  * 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;       /* Colorspace */
@@ -455,6 +506,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.
+     *     use 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;
@@ -472,6 +526,8 @@ typedef struct
     x264_param_t *param;
     /* In: raw data */
     x264_image_t img;
+    /* Out: HRD timing information. Output only when i_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;
@@ -493,8 +549,8 @@ void x264_picture_clean( x264_picture_t *pic );
 
 enum nal_unit_type_e
 {
-    NAL_UNKNOWN = 0,
-    NAL_SLICE   = 1,
+    NAL_UNKNOWN     = 0,
+    NAL_SLICE       = 1,
     NAL_SLICE_DPA   = 2,
     NAL_SLICE_DPB   = 3,
     NAL_SLICE_DPC   = 4,
@@ -503,6 +559,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