]> git.sesse.net Git - x264/commitdiff
Move presets, tunings, and profiles into libx264
authorFiona Glaser <fiona@x264.com>
Sun, 21 Feb 2010 09:56:12 +0000 (01:56 -0800)
committerFiona Glaser <fiona@x264.com>
Tue, 23 Feb 2010 09:46:19 +0000 (01:46 -0800)
Now any application calling libx264 can use them.
Full documentation and guidelines for usage are included in x264.h.

common/common.c
x264.c
x264.h

index 0dd7af527050a2b07bb8d72062685cd11486d627..a99b65bfe1c65fa5d458139b7ad5db8cc2857036 100644 (file)
@@ -36,7 +36,7 @@ static void x264_log_default( void *, int, const char *, va_list );
 /****************************************************************************
  * x264_param_default:
  ****************************************************************************/
-void    x264_param_default( x264_param_t *param )
+void x264_param_default( x264_param_t *param )
 {
     /* */
     memset( param, 0, sizeof( x264_param_t ) );
@@ -160,6 +160,270 @@ void    x264_param_default( x264_param_t *param )
     param->b_dts_compress = 0;
 }
 
+static int x264_param_apply_preset( x264_param_t *param, const char *preset )
+{
+    if( !strcasecmp( preset, "ultrafast" ) )
+    {
+        param->i_frame_reference = 1;
+        param->i_scenecut_threshold = 0;
+        param->b_deblocking_filter = 0;
+        param->b_cabac = 0;
+        param->i_bframe = 0;
+        param->analyse.intra = 0;
+        param->analyse.inter = 0;
+        param->analyse.b_transform_8x8 = 0;
+        param->analyse.i_me_method = X264_ME_DIA;
+        param->analyse.i_subpel_refine = 0;
+        param->rc.i_aq_mode = 0;
+        param->analyse.b_mixed_references = 0;
+        param->analyse.i_trellis = 0;
+        param->i_bframe_adaptive = X264_B_ADAPT_NONE;
+        param->rc.b_mb_tree = 0;
+        param->analyse.i_weighted_pred = X264_WEIGHTP_NONE;
+    }
+    else if( !strcasecmp( preset, "veryfast" ) )
+    {
+        param->analyse.inter = X264_ANALYSE_I8x8|X264_ANALYSE_I4x4;
+        param->analyse.i_me_method = X264_ME_DIA;
+        param->analyse.i_subpel_refine = 1;
+        param->i_frame_reference = 1;
+        param->analyse.b_mixed_references = 0;
+        param->analyse.i_trellis = 0;
+        param->rc.b_mb_tree = 0;
+        param->analyse.i_weighted_pred = X264_WEIGHTP_NONE;
+    }
+    else if( !strcasecmp( preset, "faster" ) )
+    {
+        param->analyse.b_mixed_references = 0;
+        param->i_frame_reference = 2;
+        param->analyse.i_subpel_refine = 4;
+        param->rc.b_mb_tree = 0;
+        param->analyse.i_weighted_pred = X264_WEIGHTP_BLIND;
+    }
+    else if( !strcasecmp( preset, "fast" ) )
+    {
+        param->i_frame_reference = 2;
+        param->analyse.i_subpel_refine = 6;
+        param->rc.i_lookahead = 30;
+    }
+    else if( !strcasecmp( preset, "medium" ) )
+    {
+        /* Default is medium */
+    }
+    else if( !strcasecmp( preset, "slow" ) )
+    {
+        param->analyse.i_me_method = X264_ME_UMH;
+        param->analyse.i_subpel_refine = 8;
+        param->i_frame_reference = 5;
+        param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
+        param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
+        param->rc.i_lookahead = 50;
+    }
+    else if( !strcasecmp( preset, "slower" ) )
+    {
+        param->analyse.i_me_method = X264_ME_UMH;
+        param->analyse.i_subpel_refine = 9;
+        param->i_frame_reference = 8;
+        param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
+        param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
+        param->analyse.inter |= X264_ANALYSE_PSUB8x8;
+        param->analyse.i_trellis = 2;
+        param->rc.i_lookahead = 60;
+    }
+    else if( !strcasecmp( preset, "veryslow" ) )
+    {
+        param->analyse.i_me_method = X264_ME_UMH;
+        param->analyse.i_subpel_refine = 10;
+        param->analyse.i_me_range = 24;
+        param->i_frame_reference = 16;
+        param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
+        param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
+        param->analyse.inter |= X264_ANALYSE_PSUB8x8;
+        param->analyse.i_trellis = 2;
+        param->i_bframe = 8;
+        param->rc.i_lookahead = 60;
+    }
+    else if( !strcasecmp( preset, "placebo" ) )
+    {
+        param->analyse.i_me_method = X264_ME_TESA;
+        param->analyse.i_subpel_refine = 10;
+        param->analyse.i_me_range = 24;
+        param->i_frame_reference = 16;
+        param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
+        param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
+        param->analyse.inter |= X264_ANALYSE_PSUB8x8;
+        param->analyse.b_fast_pskip = 0;
+        param->analyse.i_trellis = 2;
+        param->i_bframe = 16;
+        param->rc.i_lookahead = 60;
+    }
+    else
+    {
+        fprintf( stderr, "x264 [error]: invalid preset '%s'\n", preset );
+        return -1;
+    }
+    return 0;
+}
+
+static int x264_param_apply_tune( x264_param_t *param, const char *tune )
+{
+    char *tmp = x264_malloc( strlen( tune ) );
+    if( !tmp )
+        return -1;
+    tmp = strcpy( tmp, tune );
+    char *s = strtok( tmp, ",./-+" );
+    int psy_tuning_used = 0;
+    while( s )
+    {
+        if( !strncasecmp( s, "film", 4 ) )
+        {
+            if( psy_tuning_used++ ) goto psy_failure;
+            param->i_deblocking_filter_alphac0 = -1;
+            param->i_deblocking_filter_beta = -1;
+            param->analyse.f_psy_trellis = 0.15;
+        }
+        else if( !strncasecmp( s, "animation", 9 ) )
+        {
+            if( psy_tuning_used++ ) goto psy_failure;
+            param->i_frame_reference = param->i_frame_reference > 1 ? param->i_frame_reference*2 : 1;
+            param->i_deblocking_filter_alphac0 = 1;
+            param->i_deblocking_filter_beta = 1;
+            param->analyse.f_psy_rd = 0.4;
+            param->rc.f_aq_strength = 0.6;
+            param->i_bframe += 2;
+        }
+        else if( !strncasecmp( s, "grain", 5 ) )
+        {
+            if( psy_tuning_used++ ) goto psy_failure;
+            param->i_deblocking_filter_alphac0 = -2;
+            param->i_deblocking_filter_beta = -2;
+            param->analyse.f_psy_trellis = 0.25;
+            param->analyse.b_dct_decimate = 0;
+            param->rc.f_pb_factor = 1.1;
+            param->rc.f_ip_factor = 1.1;
+            param->rc.f_aq_strength = 0.5;
+            param->analyse.i_luma_deadzone[0] = 6;
+            param->analyse.i_luma_deadzone[1] = 6;
+            param->rc.f_qcompress = 0.8;
+        }
+        else if( !strncasecmp( s, "psnr", 4 ) )
+        {
+            if( psy_tuning_used++ ) goto psy_failure;
+            param->rc.i_aq_mode = X264_AQ_NONE;
+            param->analyse.b_psy = 0;
+        }
+        else if( !strncasecmp( s, "ssim", 4 ) )
+        {
+            if( psy_tuning_used++ ) goto psy_failure;
+            param->rc.i_aq_mode = X264_AQ_AUTOVARIANCE;
+            param->analyse.b_psy = 0;
+        }
+        else if( !strncasecmp( s, "fastdecode", 10 ) )
+        {
+            param->b_deblocking_filter = 0;
+            param->b_cabac = 0;
+            param->analyse.b_weighted_bipred = 0;
+            param->analyse.i_weighted_pred = X264_WEIGHTP_NONE;
+        }
+        else if( !strncasecmp( s, "zerolatency", 11 ) )
+        {
+            param->rc.i_lookahead = 0;
+            param->i_sync_lookahead = 0;
+            param->i_bframe = 0;
+            param->b_sliced_threads = 1;
+        }
+        else if( !strncasecmp( s, "touhou", 6 ) )
+        {
+            if( psy_tuning_used++ ) goto psy_failure;
+            param->i_frame_reference = param->i_frame_reference > 1 ? param->i_frame_reference*2 : 1;
+            param->i_deblocking_filter_alphac0 = -1;
+            param->i_deblocking_filter_beta = -1;
+            param->analyse.f_psy_trellis = 0.2;
+            param->rc.f_aq_strength = 1.3;
+            if( param->analyse.inter & X264_ANALYSE_PSUB16x16 )
+                param->analyse.inter |= X264_ANALYSE_PSUB8x8;
+        }
+        else
+        {
+            fprintf( stderr, "x264 [error]: invalid tune '%s'\n", s );
+            return -1;
+        }
+        if( 0 )
+        {
+    psy_failure:
+            fprintf( stderr, "x264 [warning]: only 1 psy tuning can be used: ignoring tune %s\n", s );
+        }
+        s = strtok( NULL, ",./-+" );
+    }
+    return 0;
+}
+
+int x264_param_default_preset( x264_param_t *param, const char *preset, const char *tune )
+{
+    x264_param_default( param );
+
+    if( preset && x264_param_apply_preset( param, preset ) < 0 )
+        return -1;
+    if( tune && x264_param_apply_tune( param, tune ) < 0 )
+        return -1;
+    return 0;
+}
+
+void x264_param_apply_fastfirstpass( x264_param_t *param )
+{
+    /* Set faster options in case of turbo firstpass. */
+    if( param->rc.b_stat_read && !param->rc.b_stat_write )
+    {
+        param->i_frame_reference = 1;
+        param->analyse.b_transform_8x8 = 0;
+        param->analyse.inter = 0;
+        param->analyse.i_me_method = X264_ME_DIA;
+        param->analyse.i_subpel_refine = X264_MIN( 2, param->analyse.i_subpel_refine );
+        param->analyse.i_trellis = 0;
+    }
+}
+
+int x264_param_apply_profile( x264_param_t *param, const char *profile )
+{
+    if( !profile )
+        return 0;
+
+    if( !strcasecmp( profile, "baseline" ) )
+    {
+        param->analyse.b_transform_8x8 = 0;
+        param->b_cabac = 0;
+        param->i_cqm_preset = X264_CQM_FLAT;
+        param->i_bframe = 0;
+        param->analyse.i_weighted_pred = X264_WEIGHTP_NONE;
+        if( param->b_interlaced )
+        {
+            fprintf( stderr, "x264 [error]: baseline profile doesn't support interlacing\n" );
+            return -1;
+        }
+    }
+    else if( !strcasecmp( profile, "main" ) )
+    {
+        param->analyse.b_transform_8x8 = 0;
+        param->i_cqm_preset = X264_CQM_FLAT;
+    }
+    else if( !strcasecmp( profile, "high" ) )
+    {
+        /* Default */
+    }
+    else
+    {
+        fprintf( stderr, "x264 [error]: invalid profile: %s\n", profile );
+        return -1;
+    }
+    if( (param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant == 0) ||
+        (param->rc.i_rc_method == X264_RC_CRF && param->rc.f_rf_constant == 0) )
+    {
+        fprintf( stderr, "x264 [error]: %s profile doesn't support lossless\n", profile );
+        return -1;
+    }
+    return 0;
+}
+
 static int parse_enum( const char *arg, const char * const *names, int *dst )
 {
     int i;
diff --git a/x264.c b/x264.c
index 959626adc327042d6f5d05135ccee62a64596adc..2875dd16e9b094ed8e161ff7af0441e95ff15451 100644 (file)
--- a/x264.c
+++ b/x264.c
@@ -115,8 +115,6 @@ int main( int argc, char **argv )
     _setmode(_fileno(stdout), _O_BINARY);
 #endif
 
-    x264_param_default( &param );
-
     /* Parse command line */
     if( Parse( argc, argv, &param, &opt ) < 0 )
         return -1;
@@ -799,12 +797,13 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
     char *profile = NULL;
     int b_thread_input = 0;
     int b_turbo = 1;
-    int b_pass1 = 0;
     int b_user_ref = 0;
     int b_user_fps = 0;
     int b_user_interlaced = 0;
     int i;
     cli_input_opt_t input_opt;
+    char *preset = NULL;
+    char *tune = NULL;
 
     memset( opt, 0, sizeof(cli_opt_t) );
     memset( &input_opt, 0, sizeof(cli_input_opt_t) );
@@ -816,219 +815,20 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
         int c = getopt_long( argc, argv, short_options, long_options, NULL );
         if( c == -1 )
             break;
-
         if( c == OPT_PRESET )
         {
-            if( !strcasecmp( optarg, "ultrafast" ) )
-            {
-                param->i_frame_reference = 1;
-                param->i_scenecut_threshold = 0;
-                param->b_deblocking_filter = 0;
-                param->b_cabac = 0;
-                param->i_bframe = 0;
-                param->analyse.intra = 0;
-                param->analyse.inter = 0;
-                param->analyse.b_transform_8x8 = 0;
-                param->analyse.i_me_method = X264_ME_DIA;
-                param->analyse.i_subpel_refine = 0;
-                param->rc.i_aq_mode = 0;
-                param->analyse.b_mixed_references = 0;
-                param->analyse.i_trellis = 0;
-                param->i_bframe_adaptive = X264_B_ADAPT_NONE;
-                param->rc.b_mb_tree = 0;
-                param->analyse.i_weighted_pred = X264_WEIGHTP_NONE;
-            }
-            else if( !strcasecmp( optarg, "veryfast" ) )
-            {
-                param->analyse.inter = X264_ANALYSE_I8x8|X264_ANALYSE_I4x4;
-                param->analyse.i_me_method = X264_ME_DIA;
-                param->analyse.i_subpel_refine = 1;
-                param->i_frame_reference = 1;
-                param->analyse.b_mixed_references = 0;
-                param->analyse.i_trellis = 0;
-                param->rc.b_mb_tree = 0;
-                param->analyse.i_weighted_pred = X264_WEIGHTP_NONE;
-            }
-            else if( !strcasecmp( optarg, "faster" ) )
-            {
-                param->analyse.b_mixed_references = 0;
-                param->i_frame_reference = 2;
-                param->analyse.i_subpel_refine = 4;
-                param->rc.b_mb_tree = 0;
-                param->analyse.i_weighted_pred = X264_WEIGHTP_BLIND;
-            }
-            else if( !strcasecmp( optarg, "fast" ) )
-            {
-                param->i_frame_reference = 2;
-                param->analyse.i_subpel_refine = 6;
-                param->rc.i_lookahead = 30;
-            }
-            else if( !strcasecmp( optarg, "medium" ) )
-            {
-                /* Default is medium */
-            }
-            else if( !strcasecmp( optarg, "slow" ) )
-            {
-                param->analyse.i_me_method = X264_ME_UMH;
-                param->analyse.i_subpel_refine = 8;
-                param->i_frame_reference = 5;
-                param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
-                param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
-                param->rc.i_lookahead = 50;
-            }
-            else if( !strcasecmp( optarg, "slower" ) )
-            {
-                param->analyse.i_me_method = X264_ME_UMH;
-                param->analyse.i_subpel_refine = 9;
-                param->i_frame_reference = 8;
-                param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
-                param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
-                param->analyse.inter |= X264_ANALYSE_PSUB8x8;
-                param->analyse.i_trellis = 2;
-                param->rc.i_lookahead = 60;
-            }
-            else if( !strcasecmp( optarg, "veryslow" ) )
-            {
-                param->analyse.i_me_method = X264_ME_UMH;
-                param->analyse.i_subpel_refine = 10;
-                param->analyse.i_me_range = 24;
-                param->i_frame_reference = 16;
-                param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
-                param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
-                param->analyse.inter |= X264_ANALYSE_PSUB8x8;
-                param->analyse.i_trellis = 2;
-                param->i_bframe = 8;
-                param->rc.i_lookahead = 60;
-            }
-            else if( !strcasecmp( optarg, "placebo" ) )
-            {
-                param->analyse.i_me_method = X264_ME_TESA;
-                param->analyse.i_subpel_refine = 10;
-                param->analyse.i_me_range = 24;
-                param->i_frame_reference = 16;
-                param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
-                param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;
-                param->analyse.inter |= X264_ANALYSE_PSUB8x8;
-                param->analyse.b_fast_pskip = 0;
-                param->analyse.i_trellis = 2;
-                param->i_bframe = 16;
-                param->rc.i_lookahead = 60;
+            preset = optarg;
+            if( !strcmp( preset, "placebo" ) )
                 b_turbo = 0;
-            }
-            else
-            {
-                fprintf( stderr, "x264 [error]: invalid preset '%s'\n", optarg );
-                return -1;
-            }
         }
-        else if( c == '?' )
-            return -1;
-    }
-
-    /* Tunings are applied next. */
-    for( optind = 0;; )
-    {
-        int c = getopt_long( argc, argv, short_options, long_options, NULL );
-        if( c == -1 )
-            break;
-
         if( c == OPT_TUNE )
-        {
-            char *s = strtok( optarg, ",./-+" );
-            int psy_tuning_used = 0;
-            while( s )
-            {
-                if( !strncasecmp( s, "film", 4 ) )
-                {
-                    if( psy_tuning_used ) goto psy_failure;
-                    param->i_deblocking_filter_alphac0 = -1;
-                    param->i_deblocking_filter_beta = -1;
-                    param->analyse.f_psy_trellis = 0.15;
-                    psy_tuning_used = 1;
-                }
-                else if( !strncasecmp( s, "animation", 9 ) )
-                {
-                    if( psy_tuning_used ) goto psy_failure;
-                    param->i_frame_reference = param->i_frame_reference > 1 ? param->i_frame_reference*2 : 1;
-                    param->i_deblocking_filter_alphac0 = 1;
-                    param->i_deblocking_filter_beta = 1;
-                    param->analyse.f_psy_rd = 0.4;
-                    param->rc.f_aq_strength = 0.6;
-                    param->i_bframe += 2;
-                    psy_tuning_used = 1;
-                }
-                else if( !strncasecmp( s, "grain", 5 ) )
-                {
-                    if( psy_tuning_used ) goto psy_failure;
-                    param->i_deblocking_filter_alphac0 = -2;
-                    param->i_deblocking_filter_beta = -2;
-                    param->analyse.f_psy_trellis = 0.25;
-                    param->analyse.b_dct_decimate = 0;
-                    param->rc.f_pb_factor = 1.1;
-                    param->rc.f_ip_factor = 1.1;
-                    param->rc.f_aq_strength = 0.5;
-                    param->analyse.i_luma_deadzone[0] = 6;
-                    param->analyse.i_luma_deadzone[1] = 6;
-                    param->rc.f_qcompress = 0.8;
-                    psy_tuning_used = 1;
-                }
-                else if( !strncasecmp( s, "psnr", 4 ) )
-                {
-                    if( psy_tuning_used ) goto psy_failure;
-                    param->rc.i_aq_mode = X264_AQ_NONE;
-                    param->analyse.b_psy = 0;
-                    psy_tuning_used = 1;
-                }
-                else if( !strncasecmp( s, "ssim", 4 ) )
-                {
-                    if( psy_tuning_used ) goto psy_failure;
-                    param->rc.i_aq_mode = X264_AQ_AUTOVARIANCE;
-                    param->analyse.b_psy = 0;
-                    psy_tuning_used = 1;
-                }
-                else if( !strncasecmp( s, "fastdecode", 10 ) )
-                {
-                    param->b_deblocking_filter = 0;
-                    param->b_cabac = 0;
-                    param->analyse.b_weighted_bipred = 0;
-                    param->analyse.i_weighted_pred = X264_WEIGHTP_NONE;
-                }
-                else if( !strncasecmp( s, "zerolatency", 11 ) )
-                {
-                    param->rc.i_lookahead = 0;
-                    param->i_sync_lookahead = 0;
-                    param->i_bframe = 0;
-                    param->b_sliced_threads = 1;
-                }
-                else if( !strncasecmp( s, "touhou", 6 ) )
-                {
-                    if( psy_tuning_used ) goto psy_failure;
-                    param->i_frame_reference = param->i_frame_reference > 1 ? param->i_frame_reference*2 : 1;
-                    param->i_deblocking_filter_alphac0 = -1;
-                    param->i_deblocking_filter_beta = -1;
-                    param->analyse.f_psy_trellis = 0.2;
-                    param->rc.f_aq_strength = 1.3;
-                    if( param->analyse.inter & X264_ANALYSE_PSUB16x16 )
-                        param->analyse.inter |= X264_ANALYSE_PSUB8x8;
-                    psy_tuning_used = 1;
-                }
-                else
-                {
-                    fprintf( stderr, "x264 [error]: invalid tune '%s'\n", s );
-                    return -1;
-                }
-                if( 0 )
-                {
-psy_failure:
-                    fprintf( stderr, "x264 [warning]: only 1 psy tuning can be used: ignoring tune %s\n", s );
-                }
-                s = strtok( NULL, ",./-+" );
-            }
-        }
+            tune = optarg;
         else if( c == '?' )
             return -1;
     }
 
+    x264_param_default_preset( param, preset, tune );
+
     /* Parse command line options */
     for( optind = 0;; )
     {
@@ -1144,9 +944,6 @@ psy_failure:
             case 'r':
                 b_user_ref = 1;
                 goto generic_option;
-            case 'p':
-                b_pass1 = atoi( optarg ) == 1;
-                goto generic_option;
             case OPT_FPS:
                 b_user_fps = 1;
                 param->b_vfr_input = 0;
@@ -1185,54 +982,12 @@ generic_option:
         }
     }
 
-    /* Set faster options in case of turbo firstpass. */
-    if( b_turbo && b_pass1 )
-    {
-        param->i_frame_reference = 1;
-        param->analyse.b_transform_8x8 = 0;
-        param->analyse.inter = 0;
-        param->analyse.i_me_method = X264_ME_DIA;
-        param->analyse.i_subpel_refine = X264_MIN( 2, param->analyse.i_subpel_refine );
-        param->analyse.i_trellis = 0;
-    }
+    /* If first pass mode is used, apply faster settings. */
+    if( b_turbo )
+        x264_param_apply_fastfirstpass( param );
 
     /* Apply profile restrictions. */
-    if( profile )
-    {
-        if( !strcasecmp( profile, "baseline" ) )
-        {
-            param->analyse.b_transform_8x8 = 0;
-            param->b_cabac = 0;
-            param->i_cqm_preset = X264_CQM_FLAT;
-            param->i_bframe = 0;
-            param->analyse.i_weighted_pred = X264_WEIGHTP_NONE;
-            if( param->b_interlaced )
-            {
-                fprintf( stderr, "x264 [error]: baseline profile doesn't support interlacing\n" );
-                return -1;
-            }
-        }
-        else if( !strcasecmp( profile, "main" ) )
-        {
-            param->analyse.b_transform_8x8 = 0;
-            param->i_cqm_preset = X264_CQM_FLAT;
-        }
-        else if( !strcasecmp( profile, "high" ) )
-        {
-            /* Default */
-        }
-        else
-        {
-            fprintf( stderr, "x264 [error]: invalid profile: %s\n", profile );
-            return -1;
-        }
-        if( (param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant == 0) ||
-            (param->rc.i_rc_method == X264_RC_CRF && param->rc.f_rf_constant == 0) )
-        {
-            fprintf( stderr, "x264 [error]: %s profile doesn't support lossless\n", profile );
-            return -1;
-        }
-    }
+    x264_param_apply_profile( param, profile );
 
     /* Get the file name */
     if( optind > argc - 1 || !output_filename )
diff --git a/x264.h b/x264.h
index e7d19b719755e4503fc62f84f15e48d9ca28a575..f317e9859c67eabf406bbb62a33fa72bf49ffab1 100644 (file)
--- a/x264.h
+++ b/x264.h
 
 #include <stdarg.h>
 
-#define X264_BUILD 85
+#define X264_BUILD 86
 
 /* x264_t:
  *      opaque handler for encoder */
 typedef struct x264_t x264_t;
 
 /****************************************************************************
- * Initialisation structure and function.
+ * Encoder parameters
  ****************************************************************************/
 /* CPU flags
  */
@@ -332,6 +332,10 @@ typedef struct x264_param_t
     void (*param_free)( void* );
 } x264_param_t;
 
+/****************************************************************************
+ * H.264 level restriction information
+ ****************************************************************************/
+
 typedef struct {
     int level_idc;
     int mbps;        /* max macroblock processing rate (macroblocks/sec) */
@@ -350,6 +354,10 @@ typedef struct {
 /* all of the levels defined in the standard, terminated by .level_idc=0 */
 extern const x264_level_t x264_levels[];
 
+/****************************************************************************
+ * Basic parameter handling functions
+ ****************************************************************************/
+
 /* x264_param_default:
  *      fill x264_param_t with default values and do CPU detection */
 void    x264_param_default( x264_param_t * );
@@ -366,15 +374,73 @@ void    x264_param_default( x264_param_t * );
 int x264_param_parse( x264_param_t *, const char *name, const char *value );
 
 /****************************************************************************
- * Picture structures and functions.
+ * Advanced parameter handling functions
+ ****************************************************************************/
+
+/* These functions expose the full power of x264's preset-tune-profile system for
+ * easy adjustment of large numbers of internal parameters.
+ *
+ * In order to replicate x264CLI's option handling, these functions MUST be called
+ * in the following order:
+ * 1) x264_param_default_preset
+ * 2) Custom user options (via param_parse or directly assigned variables)
+ * 3) x264_param_apply_fastfirstpass
+ * 4) x264_param_apply_profile
+ *
+ * Additionally, x264CLI does not apply step 3 if the preset chosen is "placebo"
+ * or --slow-firstpass is set. */
+
+/* x264_param_default_preset:
+ *      The same as x264_param_default, but also use the passed preset and tune
+ *      to modify the default settings.
+ *      (either can be NULL, which implies no preset or no tune, respectively)
+ *
+ *      Currently available presets are, ordered from fastest to slowest: */
+static const char * const x264_preset_names[] = { "ultrafast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo", 0 };
+
+/*      Warning: the speed of these presets scales dramatically.  Ultrafast is a full
+ *      100 times faster than placebo!
+ *
+ *      Currently available tunings are: */
+static const char * const x264_tune_names[] = { "film", "animation", "grain", "psnr", "ssim", "fastdecode", "zerolatency", 0 };
+
+/*      Multiple tunings can be used if separated by a delimiter in ",./-+",
+ *      however multiple psy tunings cannot be used.
+ *      film, animation, grain, psnr, and ssim are psy tunings.
+ *
+ *      returns 0 on success, negative on failure (e.g. invalid preset/tune name). */
+int     x264_param_default_preset( x264_param_t *, const char *preset, const char *tune );
+
+/* x264_param_apply_fastfirstpass:
+ *      If first-pass mode is set (rc.b_stat_read == 1, rc.b_stat_write == 0),
+ *      modify the encoder settings to disable options generally not useful on
+ *      the first pass. */
+void    x264_param_apply_fastfirstpass( x264_param_t * );
+
+/* x264_param_apply_profile:
+ *      Applies the restrictions of the given profile.
+ *      Currently available profiles are, from most to least restrictive: */
+static const char * const x264_profile_names[] = { "baseline", "main", "high", 0 };
+
+/*      (can be NULL, in which case the function will do nothing)
+ *
+ *      Does NOT guarantee that the given profile will be used: if the restrictions
+ *      of "High" are applied to settings that are already Baseline-compatible, the
+ *      stream will remain baseline.  In short, it does not increase settings, only
+ *      decrease them.
+ *
+ *      returns 0 on success, negative on failure (e.g. invalid profile name). */
+int     x264_param_apply_profile( x264_param_t *, const char *profile );
+
+/****************************************************************************
+ * Picture structures and functions
  ****************************************************************************/
 typedef struct
 {
-    int     i_csp;
-
-    int     i_plane;
-    int     i_stride[4];
-    uint8_t *plane[4];
+    int     i_csp;       /* Colorspace */
+    int     i_plane;     /* Number of image planes */
+    int     i_stride[4]; /* Strides for each plane */
+    uint8_t *plane[4];   /* Pointers to each plane */
 } x264_image_t;
 
 typedef struct
@@ -421,9 +487,9 @@ int x264_picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_heigh
 void x264_picture_clean( x264_picture_t *pic );
 
 /****************************************************************************
- * NAL structure and functions:
+ * NAL structure and functions
  ****************************************************************************/
-/* nal */
+
 enum nal_unit_type_e
 {
     NAL_UNKNOWN = 0,
@@ -465,7 +531,7 @@ typedef struct
 } x264_nal_t;
 
 /****************************************************************************
- * Encoder functions:
+ * Encoder functions
  ****************************************************************************/
 
 /* Force a link error in the case of linking against an incompatible API version.
@@ -497,16 +563,16 @@ int     x264_encoder_reconfig( x264_t *, x264_param_t * );
 void    x264_encoder_parameters( x264_t *, x264_param_t * );
 /* x264_encoder_headers:
  *      return the SPS and PPS that will be used for the whole stream.
- *      if i_nal > 0, returns the total size of all NAL payloads.
+ *      *pi_nal is the number of NAL units outputted in pp_nal.
  *      returns negative on error.
  *      the payloads of all output NALs are guaranteed to be sequential in memory. */
-int     x264_encoder_headers( x264_t *, x264_nal_t **, int * );
+int     x264_encoder_headers( x264_t *, x264_nal_t **pp_nal, int *pi_nal );
 /* x264_encoder_encode:
  *      encode one picture.
- *      if i_nal > 0, returns the total size of all NAL payloads.
+ *      *pi_nal is the number of NAL units outputted in pp_nal.
  *      returns negative on error, zero if no NAL units returned.
  *      the payloads of all output NALs are guaranteed to be sequential in memory. */
-int     x264_encoder_encode ( x264_t *, x264_nal_t **, int *, x264_picture_t *, x264_picture_t * );
+int     x264_encoder_encode( x264_t *, x264_nal_t **pp_nal, int *pi_nal, x264_picture_t *pic_in, x264_picture_t *pic_out );
 /* x264_encoder_close:
  *      close an encoder handler */
 void    x264_encoder_close  ( x264_t * );