summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2018-01-31 06:50:21 +0100
committerKevin Mitchell <kevmitch@gmail.com>2018-02-03 05:00:52 -0800
commitafb167cfd2521198539fbd23d772a252554221f0 (patch)
treedbd95c0f370734d94da5db9888b7e74ddd600431
parent174261450589d8a6ff21426c1cfc3f2508620583 (diff)
downloadmpv-afb167cfd2521198539fbd23d772a252554221f0.tar.bz2
mpv-afb167cfd2521198539fbd23d772a252554221f0.tar.xz
options: slightly improve filter help output for lavfi bridge
--vf=help will now list libavfilter filters, and e.g. --vf=yadif=help will list libavfilter filter options. The latter is rather bare, because the AVOption API is really awful (holy shit how is it so bad), and would require us to handle _every_ option type manually. Alternatively we could call av_opt_show2(), which ffmpeg uses for help output in its CLI tools and which is much more detailed. But it's rather foreign and forces output through av_log(), so I don't really want to use it.
-rwxr-xr-xTOOLS/zsh.pl8
-rw-r--r--filters/f_lavfi.c51
-rw-r--r--filters/f_lavfi.h6
-rw-r--r--filters/user_filters.c26
-rw-r--r--options/m_option.c10
-rw-r--r--options/m_option.h6
6 files changed, 97 insertions, 10 deletions
diff --git a/TOOLS/zsh.pl b/TOOLS/zsh.pl
index 45c3ced3a0..482aa5e125 100755
--- a/TOOLS/zsh.pl
+++ b/TOOLS/zsh.pl
@@ -29,11 +29,11 @@ my @opts = parse_main_opts('--list-options', '^ (\-\-[^\s\*]*)\*?\s*(.*)');
die "Couldn't find any options" unless (@opts);
-my @ao = parse_opts('--ao=help', '^ ([^\s\:]*)\s*: (.*)');
-my @vo = parse_opts('--vo=help', '^ ([^\s\:]*)\s*: (.*)');
+my @ao = parse_opts('--ao=help', '^ ([^\s\:]*)\s*(.*)');
+my @vo = parse_opts('--vo=help', '^ ([^\s\:]*)\s*(.*)');
-my @af = parse_opts('--af=help', '^ ([^\s\:]*)\s*: (.*)');
-my @vf = parse_opts('--vf=help', '^ ([^\s\:]*)\s*: (.*)');
+my @af = parse_opts('--af=help', '^ ([^\s\:]*)\s*(.*)');
+my @vf = parse_opts('--vf=help', '^ ([^\s\:]*)\s*(.*)');
my @protos = parse_opts('--list-protocols', '^ ([^\s]*)');
diff --git a/filters/f_lavfi.c b/filters/f_lavfi.c
index b3f74b508b..745d1699a7 100644
--- a/filters/f_lavfi.c
+++ b/filters/f_lavfi.c
@@ -903,15 +903,58 @@ static bool is_usable(const AVFilter *filter, int media_type)
is_single_media_only(filter->outputs, media_type);
}
-static void print_help(struct mp_log *log, int mediatype, char *name, char *ex)
+static void dump_list(struct mp_log *log, int media_type)
{
- mp_info(log, "List of libavfilter filters:\n");
+ mp_info(log, "Available libavfilter filters:\n");
for (const AVFilter *filter = avfilter_next(NULL); filter;
filter = avfilter_next(filter))
{
- if (is_usable(filter, mediatype))
- mp_info(log, " %-16s %s\n", filter->name, filter->description);
+ if (is_usable(filter, media_type))
+ mp_info(log, " %-16s %s\n", filter->name, filter->description);
}
+}
+
+void print_lavfi_help(struct mp_log *log, const char *name, int media_type)
+{
+ const AVFilter *f = avfilter_get_by_name(name);
+ if (!f) {
+ mp_err(log, "Filter '%s' not found.\n", name);
+ return;
+ }
+ if (!is_usable(f, media_type)) {
+ mp_err(log, "Filter '%s' is not usable in this context (wrong media \n"
+ "types or wrong number of inputs/outputs).\n", name);
+ }
+ mp_info(log, "Options:\n\n");
+ const AVClass *class = f->priv_class;
+ // av_opt_next() requires this for some retarded incomprehensible reason.
+ const AVClass **c = &class;
+ int offset= -1;
+ int count = 0;
+ for (const AVOption *o = av_opt_next(c, 0); o; o = av_opt_next(c, o)) {
+ // This is how libavfilter (at the time) decided to assign positional
+ // options (called "shorthand" in the libavfilter code). So we
+ // duplicate it exactly.
+ if (o->type == AV_OPT_TYPE_CONST || o->offset == offset)
+ continue;
+ offset = o->offset;
+
+ mp_info(log, " %s\n", o->name);
+ count++;
+ }
+ mp_info(log, "\nTotal: %d options\n", count);
+}
+
+void print_lavfi_help_list(struct mp_log *log, int media_type)
+{
+ dump_list(log, media_type);
+ mp_info(log, "\nIf libavfilter filters clash with builtin mpv filters,\n"
+ "prefix them with lavfi- to select the libavfilter one.\n\n");
+}
+
+static void print_help(struct mp_log *log, int mediatype, char *name, char *ex)
+{
+ dump_list(log, mediatype);
mp_info(log, "\n"
"This lists %s->%s filters only. Refer to\n"
"\n"
diff --git a/filters/f_lavfi.h b/filters/f_lavfi.h
index 7efc96c3de..089d4aee1f 100644
--- a/filters/f_lavfi.h
+++ b/filters/f_lavfi.h
@@ -28,3 +28,9 @@ struct mp_lavfi *mp_lavfi_create_filter(struct mp_filter *parent,
enum mp_frame_type type, bool bidir,
char **graph_opts,
const char *filter, char **filter_opts);
+
+// Print libavfilter list for --vf/--af
+void print_lavfi_help_list(struct mp_log *log, int media_type);
+
+// Print libavfilter help for the given filter
+void print_lavfi_help(struct mp_log *log, const char *name, int media_type);
diff --git a/filters/user_filters.c b/filters/user_filters.c
index 30358a4a94..89d7743d53 100644
--- a/filters/user_filters.c
+++ b/filters/user_filters.c
@@ -1,3 +1,5 @@
+#include <libavutil/avutil.h>
+
#include "config.h"
#include "common/common.h"
@@ -36,11 +38,23 @@ static bool get_af_desc(struct m_obj_desc *dst, int index)
return get_desc_from(af_list, MP_ARRAY_SIZE(af_list), dst, index);
}
+static void print_af_help_list(struct mp_log *log)
+{
+ print_lavfi_help_list(log, AVMEDIA_TYPE_AUDIO);
+}
+
+static void print_af_lavfi_help(struct mp_log *log, const char *name)
+{
+ print_lavfi_help(log, name, AVMEDIA_TYPE_AUDIO);
+}
+
const struct m_obj_list af_obj_list = {
.get_desc = get_af_desc,
.description = "audio filters",
.allow_disable_entries = true,
.allow_unknown_entries = true,
+ .print_help_list = print_af_help_list,
+ .print_unknown_entry_help = print_af_lavfi_help,
};
// --vf option
@@ -72,11 +86,23 @@ static bool get_vf_desc(struct m_obj_desc *dst, int index)
return get_desc_from(vf_list, MP_ARRAY_SIZE(vf_list), dst, index);
}
+static void print_vf_help_list(struct mp_log *log)
+{
+ print_lavfi_help_list(log, AVMEDIA_TYPE_VIDEO);
+}
+
+static void print_vf_lavfi_help(struct mp_log *log, const char *name)
+{
+ print_lavfi_help(log, name, AVMEDIA_TYPE_VIDEO);
+}
+
const struct m_obj_list vf_obj_list = {
.get_desc = get_vf_desc,
.description = "video filters",
.allow_disable_entries = true,
.allow_unknown_entries = true,
+ .print_help_list = print_vf_help_list,
+ .print_unknown_entry_help = print_vf_lavfi_help,
};
// Create a bidir, single-media filter from command line arguments.
diff --git a/options/m_option.c b/options/m_option.c
index 522e771356..e777c5a19e 100644
--- a/options/m_option.c
+++ b/options/m_option.c
@@ -2940,6 +2940,8 @@ print_help: ;
if (desc->print_help)
desc->print_help(log);
m_config_print_option_list(config, "*");
+ } else if (list->print_unknown_entry_help) {
+ list->print_unknown_entry_help(log, mp_tprintf(80, "%.*s", BSTR_P(name)));
} else {
mp_warn(log, "Option %.*s: item %.*s doesn't exist.\n",
BSTR_P(opt_name), BSTR_P(name));
@@ -3155,11 +3157,17 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt,
if (!ol->get_desc(&desc, n))
break;
if (!desc.hidden) {
- mp_info(log, " %-15s: %s\n",
+ mp_info(log, " %-16s %s\n",
desc.name, desc.description);
}
}
mp_info(log, "\n");
+ if (ol->print_help_list)
+ ol->print_help_list(log);
+ if (!ol->use_global_options) {
+ mp_info(log, "Get help on individual entries via: --%s=entry=help\n",
+ opt->name);
+ }
return M_OPT_EXIT;
}
diff --git a/options/m_option.h b/options/m_option.h
index f47dac294e..af082a893d 100644
--- a/options/m_option.h
+++ b/options/m_option.h
@@ -129,7 +129,7 @@ struct m_obj_desc {
const char *init_options;
// Don't list entry with "help"
bool hidden;
- // Callback to print custom help if "help" is passed
+ // Callback to print custom help if "vf=entry=help" is passed
void (*print_help)(struct mp_log *log);
// Callback that allows you to override the static default values. The
// pointer p points to the struct described by options/priv_size, with
@@ -159,6 +159,10 @@ struct m_obj_list {
bool disallow_positional_parameters;
// Each sub-item is backed by global options (for AOs and VOs).
bool use_global_options;
+ // Callback to print additional custom help if "vf=help" is passed
+ void (*print_help_list)(struct mp_log *log);
+ // Callback to print help for _unknown_ entries with "vf=entry=help"
+ void (*print_unknown_entry_help)(struct mp_log *log, const char *name);
};
// Find entry by name