avfiltergraph.c
Go to the documentation of this file.
1 /*
2  * filter graphs
3  * Copyright (c) 2008 Vitor Sessak
4  * Copyright (c) 2007 Bobby Bingham
5  *
6  * This file is part of Libav.
7  *
8  * Libav is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * Libav is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with Libav; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include <ctype.h>
24 #include <string.h>
25 
26 #include "libavutil/avstring.h"
27 #include "avfilter.h"
28 #include "avfiltergraph.h"
29 #include "internal.h"
30 
32 {
33  return av_mallocz(sizeof(AVFilterGraph));
34 }
35 
37 {
38  if (!*graph)
39  return;
40  for (; (*graph)->filter_count > 0; (*graph)->filter_count--)
41  avfilter_free((*graph)->filters[(*graph)->filter_count - 1]);
42  av_freep(&(*graph)->scale_sws_opts);
43  av_freep(&(*graph)->filters);
44  av_freep(graph);
45 }
46 
48 {
50  sizeof(AVFilterContext*) * (graph->filter_count+1));
51  if (!filters)
52  return AVERROR(ENOMEM);
53 
54  graph->filters = filters;
55  graph->filters[graph->filter_count++] = filter;
56 
57  return 0;
58 }
59 
61  const char *name, const char *args, void *opaque,
62  AVFilterGraph *graph_ctx)
63 {
64  int ret;
65 
66  if ((ret = avfilter_open(filt_ctx, filt, name)) < 0)
67  goto fail;
68  if ((ret = avfilter_init_filter(*filt_ctx, args, opaque)) < 0)
69  goto fail;
70  if ((ret = avfilter_graph_add_filter(graph_ctx, *filt_ctx)) < 0)
71  goto fail;
72  return 0;
73 
74 fail:
75  if (*filt_ctx)
76  avfilter_free(*filt_ctx);
77  *filt_ctx = NULL;
78  return ret;
79 }
80 
82 {
83  AVFilterContext *filt;
84  int i, j;
85 
86  for (i = 0; i < graph->filter_count; i++) {
87  filt = graph->filters[i];
88 
89  for (j = 0; j < filt->input_count; j++) {
90  if (!filt->inputs[j] || !filt->inputs[j]->src) {
91  av_log(log_ctx, AV_LOG_ERROR,
92  "Input pad \"%s\" for the filter \"%s\" of type \"%s\" not connected to any source\n",
93  filt->input_pads[j].name, filt->name, filt->filter->name);
94  return AVERROR(EINVAL);
95  }
96  }
97 
98  for (j = 0; j < filt->output_count; j++) {
99  if (!filt->outputs[j] || !filt->outputs[j]->dst) {
100  av_log(log_ctx, AV_LOG_ERROR,
101  "Output pad \"%s\" for the filter \"%s\" of type \"%s\" not connected to any destination\n",
102  filt->output_pads[j].name, filt->name, filt->filter->name);
103  return AVERROR(EINVAL);
104  }
105  }
106  }
107 
108  return 0;
109 }
110 
112 {
113  AVFilterContext *filt;
114  int i, ret;
115 
116  for (i=0; i < graph->filter_count; i++) {
117  filt = graph->filters[i];
118 
119  if (!filt->output_count) {
120  if ((ret = avfilter_config_links(filt)))
121  return ret;
122  }
123  }
124 
125  return 0;
126 }
127 
129 {
130  int i;
131 
132  for (i = 0; i < graph->filter_count; i++)
133  if (graph->filters[i]->name && !strcmp(name, graph->filters[i]->name))
134  return graph->filters[i];
135 
136  return NULL;
137 }
138 
139 static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
140 {
141  int i, j, ret;
142  int scaler_count = 0;
143  char inst_name[30];
144 
145  /* ask all the sub-filters for their supported media formats */
146  for (i = 0; i < graph->filter_count; i++) {
147  if (graph->filters[i]->filter->query_formats)
148  graph->filters[i]->filter->query_formats(graph->filters[i]);
149  else
151  }
152 
153  /* go through and merge as many format lists as possible */
154  for (i = 0; i < graph->filter_count; i++) {
155  AVFilterContext *filter = graph->filters[i];
156 
157  for (j = 0; j < filter->input_count; j++) {
158  AVFilterLink *link = filter->inputs[j];
159  if (link && link->in_formats != link->out_formats) {
161  link->out_formats)) {
163  char scale_args[256];
164  /* couldn't merge format lists. auto-insert scale filter */
165  snprintf(inst_name, sizeof(inst_name), "auto-inserted scaler %d",
166  scaler_count++);
167  av_strlcpy(scale_args, "0:0", sizeof(scale_args));
168  if (graph->scale_sws_opts) {
169  av_strlcat(scale_args, ":", sizeof(scale_args));
170  av_strlcat(scale_args, graph->scale_sws_opts, sizeof(scale_args));
171  }
172  if ((ret = avfilter_graph_create_filter(&scale, avfilter_get_by_name("scale"),
173  inst_name, scale_args, NULL, graph)) < 0)
174  return ret;
175  if ((ret = avfilter_insert_filter(link, scale, 0, 0)) < 0)
176  return ret;
177 
178  scale->filter->query_formats(scale);
179  if (((link = scale-> inputs[0]) &&
181  ((link = scale->outputs[0]) &&
183  av_log(log_ctx, AV_LOG_ERROR,
184  "Impossible to convert between the formats supported by the filter "
185  "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
186  return AVERROR(EINVAL);
187  }
188  }
189  }
190  }
191  }
192 
193  return 0;
194 }
195 
196 static void pick_format(AVFilterLink *link)
197 {
198  if (!link || !link->in_formats)
199  return;
200 
201  link->in_formats->format_count = 1;
202  link->format = link->in_formats->formats[0];
203 
206 }
207 
208 static void pick_formats(AVFilterGraph *graph)
209 {
210  int i, j;
211 
212  for (i = 0; i < graph->filter_count; i++) {
213  AVFilterContext *filter = graph->filters[i];
214 
215  for (j = 0; j < filter->input_count; j++)
216  pick_format(filter->inputs[j]);
217  for (j = 0; j < filter->output_count; j++)
218  pick_format(filter->outputs[j]);
219  }
220 }
221 
223 {
224  int ret;
225 
226  /* find supported formats from sub-filters, and merge along links */
227  if ((ret = query_formats(graph, log_ctx)) < 0)
228  return ret;
229 
230  /* Once everything is merged, it's possible that we'll still have
231  * multiple valid media format choices. We pick the first one. */
232  pick_formats(graph);
233 
234  return 0;
235 }
236 
237 int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
238 {
239  int ret;
240 
241  if ((ret = ff_avfilter_graph_check_validity(graphctx, log_ctx)))
242  return ret;
243  if ((ret = ff_avfilter_graph_config_formats(graphctx, log_ctx)))
244  return ret;
245  if ((ret = ff_avfilter_graph_config_links(graphctx, log_ctx)))
246  return ret;
247 
248  return 0;
249 }