From: Loren Merritt Date: Wed, 16 Jul 2008 02:16:16 +0000 (-0600) Subject: autodetect level based on resolution/bitrate/refs/etc, rather than defaulting to... X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=579e930f34e88196fa96ca576b78891f3df69c87;p=x264 autodetect level based on resolution/bitrate/refs/etc, rather than defaulting to L5.1 if vbv is not enabled (and especially in crf/cqp), we have to guess max bitrate, so we might underestimate the required level. --- diff --git a/common/common.c b/common/common.c index 71a29b1a..22b1d5ce 100644 --- a/common/common.c +++ b/common/common.c @@ -61,7 +61,7 @@ void x264_param_default( x264_param_t *param ) 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; @@ -122,7 +122,7 @@ void x264_param_default( x264_param_t *param ) 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; diff --git a/encoder/encoder.c b/encoder/encoder.c index fb34ca87..5b737db7 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -496,12 +496,27 @@ static int x264_validate_parameters( x264_t *h ) { 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; @@ -649,7 +664,7 @@ x264_t *x264_encoder_open ( x264_param_t *param ) 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 ) { diff --git a/encoder/set.c b/encoder/set.c index f47954d0..3dbed5d5 100644 --- a/encoder/set.c +++ b/encoder/set.c @@ -526,26 +526,36 @@ const x264_level_t x264_levels[] = { 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 ); @@ -553,7 +563,8 @@ void x264_validate_levels( x264_t *h ) 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; } diff --git a/encoder/set.h b/encoder/set.h index b4fa6b1f..3611c9ad 100644 --- a/encoder/set.h +++ b/encoder/set.h @@ -29,6 +29,6 @@ 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_validate_levels( x264_t *h ); +int x264_validate_levels( x264_t *h, int verbose ); #endif