diff --git a/common/common.c b/common/common.c old mode 100644 new mode 100755 index 2d00384..c1b45d9 --- a/common/common.c +++ b/common/common.c @@ -140,6 +140,7 @@ void x264_param_default( x264_param_t *param ) param->b_repeat_headers = 1; param->b_aud = 0; + param->b_filler = 0; } static int parse_enum( const char *arg, const char * const *names, int *dst ) @@ -527,6 +528,8 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value ) p->analyse.b_ssim = atobool(value); OPT("aud") p->b_aud = atobool(value); + OPT("filler") + p->b_filler = atobool(value); OPT("sps-id") p->i_sps_id = atoi(value); OPT("global-header") diff --git a/common/common.h b/common/common.h old mode 100644 new mode 100755 index b9f4869..329e609 --- a/common/common.h +++ b/common/common.h @@ -249,6 +249,7 @@ struct x264_t uint8_t *p_bitstream; /* will hold data for all nal */ bs_t bs; int i_frame_size; + int i_filler_size; } out; /* frame number/poc */ @@ -555,6 +556,8 @@ struct x264_t int i_direct_score[2]; int i_direct_frames[2]; + int64_t i_filler_size; + } stat; /* CPU functions dependents */ diff --git a/encoder/encoder.c b/encoder/encoder.c old mode 100644 new mode 100755 index 7637dc2..3934462 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -778,8 +778,8 @@ int x264_encoder_reconfig( x264_t *h, x264_param_t *param ) return x264_validate_parameters( h ); } -/* internal usage */ -static void x264_nal_start( x264_t *h, int i_type, int i_ref_idc ) + +void x264_nal_start( x264_t *h, int i_type, int i_ref_idc ) { x264_nal_t *nal = &h->out.nal[h->out.i_nal]; @@ -789,7 +789,8 @@ static void x264_nal_start( x264_t *h, int i_type, int i_ref_idc ) nal->i_payload= 0; nal->p_payload= &h->out.p_bitstream[bs_pos( &h->out.bs ) / 8]; } -static void x264_nal_end( x264_t *h ) + +void x264_nal_end( x264_t *h ) { x264_nal_t *nal = &h->out.nal[h->out.i_nal]; nal->i_payload = &h->out.p_bitstream[bs_pos( &h->out.bs ) / 8] - nal->p_payload; @@ -1611,6 +1612,13 @@ static void x264_encoder_frame_end( x264_t *h, x264_t *thread_current, return; } + /* ---------------------- Update encoder state ------------------------- */ + + /* update rc */ + x264_cpu_restore( h->param.cpu ); + x264_ratecontrol_end( h, h->out.i_frame_size * 8 ); + + x264_frame_push_unused( thread_current, h->fenc ); /* End bitstream, set output */ @@ -1635,10 +1643,6 @@ static void x264_encoder_frame_end( x264_t *h, x264_t *thread_current, /* ---------------------- Update encoder state ------------------------- */ - /* update rc */ - x264_cpu_restore( h->param.cpu ); - x264_ratecontrol_end( h, h->out.i_frame_size * 8 ); - /* restore CPU state (before using float again) */ x264_cpu_restore( h->param.cpu ); @@ -1653,6 +1657,7 @@ static void x264_encoder_frame_end( x264_t *h, x264_t *thread_current, h->stat.i_slice_count[h->sh.i_type]++; h->stat.i_slice_size[h->sh.i_type] += h->out.i_frame_size + NALU_OVERHEAD; h->stat.f_slice_qp[h->sh.i_type] += h->fdec->f_qp_avg_aq; + h->stat.i_filler_size += h->out.i_filler_size; for( i = 0; i < X264_MBTYPE_MAX; i++ ) h->stat.i_mb_count[h->sh.i_type][i] += h->stat.frame.i_mb_count[i]; @@ -1878,7 +1883,7 @@ void x264_encoder_close ( x264_t *h ) float fps = (float) h->param.i_fps_num / h->param.i_fps_den; #define SUM3(p) (p[SLICE_TYPE_I] + p[SLICE_TYPE_P] + p[SLICE_TYPE_B]) #define SUM3b(p,o) (p[SLICE_TYPE_I][o] + p[SLICE_TYPE_P][o] + p[SLICE_TYPE_B][o]) - float f_bitrate = fps * SUM3(h->stat.i_slice_size) / i_count / 125; + float f_bitrate = fps * (SUM3(h->stat.i_slice_size) + h->stat.i_filler_size) / i_count / 125; if( h->pps->b_transform_8x8_mode ) { diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c old mode 100644 new mode 100755 index bb10f5c..f844c0f --- a/encoder/ratecontrol.c +++ b/encoder/ratecontrol.c @@ -1240,6 +1240,8 @@ static void update_predictor( predictor_t *p, double q, double var, double bits p->coeff += bits*q / var; } +#define FILLER_OVERHEAD (5 + 1) + // update VBV after encoding a frame static void update_vbv( x264_t *h, int bits ) { @@ -1253,6 +1255,17 @@ static void update_vbv( x264_t *h, int bits ) return; rct->buffer_fill_final += rct->buffer_rate - bits; + + if (rct->buffer_fill_final >= rct->buffer_size && + h->param.b_filler && + h->thread[0]->param.rc.i_vbv_max_bitrate == h->param.rc.i_bitrate) + { + int padding = (rct->buffer_fill_final - rct->buffer_size) / 8; + x264_filler_write(h, padding); + h->out.i_filler_size = padding+FILLER_OVERHEAD; + rct->buffer_fill_final -= h->out.i_filler_size * 8; + } + if( rct->buffer_fill_final < 0 && !rct->b_2pass ) x264_log( h, X264_LOG_WARNING, "VBV underflow (%.0f bits)\n", rct->buffer_fill_final ); rct->buffer_fill_final = x264_clip3f( rct->buffer_fill_final, 0, rct->buffer_size ); diff --git a/encoder/set.c b/encoder/set.c old mode 100644 new mode 100755 index 6cf8773..23c0724 --- a/encoder/set.c +++ b/encoder/set.c @@ -28,6 +28,8 @@ #include "config.h" #endif +#include "set.h" + static void transpose( uint8_t *buf, int w ) { int i, j; @@ -503,6 +505,20 @@ void x264_sei_version_write( x264_t *h, bs_t *s ) x264_free( version ); } + +void x264_filler_write( x264_t *h, int filler_bytes ) +{ + int i; + + x264_nal_start( h, NAL_FILLER, NAL_PRIORITY_DISPOSABLE ); + for (i=0; i< filler_bytes; i++) + { + bs_write( &h->out.bs, 8, 0xFF ); + } + bs_rbsp_trailing(&h->out.bs); + x264_nal_end( h ); +} + 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 old mode 100644 new mode 100755 index dac2d2f..0cf4e82 --- a/encoder/set.h +++ b/encoder/set.h @@ -24,11 +24,15 @@ #ifndef _ENCODER_SET_H #define _ENCODER_SET_H 1 +void x264_nal_start( x264_t *h, int i_type, int i_ref_idc ); +void x264_nal_end( x264_t *h ); + void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ); void x264_sps_write( bs_t *s, x264_sps_t *sps ); void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t *sps ); void x264_pps_write( bs_t *s, x264_pps_t *pps ); void x264_sei_version_write( x264_t *h, bs_t *s ); +void x264_filler_write( x264_t *h, int filler_bytes ); void x264_validate_levels( x264_t *h ); #endif diff --git a/x264.c b/x264.c old mode 100644 new mode 100755 index 51bd0cd..f1622ca --- a/x264.c +++ b/x264.c @@ -320,6 +320,7 @@ static void Help( x264_param_t *defaults, int b_longhelp ) H1( " --visualize Show MB types overlayed on the encoded video\n" ); H1( " --sps-id Set SPS and PPS id numbers [%d]\n", defaults->i_sps_id ); H1( " --aud Use access unit delimiters\n" ); + H1( " --filler Use filler data access units\n" ); H0( "\n" ); } @@ -447,6 +448,7 @@ static int Parse( int argc, char **argv, { "visualize",no_argument, NULL, OPT_VISUALIZE }, { "sps-id", required_argument, NULL, 0 }, { "aud", no_argument, NULL, 0 }, + { "filler", no_argument, NULL, 0 }, { "nr", required_argument, NULL, 0 }, { "cqm", required_argument, NULL, 0 }, { "cqmfile", required_argument, NULL, 0 }, diff --git a/x264.h b/x264.h old mode 100644 new mode 100755 index e49f1a4..9d0ca18 --- a/x264.h +++ b/x264.h @@ -283,6 +283,7 @@ typedef struct x264_param_t } rc; /* Muxing parameters */ + int b_filler; /* use filler data */ int b_aud; /* generate access unit delimiters */ int b_repeat_headers; /* put SPS/PPS before each keyframe */ int i_sps_id; /* SPS and PPS id number */ @@ -372,6 +373,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