From: Henrik Gramner Date: Sun, 1 Jul 2018 18:34:48 +0000 (+0200) Subject: cli: Bash autocomplete support X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=74c051f2c4945cf2a279e36051537a2a1897c120;p=libx264 cli: Bash autocomplete support Allows for automatic command line completion for both options and values. Options such as --input-csp and --input-fmt will dynamically retrieve supported values from libavformat when compiled with lavf support. Execute 'source tools/bash-autocomplete.sh' in bash to enable. --- diff --git a/Makefile b/Makefile index c692d021..190048ba 100644 --- a/Makefile +++ b/Makefile @@ -27,8 +27,8 @@ SRCS_X = common/mc.c common/predict.c common/pixel.c common/macroblock.c \ SRCS_8 = -SRCCLI = x264.c input/input.c input/timecode.c input/raw.c input/y4m.c \ - output/raw.c output/matroska.c output/matroska_ebml.c \ +SRCCLI = x264.c autocomplete.c input/input.c input/timecode.c input/raw.c \ + input/y4m.c output/raw.c output/matroska.c output/matroska_ebml.c \ output/flv.c output/flv_bytestream.c filters/filters.c \ filters/video/video.c filters/video/source.c filters/video/internal.c \ filters/video/resize.c filters/video/fix_vfr_pts.c \ diff --git a/autocomplete.c b/autocomplete.c new file mode 100644 index 00000000..ad214d56 --- /dev/null +++ b/autocomplete.c @@ -0,0 +1,404 @@ +/***************************************************************************** + * autocomplete: x264cli shell autocomplete + ***************************************************************************** + * Copyright (C) 2018 x264 project + * + * Authors: Henrik Gramner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. + * + * This program is also available under a commercial proprietary license. + * For more information, contact us at licensing@x264.com. + *****************************************************************************/ + +#include "x264cli.h" +#include "input/input.h" + +#if HAVE_LAVF +#include +#include +#endif + +static const char * const level_names[] = +{ + "1", "1.1", "1.2", "1.3", "1b", + "2", "2.1", "2.2", + "3", "3.1", "3.2", + "4", "4.1", "4.2", + "5", "5.1", "5.2", + "6", "6.1", "6.2", + NULL +}; + +/* Options requiring a value for which we provide suggestions. */ +static const char * const opts_suggest[] = +{ + "--alternative-transfer", + "--aq-mode", + "--asm", + "--avcintra-class", + "--avcintra-flavor", + "--b-adapt", + "--b-pyramid", + "--colormatrix", + "--colorprim", + "--cqm", + "--demuxer", + "--direct", + "--frame-packing", + "--input-csp", + "--input-fmt", + "--input-range", + "--level", + "--log-level", + "--me", + "--muxer", + "--nal-hrd", + "--output-csp", + "--overscan", + "--pass", "-p", + "--preset", + "--profile", + "--pulldown", + "--range", + "--subme", "-m", + "--transfer", + "--trellis", "-t", + "--tune", + "--videoformat", + "--weightp", + NULL +}; + +/* Options requiring a value for which we don't provide suggestions. */ +static const char * const opts_nosuggest[] = +{ + "--b-bias", + "--bframes", "-b", + "--deblock", "-f", + "--bitrate", "-B", + "--chroma-qp-offset", + "--chromaloc", + "--cplxblur", + "--cqm4", + "--cqm4i", + "--cqm4ic", + "--cqm4iy", + "--cqm4p", + "--cqm4pc", + "--cqm4py", + "--cqm8", + "--cqm8i", + "--cqm8p", + "--crf", + "--crf-max", + "--crop-rect", + "--deadzone-inter", + "--deadzone-intra", + "--fps", + "--frames", + "--input-depth", + "--input-res", + "--ipratio", + "--keyint", "-I", + "--lookahead-threads", + "--merange", + "--min-keyint", "-i", + "--mvrange", + "--mvrange-thread", + "--nr", + "--opencl-device", + "--output-depth", + "--partitions", "-A", + "--pbratio", + "--psy-rd", + "--qblur", + "--qcomp", + "--qp", "-q", + "--qpmax", + "--qpmin", + "--qpstep", + "--ratetol", + "--ref", "-r", + "--rc-lookahead", + "--sar", + "--scenecut", + "--seek", + "--slices", + "--slices-max", + "--slice-max-size", + "--slice-max-mbs", + "--slice-min-mbs", + "--sps-id", + "--sync-lookahead", + "--threads", + "--timebase", + "--vbv-bufsize", + "--vbv-init", + "--vbv-maxrate", + "--video-filter", "--vf", + "--zones", + NULL +}; + +/* Options requiring a filename. */ +static const char * const opts_filename[] = +{ + "--cqmfile", + "--dump-yuv", + "--index", + "--opencl-clbin", + "--output", "-o", + "--qpfile", + "--stats", + "--tcfile-in", + "--tcfile-out", + NULL +}; + +/* Options without an associated value. */ +static const char * const opts_standalone[] = +{ + "--8x8dct", + "--aud", + "--bff", + "--bluray-compat", + "--cabac", + "--constrained-intra", + "--cpu-independent", + "--dts-compress", + "--fake-interlaced", + "--fast-pskip", + "--filler", + "--force-cfr", + "--mbtree", + "--mixed-refs", + "--no-8x8dct", + "--no-asm", + "--no-cabac", + "--no-chroma-me", + "--no-dct-decimate", + "--no-deblock", + "--no-fast-pskip", + "--no-mbtree", + "--no-mixed-refs", + "--no-progress", + "--no-psy", + "--no-scenecut", + "--no-weightb", + "--non-deterministic", + "--open-gop", + "--opencl", + "--pic-struct", + "--psnr", + "--quiet", + "--sliced-threads", + "--slow-firstpass", + "--ssim", + "--stitchable", + "--tff", + "--thread-input", + "--verbose", "-v", + "--weightb", + NULL +}; + +/* Options which shouldn't be suggested in combination with other options. */ +static const char * const opts_special[] = +{ + "--fullhelp", + "--help", "-h", + "--longhelp", + "--version", + NULL +}; + +static int list_contains( const char * const *list, const char *s ) +{ + if( *s ) + for( ; *list; list++ ) + if( !strcmp( *list, s ) ) + return 1; + return 0; +} + +static void suggest( const char *s, const char *cur, int cur_len ) +{ + if( s && *s && !strncmp( s, cur, cur_len ) ) + printf( "%s\n", s ); +} + +static void suggest_lower( const char *s, const char *cur, int cur_len ) +{ + if( s && *s && !strncasecmp( s, cur, cur_len ) ) + { + for( ; *s; s++ ) + putchar( *s < 'A' || *s > 'Z' ? *s : *s | 0x20 ); + putchar( '\n' ); + } +} + +static void suggest_num_range( int start, int end, const char *cur, int cur_len ) +{ + char buf[16]; + for( int i = start; i <= end; i++ ) + { + snprintf( buf, sizeof( buf ), "%d", i ); + suggest( buf, cur, cur_len ); + } +} + +#if HAVE_LAVF +/* Suggest each token in a string separated by delimiters. */ +static void suggest_token( const char *s, int delim, const char *cur, int cur_len ) +{ + if( s && *s ) + { + for( const char *tok_end; (tok_end = strchr( s, delim )); s = tok_end + 1 ) + { + int tok_len = tok_end - s; + if( tok_len && tok_len >= cur_len && !strncmp( s, cur, cur_len ) ) + printf( "%.*s\n", tok_len, s ); + } + suggest( s, cur, cur_len ); + } +} +#endif + +#define OPT( opt ) else if( !strcmp( prev, opt ) ) +#define OPT2( opt1, opt2 ) else if( !strcmp( prev, opt1 ) || !strcmp( prev, opt2 ) ) +#define OPT_TYPE( type ) list_contains( opts_##type, prev ) + +#define suggest( s ) suggest( s, cur, cur_len ) +#define suggest_lower( s ) suggest_lower( s, cur, cur_len ) +#define suggest_list( list ) for( const char * const *s = list; *s; s++ ) suggest( *s ) +#define suggest_num_range( start, end ) suggest_num_range( start, end, cur, cur_len ) +#define suggest_token( s, delim ) suggest_token( s, delim, cur, cur_len ) + +int x264_cli_autocomplete( const char *prev, const char *cur ) +{ + int cur_len = strlen( cur ); + if( 0 ); + OPT( "--alternative-transfer" ) + suggest_list( x264_transfer_names ); + OPT( "--aq-mode" ) + suggest_num_range( 0, 3 ); + OPT( "--asm" ) + for( const x264_cpu_name_t *cpu = x264_cpu_names; cpu->flags; cpu++ ) + suggest_lower( cpu->name ); + OPT( "--avcintra-class" ) + suggest_list( x264_avcintra_class_names ); + OPT( "--avcintra-flavor" ) + suggest_list( x264_avcintra_flavor_names ); + OPT( "--b-adapt" ) + suggest_num_range( 0, 2 ); + OPT( "--b-pyramid" ) + suggest_list( x264_b_pyramid_names ); + OPT( "--colormatrix" ) + suggest_list( x264_colmatrix_names ); + OPT( "--colorprim" ) + suggest_list( x264_colorprim_names ); + OPT( "--cqm" ) + suggest_list( x264_cqm_names ); + OPT( "--demuxer" ) + suggest_list( x264_demuxer_names ); + OPT( "--direct" ) + suggest_list( x264_direct_pred_names ); + OPT( "--frame-packing" ) + suggest_num_range( 0, 7 ); + OPT( "--input-csp" ) + { + for( int i = X264_CSP_NONE+1; i < X264_CSP_CLI_MAX; i++ ) + suggest( x264_cli_csps[i].name ); +#if HAVE_LAVF + for( const AVPixFmtDescriptor *d = NULL; (d = av_pix_fmt_desc_next( d )); ) + suggest( d->name ); +#endif + } + OPT( "--input-fmt" ) + { +#if HAVE_LAVF + av_register_all(); + for( const AVInputFormat *f = NULL; (f = av_iformat_next( f )); ) + suggest_token( f->name, ',' ); +#endif + } + OPT( "--input-range" ) + suggest_list( x264_range_names ); + OPT( "--level" ) + suggest_list( level_names ); + OPT( "--log-level" ) + suggest_list( x264_log_level_names ); + OPT( "--me" ) + suggest_list( x264_motion_est_names ); + OPT( "--muxer" ) + suggest_list( x264_muxer_names ); + OPT( "--nal-hrd" ) + suggest_list( x264_nal_hrd_names ); + OPT( "--output-csp" ) + suggest_list( x264_output_csp_names ); + OPT( "--output-depth" ) + { +#if HAVE_BITDEPTH8 + suggest( "8" ); +#endif +#if HAVE_BITDEPTH10 + suggest( "10" ); +#endif + } + OPT( "--overscan" ) + suggest_list( x264_overscan_names ); + OPT2( "--partitions", "-A" ) + suggest_list( x264_partition_names ); + OPT2( "--pass", "-p" ) + suggest_num_range( 1, 3 ); + OPT( "--preset" ) + suggest_list( x264_preset_names ); + OPT( "--profile" ) + suggest_list( x264_valid_profile_names ); + OPT( "--pulldown" ) + suggest_list( x264_pulldown_names ); + OPT( "--range" ) + suggest_list( x264_range_names ); + OPT2( "--subme", "-m" ) + suggest_num_range( 0, 11 ); + OPT( "--transfer" ) + suggest_list( x264_transfer_names ); + OPT2( "--trellis", "-t" ) + suggest_num_range( 0, 2 ); + OPT( "--tune" ) + suggest_list( x264_tune_names ); + OPT( "--videoformat" ) + suggest_list( x264_vidformat_names ); + OPT( "--weightp" ) + suggest_num_range( 0, 2 ); + else if( !OPT_TYPE( nosuggest ) && !OPT_TYPE( special ) ) + { + if( OPT_TYPE( filename ) || strncmp( cur, "--", 2 ) ) + return 1; /* Fall back to default shell filename autocomplete. */ + + /* Suggest options. */ + suggest_list( opts_suggest ); + suggest_list( opts_nosuggest ); + suggest_list( opts_filename ); + suggest_list( opts_standalone ); + + /* Only suggest special options if no other options have been specified. */ + if( !*prev ) + suggest_list( opts_special ); + } + + return 0; +} diff --git a/tools/bash-autocomplete.sh b/tools/bash-autocomplete.sh new file mode 100644 index 00000000..7bbb821a --- /dev/null +++ b/tools/bash-autocomplete.sh @@ -0,0 +1,15 @@ +_x264() +{ + local path args cur prev + + path="${COMP_LINE%%[[:blank:]]*}" + args="${COMP_LINE:${#path}:$((COMP_POINT-${#path}))}" + cur="${args##*[[:blank:]=]}" + prev="$(sed 's/[[:blank:]=]*$//; s/^.*[[:blank:]]//' <<< "${args%%"$cur"}")" + + # Expand ~ + printf -v path '%q' "$path" && eval path="${path/#'\~'/'~'}" + + COMPREPLY=($("$path" --autocomplete "$prev" "$cur")) && compopt +o default +} 2>/dev/null +complete -o default -F _x264 x264 diff --git a/x264.c b/x264.c index d67d1058..8808008e 100644 --- a/x264.c +++ b/x264.c @@ -166,11 +166,52 @@ static cli_output_t cli_output; /* video filter operation struct */ static cli_vid_filter_t filter; -static const char * const demuxer_names[] = +const char * const x264_avcintra_class_names[] = { "50", "100", "200", 0 }; +const char * const x264_cqm_names[] = { "flat", "jvt", 0 }; +const char * const x264_log_level_names[] = { "none", "error", "warning", "info", "debug", 0 }; +const char * const x264_partition_names[] = { "p8x8", "p4x4", "b8x8", "i8x8", "i4x4", "none", "all", 0 }; +const char * const x264_pulldown_names[] = { "none", "22", "32", "64", "double", "triple", "euro", 0 }; +const char * const x264_range_names[] = { "auto", "tv", "pc", 0 }; + +const char * const x264_output_csp_names[] = { - "auto", - "raw", - "y4m", +#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I400 + "i400", +#endif +#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I420 + "i420", +#endif +#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I422 + "i422", +#endif +#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I444 + "i444", "rgb", +#endif + 0 +}; + +const char * const x264_valid_profile_names[] = +{ +#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT <= X264_CSP_I420 +#if HAVE_BITDEPTH8 +#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I420 + "baseline", "main", +#endif + "high", +#endif +#if HAVE_BITDEPTH10 + "high10", +#endif +#endif +#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I422 + "high422", +#endif + "high444", 0 +}; + +const char * const x264_demuxer_names[] = +{ + "auto", "raw", "y4m", #if HAVE_AVS "avs", #endif @@ -183,36 +224,15 @@ static const char * const demuxer_names[] = 0 }; -static const char * const muxer_names[] = +const char * const x264_muxer_names[] = { - "auto", - "raw", - "mkv", - "flv", + "auto", "raw", "mkv", "flv", #if HAVE_GPAC || HAVE_LSMASH "mp4", #endif 0 }; -static const char * const pulldown_names[] = { "none", "22", "32", "64", "double", "triple", "euro", 0 }; -static const char * const log_level_names[] = { "none", "error", "warning", "info", "debug", 0 }; -static const char * const output_csp_names[] = -{ -#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I400 - "i400", -#endif -#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I420 - "i420", -#endif -#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I422 - "i422", -#endif -#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I444 - "i444", "rgb", -#endif - 0 -}; static const char * const chroma_format_names[] = { [0] = "all", @@ -222,8 +242,6 @@ static const char * const chroma_format_names[] = [X264_CSP_I444] = "i444" }; -static const char * const range_names[] = { "auto", "tv", "pc", 0 }; - typedef struct { int mod; @@ -357,6 +375,9 @@ static void print_version_info( void ) static int main_internal( int argc, char **argv ) { + if( argc == 4 && !strcmp( argv[1], "--autocomplete" ) ) + return x264_cli_autocomplete( argv[2], argv[3] ); + x264_param_t param; cli_opt_t opt = {0}; int ret = 0; @@ -588,23 +609,7 @@ static void help( x264_param_t *defaults, int longhelp ) " - high444:\n" " Support for bit depth 8-10.\n" " Support for 4:2:0/4:2:2/4:4:4 chroma subsampling.\n" ); - else H0( - " - " -#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT <= X264_CSP_I420 -#if HAVE_BITDEPTH8 -#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I420 - "baseline,main," -#endif - "high," -#endif -#if HAVE_BITDEPTH10 - "high10," -#endif -#endif -#if !X264_CHROMA_FORMAT || X264_CHROMA_FORMAT == X264_CSP_I422 - "high422," -#endif - "high444\n" ); + else H0( " - %s\n", stringify_names( buf, x264_valid_profile_names ) ); H0( " --preset Use a preset to select encoding settings [medium]\n" " Overridden by user settings.\n" ); H2( " - ultrafast:\n" @@ -791,9 +796,8 @@ static void help( x264_param_t *defaults, int longhelp ) H1( "Analysis:\n" ); H1( "\n" ); H1( " -A, --partitions Partitions to consider [\"p8x8,b8x8,i8x8,i4x4\"]\n" - " - p8x8, p4x4, b8x8, i8x8, i4x4\n" - " - none, all\n" - " (p4x4 requires p8x8. i8x8 requires --8x8dct.)\n" ); + " - %s\n" + " (p4x4 requires p8x8. i8x8 requires --8x8dct.)\n", stringify_names( buf, x264_partition_names ) ); H1( " --direct Direct MV prediction mode [\"%s\"]\n" " - none, spatial, temporal, auto\n", strtable_lookup( x264_direct_pred_names, defaults->analyse.i_direct_mv_pred ) ); @@ -845,8 +849,8 @@ static void help( x264_param_t *defaults, int longhelp ) H2( " --deadzone-inter Set the size of the inter luma quantization deadzone [%d]\n", defaults->analyse.i_luma_deadzone[0] ); H2( " --deadzone-intra Set the size of the intra luma quantization deadzone [%d]\n", defaults->analyse.i_luma_deadzone[1] ); H2( " Deadzones should be in the range 0 - 32.\n" ); - H2( " --cqm Preset quant matrices [\"flat\"]\n" - " - jvt, flat\n" ); + H2( " --cqm Preset quant matrices [\"%s\"]\n" + " - %s\n", x264_cqm_names[0], stringify_names( buf, x264_cqm_names ) ); H1( " --cqmfile Read custom quant matrices from a JM-compatible file\n" ); H2( " Overrides any other --cqm* options.\n" ); H2( " --cqm4 Set all 4x4 quant matrices\n" @@ -869,7 +873,7 @@ static void help( x264_param_t *defaults, int longhelp ) " - component, pal, ntsc, secam, mac, undef\n", strtable_lookup( x264_vidformat_names, defaults->vui.i_vidformat ) ); H2( " --range Specify color range [\"%s\"]\n" - " - %s\n", range_names[0], stringify_names( buf, range_names ) ); + " - %s\n", x264_range_names[0], stringify_names( buf, x264_range_names ) ); H2( " --colorprim Specify color primaries [\"%s\"]\n" " - undef, bt709, bt470m, bt470bg, smpte170m,\n" " smpte240m, film, bt2020, smpte428,\n" @@ -907,24 +911,24 @@ static void help( x264_param_t *defaults, int longhelp ) H0( "\n" ); H0( " -o, --output Specify output file\n" ); H1( " --muxer Specify output container format [\"%s\"]\n" - " - %s\n", muxer_names[0], stringify_names( buf, muxer_names ) ); + " - %s\n", x264_muxer_names[0], stringify_names( buf, x264_muxer_names ) ); H1( " --demuxer Specify input container format [\"%s\"]\n" - " - %s\n", demuxer_names[0], stringify_names( buf, demuxer_names ) ); + " - %s\n", x264_demuxer_names[0], stringify_names( buf, x264_demuxer_names ) ); H1( " --input-fmt Specify input file format (requires lavf support)\n" ); H1( " --input-csp Specify input colorspace format for raw input\n" ); print_csp_names( longhelp ); H1( " --output-csp Specify output colorspace [\"%s\"]\n" " - %s\n", #if X264_CHROMA_FORMAT - output_csp_names[0], + x264_output_csp_names[0], #else "i420", #endif - stringify_names( buf, output_csp_names ) ); + stringify_names( buf, x264_output_csp_names ) ); H1( " --input-depth Specify input bit depth for raw input\n" ); H1( " --output-depth Specify output bit depth\n" ); H1( " --input-range Specify input color range [\"%s\"]\n" - " - %s\n", range_names[0], stringify_names( buf, range_names ) ); + " - %s\n", x264_range_names[0], stringify_names( buf, x264_range_names ) ); H1( " --input-res Specify input resolution (width x height)\n" ); H1( " --index Filename for input index file\n" ); H0( " --sar width:height Specify Sample Aspect Ratio\n" ); @@ -934,7 +938,7 @@ static void help( x264_param_t *defaults, int longhelp ) H0( " --level Specify level (as defined by Annex A)\n" ); H1( " --bluray-compat Enable compatibility hacks for Blu-ray support\n" ); H1( " --avcintra-class Use compatibility hacks for AVC-Intra class\n" - " - 50, 100, 200\n" ); + " - %s\n", stringify_names( buf, x264_avcintra_class_names ) ); H1( " --avcintra-flavor AVC-Intra flavor [\"%s\"]\n" " - %s\n", x264_avcintra_flavor_names[0], stringify_names( buf, x264_avcintra_flavor_names ) ); H1( " --stitchable Don't optimize headers based on video content\n" @@ -944,8 +948,8 @@ static void help( x264_param_t *defaults, int longhelp ) H1( " --no-progress Don't show the progress indicator while encoding\n" ); H0( " --quiet Quiet Mode\n" ); H1( " --log-level Specify the maximum level of logging [\"%s\"]\n" - " - %s\n", strtable_lookup( log_level_names, cli_log_level - X264_LOG_NONE ), - stringify_names( buf, log_level_names ) ); + " - %s\n", strtable_lookup( x264_log_level_names, cli_log_level - X264_LOG_NONE ), + stringify_names( buf, x264_log_level_names ) ); H1( " --psnr Enable PSNR computation\n" ); H1( " --ssim Enable SSIM computation\n" ); H1( " --threads Force a specific number of threads\n" ); @@ -1396,9 +1400,9 @@ static int parse_enum_value( const char *arg, const char * const *names, int *ds static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt ) { char *input_filename = NULL; - const char *demuxer = demuxer_names[0]; + const char *demuxer = x264_demuxer_names[0]; char *output_filename = NULL; - const char *muxer = muxer_names[0]; + const char *muxer = x264_muxer_names[0]; char *tcfile_name = NULL; x264_param_t defaults; char *profile = NULL; @@ -1480,10 +1484,10 @@ static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt ) output_filename = optarg; break; case OPT_MUXER: - FAIL_IF_ERROR( parse_enum_name( optarg, muxer_names, &muxer ), "Unknown muxer `%s'\n", optarg ); + FAIL_IF_ERROR( parse_enum_name( optarg, x264_muxer_names, &muxer ), "Unknown muxer `%s'\n", optarg ); break; case OPT_DEMUXER: - FAIL_IF_ERROR( parse_enum_name( optarg, demuxer_names, &demuxer ), "Unknown demuxer `%s'\n", optarg ); + FAIL_IF_ERROR( parse_enum_name( optarg, x264_demuxer_names, &demuxer ), "Unknown demuxer `%s'\n", optarg ); break; case OPT_INDEX: input_opt.index_file = optarg; @@ -1508,7 +1512,7 @@ static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt ) cli_log_level = param->i_log_level = X264_LOG_DEBUG; break; case OPT_LOG_LEVEL: - if( !parse_enum_value( optarg, log_level_names, &cli_log_level ) ) + if( !parse_enum_value( optarg, x264_log_level_names, &cli_log_level ) ) cli_log_level += X264_LOG_NONE; else cli_log_level = atoi( optarg ); @@ -1547,7 +1551,7 @@ static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt ) input_opt.timebase = optarg; break; case OPT_PULLDOWN: - FAIL_IF_ERROR( parse_enum_value( optarg, pulldown_names, &opt->i_pulldown ), "Unknown pulldown `%s'\n", optarg ); + FAIL_IF_ERROR( parse_enum_value( optarg, x264_pulldown_names, &opt->i_pulldown ), "Unknown pulldown `%s'\n", optarg ); break; case OPT_VIDEO_FILTER: vid_filters = optarg; @@ -1571,7 +1575,7 @@ static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt ) output_opt.use_dts_compress = 1; break; case OPT_OUTPUT_CSP: - FAIL_IF_ERROR( parse_enum_value( optarg, output_csp_names, &output_csp ), "Unknown output csp `%s'\n", optarg ); + FAIL_IF_ERROR( parse_enum_value( optarg, x264_output_csp_names, &output_csp ), "Unknown output csp `%s'\n", optarg ); // correct the parsed value to the libx264 csp value #if X264_CHROMA_FORMAT static const uint8_t output_csp_fix[] = { X264_CHROMA_FORMAT, X264_CSP_RGB }; @@ -1581,11 +1585,11 @@ static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt ) param->i_csp = output_csp = output_csp_fix[output_csp]; break; case OPT_INPUT_RANGE: - FAIL_IF_ERROR( parse_enum_value( optarg, range_names, &input_opt.input_range ), "Unknown input range `%s'\n", optarg ); + FAIL_IF_ERROR( parse_enum_value( optarg, x264_range_names, &input_opt.input_range ), "Unknown input range `%s'\n", optarg ); input_opt.input_range += RANGE_AUTO; break; case OPT_RANGE: - FAIL_IF_ERROR( parse_enum_value( optarg, range_names, ¶m->vui.b_fullrange ), "Unknown range `%s'\n", optarg ); + FAIL_IF_ERROR( parse_enum_value( optarg, x264_range_names, ¶m->vui.b_fullrange ), "Unknown range `%s'\n", optarg ); input_opt.output_range = param->vui.b_fullrange += RANGE_AUTO; break; default: diff --git a/x264cli.h b/x264cli.h index 31d26ec9..7e1675ed 100644 --- a/x264cli.h +++ b/x264cli.h @@ -34,6 +34,17 @@ typedef void *hnd_t; +extern const char * const x264_avcintra_class_names[]; +extern const char * const x264_cqm_names[]; +extern const char * const x264_log_level_names[]; +extern const char * const x264_partition_names[]; +extern const char * const x264_pulldown_names[]; +extern const char * const x264_range_names[]; +extern const char * const x264_output_csp_names[]; +extern const char * const x264_valid_profile_names[]; +extern const char * const x264_demuxer_names[]; +extern const char * const x264_muxer_names[]; + static inline uint64_t gcd( uint64_t a, uint64_t b ) { while( 1 ) @@ -62,6 +73,7 @@ static inline char *get_filename_extension( char *filename ) void x264_cli_log( const char *name, int i_level, const char *fmt, ... ); void x264_cli_printf( int i_level, const char *fmt, ... ); +int x264_cli_autocomplete( const char *prev, const char *cur ); #ifdef _WIN32 void x264_cli_set_console_title( const char *title );