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

Unified · Split

libavfilter/avfiltergraph.c+347−3
@@ -29,12 +29,344 @@ · 28 unmodified lines
2929 typedef struct AVFilterGraph {
3030 unsigned filter_count;
3131 AVFilterContext **filters;
32+
33+ /** fake filter to handle links to internal filters */
34+ AVFilterContext *link_filter;
3235 } GraphContext;
3336
37+typedef struct {
38+ AVFilterContext *graph;
39+} GraphLinkContext;
40+
41+static 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 */
51+static 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 */
58+static 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 */
73+static 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+
82+static 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 */
103+static 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 */
110+static 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+
120+static 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+
136+static 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+
146+static 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+
154+static 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+
164+static 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 */
174+static 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+
188+static AVFilterLink *get_intern_input_link(AVFilterLink *link)
189+{
190+ GraphContext *graph = link->dst->priv;
191+ return graph->link_filter->outputs[link->dstpad];
192+}
193+
194+static 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+
201+static 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+
208+static 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+
216+static 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+
223+static 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+
232+static 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+
250+static AVFilterLink *get_intern_output_link(AVFilterLink *link)
251+{
252+ GraphContext *graph = link->src->priv;
253+ return graph->link_filter->inputs[link->srcpad];
254+}
255+
256+static 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+
265+static 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+
273+static 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+
297+static 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+
330+static 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+
34362 static void uninit(AVFilterContext *ctx)
35363 {
36364 GraphContext *graph = ctx->priv;
37365
366+ if(graph->link_filter) {
367+ avfilter_destroy(graph->link_filter);
368+ graph->link_filter = NULL;
369+ }
38370 for(; graph->filter_count > 0; graph->filter_count --)
39371 avfilter_destroy(graph->filters[graph->filter_count - 1]);
40372 av_freep(&graph->filters);
@@ -122,9 +454,14 @@ static int graph_load_chain(AVFilterContext *graphctx, · 81 unmodified lines
122454 }
123455 }
124456 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");
125459 filters[0] = filters[1];
126460 }
127461
462+ if(filters[1]->output_count > 0)
463+ add_graph_output(graphctx, filters[1], 0, "default");
464+
128465 if(last) *last = filters[1];
129466 return 0;
130467
@@ -170,14 +507,21 @@ done: · 39 unmodified lines
170507
171508 static int init(AVFilterContext *ctx, const char *args, void *opaque)
172509 {
173− AVFilterContext **filters = opaque;
510+ GraphContext *gctx = ctx->priv;
174511
175512 if(!args)
176513 return 0;
177− if(!opaque)
514+
515+ if(!(gctx->link_filter = avfilter_create(&vf_graph_dummy, NULL)))
178516 return -1;
517+ if(avfilter_init_filter(gctx->link_filter, NULL, ctx))
518+ goto fail;
179519
180− return graph_load_chain_from_string(ctx, args, filters, filters + 1);
520+ return graph_load_chain_from_string(ctx, args, NULL, NULL);
521+
522+fail:
523+ avfilter_destroy(gctx->link_filter);
524+ return -1;
181525 }
182526
183527 AVFilter 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