autodetect level based on resolution/bitrate/refs/etc, rather than defaulting to...
authorLoren Merritt <pengvado@akuvian.org>
Wed, 16 Jul 2008 02:16:16 +0000 (20:16 -0600)
committerLoren Merritt <pengvado@akuvian.org>
Fri, 18 Jul 2008 02:26:29 +0000 (20:26 -0600)
if vbv is not enabled (and especially in crf/cqp), we have to guess max bitrate, so we might underestimate the required level.

common/common.c
encoder/encoder.c
encoder/set.c
encoder/set.h

index 71a29b1..22b1d5c 100644 (file)
@@ -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;
index fb34ca8..5b737db 100644 (file)
@@ -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 )
     {
index f47954d..3dbed5d 100644 (file)
@@ -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;
 }
index b4fa6b1..3611c9a 100644 (file)
@@ -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