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.
This commit is contained in:
wm4 2017-04-03 18:04:18 +02:00
parent 13160530f2
commit 31611fc46b
4 changed files with 58 additions and 11 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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;

View File

@ -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)