static void *filter_child_next(void *obj, void *prev)
{
AVFilterContext *ctx = obj;
- if (!prev && ctx->filter && ctx->filter->priv_class)
+ if (!prev && ctx->filter && ctx->filter->priv_class && ctx->priv)
return ctx->priv;
return NULL;
}
static const AVClass *filter_child_class_next(const AVClass *prev)
{
- AVFilter **filter_ptr = NULL;
+ AVFilter **f = NULL;
/* find the filter that corresponds to prev */
- while (prev && *(filter_ptr = av_filter_next(filter_ptr)))
- if ((*filter_ptr)->priv_class == prev)
+ while (prev && *(f = av_filter_next(f)))
+ if ((*f)->priv_class == prev)
break;
/* could not find filter corresponding to prev */
- if (prev && !(*filter_ptr))
+ if (prev && !(*f))
return NULL;
/* find next filter with specific options */
- while (*(filter_ptr = av_filter_next(filter_ptr)))
- if ((*filter_ptr)->priv_class)
- return (*filter_ptr)->priv_class;
+ while (*(f = av_filter_next(f)))
+ if ((*f)->priv_class)
+ return (*f)->priv_class;
return NULL;
}
.child_class_next = filter_child_class_next,
};
-const AVClass *avfilter_get_class(void)
-{
- return &avfilter_class;
-}
-
int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name)
{
AVFilterContext *ret;
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 count;
+}
+
+// TODO: drop me
+static const char *const filters_left_to_update[] = {
+ "abuffer",
+ "aconvert",
+ "aevalsrc",
+ "amerge",
+ "anullsrc",
+ "aresample",
+ "asendcmd",
+ "asetnsamples",
+ "astreamsync",
+ "atempo",
+ "bbox",
+ "blackdetect",
+ "buffer",
+ "flite",
+ "hue",
+ "mp",
+ "pan",
+ "removelogo",
+ "scale",
+ "sendcmd",
+ "setdar",
+ "setsar",
+};
+static int filter_use_deprecated_init(const char *name)
+{
+ int i;
+ for (i = 0; i < FF_ARRAY_ELEMS(filters_left_to_update); i++)
+ if (!strcmp(name, filters_left_to_update[i]))
+ return 1;
return 0;
}
AVDictionary *options = NULL;
AVDictionaryEntry *e;
int ret=0;
- int anton_options =
- !strcmp(filter->filter->name, "aformat") ||
- !strcmp(filter->filter->name, "ass") ||
- !strcmp(filter->filter->name, "blackframe") ||
- !strcmp(filter->filter->name, "boxblur" ) ||
- !strcmp(filter->filter->name, "colormatrix") ||
- !strcmp(filter->filter->name, "crop" ) ||
- !strcmp(filter->filter->name, "cropdetect") ||
- !strcmp(filter->filter->name, "curves" ) ||
- !strcmp(filter->filter->name, "decimate" ) ||
- !strcmp(filter->filter->name, "delogo" ) ||
- !strcmp(filter->filter->name, "drawbox" ) ||
- !strcmp(filter->filter->name, "drawtext" ) ||
- !strcmp(filter->filter->name, "ebur128" ) ||
- !strcmp(filter->filter->name, "edgedetect") ||
- !strcmp(filter->filter->name, "fade" ) ||
- !strcmp(filter->filter->name, "field" ) ||
- !strcmp(filter->filter->name, "fieldorder") ||
- !strcmp(filter->filter->name, "fps" ) ||
- !strcmp(filter->filter->name, "frei0r" ) ||
- !strcmp(filter->filter->name, "frei0r_src") ||
- !strcmp(filter->filter->name, "geq" ) ||
- !strcmp(filter->filter->name, "gradfun" ) ||
- !strcmp(filter->filter->name, "hqdn3d" ) ||
- !strcmp(filter->filter->name, "ocv" ) ||
- !strcmp(filter->filter->name, "lut" ) ||
- !strcmp(filter->filter->name, "lutyuv" ) ||
- !strcmp(filter->filter->name, "lutrgb" ) ||
- !strcmp(filter->filter->name, "negate" ) ||
- !strcmp(filter->filter->name, "overlay" ) ||
- !strcmp(filter->filter->name, "pad" ) ||
- !strcmp(filter->filter->name, "format") ||
- !strcmp(filter->filter->name, "noformat") ||
- !strcmp(filter->filter->name, "perms") ||
- !strcmp(filter->filter->name, "pp" ) ||
- !strcmp(filter->filter->name, "aperms") ||
- !strcmp(filter->filter->name, "resample") ||
- !strcmp(filter->filter->name, "setpts" ) ||
- !strcmp(filter->filter->name, "settb" ) ||
- !strcmp(filter->filter->name, "showspectrum") ||
- !strcmp(filter->filter->name, "silencedetect") ||
- !strcmp(filter->filter->name, "smartblur") ||
- !strcmp(filter->filter->name, "subtitles") ||
- !strcmp(filter->filter->name, "thumbnail") ||
-// !strcmp(filter->filter->name, "scale" ) ||
- !strcmp(filter->filter->name, "select") ||
- 0
- ;
+ int deprecated_init = filter_use_deprecated_init(filter->filter->name);
+ // TODO: remove old shorthand
if (filter->filter->shorthand) {
av_assert0(filter->priv);
av_assert0(filter->filter->priv_class);
args = NULL;
}
- if (anton_options && args && *args && filter->filter->priv_class) {
+ if (!deprecated_init && args && *args) {
+ if (!filter->filter->priv_class) {
+ av_log(filter, AV_LOG_ERROR, "This filter does not take any "
+ "options, but options were provided: %s.\n", args);
+ return AVERROR(EINVAL);
+ }
+
#if FF_API_OLD_FILTER_OPTS
if (!strcmp(filter->filter->name, "scale") &&
strchr(args, ':') < strchr(args, '=')) {
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(©);
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") ||
while ((p = strchr(p, ':')))
*p++ = '|';
- ret = process_unnamed_options(filter, &options, copy);
+ ret = process_options(filter, &options, copy);
av_freep(©);
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;
}
}
- if (anton_options && filter->filter->priv_class) {
+ if (!deprecated_init && filter->filter->priv_class) {
ret = av_opt_set_dict(filter->priv, &options);
if (ret < 0) {
av_log(filter, AV_LOG_ERROR, "Error applying options to the filter.\n");
return ff_filter_frame_framed(link, frame);
}
}
+
+const AVClass *avfilter_get_class(void)
+{
+ return &avfilter_class;
+}