summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-04-03 18:04:18 +0200
committerwm4 <wm4@nowhere>2017-04-03 18:12:42 +0200
commit31611fc46b29e0704004e21f1e25de2f9608e109 (patch)
treeaa45539886860960bc436cb481688d1b66f885bf /common
parent13160530f2ef05b24dc9331fe42b00def1e4d071 (diff)
downloadmpv-31611fc46b29e0704004e21f1e25de2f9608e109.tar.bz2
mpv-31611fc46b29e0704004e21f1e25de2f9608e109.tar.xz
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.
Diffstat (limited to 'common')
-rw-r--r--common/av_common.c30
1 files changed, 30 insertions, 0 deletions
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);