summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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