cli: Bash autocomplete support
authorHenrik Gramner <henrik@gramner.com>
Sun, 1 Jul 2018 18:34:48 +0000 (20:34 +0200)
committerHenrik Gramner <henrik@gramner.com>
Thu, 31 Jan 2019 19:01:06 +0000 (20:01 +0100)
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.

Makefile
autocomplete.c [new file with mode: 0644]
tools/bash-autocomplete.sh [new file with mode: 0644]
x264.c
x264cli.h

index c692d02..190048b 100644 (file)
--- 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 (file)
index 0000000..ad214d5
--- /dev/null
@@ -0,0 +1,404 @@
+/*****************************************************************************
+ * autocomplete: x264cli shell autocomplete
+ *****************************************************************************
+ * Copyright (C) 2018 x264 project
+ *
+ * Authors: Henrik Gramner <henrik@gramner.com>
+ *
+ * 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 <libavformat/avformat.h>
+#include <libavutil/pixdesc.h>
+#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 (file)
index 0000000..7bbb821
--- /dev/null
@@ -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 d67d105..d7f7c84 100644 (file)
--- a/x264.c
+++ b/x264.c
@@ -166,11 +166,50 @@ 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
@@ -182,37 +221,14 @@ static const char * const demuxer_names[] =
 #endif
     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 +238,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 +371,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 +605,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 <string>       Use a preset to select encoding settings [medium]\n"
         "                                  Overridden by user settings.\n" );
     H2( "                                  - ultrafast:\n"
@@ -791,9 +792,8 @@ static void help( x264_param_t *defaults, int longhelp )
     H1( "Analysis:\n" );
     H1( "\n" );
     H1( "  -A, --partitions <string>   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 <string>       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 +845,8 @@ static void help( x264_param_t *defaults, int longhelp )
     H2( "      --deadzone-inter <int>  Set the size of the inter luma quantization deadzone [%d]\n", defaults->analyse.i_luma_deadzone[0] );
     H2( "      --deadzone-intra <int>  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 <string>          Preset quant matrices [\"flat\"]\n"
-        "                                  - jvt, flat\n" );
+    H2( "      --cqm <string>          Preset quant matrices [\"%s\"]\n"
+        "                                  - %s\n", x264_cqm_names[0], stringify_names( buf, x264_cqm_names ) );
     H1( "      --cqmfile <string>      Read custom quant matrices from a JM-compatible file\n" );
     H2( "                                  Overrides any other --cqm* options.\n" );
     H2( "      --cqm4 <list>           Set all 4x4 quant matrices\n"
@@ -869,7 +869,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 <string>        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 <string>    Specify color primaries [\"%s\"]\n"
         "                                  - undef, bt709, bt470m, bt470bg, smpte170m,\n"
         "                                    smpte240m, film, bt2020, smpte428,\n"
@@ -907,24 +907,24 @@ static void help( x264_param_t *defaults, int longhelp )
     H0( "\n" );
     H0( "  -o, --output <string>       Specify output file\n" );
     H1( "      --muxer <string>        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 <string>      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 <string>    Specify input file format (requires lavf support)\n" );
     H1( "      --input-csp <string>    Specify input colorspace format for raw input\n" );
     print_csp_names( longhelp );
     H1( "      --output-csp <string>   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 <integer> Specify input bit depth for raw input\n" );
     H1( "      --output-depth <integer> Specify output bit depth\n" );
     H1( "      --input-range <string>  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 <intxint>   Specify input resolution (width x height)\n" );
     H1( "      --index <string>        Filename for input index file\n" );
     H0( "      --sar width:height      Specify Sample Aspect Ratio\n" );
@@ -934,7 +934,7 @@ static void help( x264_param_t *defaults, int longhelp )
     H0( "      --level <string>        Specify level (as defined by Annex A)\n" );
     H1( "      --bluray-compat         Enable compatibility hacks for Blu-ray support\n" );
     H1( "      --avcintra-class <integer> Use compatibility hacks for AVC-Intra class\n"
-        "                                  - 50, 100, 200\n" );
+        "                                  - %s\n", stringify_names( buf, x264_avcintra_class_names ) );
     H1( "      --avcintra-flavor <string> 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 +944,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 <string>    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 <integer>     Force a specific number of threads\n" );
@@ -1396,9 +1396,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 +1480,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 +1508,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 +1547,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 +1571,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 +1581,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, &param->vui.b_fullrange ), "Unknown range `%s'\n", optarg );
+                FAIL_IF_ERROR( parse_enum_value( optarg, x264_range_names, &param->vui.b_fullrange ), "Unknown range `%s'\n", optarg );
                 input_opt.output_range = param->vui.b_fullrange += RANGE_AUTO;
                 break;
             default:
index 31d26ec..7e1675e 100644 (file)
--- a/x264cli.h
+++ b/x264cli.h
 
 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 );