Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/common/common.c b/common/common.c
- index 0dd7af5..47b3ae0 100644
- --- a/common/common.c
- +++ b/common/common.c
- @@ -158,6 +158,10 @@ 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;
- + param->b_pulldown = 0;
- }
- static int parse_enum( const char *arg, const char * const *names, int *dst )
- @@ -403,6 +407,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")
- @@ -622,6 +633,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
- @@ -697,6 +712,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;
- }
- @@ -907,7 +923,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 );
- @@ -960,6 +977,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=%s", x264_nal_hrd_names[p->i_nal_hrd] );
- return buf;
- }
- diff --git a/common/common.h b/common/common.h
- index e2e8fac..a94c69e 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 = 4,
- + SEI_USER_DATA_UNREGISTERED = 5,
- + SEI_RECOVERY_POINT = 6,
- +};
- +
- typedef struct
- {
- x264_sps_t *sps;
- @@ -367,6 +381,13 @@ 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 */
- + int i_last_duration; /* Duration of last frame */
- +
- /* We use only one SPS and one PPS */
- x264_sps_t sps_array[1];
- x264_sps_t *sps;
- @@ -449,7 +470,8 @@ struct x264_t
- x264_frame_t *fref1[16+3]; /* ref list 1 */
- int b_ref_reorder[2];
- -
- + /* hrd */
- + int initial_cpb_removal_delay;
- /* Current MB DCT coeffs */
- struct
- diff --git a/common/frame.c b/common/frame.c
- index d89f5ab..34376cc 100644
- --- a/common/frame.c
- +++ b/common/frame.c
- @@ -73,6 +73,13 @@ 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->orig = frame;
- /* all 4 luma planes allocated together, since the cacheline split code
- @@ -225,6 +232,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 7c8e2ff..f8436be 100644
- --- a/common/frame.h
- +++ b/common/frame.h
- @@ -36,12 +36,18 @@ typedef struct x264_frame
- int i_qpplus1;
- int64_t i_pts;
- int64_t i_reordered_pts;
- + int i_duration; /* in timebase units. used for vfr */
- + int i_cpb_duration;
- + int i_cpb_delay; /* in 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 */
- @@ -108,6 +114,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..5223ef5 100644
- --- a/common/osdep.h
- +++ b/common/osdep.h
- @@ -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
- 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 df62389..6b0eb47 100644
- --- a/encoder/encoder.c
- +++ b/encoder/encoder.c
- @@ -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,
- @@ -777,6 +775,26 @@ static int x264_validate_parameters( x264_t *h )
- h->param.analyse.b_ssim = 0;
- }
- + // pulldown is a form of vfr
- + if( h->param.b_pulldown )
- + h->param.b_vfr_input = 1;
- +
- + if( h->param.b_pulldown || 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 && !h->param.rc.i_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 +808,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_pulldown );
- BOOLIFY( analyse.b_transform_8x8 );
- BOOLIFY( analyse.b_weighted_bipred );
- BOOLIFY( analyse.b_chroma_me );
- @@ -907,6 +927,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 );
- @@ -934,6 +955,7 @@ 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_vbv_buffer_size > 0;
- 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;
- @@ -961,7 +983,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 = h->i_last_duration = 0;
- x264_rdo_init();
- /* init CPU functions */
- @@ -1069,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 */
- @@ -1142,6 +1170,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,6 +1180,9 @@ int x264_encoder_reconfig( x264_t *h, x264_param_t *param )
- COPY( rc.i_bitrate );
- }
- COPY( rc.f_rf_constant );
- +
- + if( h->param.b_pulldown != param->b_pulldown && h->param.b_pic_struct )
- + COPY( b_pulldown );
- #undef COPY
- mbcmp_init( h );
- @@ -1211,10 +1243,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. */
- @@ -1223,13 +1259,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;
- @@ -1237,7 +1275,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);
- }
- /****************************************************************************
- @@ -1251,11 +1289,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 );
- @@ -1269,7 +1302,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;
- @@ -1693,7 +1733,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->param.b_tff ? 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 )
- {
- @@ -2101,6 +2148,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 )
- {
- @@ -2148,6 +2196,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 ) || ( 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 )
- @@ -2296,13 +2359,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;
- @@ -2324,22 +2386,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 );
- @@ -2355,6 +2406,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 )
- {
- int time_to_recovery = X264_MIN( h->sps->i_mb_width - 1, h->param.i_keyint_max ) + h->param.i_bframe;
- @@ -2365,6 +2442,16 @@ int x264_encoder_encode( x264_t *h,
- }
- }
- + /* 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;
- + }
- +
- /* Init the rate control */
- /* FIXME: Include slice header bit cost. */
- x264_ratecontrol_start( h, h->fenc->i_qpplus1, overhead*8 );
- @@ -2438,13 +2525,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 )
- @@ -2491,9 +2572,38 @@ 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;
- + 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 = next_size < FILLER_OVERHEAD ? FILLER_OVERHEAD - next_size : 0;
- + f = h->param.i_slice_max_size - FILLER_OVERHEAD - overflow;
- + }
- + else
- + f = X264_MAX( 0, filler - 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;
- + frame_size += x264_encoder_encapsulate_nals( h, h->out.i_nal-1 );
- + filler -= f + FILLER_OVERHEAD;
- + }
- +
- + /* 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 8c61582..49374af 100644
- --- a/encoder/ratecontrol.c
- +++ b/encoder/ratecontrol.c
- @@ -94,6 +94,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;
- @@ -148,13 +149,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;
- + 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 );
- @@ -396,6 +402,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) )
- @@ -409,8 +425,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 = (int64_t)h->sps->vui.i_time_scale * h->param.i_keyint_max * MAX_DURATION / h->sps->vui.i_num_units_in_tick;
- + int max_dpb_output_delay = (int64_t)h->sps->vui.i_time_scale * h->sps->vui.i_max_dec_frame_buffering * MAX_DURATION / 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 = (double)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);
- @@ -426,15 +493,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 )
- @@ -1294,7 +1352,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;
- @@ -1405,7 +1463,44 @@ 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 );
- + }
- + }
- + // 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 + X264_MAX( FILLER_OVERHEAD, *filler )*8) / 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");
- @@ -1542,8 +1637,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;
- @@ -1551,14 +1648,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 );
- + rct->buffer_fill_final += h->fenc->i_cpb_duration * rcc->vbv_max_rate * h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
- +
- + if( h->sps->vui.hrd.b_cbr_hrd && rct->buffer_fill_final >= rcc->buffer_size )
- + {
- + filler = (rct->buffer_fill_final - rcc->buffer_size) / 8;
- + rct->buffer_fill_final -= X264_MAX( FILLER_OVERHEAD, 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
- @@ -2078,6 +2202,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)
- diff --git a/encoder/ratecontrol.h b/encoder/ratecontrol.h
- index 2767866..f070a9c 100644
- --- a/encoder/ratecontrol.h
- +++ b/encoder/ratecontrol.h
- @@ -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
- diff --git a/encoder/set.c b/encoder/set.c
- index f79919b..392eefd 100644
- --- a/encoder/set.c
- +++ b/encoder/set.c
- @@ -28,6 +28,9 @@
- #define bs_write_ue bs_write_ue_big
- +// Indexed by pic_struct values
- +static int 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;
- @@ -179,15 +182,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_fixed_frame_rate = !param->b_vfr_input || param->b_pulldown;
- }
- + 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 +212,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 +351,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 +505,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_RECOVERY_POINT );
- payload_size = bs_size_ue( recovery_frame_cnt ) + 4;
- bs_write( s, 8, (payload_size + 7) / 8);
- @@ -512,7 +541,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 +563,96 @@ 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"
- +
- + // These clock timestamps are not standardised so we don't set them
- + // They could be time of origin, capture or alternative ideal display
- + for( i = 0; i < num_clock_ts[pic_struct]; i++ )
- + bs_write1( s, 0 ); // clock_timestamp_flag
- + }
- +
- + 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/encoder/slicetype.c b/encoder/slicetype.c
- index bb2ed64..8acf6c7 100644
- --- a/encoder/slicetype.c
- +++ b/encoder/slicetype.c
- @@ -1326,6 +1326,27 @@ void x264_slicetype_decide( x264_t *h )
- x264_weights_analyse( h, h->lookahead->next.list[bframes], h->lookahead->last_nonb, 0 );
- }
- + int lookahead_size = h->lookahead->next.i_size;
- +
- + for( i = 0; i <= bframes; i++ )
- + {
- + if( h->param.b_vfr_input )
- + {
- + if( lookahead_size-- > 1 )
- + h->i_last_duration = h->lookahead->next.list[i]->i_duration = 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_last_duration;
- + }
- + else
- + {
- + h->lookahead->next.list[i]->i_duration = (int64_t)h->param.i_timebase_den * h->param.i_fps_den /
- + h->param.i_timebase_num / h->param.i_fps_num;
- + }
- + h->lookahead->next.list[i]->i_field_cnt = h->i_disp_fields;
- + h->i_disp_fields += 2 * h->lookahead->next.list[i]->i_duration;
- + }
- +
- /* shift sequence to coded order.
- use a small temporary list to avoid shifting the entire next buffer around */
- int i_coded = h->lookahead->next.list[0]->i_frame;
- @@ -1342,8 +1363,35 @@ 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++;
- + {
- + x264_frame_t *cur_frame = h->lookahead->next.list[i];
- +
- + cur_frame->i_coded = i_coded++;
- +
- + cur_frame->i_cpb_delay = h->i_cpb_delay;
- + cur_frame->i_dpb_output_delay = cur_frame->i_field_cnt - h->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( i )
- + h->lookahead->next.list[i-1]->i_cpb_duration += cur_frame->i_dpb_output_delay;
- + }
- +
- + if( h->lookahead->next.list[i]->b_keyframe )
- + h->i_cpb_delay = 0;
- +
- + h->i_cpb_delay += cur_frame->i_duration * 2;
- + h->i_coded_fields += cur_frame->i_duration* 2;
- + cur_frame->i_cpb_duration = cur_frame->i_duration * 2;
- + }
- }
- int x264_rc_analyse_slice( x264_t *h )
- diff --git a/input/avs.c b/input/avs.c
- index 79b5c80..e4653aa 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 2e0a0e4..04f4428 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 fb39ced..25e91d5 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 b99eaed..9fff33e 100644
- --- a/output/mp4.c
- +++ b/output/mp4.c
- @@ -228,13 +228,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 959626a..23d1caa 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,31 @@ static const char * const muxer_names[] =
- 0
- };
- +static const char * const pulldown_names[] = { "", "22", "32", "64", "double", "triple", "euro", 0 };
- +
- +typedef struct{
- + int mod;
- + int *pattern;
- + int i_timebase_multiplier;
- +} cli_pulldown_t;
- +
- +enum pulldown_type_e
- +{
- + X264_PULLDOWN_22 = 1,
- + X264_PULLDOWN_32 = 2,
- + X264_PULLDOWN_64 = 3,
- + X264_PULLDOWN_DOUBLE = 4,
- + X264_PULLDOWN_TRIPLE = 5,
- + X264_PULLDOWN_EURO = 6,
- +};
- +
- +// indexed by pic_struct enum
- +static float 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 );
- -
- +static int set_pulldown( cli_pulldown_t *pulldown, int i_pulldown, x264_param_t *param );
- /****************************************************************************
- * main:
- ****************************************************************************/
- @@ -334,7 +356,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" );
- @@ -476,6 +499,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 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" );
- @@ -508,6 +536,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"
- + " - 22, 32, 64, double, triple, euro\n" );
- H0( "\n" );
- }
- @@ -529,6 +559,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[] =
- @@ -557,6 +588,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 },
- @@ -663,6 +696,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}
- };
- @@ -677,9 +713,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;
- @@ -689,7 +729,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;
- }
- @@ -697,7 +736,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;
- }
- @@ -786,6 +824,88 @@ 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, x264_param_t *param )
- +{
- + float f_max_fps_factor = 1;
- + // multiplier used when repeat field frames make frame duration not an multiple of timebase_den
- + pulldown->i_timebase_multiplier = 1;
- + param->b_vfr_input = 1;
- +
- + switch( i_pulldown )
- + {
- + case X264_PULLDOWN_22:
- + pulldown->mod = 1;
- + pulldown->pattern = malloc( pulldown->mod*sizeof(int) );
- + if( !pulldown->pattern )
- + return -1;
- + pulldown->pattern[0] = PIC_STRUCT_TOP_BOTTOM;
- + break;
- + 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;
- + f_max_fps_factor = 1.25;
- + pulldown->i_timebase_multiplier = 2;
- + 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;
- + f_max_fps_factor = 2.5;
- + 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;
- + f_max_fps_factor = 2;
- + break;
- +
- + case X264_PULLDOWN_TRIPLE:
- + pulldown->mod = 1;
- + pulldown->pattern = malloc( pulldown->mod*sizeof(int) );
- + if( !pulldown->pattern )
- + return -1;
- + pulldown->pattern[0] = PIC_STRUCT_TRIPLE;
- + f_max_fps_factor = 3;
- + break;
- +
- + case X264_PULLDOWN_EURO:
- + pulldown->mod = 24;
- + 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;
- + f_max_fps_factor = 25.0/24.0;
- + pulldown->i_timebase_multiplier = 2;
- + break;
- + }
- +
- + param->i_timebase_num = param->i_fps_den;
- + param->i_timebase_den = param->i_fps_num * f_max_fps_factor * pulldown->i_timebase_multiplier;
- +
- + return 0;
- +}
- +
- /*****************************************************************************
- * Parse:
- *****************************************************************************/
- @@ -1154,6 +1274,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:
- {
- @@ -1440,6 +1570,7 @@ static int Encode( x264_param_t *param, cli_opt_t *opt )
- {
- x264_t *h;
- x264_picture_t pic;
- + cli_pulldown_t pulldown;
- int i_frame, i_frame_total, i_frame_output;
- int64_t i_start, i_end;
- @@ -1455,6 +1586,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;
- + int64_t pulldown_pts = 0;
- opt->b_progress &= param->i_log_level < X264_LOG_DEBUG;
- i_frame_total = input.get_frame_total( opt->hin );
- @@ -1465,6 +1597,14 @@ 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_pulldown = 1;
- + if( set_pulldown( &pulldown, opt->i_pulldown, param ) < 0 )
- + return -1;
- + }
- +
- if( ( h = x264_encoder_open( param ) ) == NULL )
- {
- fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );
- @@ -1524,6 +1664,14 @@ static int Encode( x264_param_t *param, cli_opt_t *opt )
- if( !param->b_vfr_input )
- pic.i_pts = i_frame;
- +
- + if( param->b_pulldown )
- + {
- + pic.i_pic_struct = pulldown.pattern[ i_frame % pulldown.mod ];
- + pic.i_pts = pulldown_pts;
- + pulldown_pts += frame_duration[pic.i_pic_struct] * pulldown.i_timebase_multiplier;
- + }
- +
- if( pic.i_pts <= largest_pts )
- {
- if( param->i_log_level >= X264_LOG_WARNING )
- @@ -1537,6 +1685,7 @@ static int Encode( x264_param_t *param, cli_opt_t *opt )
- }
- pic.i_pts = largest_pts + ticks_per_frame;
- }
- +
- second_largest_pts = largest_pts;
- largest_pts = pic.i_pts;
- @@ -1610,5 +1759,8 @@ static int Encode( x264_param_t *param, cli_opt_t *opt )
- (double) i_file * 8 / ( 1000 * duration ) );
- }
- + if( param->b_pulldown )
- + free( pulldown.pattern );
- +
- return 0;
- }
- diff --git a/x264.h b/x264.h
- index e7d19b7..276cbaa 100644
- --- a/x264.h
- +++ b/x264.h
- @@ -35,7 +35,7 @@
- #include <stdarg.h>
- -#define X264_BUILD 85
- +#define X264_BUILD 86
- /* 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,8 @@ typedef struct x264_param_t
- int i_level_idc;
- int i_frame_total; /* number of frames to encode if known, else 0 */
- + int i_nal_hrd; /* Use Buffering and Picture Timing SEI's to signal HRD */
- +
- struct
- {
- /* they will be reduced to be 0 < x <= 65535 and prime */
- @@ -320,6 +328,21 @@ 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:
- + * Set b_pulldown to use pulldown and pass the correct pic_struct with the frame
- + * The input timebase should be the timebase relating to the output framerate. This should be constant.
- + * b_pic_struct must also be on. Pulldown is (almost always) a form of VFR so b_vfr_input must be on.
- + * PTS must also be the PTS of the pulldowned frame
- + *
- + * Pulldown changes are not clearly defined in H.264. Therefore, it is the calling app's responsibility to manage this.
- + */
- +
- + int b_pulldown;
- +
- + 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.
- + * 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;
- @@ -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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement