[x264-devel] [PATCH] filler data

Limin Wang lance.lmwang at gmail.com
Tue Apr 15 08:29:21 CEST 2008


Hi,


Before I had written the same code for vbv buffer overflow, but I did not add
i_filler_size field as I count the padding byte into i_frame_size direct.
Another difference is I haven't export x264_nal_start/end interface to public.
For real CBR, I think it's force to fill stuffing data, so I enable it directly.
Attached is my old patch. 


Thanks,
Limin
* Gabriel Bouvigne <gabriel.bouvigne at joost.com> [2008-04-14 12:23:52 +0200]:

> Allows automatic insertion of filler data. Stream must be CBR, otherwise  
> filler won't be inserted.
> Use --filler to enable filler data.
>
> --
> Gabriel

> 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 <integer>      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

> _______________________________________________
> x264-devel mailing list
> x264-devel at videolan.org
> http://mailman.videolan.org/listinfo/x264-devel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: overflow.patch
Type: text/x-diff
Size: 6292 bytes
Desc: not available
Url : http://mailman.videolan.org/pipermail/x264-devel/attachments/20080415/8e5a91fe/attachment-0001.patch 


More information about the x264-devel mailing list