summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/filters.texi21
-rw-r--r--libavcodec/dfa.c16
-rw-r--r--libavfilter/avfilter.c90
-rw-r--r--libavfilter/avfilter.h8
-rw-r--r--libavfilter/version.h3
5 files changed, 121 insertions, 17 deletions
diff --git a/doc/filters.texi b/doc/filters.texi
index 60d00bbf29..512f943d83 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -130,8 +130,25 @@ 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, and are described in the filter
-descriptions below.
+initialize the filter instance. It may have one of the two allowed forms:
+@itemize
+
+@item
+A ':'-separated list of @var{key=value} pairs.
+
+@item
+A ':'-separated list of @var{value}. In this case, the keys are assumed to be
+the option names in the order they are declared. E.g. the @code{fade} filter
+declares three options in this order -- @option{type}, @option{start_frame} and
+@option{nb_frames}. Then the parameter list @var{in:0:30} means that the value
+@var{in} is assigned to the option @option{type}, @var{0} to
+@option{start_frame} and @var{30} to @option{nb_frames}.
+
+@end itemize
+
+If the option value itself is a list of items (e.g. the @code{format} filter
+takes a list of pixel formats), the items in the list are usually separated by
+'|'.
The list of arguments can be quoted using the character "'" as initial
and ending mark, and the character '\' for escaping the characters
diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c
index 4c77f4e273..32459098a7 100644
--- a/libavcodec/dfa.c
+++ b/libavcodec/dfa.c
@@ -292,17 +292,19 @@ static int decode_tdlt(GetByteContext *gb, uint8_t *frame, int width, int height
{
const uint8_t *frame_end = frame + width * height;
uint32_t segments = bytestream2_get_le32(gb);
+ int skip, copy;
while (segments--) {
- int count = bytestream2_get_byte(gb) << 1;
- int skip = bytestream2_get_byte(gb) << 1;
-
- if (frame_end - frame < skip + count)
+ if (bytestream2_get_bytes_left(gb) < 2)
return AVERROR_INVALIDDATA;
- frame += skip;
- if (bytestream2_get_buffer(gb, frame, count) != count)
+ copy = bytestream2_get_byteu(gb) * 2;
+ skip = bytestream2_get_byteu(gb) * 2;
+ if (frame_end - frame < copy + skip ||
+ bytestream2_get_bytes_left(gb) < copy)
return AVERROR_INVALIDDATA;
- frame += count;
+ frame += skip;
+ bytestream2_get_buffer(gb, frame, copy);
+ frame += copy;
}
return 0;
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index b689fbe9d4..0b6a65266f 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -516,6 +516,11 @@ int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *in
goto err;
}
+ if (filter->priv_class) {
+ *(const AVClass**)ret->priv = filter->priv_class;
+ av_opt_set_defaults(ret->priv);
+ }
+
ret->nb_inputs = pad_count(filter->inputs);
if (ret->nb_inputs ) {
ret->input_pads = av_malloc(sizeof(AVFilterPad) * ret->nb_inputs);
@@ -567,8 +572,6 @@ void avfilter_free(AVFilterContext *filter)
if (filter->filter->uninit)
filter->filter->uninit(filter);
- if (filter->filter->shorthand)
- av_opt_free(filter->priv);
for (i = 0; i < filter->nb_inputs; i++) {
if ((link = filter->inputs[i])) {
@@ -597,6 +600,9 @@ void avfilter_free(AVFilterContext *filter)
avfilter_link_free(&link);
}
+ if (filter->filter->priv_class || filter->filter->shorthand)
+ av_opt_free(filter->priv);
+
av_freep(&filter->name);
av_freep(&filter->input_pads);
av_freep(&filter->output_pads);
@@ -609,9 +615,45 @@ 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)
+{
+ const AVOption *o = NULL;
+ const char *p = args;
+ char *val;
+
+ while (*p) {
+ 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->type == AV_OPT_TYPE_CONST)
+ continue;
+
+ val = av_get_token(&p, ":");
+ if (!val)
+ return AVERROR(ENOMEM);
+
+ av_dict_set(options, o->name, val, 0);
+
+ av_freep(&val);
+ if (*p)
+ p++;
+ }
+
+ return 0;
+}
+
int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque)
{
+ AVDictionary *options = NULL;
+ AVDictionaryEntry *e;
int ret=0;
+ int anton_options = 0;
if (filter->filter->shorthand) {
av_assert0(filter->priv);
@@ -624,10 +666,46 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
return ret;
args = NULL;
}
- if (filter->filter->init_opaque)
- ret = filter->filter->init_opaque(filter, args, opaque);
- else if (filter->filter->init)
- ret = filter->filter->init(filter, args);
+
+ if (anton_options && args && *args && filter->filter->priv_class) {
+ if (strchr(args, '=')) {
+ /* assume a list of key1=value1:key2=value2:... */
+ ret = av_dict_parse_string(&options, args, "=", ":", 0);
+ if (ret < 0)
+ goto fail;
+ } else {
+ ret = process_unnamed_options(filter, &options, args);
+ if (ret < 0)
+ goto fail;
+ }
+ }
+
+ if (anton_options && 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");
+ goto fail;
+ }
+ }
+
+ if (filter->filter->init || filter->filter->init_opaque) {
+ if (filter->filter->init_opaque)
+ ret = filter->filter->init_opaque(filter, args, opaque);
+ else
+ ret = filter->filter->init(filter, args);
+ if (ret < 0)
+ goto fail;
+ }
+
+ if ((e = av_dict_get(options, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
+ av_log(filter, AV_LOG_ERROR, "No such option: %s.\n", e->key);
+ ret = AVERROR_OPTION_NOT_FOUND;
+ goto fail;
+ }
+
+fail:
+ av_dict_free(&options);
+
return ret;
}
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 7583dccfbe..282d4dfb51 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -431,6 +431,12 @@ typedef struct AVFilter {
const AVFilterPad *inputs; ///< NULL terminated list of inputs. NULL if none
const AVFilterPad *outputs; ///< NULL terminated list of outputs. NULL if none
+ /**
+ * A class for the private data, used to access filter private
+ * AVOptions.
+ */
+ const AVClass *priv_class;
+
/*****************************************************************
* All fields below this line are not part of the public API. They
* may not be used outside of libavfilter and can be changed and
@@ -485,8 +491,6 @@ typedef struct AVFilter {
*/
int (*init_opaque)(AVFilterContext *ctx, const char *args, void *opaque);
- const AVClass *priv_class; ///< private class, containing filter specific options
-
/**
* Shorthand syntax for init arguments.
* If this field is set (even to an empty list), just before init the
diff --git a/libavfilter/version.h b/libavfilter/version.h
index a2858359dd..2a70671c3f 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -63,5 +63,8 @@
#ifndef FF_API_AVFILTERBUFFER
#define FF_API_AVFILTERBUFFER (LIBAVFILTER_VERSION_MAJOR < 4)
#endif
+#ifndef FF_API_OLD_FILTER_OPTS
+#define FF_API_OLD_FILTER_OPTS (LIBAVFILTER_VERSION_MAJOR < 4)
+#endif
#endif /* AVFILTER_VERSION_H */