static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) { int i, j; int scaler_count = 0; char inst_name[30]; /* ask all the sub-filters for their supported colorspaces */ for(i = 0; i < graph->filter_count; i ++) { if(graph->filters[i]->filter->query_formats) graph->filters[i]->filter->query_formats(graph->filters[i]); else avfilter_default_query_formats(graph->filters[i]); } /* go through and merge as many format lists as possible */ for(i = 0; i < graph->filter_count; i ++) { AVFilterContext *filter = graph->filters[i]; for(j = 0; j < filter->input_count; j ++) { AVFilterLink *link = filter->inputs[j]; if(link && link->in_formats != link->out_formats) { if(!avfilter_merge_formats(link->in_formats, link->out_formats)) { AVFilterContext *scale; char scale_args[256]; /* couldn't merge format lists. auto-insert scale filter */ snprintf(inst_name, sizeof(inst_name), "auto-inserted scaler %d", scaler_count++); scale = avfilter_open(avfilter_get_by_name("scale"),inst_name); snprintf(scale_args, sizeof(scale_args), "0:0:%s", graph->scale_sws_opts); if(!scale || scale->filter->init(scale, scale_args, NULL) || avfilter_insert_filter(link, scale, 0, 0)) { avfilter_destroy(scale); return -1; } if (avfilter_graph_add_filter(graph, scale) < 0) return -1; scale->filter->query_formats(scale); if (((link = scale-> inputs[0]) && !avfilter_merge_formats(link->in_formats, link->out_formats)) || ((link = scale->outputs[0]) && !avfilter_merge_formats(link->in_formats, link->out_formats))) { av_log(log_ctx, AV_LOG_ERROR, "Impossible to convert between the formats supported by the filter " "'%s' and the filter '%s'\n", link->src->name, link->dst->name); return -1; } } } } } return 0; }
/** * Create an instance of a filter, initialize and insert it in the * filtergraph in *ctx. * * @param ctx the filtergraph context * @param put here a filter context in case of successful creation and configuration, NULL otherwise. * @param index an index which is supposed to be unique for each filter instance added to the filtergraph * @param filt_name the name of the filter to create * @param args the arguments provided to the filter during its initialization * @param log_ctx the log context to use * @return 0 in case of success, a negative AVERROR code otherwise */ static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int index, const char *filt_name, const char *args, void *log_ctx) { AVFilter *filt; char inst_name[30]; char tmp_args[256]; int ret; snprintf(inst_name, sizeof(inst_name), "Parsed filter %d %s", index, filt_name); filt = avfilter_get_by_name(filt_name); if (!filt) { av_log(log_ctx, AV_LOG_ERROR, "No such filter: '%s'\n", filt_name); return AVERROR(EINVAL); } ret = avfilter_open(filt_ctx, filt, inst_name); if (!*filt_ctx) { av_log(log_ctx, AV_LOG_ERROR, "Error creating filter '%s'\n", filt_name); return ret; } if ((ret = avfilter_graph_add_filter(ctx, *filt_ctx)) < 0) { avfilter_free(*filt_ctx); return ret; } if (!strcmp(filt_name, "scale") && args && !strstr(args, "flags") && ctx->scale_sws_opts) { snprintf(tmp_args, sizeof(tmp_args), "%s:%s", args, ctx->scale_sws_opts); args = tmp_args; } if ((ret = avfilter_init_filter(*filt_ctx, args, NULL)) < 0) { av_log(log_ctx, AV_LOG_ERROR, "Error initializing filter '%s' with args '%s'\n", filt_name, args); return ret; } return 0; }
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, AVFilter *filt, const char *name, const char *args, void *opaque, AVFilterGraph *graph_ctx) { int ret; if ((ret = avfilter_open(filt_ctx, filt, name)) < 0) goto fail; if ((ret = avfilter_init_filter(*filt_ctx, args, opaque)) < 0) goto fail; if ((ret = avfilter_graph_add_filter(graph_ctx, *filt_ctx)) < 0) goto fail; return 0; fail: if (*filt_ctx) avfilter_free(*filt_ctx); *filt_ctx = NULL; return ret; }