mirror of https://github.com/mpv-player/mpv
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:
parent
13160530f2
commit
31611fc46b
|
@ -60,11 +60,11 @@ normal filter parameters.
|
||||||
implemented in mpv only).
|
implemented in mpv only).
|
||||||
|
|
||||||
If a filter is not builtin, the ``lavfi-bridge`` will be automatically
|
If a filter is not builtin, the ``lavfi-bridge`` will be automatically
|
||||||
tried. Keep in mind that this filter does not support positional arguments
|
tried. This bridge does not support help output, and does not verify
|
||||||
like ``--vf=name=arg1:arg2``. Instead, you must use
|
parameters before the filter is actually used. Although the mpv syntax
|
||||||
``--vf=name=arg1name=arg1value:...``. This bridge also does not support
|
is rather similar to libavfilter's, it's not the same. (Which means not
|
||||||
help output, and does not verify parameters before the filter is actually
|
everything accepted by vf_lavfi's ``graph`` option will be accepted by
|
||||||
used.
|
``--vf``.)
|
||||||
|
|
||||||
Video filters are managed in lists. There are a few commands to manage the
|
Video filters are managed in lists. There are a few commands to manage the
|
||||||
filter list.
|
filter list.
|
||||||
|
|
|
@ -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);
|
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, ...
|
// 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
|
// Set these options on given avobj (using av_opt_set..., meaning avobj must
|
||||||
// point to a struct that has AVClass as first member).
|
// 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++) {
|
for (int n = 0; kv && kv[n * 2]; n++) {
|
||||||
char *k = kv[n * 2 + 0];
|
char *k = kv[n * 2 + 0];
|
||||||
char *v = kv[n * 2 + 1];
|
char *v = kv[n * 2 + 1];
|
||||||
|
resolve_positional_arg(avobj, &k);
|
||||||
int r = av_opt_set(avobj, k, v, AV_OPT_SEARCH_CHILDREN);
|
int r = av_opt_set(avobj, k, v, AV_OPT_SEARCH_CHILDREN);
|
||||||
if (r == AVERROR_OPTION_NOT_FOUND) {
|
if (r == AVERROR_OPTION_NOT_FOUND) {
|
||||||
mp_err(log, "AVOption '%s' not found.\n", k);
|
mp_err(log, "AVOption '%s' not found.\n", k);
|
||||||
|
|
|
@ -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,
|
static int get_obj_param(struct mp_log *log, bstr opt_name, bstr obj_name,
|
||||||
struct m_config *config, bstr name, bstr val,
|
struct m_config *config, bstr name, bstr val,
|
||||||
int flags, bool nopos,
|
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;
|
int r;
|
||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
*out_name = name; // preserve args for opengl-hq legacy handling
|
// Duplicates the logic below, but with unknown parameter types/names.
|
||||||
*out_val = val;
|
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;
|
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,
|
// If it's just "name", and the associated option exists and is a flag,
|
||||||
// don't accept it as positional argument.
|
// don't accept it as positional argument.
|
||||||
if (val.start || m_config_option_requires_param(config, name) == 0 || nopos) {
|
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;
|
char **args = NULL;
|
||||||
int num_args = 0;
|
int num_args = 0;
|
||||||
int r = 1;
|
int r = 1;
|
||||||
|
char tmp[80];
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
args = *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"))
|
if (bstr_equals0(fname, "help"))
|
||||||
goto print_help;
|
goto print_help;
|
||||||
r = get_obj_param(log, opt_name, name, config, fname, fval, flags,
|
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)
|
if (r < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,7 @@ static bool recreate_graph(struct vf_instance *vf, struct mp_image_params *fmt)
|
||||||
if (!filter)
|
if (!filter)
|
||||||
goto error;
|
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;
|
goto error;
|
||||||
|
|
||||||
if (avfilter_init_str(filter, NULL) < 0)
|
if (avfilter_init_str(filter, NULL) < 0)
|
||||||
|
|
Loading…
Reference in New Issue