|
|
|
@ -21,9 +21,11 @@ |
|
|
|
|
|
|
|
|
|
/* #define DEBUG */ |
|
|
|
|
|
|
|
|
|
#include "libavutil/avstring.h" |
|
|
|
|
#include "libavutil/channel_layout.h" |
|
|
|
|
#include "libavutil/common.h" |
|
|
|
|
#include "libavutil/imgutils.h" |
|
|
|
|
#include "libavutil/opt.h" |
|
|
|
|
#include "libavutil/pixdesc.h" |
|
|
|
|
#include "libavutil/rational.h" |
|
|
|
|
#include "libavutil/samplefmt.h" |
|
|
|
@ -346,6 +348,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); |
|
|
|
@ -422,6 +429,9 @@ void avfilter_free(AVFilterContext *filter) |
|
|
|
|
av_freep(&link); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (filter->filter->priv_class) |
|
|
|
|
av_opt_free(filter->priv); |
|
|
|
|
|
|
|
|
|
av_freep(&filter->name); |
|
|
|
|
av_freep(&filter->input_pads); |
|
|
|
|
av_freep(&filter->output_pads); |
|
|
|
@ -431,12 +441,81 @@ 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; |
|
|
|
|
|
|
|
|
|
if (filter->filter->init) |
|
|
|
|
if (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 (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) { |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|