if vbv is not enabled (and especially in crf/cqp), we have to guess max bitrate, so we might underestimate the required level.
param->vui.i_chroma_loc= 0; /* left center */
param->i_fps_num = 25;
param->i_fps_den = 1;
- param->i_level_idc = 51; /* as close to "unrestricted" as we can get */
+ param->i_level_idc = -1;
/* Encoder parameters */
param->i_frame_reference = 1;
param->analyse.b_chroma_me = 1;
param->analyse.i_mv_range_thread = -1;
param->analyse.i_mv_range = -1; // set from level_idc
- param->analyse.i_direct_8x8_inference = -1; // set from level_idc
+ param->analyse.i_direct_8x8_inference = 1;
param->analyse.i_chroma_qp_offset = 0;
param->analyse.b_fast_pskip = 1;
param->analyse.b_dct_decimate = 1;
{
const x264_level_t *l = x264_levels;
- while( l->level_idc != 0 && l->level_idc != h->param.i_level_idc )
- l++;
- if( l->level_idc == 0 )
+ if( h->param.i_level_idc < 0 )
{
- x264_log( h, X264_LOG_ERROR, "invalid level_idc: %d\n", h->param.i_level_idc );
- return -1;
+ if( h->param.rc.i_rc_method == X264_RC_ABR && h->param.rc.i_vbv_buffer_size <= 0 )
+ h->param.rc.i_vbv_max_bitrate = h->param.rc.i_bitrate * 2;
+ h->sps = h->sps_array;
+ x264_sps_init( h->sps, h->param.i_sps_id, &h->param );
+ do h->param.i_level_idc = l->level_idc;
+ while( l[1].level_idc && x264_validate_levels( h, 0 ) && l++ );
+ if( h->param.rc.i_vbv_buffer_size <= 0 )
+ h->param.rc.i_vbv_max_bitrate = 0;
+ x264_log( h, X264_LOG_DEBUG, "level_idc: %d\n", h->param.i_level_idc );
+ }
+ else
+ {
+ while( l->level_idc && l->level_idc != h->param.i_level_idc )
+ l++;
+ if( l->level_idc == 0 )
+ {
+ x264_log( h, X264_LOG_ERROR, "invalid level_idc: %d\n", h->param.i_level_idc );
+ return -1;
+ }
}
if( h->param.analyse.i_mv_range <= 0 )
h->param.analyse.i_mv_range = l->mv_range >> h->param.b_interlaced;
h->pps = &h->pps_array[0];
x264_pps_init( h->pps, h->param.i_sps_id, &h->param, h->sps);
- x264_validate_levels( h );
+ x264_validate_levels( h, 1 );
if( x264_cqm_init( h ) < 0 )
{
{ 0 }
};
-void x264_validate_levels( x264_t *h )
+#define ERROR(...)\
+{\
+ if( verbose )\
+ x264_log( h, X264_LOG_WARNING, __VA_ARGS__ );\
+ ret = 1;\
+}
+
+int x264_validate_levels( x264_t *h, int verbose )
{
- int mbs;
+ int ret = 0;
+ int mbs = h->sps->i_mb_width * h->sps->i_mb_height;
+ int dpb = mbs * 384 * h->sps->i_num_ref_frames;
const x264_level_t *l = x264_levels;
while( l->level_idc != 0 && l->level_idc != h->param.i_level_idc )
l++;
- mbs = h->sps->i_mb_width * h->sps->i_mb_height;
if( l->frame_size < mbs
|| l->frame_size*8 < h->sps->i_mb_width * h->sps->i_mb_width
|| l->frame_size*8 < h->sps->i_mb_height * h->sps->i_mb_height )
- x264_log( h, X264_LOG_WARNING, "frame MB size (%dx%d) > level limit (%d)\n",
- h->sps->i_mb_width, h->sps->i_mb_height, l->frame_size );
+ ERROR( "frame MB size (%dx%d) > level limit (%d)\n",
+ h->sps->i_mb_width, h->sps->i_mb_height, l->frame_size );
+ if( dpb > l->dpb )
+ ERROR( "DPB size (%d frames, %d bytes) > level limit (%d frames, %d bytes)\n",
+ h->sps->i_num_ref_frames, dpb, (int)(l->dpb / (384*mbs)), l->dpb );
#define CHECK( name, limit, val ) \
if( (val) > (limit) ) \
- x264_log( h, X264_LOG_WARNING, name " (%d) > level limit (%d)\n", (int)(val), (limit) );
+ ERROR( name " (%d) > level limit (%d)\n", (int)(val), (limit) );
- CHECK( "DPB size", l->dpb, mbs * 384 * h->sps->i_num_ref_frames );
CHECK( "VBV bitrate", l->bitrate, h->param.rc.i_vbv_max_bitrate );
CHECK( "VBV buffer", l->cpb, h->param.rc.i_vbv_buffer_size );
CHECK( "MV range", l->mv_range, h->param.analyse.i_mv_range );
if( h->param.i_fps_den > 0 )
CHECK( "MB rate", l->mbps, (int64_t)mbs * h->param.i_fps_num / h->param.i_fps_den );
if( h->sps->b_direct8x8_inference < l->direct8x8 )
- x264_log( h, X264_LOG_WARNING, "direct 8x8 inference (0) < level requirement (1)\n" );
+ ERROR( "direct 8x8 inference (0) < level requirement (1)\n" );
/* TODO check the rest of the limits */
+ return ret;
}
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_validate_levels( x264_t *h );
+int x264_validate_levels( x264_t *h, int verbose );
#endif