]> git.sesse.net Git - ffmpeg/blob - libavfilter/avfilter.c
62e8d7a62f53d90eccf054b2647d5709801be75a
[ffmpeg] / libavfilter / avfilter.c
1 /*
2  * Filter layer
3  * copyright (c) 2007 Bobby Bingham
4  *
5  * This file is part of FFmpeg.
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26
27 #include "avfilter.h"
28 #include "allfilters.h"
29
30 /** list of registered filters, sorted by name */
31 static int filter_count = 0;
32 static AVFilter **filters = NULL;
33
34 /* TODO: buffer pool.  see comment for avfilter_default_get_video_buffer() */
35 void avfilter_default_free_video_buffer(AVFilterPic *pic)
36 {
37     avpicture_free((AVPicture *) pic);
38     av_free(pic);
39 }
40
41 /* TODO: set the buffer's priv member to a context structure for the whole
42  * filter chain.  This will allow for a buffer pool instead of the constant
43  * alloc & free cycle currently implemented. */
44 AVFilterPicRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms)
45 {
46     AVFilterPic *pic = av_mallocz(sizeof(AVFilterPic));
47     AVFilterPicRef *ref = av_mallocz(sizeof(AVFilterPicRef));
48
49     ref->pic   = pic;
50     ref->w     = link->w;
51     ref->h     = link->h;
52     ref->perms = perms;
53
54     pic->refcount = 1;
55     pic->format   = link->format;
56     pic->free     = avfilter_default_free_video_buffer;
57     avpicture_alloc((AVPicture *)pic, pic->format, ref->w, ref->h);
58
59     memcpy(ref->data,     pic->data,     sizeof(pic->data));
60     memcpy(ref->linesize, pic->linesize, sizeof(pic->linesize));
61
62     return ref;
63 }
64
65 void avfilter_default_start_frame(AVFilterLink *link, AVFilterPicRef *picref)
66 {
67     AVFilterLink *out = NULL;
68
69     if(link->dst->output_count)
70         out = link->dst->outputs[0];
71
72     link->cur_pic = picref;
73
74     if(out) {
75         out->outpic      = avfilter_get_video_buffer(out, AV_PERM_WRITE);
76         out->outpic->pts = picref->pts;
77         avfilter_start_frame(out, avfilter_ref_pic(out->outpic, ~0));
78     }
79 }
80
81 void avfilter_default_end_frame(AVFilterLink *link)
82 {
83     AVFilterLink *out = NULL;
84
85     if(link->dst->output_count)
86         out = link->dst->outputs[0];
87
88     avfilter_unref_pic(link->cur_pic);
89     link->cur_pic = NULL;
90
91     if(out) {
92         avfilter_unref_pic(out->outpic);
93         out->outpic = NULL;
94         avfilter_end_frame(out);
95     }
96 }
97
98 AVFilterPicRef *avfilter_ref_pic(AVFilterPicRef *ref, int pmask)
99 {
100     AVFilterPicRef *ret = av_malloc(sizeof(AVFilterPicRef));
101     memcpy(ret, ref, sizeof(AVFilterPicRef));
102     ret->perms &= pmask;
103     ret->pic->refcount ++;
104     return ret;
105 }
106
107 void avfilter_unref_pic(AVFilterPicRef *ref)
108 {
109     if(-- ref->pic->refcount == 0)
110         ref->pic->free(ref->pic);
111     av_free(ref);
112 }
113
114 /**
115  * default config_link() implementation for output video links to simplify
116  * the implementation of one input one output video filters */
117 static int default_config_output_link(AVFilterLink *link)
118 {
119     if(link->src->input_count && link->src->inputs[0]) {
120     link->w = link->src->inputs[0]->w;
121     link->h = link->src->inputs[0]->h;
122     } else {
123         /* XXX: any non-simple filter which would cause this branch to be taken
124          * really should implement its own config_props() for this link. */
125         link->w =
126         link->h = 0;
127     }
128
129     return 0;
130 }
131
132 /**
133  * default query_formats() implementation for output video links to simplify
134  * the implementation of one input one output video filters */
135 static int *default_query_output_formats(AVFilterLink *link)
136 {
137     if(link->src->input_count && link->src->inputs[0])
138     return avfilter_make_format_list(1, link->src->inputs[0]->format);
139     else
140         /* XXX: any non-simple filter which would cause this branch to be taken
141          * really should implement its own query_formats() for this link */
142         return avfilter_make_format_list(0);
143 }
144
145 int avfilter_link(AVFilterContext *src, unsigned srcpad,
146                   AVFilterContext *dst, unsigned dstpad)
147 {
148     AVFilterLink *link;
149     int *fmts[2], i, j;
150
151     if(src->output_count <= srcpad || dst->input_count <= dstpad ||
152        src->outputs[srcpad]        || dst->inputs[dstpad])
153         return -1;
154
155     src->outputs[srcpad] =
156     dst->inputs[dstpad]  = link = av_malloc(sizeof(AVFilterLink));
157
158     link->src     = src;
159     link->dst     = dst;
160     link->srcpad  = srcpad;
161     link->dstpad  = dstpad;
162     link->cur_pic = NULL;
163
164     /* find a format both filters support - TODO: auto-insert conversion filter */
165     link->format = -1;
166     if(src->filter->outputs[srcpad].query_formats)
167         fmts[0] = src->filter->outputs[srcpad].query_formats(link);
168     else
169         fmts[0] = default_query_output_formats(link);
170     fmts[1] = dst->filter-> inputs[dstpad].query_formats(link);
171     for(i = 0; fmts[0][i] != -1; i ++)
172         for(j = 0; fmts[1][j] != -1; j ++)
173             if(fmts[0][i] == fmts[1][j]) {
174                 link->format = fmts[0][i];
175                 goto format_done;
176             }
177
178 format_done:
179     av_free(fmts[0]);
180     av_free(fmts[1]);
181     if(link->format == -1) {
182         /* failed to find a format.  fail at creating the link */
183         av_free(link);
184         src->outputs[srcpad] = NULL;
185         dst->inputs[dstpad]  = NULL;
186         return -1;
187     }
188
189     if (src->filter->outputs[srcpad].config_props)
190         src->filter->outputs[srcpad].config_props(link);
191     else
192         default_config_output_link(link);
193
194     if (dst->filter->inputs[dstpad].config_props)
195         dst->filter->inputs[dstpad].config_props(link);
196
197     return 0;
198 }
199
200 AVFilterPicRef *avfilter_get_video_buffer(AVFilterLink *link, int perms)
201 {
202     AVFilterPicRef *ret = NULL;
203
204     if(link->dst->filter->inputs[link->dstpad].get_video_buffer)
205         ret = link->dst->filter->inputs[link->dstpad].get_video_buffer(link, perms);
206
207     if(!ret)
208         ret = avfilter_default_get_video_buffer(link, perms);
209
210     return ret;
211 }
212
213 void avfilter_request_frame(AVFilterLink *link)
214 {
215     const AVFilterPad *pad = &link->src->filter->outputs[link->srcpad];
216
217     if(pad->request_frame)
218         pad->request_frame(link);
219     else if(link->src->inputs[0])
220         avfilter_request_frame(link->src->inputs[0]);
221 }
222
223 /* XXX: should we do the duplicating of the picture ref here, instead of
224  * forcing the source filter to do it? */
225 void avfilter_start_frame(AVFilterLink *link, AVFilterPicRef *picref)
226 {
227     void (*start_frame)(AVFilterLink *, AVFilterPicRef *);
228
229     start_frame = link->dst->filter->inputs[link->dstpad].start_frame;
230     if(!start_frame)
231         start_frame = avfilter_default_start_frame;
232
233     start_frame(link, picref);
234 }
235
236 void avfilter_end_frame(AVFilterLink *link)
237 {
238     void (*end_frame)(AVFilterLink *);
239
240     end_frame = link->dst->filter->inputs[link->dstpad].end_frame;
241     if(!end_frame)
242         end_frame = avfilter_default_end_frame;
243
244     end_frame(link);
245 }
246
247 void avfilter_draw_slice(AVFilterLink *link, uint8_t *data[4], int y, int h)
248 {
249     if(!link->dst->filter->inputs[link->dstpad].draw_slice)
250         return;
251
252     link->dst->filter->inputs[link->dstpad].draw_slice(link, data, y, h);
253 }
254
255 static int filter_cmp(const void *aa, const void *bb)
256 {
257     const AVFilter *a = *(const AVFilter **)aa, *b = *(const AVFilter **)bb;
258     return strcmp(a->name, b->name);
259 }
260
261 AVFilter *avfilter_get_by_name(char *name)
262 {
263     AVFilter key = { .name = name, };
264     AVFilter *key2 = &key;
265     AVFilter **ret;
266
267     ret = bsearch(&key2, filters, filter_count, sizeof(AVFilter **), filter_cmp);
268     if(ret)
269         return *ret;
270     return NULL;
271 }
272
273 /* FIXME: insert in order, rather than insert at end + resort */
274 void avfilter_register(AVFilter *filter)
275 {
276     filters = av_realloc(filters, sizeof(AVFilter*) * (filter_count+1));
277     filters[filter_count] = filter;
278     qsort(filters, ++filter_count, sizeof(AVFilter **), filter_cmp);
279 }
280
281 void avfilter_init(void)
282 {
283     avfilter_register(&vsrc_dummy);
284     avfilter_register(&vsrc_ppm);
285     avfilter_register(&vf_crop);
286     avfilter_register(&vf_passthrough);
287     avfilter_register(&vf_rgb2bgr);
288     avfilter_register(&vf_slicify);
289     avfilter_register(&vo_sdl);
290 }
291
292 void avfilter_uninit(void)
293 {
294     av_freep(&filters);
295     filter_count = 0;
296 }
297
298 static int pad_count(const AVFilterPad *pads)
299 {
300     AVFilterPad *p = (AVFilterPad *) pads;
301     int count;
302
303     for(count = 0; p->name; count ++) p ++;
304     return count;
305 }
306
307 static const char *filter_name(void *p)
308 {
309     AVFilterContext *filter = p;
310     return filter->filter->name;
311 }
312
313 AVFilterContext *avfilter_create(AVFilter *filter, char *inst_name)
314 {
315     AVFilterContext *ret = av_malloc(sizeof(AVFilterContext));
316
317     ret->av_class = av_mallocz(sizeof(AVClass));
318     ret->av_class->item_name = filter_name;
319     ret->filter   = filter;
320     ret->name     = inst_name ? av_strdup(inst_name) : NULL;
321     ret->priv     = av_mallocz(filter->priv_size);
322
323     ret->input_count  = pad_count(filter->inputs);
324     ret->inputs       = av_mallocz(sizeof(AVFilterLink*) * ret->input_count);
325     ret->output_count = pad_count(filter->outputs);
326     ret->outputs      = av_mallocz(sizeof(AVFilterLink*) * ret->output_count);
327
328     return ret;
329 }
330
331 void avfilter_destroy(AVFilterContext *filter)
332 {
333     int i;
334
335     if(filter->filter->uninit)
336         filter->filter->uninit(filter);
337
338     for(i = 0; i < pad_count(filter->filter->inputs); i ++) {
339         if(filter->inputs[i])
340             filter->inputs[i]->src->outputs[filter->inputs[i]->srcpad] = NULL;
341         av_free(filter->inputs[i]);
342     }
343     for(i = 0; i < pad_count(filter->filter->outputs); i ++) {
344         if(filter->outputs[i])
345             filter->outputs[i]->dst->inputs[filter->outputs[i]->dstpad] = NULL;
346         av_free(filter->outputs[i]);
347     }
348
349     av_free(filter->name);
350     av_free(filter->inputs);
351     av_free(filter->outputs);
352     av_free(filter->priv);
353     av_free(filter->av_class);
354     av_free(filter);
355 }
356
357 AVFilterContext *avfilter_create_by_name(char *name, char *inst_name)
358 {
359     AVFilter *filt;
360
361     if(!(filt = avfilter_get_by_name(name))) return NULL;
362     return avfilter_create(filt, inst_name);
363 }
364
365 int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque)
366 {
367     int ret, i;
368
369     if(filter->filter->init)
370         if((ret = filter->filter->init(filter, args, opaque))) return ret;
371     return 0;
372 }
373
374 int *avfilter_make_format_list(int len, ...)
375 {
376     int *ret, i;
377     va_list vl;
378
379     ret = av_malloc(sizeof(int) * (len + 1));
380     va_start(vl, len);
381     for(i = 0; i < len; i ++)
382         ret[i] = va_arg(vl, int);
383     va_end(vl);
384     ret[len] = -1;
385
386     return ret;
387 }
388