]> git.sesse.net Git - x264/commitdiff
Improve quantizer handling
authorFiona Glaser <fiona@x264.com>
Sun, 31 Oct 2010 22:51:48 +0000 (15:51 -0700)
committerFiona Glaser <fiona@x264.com>
Wed, 10 Nov 2010 08:16:23 +0000 (00:16 -0800)
The default value for i_qpplus1 in x264_picture_t is now X264_QP_AUTO.  This is currently 0, but may change in the future.
qpfiles no longer use -1 to indicate "auto"; QP is just omitted.  The old method should still work though.

CRF values now make sense in high bit depth mode.
--qp should be used for lossless mode, not --crf.
--crf 0 will still work as expected in 8-bit mode, but won't be lossless with higher bit depths.
Add bit depth to statsfiles.

These changes are required to make the QP interface sensible in combination with high bit depth.

common/common.c
common/frame.c
encoder/encoder.c
encoder/ratecontrol.c
x264.c
x264.h

index 3fe5c96af848d05d163d98b46b077fa49617c14b..bdab98dedecb47bc28d2067e1e1f0f3c49bf92d1 100644 (file)
@@ -97,7 +97,7 @@ void x264_param_default( x264_param_t *param )
     param->rc.i_vbv_buffer_size = 0;
     param->rc.f_vbv_buffer_init = 0.9;
     param->rc.i_qp_constant = 23 + QP_BD_OFFSET;
-    param->rc.f_rf_constant = 23 + QP_BD_OFFSET;
+    param->rc.f_rf_constant = 23;
     param->rc.i_qp_min = 10;
     param->rc.i_qp_max = QP_MAX;
     param->rc.i_qp_step = 4;
@@ -1038,7 +1038,7 @@ void x264_picture_init( x264_picture_t *pic )
 {
     memset( pic, 0, sizeof( x264_picture_t ) );
     pic->i_type = X264_TYPE_AUTO;
-    pic->i_qpplus1 = 0;
+    pic->i_qpplus1 = X264_QP_AUTO;
     pic->i_pic_struct = PIC_STRUCT_AUTO;
 }
 
@@ -1197,6 +1197,7 @@ char *x264_param2string( x264_param_t *p, int b_res )
         s += sprintf( s, "%dx%d ", p->i_width, p->i_height );
         s += sprintf( s, "fps=%u/%u ", p->i_fps_num, p->i_fps_den );
         s += sprintf( s, "timebase=%u/%u ", p->i_timebase_num, p->i_timebase_den );
+        s += sprintf( s, "bitdepth=%d", BIT_DEPTH );
     }
 
     s += sprintf( s, "cabac=%d", p->b_cabac );
index b24d9f92e89a766284b6ed6eea4880b53c2d9fa1..96291f043f66f8baf84438a91c10fa7c2bc2c680 100644 (file)
@@ -78,7 +78,7 @@ x264_frame_t *x264_frame_new( x264_t *h, int b_fdec )
 
     frame->i_poc = -1;
     frame->i_type = X264_TYPE_AUTO;
-    frame->i_qpplus1 = 0;
+    frame->i_qpplus1 = X264_QP_AUTO;
     frame->i_pts = -1;
     frame->i_frame = -1;
     frame->i_frame_num = -1;
index 5315f921bcd62491f9b58b9149a8d14eb099dd96..09d1e2f3f766bdcb6daf1b72d3ce52424e77d6cc 100644 (file)
@@ -488,11 +488,11 @@ static int x264_validate_parameters( x264_t *h )
         x264_log( h, X264_LOG_ERROR, "no ratecontrol method specified\n" );
         return -1;
     }
-    h->param.rc.f_rf_constant = x264_clip3f( h->param.rc.f_rf_constant, 0, QP_MAX );
+    h->param.rc.f_rf_constant = x264_clip3f( h->param.rc.f_rf_constant, -QP_BD_OFFSET, 51 );
     h->param.rc.i_qp_constant = x264_clip3( h->param.rc.i_qp_constant, 0, QP_MAX );
     if( h->param.rc.i_rc_method == X264_RC_CRF )
     {
-        h->param.rc.i_qp_constant = h->param.rc.f_rf_constant;
+        h->param.rc.i_qp_constant = h->param.rc.f_rf_constant + QP_BD_OFFSET;
         h->param.rc.i_bitrate = 0;
     }
     if( (h->param.rc.i_rc_method == X264_RC_CQP || h->param.rc.i_rc_method == X264_RC_CRF)
index e2a5993c3fd4862ebdab56e4aa573a3a9299e53e..dd9c3cba2825b8eec759fc17ec1f4bcb82af149a 100644 (file)
@@ -90,7 +90,6 @@ struct x264_ratecontrol_t
     float qpa_rc;               /* average of macroblocks' qp before aq */
     float qpa_aq;               /* average of macroblocks' qp after aq */
     float qp_novbv;             /* QP for the current frame if 1-pass VBV was disabled. */
-    int qp_force;
 
     /* VBV stuff */
     double buffer_size;
@@ -456,7 +455,7 @@ void x264_ratecontrol_init_reconfigurable( x264_t *h, int b_init )
         double base_cplx = h->mb.i_mb_count * (h->param.i_bframe ? 120 : 80);
         double mbtree_offset = h->param.rc.b_mb_tree ? (1.0-h->param.rc.f_qcompress)*13.5 : 0;
         rc->rate_factor_constant = pow( base_cplx, 1 - rc->qcompress )
-                                 / qp2qscale( h->param.rc.f_rf_constant + mbtree_offset );
+                                 / qp2qscale( h->param.rc.f_rf_constant + mbtree_offset + QP_BD_OFFSET );
     }
 
     if( h->param.rc.i_vbv_max_bitrate > 0 && h->param.rc.i_vbv_buffer_size > 0 )
@@ -621,7 +620,7 @@ int x264_ratecontrol_new( x264_t *h )
     if( rc->b_abr )
     {
         /* FIXME ABR_INIT_QP is actually used only in CRF */
-#define ABR_INIT_QP ( h->param.rc.i_rc_method == X264_RC_CRF ? h->param.rc.f_rf_constant : 24 )
+#define ABR_INIT_QP (( h->param.rc.i_rc_method == X264_RC_CRF ? h->param.rc.f_rf_constant : 24 ) + QP_BD_OFFSET)
         rc->accum_p_norm = .01;
         rc->accum_p_qp = ABR_INIT_QP * rc->accum_p_norm;
         /* estimated ratio that produces a reasonable QP for the first I-frame */
@@ -732,6 +731,7 @@ int x264_ratecontrol_new( x264_t *h )
                 return -1;
             }
 
+            CMP_OPT_FIRST_PASS( "bitdepth", BIT_DEPTH );
             CMP_OPT_FIRST_PASS( "weightp", X264_MAX( 0, h->param.analyse.i_weighted_pred ) );
             CMP_OPT_FIRST_PASS( "bframes", h->param.i_bframe );
             CMP_OPT_FIRST_PASS( "b_pyramid", h->param.i_bframe_pyramid );
@@ -1173,8 +1173,6 @@ void x264_ratecontrol_start( x264_t *h, int i_force_qp, int overhead )
         x264_encoder_reconfig( h, zone->param );
     rc->prev_zone = zone;
 
-    rc->qp_force = i_force_qp;
-
     if( h->param.rc.b_stat_read )
     {
         int frame = h->fenc->i_frame;
@@ -1230,7 +1228,7 @@ void x264_ratecontrol_start( x264_t *h, int i_force_qp, int overhead )
     if( h->sh.i_type != SLICE_TYPE_B )
         rc->bframes = h->fenc->i_bframes;
 
-    if( i_force_qp )
+    if( i_force_qp != X264_QP_AUTO )
     {
         q = i_force_qp - 1;
     }
diff --git a/x264.c b/x264.c
index db73afd742fad6f03391f91b3a62ac691342640e..9846be717b7489f63cf88586b9ada446870925c0 100644 (file)
--- a/x264.c
+++ b/x264.c
@@ -381,7 +381,7 @@ static void help( x264_param_t *defaults, int longhelp )
     H0( "            x264 --pass 2 --bitrate 1000 -o <output> <input>\n" );
     H0( "\n" );
     H0( "      Lossless:\n" );
-    H0( "            x264 --crf 0 -o <output> <input>\n" );
+    H0( "            x264 --qp 0 -o <output> <input>\n" );
     H0( "\n" );
     H0( "      Maximum PSNR at the cost of speed and visual quality:\n" );
     H0( "            x264 --preset placebo --tune psnr -o <output> <input>\n" );
@@ -538,7 +538,7 @@ static void help( x264_param_t *defaults, int longhelp )
     H0( "\n" );
     H1( "  -q, --qp <integer>          Force constant QP (0-%d, 0=lossless)\n", QP_MAX );
     H0( "  -B, --bitrate <integer>     Set bitrate (kbit/s)\n" );
-    H0( "      --crf <float>           Quality-based VBR (0-%d, 0=lossless) [%.1f]\n", QP_MAX, defaults->rc.f_rf_constant );
+    H0( "      --crf <float>           Quality-based VBR (%d-51) [%.1f]\n", 51 - QP_MAX, defaults->rc.f_rf_constant );
     H1( "      --rc-lookahead <integer> Number of frames for frametype lookahead [%d]\n", defaults->rc.i_lookahead );
     H0( "      --vbv-maxrate <integer> Max local bitrate (kbit/s) [%d]\n", defaults->rc.i_vbv_max_bitrate );
     H0( "      --vbv-bufsize <integer> Set size of the VBV buffer (kbit) [%d]\n", defaults->rc.i_vbv_buffer_size );
@@ -576,7 +576,7 @@ static void help( x264_param_t *defaults, int longhelp )
         "                                  or  b=<float> (bitrate multiplier)\n" );
     H2( "      --qpfile <string>       Force frametypes and QPs for some or all frames\n"
         "                              Format of each line: framenumber frametype QP\n"
-        "                              QP of -1 lets x264 choose. Frametypes: I,i,K,P,B,b.\n"
+        "                              QP is optional (none lets x264 choose). Frametypes: I,i,K,P,B,b.\n"
         "                                  K=<I or i> depending on open-gop setting\n"
         "                              QPs are restricted by qpmin/qpmax.\n" );
     H1( "\n" );
@@ -1485,16 +1485,17 @@ static void parse_qpfile( cli_opt_t *opt, x264_picture_t *pic, int i_frame )
     {
         file_pos = ftell( opt->qpfile );
         ret = fscanf( opt->qpfile, "%d %c %d\n", &num, &type, &qp );
+        pic->i_type = X264_TYPE_AUTO;
+        pic->i_qpplus1 = X264_QP_AUTO;
         if( num > i_frame || ret == EOF )
         {
-            pic->i_type = X264_TYPE_AUTO;
-            pic->i_qpplus1 = 0;
             fseek( opt->qpfile, file_pos, SEEK_SET );
             break;
         }
         if( num < i_frame && ret == 3 )
             continue;
-        pic->i_qpplus1 = qp+1;
+        if( ret == 3 && qp >= 0 )
+            pic->i_qpplus1 = qp+1;
         if     ( type == 'I' ) pic->i_type = X264_TYPE_IDR;
         else if( type == 'i' ) pic->i_type = X264_TYPE_I;
         else if( type == 'K' ) pic->i_type = X264_TYPE_KEYFRAME;
@@ -1502,13 +1503,11 @@ static void parse_qpfile( cli_opt_t *opt, x264_picture_t *pic, int i_frame )
         else if( type == 'B' ) pic->i_type = X264_TYPE_BREF;
         else if( type == 'b' ) pic->i_type = X264_TYPE_B;
         else ret = 0;
-        if( ret != 3 || qp < -1 || qp > QP_MAX )
+        if( ret < 2 || qp < -1 || qp > QP_MAX )
         {
             x264_cli_log( "x264", X264_LOG_ERROR, "can't parse qpfile for frame %d\n", i_frame );
             fclose( opt->qpfile );
             opt->qpfile = NULL;
-            pic->i_type = X264_TYPE_AUTO;
-            pic->i_qpplus1 = 0;
             break;
         }
     }
@@ -1594,7 +1593,6 @@ static int encode( x264_param_t *param, cli_opt_t *opt )
 
     opt->b_progress &= param->i_log_level < X264_LOG_DEBUG;
     i_update_interval = param->i_frame_total ? x264_clip3( param->i_frame_total / 1000, 1, 10 ) : 10;
-    x264_picture_init( &pic );
 
     /* set up pulldown */
     if( opt->i_pulldown && !param->b_vfr_input )
@@ -1649,6 +1647,7 @@ static int encode( x264_param_t *param, cli_opt_t *opt )
     {
         if( filter.get_frame( opt->hin, &cli_pic, i_frame + opt->i_seek ) )
             break;
+        x264_picture_init( &pic );
         convert_cli_to_lib_pic( &pic, &cli_pic );
 
         if( !param->b_vfr_input )
@@ -1681,12 +1680,6 @@ static int encode( x264_param_t *param, cli_opt_t *opt )
 
         if( opt->qpfile )
             parse_qpfile( opt, &pic, i_frame + opt->i_seek );
-        else
-        {
-            /* Do not force any parameters */
-            pic.i_type = X264_TYPE_AUTO;
-            pic.i_qpplus1 = 0;
-        }
 
         prev_dts = last_dts;
         i_frame_size = encode_frame( h, opt->hout, &pic, &last_dts );
diff --git a/x264.h b/x264.h
index cd2fe9cca79bcf9f4e65729ea44873526c97d278..2183de333869a47ca6b37b7c4bfcb14fb3aee636 100644 (file)
--- a/x264.h
+++ b/x264.h
@@ -143,6 +143,7 @@ typedef struct
 #define X264_RC_CQP                  0
 #define X264_RC_CRF                  1
 #define X264_RC_ABR                  2
+#define X264_QP_AUTO                 0
 #define X264_AQ_NONE                 0
 #define X264_AQ_VARIANCE             1
 #define X264_AQ_AUTOVARIANCE         2
@@ -343,7 +344,7 @@ typedef struct x264_param_t
     {
         int         i_rc_method;    /* X264_RC_* */
 
-        int         i_qp_constant;  /* 0 to (51 + 6*(x264_bit_depth-8)) */
+        int         i_qp_constant;  /* 0 to (51 + 6*(x264_bit_depth-8)). 0=lossless */
         int         i_qp_min;       /* min allowed QP value */
         int         i_qp_max;       /* max allowed QP value */
         int         i_qp_step;      /* max QP step between frames */
@@ -658,7 +659,7 @@ typedef struct
      *     mixing of auto and forced frametypes is done.
      * Out: type of the picture encoded */
     int     i_type;
-    /* In: force quantizer for > 0 */
+    /* In: force quantizer for != X264_QP_AUTO */
     int     i_qpplus1;
     /* In: pic_struct, for pulldown/doubling/etc...used only if b_pic_timing_sei=1.
      *     use pic_struct_e for pic_struct inputs */