History

Let the filter graph export input and output pads from the filters it contains.

Commited in SoC by Bobby Bingham on 2007-08-07 22:33:46 Originally committed as revision 12696 to svn://svn.ffmpeg.org/ffmpeg/trunk

Vitor Sessak committed 18 years ago

Commit 7f8fb521 parent 256d0e01 file · +347 −3Browse files

Showing the changes to libavfilter/avfiltergraph.c (1 of 1 file). Show all

Unified · Split

libavfilter/avfiltergraph.c+347−3
@@ -29,12 +29,344 @@ · 28 unmodified lines
29typedef struct AVFilterGraph {29typedef struct AVFilterGraph {
30 unsigned filter_count;30 unsigned filter_count;
31 AVFilterContext **filters;31 AVFilterContext **filters;
32
33 /** fake filter to handle links to internal filters */
34 AVFilterContext *link_filter;
32} GraphContext;35} GraphContext;
33 36
37typedef struct {
38 AVFilterContext *graph;
39} GraphLinkContext;
40
41static int link_init(AVFilterContext *ctx, const char *args, void *opaque)
42{
43 GraphLinkContext *linkctx = ctx->priv;
44 linkctx->graph = opaque;
45 return !opaque;
46}
47
48/* given the link between the dummy filter and an internal filter whose input
49 * is being exported outside the graph, this returns the externally visible
50 * link */
51static inline AVFilterLink *get_extern_input_link(AVFilterLink *link)
52{
53 GraphLinkContext *lctx = link->src->priv;
54 return lctx->graph->inputs[link->srcpad];
55}
56
57/** query the formats supported by a filter providing input to the graph */
58static int *link_in_query_formats(AVFilterLink *link)
59{
60 AVFilterLink *link2 = get_extern_input_link(link);
61 int *(*query_formats)(AVFilterLink *);
62
63 if(!link2)
64 return avfilter_make_format_list(0);
65
66 if(!(query_formats = link2->src->output_pads[link2->srcpad].query_formats))
67 query_formats = avfilter_default_query_output_formats;
68
69 return query_formats(link2);
70}
71
72/** request a frame from a filter providing input to the graph */
73static void link_in_request_frame(AVFilterLink *link)
74{
75 AVFilterLink *link2 = get_extern_input_link(link);
76
77 if(!link2)
78 return;
79 avfilter_request_frame(link2);
80}
81
82static int link_in_config_props(AVFilterLink *link)
83{
84 AVFilterLink *link2 = get_extern_input_link(link);
85 int (*config_props)(AVFilterLink *);
86 int ret;
87
88 if(!link2)
89 return -1;
90 if(!(config_props = link2->src->output_pads[link2->srcpad].config_props))
91 config_props = avfilter_default_config_output_link;
92 ret = config_props(link2);
93
94 link->w = link2->w;
95 link->h = link2->h;
96
97 return ret;
98}
99
100/* given the link between the dummy filter and an internal filter whose input
101 * is being exported outside the graph, this returns the externally visible
102 * link */
103static inline AVFilterLink *get_extern_output_link(AVFilterLink *link)
104{
105 GraphLinkContext *lctx = link->dst->priv;
106 return lctx->graph->outputs[link->dstpad];
107}
108
109/** query the formats supported by a filter taking output from the graph */
110static int *link_out_query_formats(AVFilterLink *link)
111{
112 AVFilterLink *link2 = get_extern_output_link(link);
113
114 if(!link2)
115 return avfilter_make_format_list(0);
116
117 return link2->dst->input_pads[link2->dstpad].query_formats(link2);
118}
119
120static int link_out_config_props(AVFilterLink *link)
121{
122 AVFilterLink *link2 = get_extern_output_link(link);
123 int (*config_props)(AVFilterLink *);
124
125 if(!link2)
126 return 0;
127
128 link2->w = link->w;
129 link2->h = link->h;
130
131 if(!(config_props = link2->dst->input_pads[link2->dstpad].config_props))
132 config_props = avfilter_default_config_input_link;
133 return config_props(link2);
134}
135
136static void link_out_start_frame(AVFilterLink *link, AVFilterPicRef *picref)
137{
138 AVFilterLink *link2 = get_extern_output_link(link);
139
140 if(!link2)
141 avfilter_unref_pic(picref);
142 else
143 avfilter_start_frame(link2, picref);
144}
145
146static void link_out_end_frame(AVFilterLink *link)
147{
148 AVFilterLink *link2 = get_extern_output_link(link);
149
150 if(link2)
151 avfilter_end_frame(link2);
152}
153
154static AVFilterPicRef *link_out_get_video_buffer(AVFilterLink *link, int perms)
155{
156 AVFilterLink *link2 = get_extern_output_link(link);
157
158 if(!link2)
159 return NULL;
160 else
161 return avfilter_get_video_buffer(link2, perms);
162}
163
164static void link_out_draw_slice(AVFilterLink *link, uint8_t *data[4], int y,
165 int height)
166{
167 AVFilterLink *link2 = get_extern_output_link(link);
168
169 if(link2)
170 avfilter_draw_slice(link2, data, y, height);
171}
172
173/** dummy filter used to help export filters pads outside the graph */
174static AVFilter vf_graph_dummy =
175{
176 .name = "graph_dummy",
177 .author = "Bobby Bingham",
178
179 .priv_size = sizeof(GraphLinkContext),
180
181 .init = link_init,
182 //.uninit = uninit,
183
184 .inputs = (AVFilterPad[]) {{ .name = NULL, }},
185 .outputs = (AVFilterPad[]) {{ .name = NULL, }},
186};
187
188static AVFilterLink *get_intern_input_link(AVFilterLink *link)
189{
190 GraphContext *graph = link->dst->priv;
191 return graph->link_filter->outputs[link->dstpad];
192}
193
194static void graph_in_start_frame(AVFilterLink *link, AVFilterPicRef *picref)
195{
196 AVFilterLink *link2 = get_intern_input_link(link);
197 if(link2)
198 avfilter_start_frame(link2, picref);
199}
200
201static void graph_in_end_frame(AVFilterLink *link)
202{
203 AVFilterLink *link2 = get_intern_input_link(link);
204 if(link2)
205 avfilter_end_frame(link2);
206}
207
208static AVFilterPicRef *graph_in_get_video_buffer(AVFilterLink *link, int perms)
209{
210 AVFilterLink *link2 = get_intern_input_link(link);
211 if(link2)
212 return avfilter_get_video_buffer(link2, perms);
213 return NULL;
214}
215
216static void graph_in_draw_slice(AVFilterLink *link, uint8_t *data[4], int y, int height)
217{
218 AVFilterLink *link2 = get_intern_input_link(link);
219 if(link2)
220 avfilter_draw_slice(link2, data, y, height);
221}
222
223static int *graph_in_query_formats(AVFilterLink *link)
224{
225 AVFilterLink *link2 = get_intern_input_link(link);
226
227 if(!link2 || !link2->dst->input_pads[link2->dstpad].query_formats)
228 return avfilter_make_format_list(0);
229 return link2->dst->input_pads[link2->dstpad].query_formats(link2);
230}
231
232static int graph_in_config_props(AVFilterLink *link)
233{
234 AVFilterLink *link2 = get_intern_input_link(link);
235 int (*config_props)(AVFilterLink *);
236
237 if(!link2)
238 return -1;
239
240 /* copy link properties over to the dummy internal link */
241 link2->w = link->w;
242 link2->h = link->h;
243
244 if(!(config_props = link2->dst->input_pads[link2->dstpad].config_props))
245 return 0; /* FIXME? */
246 //config_props = avfilter_default_config_input_link;
247 return config_props(link2);
248}
249
250static AVFilterLink *get_intern_output_link(AVFilterLink *link)
251{
252 GraphContext *graph = link->src->priv;
253 return graph->link_filter->inputs[link->srcpad];
254}
255
256static int *graph_out_query_formats(AVFilterLink *link)
257{
258 AVFilterLink *link2 = get_intern_output_link(link);
259
260 if(!link2 || !link2->src->output_pads[link2->srcpad].query_formats)
261 return avfilter_make_format_list(0);
262 return link2->src->output_pads[link2->srcpad].query_formats(link2);
263}
264
265static void graph_out_request_frame(AVFilterLink *link)
266{
267 AVFilterLink *link2 = get_intern_output_link(link);
268
269 if(link2)
270 avfilter_request_frame(link2);
271}
272
273static int graph_out_config_props(AVFilterLink *link)
274{
275 AVFilterLink *link2 = get_intern_output_link(link);
276 int (*config_props)(AVFilterLink *);
277 int ret;
278
279 if(!link2)
280 return 0;
281
282 link2->w = link->w;
283 link2->h = link->h;
284 link2->format = link->format;
285
286 if(!(config_props = link2->src->output_pads[link2->srcpad].config_props))
287 config_props = avfilter_default_config_output_link;
288 ret = config_props(link2);
289
290 link->w = link2->w;
291 link->h = link2->h;
292 link->format = link2->format;
293
294 return ret;
295}
296
297static int add_graph_input(AVFilterContext *gctx, AVFilterContext *filt, unsigned idx,
298 char *name)
299{
300 GraphContext *graph = gctx->priv;
301
302 AVFilterPad graph_inpad =
303 {
304 .name = name,
305 .type = AV_PAD_VIDEO,
306 .start_frame = graph_in_start_frame,
307 .end_frame = graph_in_end_frame,
308 .get_video_buffer = graph_in_get_video_buffer,
309 .draw_slice = graph_in_draw_slice,
310 .query_formats = graph_in_query_formats,
311 .config_props = graph_in_config_props,
312 /* XXX */
313 };
314 AVFilterPad dummy_outpad =
315 {
316 .name = NULL, /* FIXME? */
317 .type = AV_PAD_VIDEO,
318 .query_formats = link_in_query_formats,
319 .request_frame = link_in_request_frame,
320 .config_props = link_in_config_props,
321 };
322
323 avfilter_insert_inpad (gctx, gctx->input_count, &graph_inpad);
324 avfilter_insert_outpad(graph->link_filter, graph->link_filter->output_count,
325 &dummy_outpad);
326 return avfilter_link(graph->link_filter,
327 graph->link_filter->output_count-1, filt, idx);
328}
329
330static int add_graph_output(AVFilterContext *gctx, AVFilterContext *filt, unsigned idx,
331 char *name)
332{
333 GraphContext *graph = gctx->priv;
334
335 AVFilterPad graph_outpad =
336 {
337 .name = name,
338 .type = AV_PAD_VIDEO,
339 .request_frame = graph_out_request_frame,
340 .query_formats = graph_out_query_formats,
341 .config_props = graph_out_config_props,
342 };
343 AVFilterPad dummy_inpad =
344 {
345 .name = NULL, /* FIXME? */
346 .type = AV_PAD_VIDEO,
347 .start_frame = link_out_start_frame,
348 .end_frame = link_out_end_frame,
349 .draw_slice = link_out_draw_slice,
350 .get_video_buffer = link_out_get_video_buffer,
351 .query_formats = link_out_query_formats,
352 .config_props = link_out_config_props,
353 };
354
355 avfilter_insert_outpad(gctx, gctx->output_count, &graph_outpad);
356 avfilter_insert_inpad (graph->link_filter, graph->link_filter->input_count,
357 &dummy_inpad);
358 return avfilter_link(filt, idx, graph->link_filter,
359 graph->link_filter->input_count-1);
360}
361
34static void uninit(AVFilterContext *ctx)362static void uninit(AVFilterContext *ctx)
35{363{
36 GraphContext *graph = ctx->priv;364 GraphContext *graph = ctx->priv;
37 365
366 if(graph->link_filter) {
367 avfilter_destroy(graph->link_filter);
368 graph->link_filter = NULL;
369 }
38 for(; graph->filter_count > 0; graph->filter_count --)370 for(; graph->filter_count > 0; graph->filter_count --)
39 avfilter_destroy(graph->filters[graph->filter_count - 1]);371 avfilter_destroy(graph->filters[graph->filter_count - 1]);
40 av_freep(&graph->filters);372 av_freep(&graph->filters);
@@ -122,9 +454,14 @@ static int graph_load_chain(AVFilterContext *graphctx, · 81 unmodified lines
122 }454 }
123 }455 }
124 avfilter_graph_add_filter(graphctx, filters[1]);456 avfilter_graph_add_filter(graphctx, filters[1]);
457 if(i == 0 && filters[1]->input_count > 0)
458 add_graph_input(graphctx, filters[1], 0, "default");
125 filters[0] = filters[1];459 filters[0] = filters[1];
126 }460 }
127 461
462 if(filters[1]->output_count > 0)
463 add_graph_output(graphctx, filters[1], 0, "default");
464
128 if(last) *last = filters[1];465 if(last) *last = filters[1];
129 return 0;466 return 0;
130 467
@@ -170,14 +507,21 @@ done: · 39 unmodified lines
170 507
171static int init(AVFilterContext *ctx, const char *args, void *opaque)508static int init(AVFilterContext *ctx, const char *args, void *opaque)
172{509{
173 AVFilterContext **filters = opaque;510 GraphContext *gctx = ctx->priv;
174 511
175 if(!args)512 if(!args)
176 return 0;513 return 0;
177 if(!opaque)514
515 if(!(gctx->link_filter = avfilter_create(&vf_graph_dummy, NULL)))
178 return -1;516 return -1;
517 if(avfilter_init_filter(gctx->link_filter, NULL, ctx))
518 goto fail;
179 519
180 return graph_load_chain_from_string(ctx, args, filters, filters + 1);520 return graph_load_chain_from_string(ctx, args, NULL, NULL);
521
522fail:
523 avfilter_destroy(gctx->link_filter);
524 return -1;
181}525}
182 526
183AVFilter vf_graph =527AVFilter vf_graph =

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t