[x264-devel] commit: autodetect level based on resolution/bitrate/refs/etc, rather than defaulting to L5.1 (Loren Merritt )
git version control
git at videolan.org
Sun Jul 20 19:45:28 CEST 2008
x264 | branch: master | Loren Merritt <pengvado at akuvian.org> | Tue Jul 15 20:16:16 2008 -0600| [14046ae09f91272751f3df4d70fb0268321ee557]
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.
> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=14046ae09f91272751f3df4d70fb0268321ee557
---
common/common.c | 4 ++--
encoder/encoder.c | 27 +++++++++++++++++++++------
encoder/set.c | 27 +++++++++++++++++++--------
encoder/set.h | 2 +-
4 files changed, 43 insertions(+), 17 deletions(-)
diff --git a/common/common.c b/common/common.c
index 71a29b1..22b1d5c 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 fb34ca8..5b737db 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 f47954d..3dbed5d 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 b4fa6b1..3611c9a 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
More information about the x264-devel
mailing list