aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar wm4 <wm4@nowhere>2017-04-03 18:04:18 +0200
committerGravatar wm4 <wm4@nowhere>2017-04-03 18:12:42 +0200
commit31611fc46b29e0704004e21f1e25de2f9608e109 (patch)
treeaa45539886860960bc436cb481688d1b66f885bf
parent13160530f2ef05b24dc9331fe42b00def1e4d071 (diff)
video: support positional arguments for automatic lavfi option bridge
Now e.g. --vf=pad=1000:1000 works. All in all pretty ugly and hacky. Just look away.
-rw-r--r--DOCS/man/vf.rst10
-rw-r--r--common/av_common.c30
-rw-r--r--options/m_option.c27
-rw-r--r--video/filter/vf_lavfi.c2
4 files changed, 58 insertions, 11 deletions
diff --git a/DOCS/man/vf.rst b/DOCS/man/vf.rst
index f2bd16033c..2d53fc4ce2 100644
--- a/DOCS/man/vf.rst
+++ b/DOCS/man/vf.rst
@@ -60,11 +60,11 @@ normal filter parameters.
implemented in mpv only).
If a filter is not builtin, the ``lavfi-bridge`` will be automatically
- tried. Keep in mind that this filter does not support positional arguments
- like ``--vf=name=arg1:arg2``. Instead, you must use
- ``--vf=name=arg1name=arg1value:...``. This bridge also does not support
- help output, and does not verify parameters before the filter is actually
- used.
+ tried. This bridge does not support help output, and does not verify
+ parameters before the filter is actually used. Although the mpv syntax
+ is rather similar to libavfilter's, it's not the same. (Which means not
+ everything accepted by vf_lavfi's ``graph`` option will be accepted by
+ ``--vf``.)
Video filters are managed in lists. There are a few commands to manage the
filter list.
diff --git a/common/av_common.c b/common/av_common.c
index 5c58f3fea8..d7ad8e172c 100644
--- a/common/av_common.c
+++ b/common/av_common.c
@@ -302,6 +302,35 @@ void mp_avdict_print_unset(struct mp_log *log, int msgl, AVDictionary *dict)
mp_msg(log, msgl, "Could not set AVOption %s='%s'\n", t->key, t->value);
}
+// If the name starts with "@", try to interpret it as a number, and set *name
+// to the name of the n-th parameter.
+static void resolve_positional_arg(void *avobj, char **name)
+{
+ if (!*name || (*name)[0] != '@')
+ return;
+
+ char *end = NULL;
+ int pos = strtol(*name + 1, &end, 10);
+ if (!end || *end)
+ return;
+
+ const AVOption *opt = NULL;
+ int offset = -1;
+ while (1) {
+ opt = av_opt_next(avobj, opt);
+ if (!opt)
+ return;
+ // This is what libavfilter's parser does to skip aliases.
+ if (opt->offset != offset && opt->type != AV_OPT_TYPE_CONST)
+ pos--;
+ if (pos < 0) {
+ *name = (char *)opt->name;
+ return;
+ }
+ offset = opt->offset;
+ }
+}
+
// kv is in the format as by OPT_KEYVALUELIST(): kv[0]=key0, kv[1]=val0, ...
// Set these options on given avobj (using av_opt_set..., meaning avobj must
// point to a struct that has AVClass as first member).
@@ -313,6 +342,7 @@ int mp_set_avopts(struct mp_log *log, void *avobj, char **kv)
for (int n = 0; kv && kv[n * 2]; n++) {
char *k = kv[n * 2 + 0];
char *v = kv[n * 2 + 1];
+ resolve_positional_arg(avobj, &k);
int r = av_opt_set(avobj, k, v, AV_OPT_SEARCH_CHILDREN);
if (r == AVERROR_OPTION_NOT_FOUND) {
mp_err(log, "AVOption '%s' not found.\n", k);
diff --git a/options/m_option.c b/options/m_option.c
index a30f89d18d..fa93dd47c7 100644
--- a/options/m_option.c
+++ b/options/m_option.c
@@ -2606,17 +2606,33 @@ static void copy_obj_settings_list(const m_option_t *opt, void *dst,
static int get_obj_param(struct mp_log *log, bstr opt_name, bstr obj_name,
struct m_config *config, bstr name, bstr val,
int flags, bool nopos,
- int *nold, bstr *out_name, bstr *out_val)
+ int *nold, bstr *out_name, bstr *out_val,
+ char *tmp, size_t tmp_size)
{
int r;
if (!config) {
- *out_name = name; // preserve args for opengl-hq legacy handling
- *out_val = val;
+ // Duplicates the logic below, but with unknown parameter types/names.
+ if (val.start || nopos) {
+ *out_name = name;
+ *out_val = val;
+ } else {
+ val = name;
+ // positional fields
+ if (val.len == 0) { // Empty field, count it and go on
+ (*nold)++;
+ return 0;
+ }
+ // Positional naming convention for/followed by mp_set_avopts().
+ snprintf(tmp, tmp_size, "@%d", *nold);
+ *out_name = bstr0(tmp);
+ *out_val = val;
+ (*nold)++;
+ }
return 1;
}
- // va.start != NULL => of the form name=val (not positional)
+ // val.start != NULL => of the form name=val (not positional)
// If it's just "name", and the associated option exists and is a flag,
// don't accept it as positional argument.
if (val.start || m_config_option_requires_param(config, name) == 0 || nopos) {
@@ -2683,6 +2699,7 @@ static int m_obj_parse_sub_config(struct mp_log *log, struct bstr opt_name,
char **args = NULL;
int num_args = 0;
int r = 1;
+ char tmp[80];
if (ret) {
args = *ret;
@@ -2708,7 +2725,7 @@ static int m_obj_parse_sub_config(struct mp_log *log, struct bstr opt_name,
if (bstr_equals0(fname, "help"))
goto print_help;
r = get_obj_param(log, opt_name, name, config, fname, fval, flags,
- nopos, &nold, &fname, &fval);
+ nopos, &nold, &fname, &fval, tmp, sizeof(tmp));
if (r < 0)
goto exit;
diff --git a/video/filter/vf_lavfi.c b/video/filter/vf_lavfi.c
index 91930e3b02..28869075b5 100644
--- a/video/filter/vf_lavfi.c
+++ b/video/filter/vf_lavfi.c
@@ -172,7 +172,7 @@ static bool recreate_graph(struct vf_instance *vf, struct mp_image_params *fmt)
if (!filter)
goto error;
- if (mp_set_avopts(vf->log, filter, p->cfg_filter_opts) < 0)
+ if (mp_set_avopts(vf->log, filter->priv, p->cfg_filter_opts) < 0)
goto error;
if (avfilter_init_str(filter, NULL) < 0)