3 * copyright (c) 2007 Bobby Bingham
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "avfiltergraph.h"
28 static const char *log_name(void *p)
30 return "Filter parser";
33 static const AVClass filter_parser_class = {
38 static const AVClass *log_ctx = &filter_parser_class;
40 static void uninit(GraphContext *graph)
42 for(; graph->filter_count > 0; graph->filter_count --)
43 avfilter_destroy(graph->filters[graph->filter_count - 1]);
44 av_freep(&graph->filters);
47 /* TODO: insert in sorted order */
48 void avfilter_graph_add_filter(GraphContext *graph, AVFilterContext *filter)
50 graph->filters = av_realloc(graph->filters,
51 sizeof(AVFilterContext*) * ++graph->filter_count);
52 graph->filters[graph->filter_count - 1] = filter;
55 /* search intelligently, once we insert in order */
56 AVFilterContext *avfilter_graph_get_filter(GraphContext *graph, char *name)
63 for(i = 0; i < graph->filter_count; i ++)
64 if(graph->filters[i]->name && !strcmp(name, graph->filters[i]->name))
65 return graph->filters[i];
70 static int query_formats(GraphContext *graph)
74 /* ask all the sub-filters for their supported colorspaces */
75 for(i = 0; i < graph->filter_count; i ++) {
76 if(graph->filters[i]->filter->query_formats)
77 graph->filters[i]->filter->query_formats(graph->filters[i]);
79 avfilter_default_query_formats(graph->filters[i]);
82 /* go through and merge as many format lists as possible */
83 for(i = 0; i < graph->filter_count; i ++) {
84 AVFilterContext *filter = graph->filters[i];
86 for(j = 0; j < filter->input_count; j ++) {
88 if(!(link = filter->inputs[j]))
90 if(link->in_formats != link->out_formats) {
91 if(!avfilter_merge_formats(link->in_formats,
93 /* couldn't merge format lists. auto-insert scale filter */
94 AVFilterContext *scale;
97 avfilter_open(avfilter_get_by_name("scale"), NULL)))
99 if(scale->filter->init(scale, NULL, NULL) ||
100 avfilter_insert_filter(link, scale, 0, 0)) {
101 avfilter_destroy(scale);
105 avfilter_graph_add_filter(graph, scale);
106 scale->filter->query_formats(scale);
107 if(!avfilter_merge_formats(scale-> inputs[0]->in_formats,
108 scale-> inputs[0]->out_formats) ||
109 !avfilter_merge_formats(scale->outputs[0]->in_formats,
110 scale->outputs[0]->out_formats))
120 static void pick_format(AVFilterLink *link)
122 if(!link || !link->in_formats)
125 link->in_formats->format_count = 1;
126 link->format = link->in_formats->formats[0];
128 avfilter_formats_unref(&link->in_formats);
129 avfilter_formats_unref(&link->out_formats);
132 static void pick_formats(GraphContext *graph)
136 for(i = 0; i < graph->filter_count; i ++) {
137 AVFilterContext *filter = graph->filters[i];
139 for(j = 0; j < filter->input_count; j ++)
140 pick_format(filter->inputs[j]);
141 for(j = 0; j < filter->output_count; j ++)
142 pick_format(filter->outputs[j]);
146 int avfilter_graph_config_formats(GraphContext *graph)
148 /* find supported formats from sub-filters, and merge along links */
149 if(query_formats(graph))
152 /* Once everything is merged, it's possible that we'll still have
153 * multiple valid colorspace choices. We pick the first one. */
159 static int graph_load_from_desc2(GraphContext *ctx, AVFilterGraphDesc *desc)
161 AVFilterGraphDescFilter *curfilt;
162 AVFilterGraphDescLink *curlink;
163 AVFilterContext *filt, *filtb;
168 /* create all filters */
169 for(curfilt = desc->filters; curfilt; curfilt = curfilt->next) {
170 snprintf(tmp, 20, "%d", curfilt->index);
171 if(!(filterdef = avfilter_get_by_name(curfilt->filter)) ||
172 !(filt = avfilter_open(filterdef, tmp))) {
173 av_log(&log_ctx, AV_LOG_ERROR,
174 "error creating filter '%s'\n", curfilt->filter);
177 avfilter_graph_add_filter(ctx, filt);
178 if(avfilter_init_filter(filt, curfilt->args, NULL)) {
179 av_log(&log_ctx, AV_LOG_ERROR,
180 "error initializing filter '%s'\n", curfilt->filter);
185 /* create all links */
186 for(curlink = desc->links; curlink; curlink = curlink->next) {
187 snprintf(tmp, 20, "%d", curlink->src);
188 if(!(filt = avfilter_graph_get_filter(ctx, tmp))) {
189 av_log(&log_ctx, AV_LOG_ERROR, "link source does not exist in graph\n");
192 snprintf(tmp, 20, "%d", curlink->dst);
193 if(!(filtb = avfilter_graph_get_filter(ctx, tmp))) {
194 av_log(&log_ctx, AV_LOG_ERROR, "link destination does not exist in graph\n");
197 if(avfilter_link(filt, curlink->srcpad, filtb, curlink->dstpad)) {
198 av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n");
210 int graph_load_from_desc3(GraphContext *graph, AVFilterGraphDesc *desc, AVFilterContext *in, int inpad, AVFilterContext *out, int outpad)
212 AVFilterGraphDescExport *curpad;
214 AVFilterContext *filt;
216 if (graph_load_from_desc2(graph, desc) < 0)
219 /* export all input pads */
220 for(curpad = desc->inputs; curpad; curpad = curpad->next) {
221 snprintf(tmp, 20, "%d", curpad->filter);
222 if(!(filt = avfilter_graph_get_filter(graph, tmp))) {
223 av_log(&log_ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n");
226 if(avfilter_link(in, inpad, filt, curpad->pad)) {
227 av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n");
232 /* export all output pads */
233 for(curpad = desc->outputs; curpad; curpad = curpad->next) {
234 snprintf(tmp, 20, "%d", curpad->filter);
235 if(!(filt = avfilter_graph_get_filter(graph, tmp))) {
236 av_log(&log_ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n");
240 if(avfilter_link(filt, curpad->pad, out, outpad)) {
241 av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n");