lavfi: restore mixed short/long option support with the new system.

process_unnamed_options() is renamed to process_options() and its code
is heavily based on av_opt_set_from_string().
This commit is contained in:
Clément Bœsch 2013-04-11 10:38:05 +02:00
parent c7b0a84e1f
commit b89ce54e74
2 changed files with 58 additions and 36 deletions

View File

@ -137,7 +137,7 @@ The name of the filter class is optionally followed by a string
"=@var{arguments}".
@var{arguments} is a string which contains the parameters used to
initialize the filter instance. It may have one of the two allowed forms:
initialize the filter instance. It may have one of the following forms:
@itemize
@item
@ -151,6 +151,12 @@ declares three options in this order -- @option{type}, @option{start_frame} and
@var{in} is assigned to the option @option{type}, @var{0} to
@option{start_frame} and @var{30} to @option{nb_frames}.
@item
A ':'-separated list of mixed direct @var{value} and long @var{key=value}
pairs. The direct @var{value} must precede the @var{key=value} pairs, and
follow the same constraints order of the previous point. The following
@var{key=value} pairs can be set in any preferred order.
@end itemize
If the option value itself is a list of items (e.g. the @code{format} filter

View File

@ -615,39 +615,64 @@ void avfilter_free(AVFilterContext *filter)
av_free(filter);
}
/* process a list of value1:value2:..., each value corresponding
* to subsequent AVOption, in the order they are declared */
static int process_unnamed_options(AVFilterContext *ctx, AVDictionary **options,
const char *args)
static int process_options(AVFilterContext *ctx, AVDictionary **options,
const char *args)
{
const AVOption *o = NULL;
const char *p = args;
char *val;
int ret, count = 0;
char *av_uninit(parsed_key), *av_uninit(value);
const char *key;
int offset= -1;
while (*p) {
if (!args)
return 0;
while (*args) {
const char *shorthand = NULL;
o = av_opt_next(ctx->priv, o);
if (!o) {
av_log(ctx, AV_LOG_ERROR, "More options provided than "
"this filter supports.\n");
return AVERROR(EINVAL);
if (o) {
if (o->type == AV_OPT_TYPE_CONST || o->offset == offset)
continue;
offset = o->offset;
shorthand = o->name;
}
if (o->type == AV_OPT_TYPE_CONST || o->offset == offset)
continue;
offset = o->offset;
val = av_get_token(&p, ":");
if (!val)
return AVERROR(ENOMEM);
ret = av_opt_get_key_value(&args, "=", ":",
shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0,
&parsed_key, &value);
if (ret < 0) {
if (ret == AVERROR(EINVAL))
av_log(ctx, AV_LOG_ERROR, "No option name near '%s'\n", args);
else
av_log(ctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", args,
av_err2str(ret));
return ret;
}
if (*args)
args++;
if (parsed_key) {
key = parsed_key;
while ((o = av_opt_next(ctx->priv, o))); /* discard all remaining shorthand */
} else {
key = shorthand;
}
av_dict_set(options, o->name, val, 0);
av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value);
av_dict_set(options, key, value, 0);
if ((ret = av_opt_set(ctx->priv, key, value, 0)) < 0) {
if (ret == AVERROR_OPTION_NOT_FOUND)
av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key);
av_free(value);
av_free(parsed_key);
return ret;
}
av_freep(&val);
if (*p)
p++;
av_free(value);
av_free(parsed_key);
count++;
}
return 0;
return count;
}
int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque)
@ -787,20 +812,11 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
ret = av_dict_parse_string(&options, p, "=", ":", 0);
}
if (ret >= 0)
ret = process_unnamed_options(filter, &options, copy);
ret = process_options(filter, &options, copy);
av_freep(&copy);
if (ret < 0)
goto fail;
} else
#endif
if (strchr(args, '=')) {
/* assume a list of key1=value1:key2=value2:... */
ret = av_dict_parse_string(&options, args, "=", ":", 0);
if (ret < 0)
goto fail;
#if FF_API_OLD_FILTER_OPTS
} else if (!strcmp(filter->filter->name, "format") ||
!strcmp(filter->filter->name, "noformat") ||
!strcmp(filter->filter->name, "frei0r") ||
@ -840,14 +856,14 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
while ((p = strchr(p, ':')))
*p++ = '|';
ret = process_unnamed_options(filter, &options, copy);
ret = process_options(filter, &options, copy);
av_freep(&copy);
if (ret < 0)
goto fail;
#endif
} else {
ret = process_unnamed_options(filter, &options, args);
ret = process_options(filter, &options, args);
if (ret < 0)
goto fail;
}