if (link->closed)
return AVERROR_EOF;
- if (link->srcpad->request_frame)
- ret = link->srcpad->request_frame(link);
- else if (link->src->inputs[0])
- ret = ff_request_frame(link->src->inputs[0]);
- if (ret == AVERROR_EOF && link->partial_buf) {
- AVFrame *pbuf = link->partial_buf;
- link->partial_buf = NULL;
- ret = ff_filter_frame_framed(link, pbuf);
+ av_assert0(!link->frame_requested);
+ link->frame_requested = 1;
+ while (link->frame_requested) {
+ if (link->srcpad->request_frame)
+ ret = link->srcpad->request_frame(link);
+ else if (link->src->inputs[0])
+ ret = ff_request_frame(link->src->inputs[0]);
+ if (ret == AVERROR_EOF && link->partial_buf) {
+ AVFrame *pbuf = link->partial_buf;
+ link->partial_buf = NULL;
+ ret = ff_filter_frame_framed(link, pbuf);
+ }
+ if (ret < 0) {
+ link->frame_requested = 0;
+ if (ret == AVERROR_EOF)
+ link->closed = 1;
+ } else {
+ av_assert0(!link->frame_requested ||
+ link->flags & FF_LINK_FLAG_REQUEST_LOOP);
+ }
}
- if (ret == AVERROR_EOF)
- link->closed = 1;
return ret;
}
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);
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])) {
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);
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 =
+ !strcmp(filter->filter->name, "aformat") ||
+ !strcmp(filter->filter->name, "format") ||
+ !strcmp(filter->filter->name, "noformat") ||
+ !strcmp(filter->filter->name, "resample")
+ ;
if (filter->filter->shorthand) {
av_assert0(filter->priv);
return ret;
args = NULL;
}
+
+ 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;
+#if FF_API_OLD_FILTER_OPTS
+ } else if (!strcmp(filter->filter->name, "format") ||
+ !strcmp(filter->filter->name, "noformat")) {
+ /* a hack for compatibility with the old syntax
+ * replace colons with |s */
+ char *copy = av_strdup(args);
+ char *p = copy;
+
+ if (!copy) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (strchr(copy, ':')) {
+ av_log(filter, AV_LOG_WARNING, "This syntax is deprecated. Use "
+ "'|' to separate the list items.\n");
+ }
+
+ while ((p = strchr(p, ':')))
+ *p++ = '|';
+
+ ret = process_unnamed_options(filter, &options, copy);
+ av_freep(©);
+
+ if (ret < 0)
+ goto fail;
+#endif
+ } 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_opaque)
ret = filter->filter->init_opaque(filter, args, opaque);
else if (filter->filter->init)
ret = filter->filter->init(filter, args);
+ else if (filter->filter->init_dict)
+ ret = filter->filter->init_dict(filter, &options);
+ 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;
}
pts = out->pts;
ret = filter_frame(link, out);
+ link->frame_requested = 0;
ff_update_link_current_pts(link, pts);
return ret;
}
int nb_channels = av_frame_get_channels(frame);
int ret = 0;
+ link->flags |= FF_LINK_FLAG_REQUEST_LOOP;
/* Handle framing (min_samples, max_samples) */
while (insamples) {
if (!pbuf) {