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
28 #include "allfilters.h"
30 /** list of registered filters */
34 struct FilterList
*next
;
37 /** helper macros to get the in/out pad on the dst/src filter */
38 #define link_dpad(link) link->dst-> input_pads[link->dstpad]
39 #define link_spad(link) link->src->output_pads[link->srcpad]
41 AVFilterPicRef
*avfilter_ref_pic(AVFilterPicRef
*ref
, int pmask
)
43 AVFilterPicRef
*ret
= av_malloc(sizeof(AVFilterPicRef
));
46 ret
->pic
->refcount
++;
50 void avfilter_unref_pic(AVFilterPicRef
*ref
)
52 if(-- ref
->pic
->refcount
== 0)
53 ref
->pic
->free(ref
->pic
);
57 void avfilter_insert_pad(unsigned idx
, unsigned *count
, size_t padidx_off
,
58 AVFilterPad
**pads
, AVFilterLink
***links
,
63 idx
= FFMIN(idx
, *count
);
65 *pads
= av_realloc(*pads
, sizeof(AVFilterPad
) * (*count
+ 1));
66 *links
= av_realloc(*links
, sizeof(AVFilterLink
*) * (*count
+ 1));
67 memmove(*pads
+idx
+1, *pads
+idx
, sizeof(AVFilterPad
) * (*count
-idx
));
68 memmove(*links
+idx
+1, *links
+idx
, sizeof(AVFilterLink
*) * (*count
-idx
));
69 memcpy(*pads
+idx
, newpad
, sizeof(AVFilterPad
));
73 for(i
= idx
+1; i
< *count
; i
++)
75 (*(unsigned *)((uint8_t *)(*links
[i
]) + padidx_off
)) ++;
78 int avfilter_link(AVFilterContext
*src
, unsigned srcpad
,
79 AVFilterContext
*dst
, unsigned dstpad
)
83 if(src
->output_count
<= srcpad
|| dst
->input_count
<= dstpad
||
84 src
->outputs
[srcpad
] || dst
->inputs
[dstpad
])
87 src
->outputs
[srcpad
] =
88 dst
->inputs
[dstpad
] = link
= av_mallocz(sizeof(AVFilterLink
));
92 link
->srcpad
= srcpad
;
93 link
->dstpad
= dstpad
;
99 static int common_format(int *fmts0
, int *fmts1
)
103 for(i
= 0; fmts0
[i
] != -1; i
++)
104 for(j
= 0; fmts1
[j
] != -1; j
++)
105 if(fmts0
[i
] == fmts1
[j
])
111 int avfilter_config_link(AVFilterLink
*link
)
113 int *fmts
[3] = {NULL
,NULL
,NULL
};
114 int (*config_link
)(AVFilterLink
*);
115 int *(*query_formats
)(AVFilterLink
*link
);
117 AVFilterContext
*scale
;
118 AVFilterLink
*link2
= NULL
;
123 /* find a format both filters support */
124 if(!(query_formats
= link_spad(link
).query_formats
))
125 query_formats
= avfilter_default_query_output_formats
;
126 fmts
[0] = query_formats(link
);
127 fmts
[1] = link_dpad(link
).query_formats(link
);
128 if((link
->format
= common_format(fmts
[0], fmts
[1])) == -1) {
129 /* no common format found. insert scale filter to convert */
130 if(!(scale
= avfilter_open(&avfilter_vf_scale
, NULL
)))
132 if(scale
->filter
->init(scale
, NULL
, NULL
)) {
133 avfilter_destroy(scale
);
137 link
->dst
->inputs
[link
->dstpad
] = NULL
;
138 if(avfilter_link(scale
, 0, link
->dst
, link
->dstpad
)) {
139 link
->dst
->inputs
[link
->dstpad
] = link
;
142 link2
= scale
->outputs
[0];
145 scale
->inputs
[0] = link
;
147 /* now try again to find working colorspaces.
148 * XXX: is it safe to assume that the scale filter always supports the
149 * same input and output colorspaces? */
150 fmts
[2] = scale
->input_pads
[0].query_formats(link
);
151 link
->format
= common_format(fmts
[0], fmts
[2]);
152 link2
->format
= common_format(fmts
[1], fmts
[2]);
159 if(link
->format
== -1 || (link2
&& link2
->format
== -1)) {
161 link
->dst
= link2
->dst
;
162 link
->dstpad
= link2
->dstpad
;
163 link
->dst
->inputs
[link
->dstpad
] = link
;
165 avfilter_destroy(scale
);
171 if(!(config_link
= link_spad(link
).config_props
))
172 config_link
= avfilter_default_config_output_link
;
173 if(config_link(link
))
176 if(!(config_link
= link_dpad(link
).config_props
))
177 config_link
= avfilter_default_config_input_link
;
178 if(config_link(link
))
182 if(!(config_link
= link_spad(link2
).config_props
))
183 config_link
= avfilter_default_config_output_link
;
184 if(config_link(link2
))
187 if(!(config_link
= link_dpad(link2
).config_props
))
188 config_link
= avfilter_default_config_input_link
;
189 if(config_link(link2
))
196 AVFilterPicRef
*avfilter_get_video_buffer(AVFilterLink
*link
, int perms
)
198 AVFilterPicRef
*ret
= NULL
;
200 if(link_dpad(link
).get_video_buffer
)
201 ret
= link_dpad(link
).get_video_buffer(link
, perms
);
204 ret
= avfilter_default_get_video_buffer(link
, perms
);
209 int avfilter_request_frame(AVFilterLink
*link
)
211 if(link_spad(link
).request_frame
)
212 return link_spad(link
).request_frame(link
);
213 else if(link
->src
->inputs
[0])
214 return avfilter_request_frame(link
->src
->inputs
[0]);
218 /* XXX: should we do the duplicating of the picture ref here, instead of
219 * forcing the source filter to do it? */
220 void avfilter_start_frame(AVFilterLink
*link
, AVFilterPicRef
*picref
)
222 void (*start_frame
)(AVFilterLink
*, AVFilterPicRef
*);
224 if(!(start_frame
= link_dpad(link
).start_frame
))
225 start_frame
= avfilter_default_start_frame
;
227 /* prepare to copy the picture if it has insufficient permissions */
228 if((link_dpad(link
).min_perms
& picref
->perms
) != link_dpad(link
).min_perms
||
229 link_dpad(link
).rej_perms
& picref
->perms
) {
230 av_log(link
->dst
, AV_LOG_INFO
,
231 "frame copy needed (have perms %x, need %x, reject %x)\n",
233 link_dpad(link
).min_perms
, link_dpad(link
).rej_perms
);
235 link
->cur_pic
= avfilter_default_get_video_buffer(link
, link_dpad(link
).min_perms
);
236 link
->srcpic
= picref
;
239 link
->cur_pic
= picref
;
241 start_frame(link
, link
->cur_pic
);
244 void avfilter_end_frame(AVFilterLink
*link
)
246 void (*end_frame
)(AVFilterLink
*);
248 /* unreference the source picture if we're feeding the destination filter
249 * a copied version dues to permission issues */
251 avfilter_unref_pic(link
->srcpic
);
255 if(!(end_frame
= link_dpad(link
).end_frame
))
256 end_frame
= avfilter_default_end_frame
;
261 void avfilter_draw_slice(AVFilterLink
*link
, int y
, int h
)
263 uint8_t *src
[4], *dst
[4];
264 int i
, j
, hsub
, vsub
;
266 /* copy the slice if needed for permission reasons */
268 avcodec_get_chroma_sub_sample(link
->format
, &hsub
, &vsub
);
270 src
[0] = link
->srcpic
-> data
[0] + y
* link
->srcpic
-> linesize
[0];
271 dst
[0] = link
->cur_pic
->data
[0] + y
* link
->cur_pic
->linesize
[0];
272 for(i
= 1; i
< 4; i
++) {
273 if(link
->srcpic
->data
[i
]) {
274 src
[i
] = link
->srcpic
-> data
[i
] + (y
>> vsub
) * link
->srcpic
-> linesize
[i
];
275 dst
[i
] = link
->cur_pic
->data
[i
] + (y
>> vsub
) * link
->cur_pic
->linesize
[i
];
277 src
[i
] = dst
[i
] = NULL
;
279 for(j
= 0; j
< h
; j
++) {
280 memcpy(dst
[0], src
[0], link
->cur_pic
->linesize
[0]);
281 src
[0] += link
->srcpic
->linesize
[0];
282 dst
[0] += link
->cur_pic
->linesize
[0];
284 for(i
= 1; i
< 4; i
++) {
285 if(!src
[i
]) continue;
287 for(j
= 0; j
< h
>> vsub
; j
++) {
288 memcpy(dst
[i
], src
[i
], link
->cur_pic
->linesize
[i
]);
289 src
[i
] += link
->srcpic
->linesize
[i
];
290 dst
[i
] += link
->cur_pic
->linesize
[i
];
295 if(!link_dpad(link
).draw_slice
)
298 link_dpad(link
).draw_slice(link
, y
, h
);
301 AVFilter
*avfilter_get_by_name(char *name
)
303 struct FilterList
*filt
;
305 for(filt
= filters
; filt
; filt
= filt
->next
)
306 if(!strcmp(filt
->filter
->name
, name
))
312 /* FIXME: insert in order, rather than insert at end + resort */
313 void avfilter_register(AVFilter
*filter
)
315 struct FilterList
*newfilt
= av_malloc(sizeof(struct FilterList
));
317 newfilt
->filter
= filter
;
318 newfilt
->next
= filters
;
322 void avfilter_init(void)
324 avfilter_register(&avfilter_vf_crop
);
325 avfilter_register(&avfilter_vf_fifo
);
326 avfilter_register(&avfilter_vf_fps
);
327 avfilter_register(&avfilter_vf_graph
);
328 avfilter_register(&avfilter_vf_graphdesc
);
329 avfilter_register(&avfilter_vf_graphfile
);
330 avfilter_register(&avfilter_vf_negate
);
331 avfilter_register(&avfilter_vf_overlay
);
332 avfilter_register(&avfilter_vf_passthrough
);
333 avfilter_register(&avfilter_vf_scale
);
334 avfilter_register(&avfilter_vf_slicify
);
335 avfilter_register(&avfilter_vf_split
);
336 avfilter_register(&avfilter_vf_vflip
);
339 void avfilter_uninit(void)
341 struct FilterList
*tmp
;
343 for(; filters
; filters
= tmp
) {
349 static int pad_count(const AVFilterPad
*pads
)
351 AVFilterPad
*p
= (AVFilterPad
*) pads
;
354 for(count
= 0; p
->name
; count
++) p
++;
358 static const char *filter_name(void *p
)
360 AVFilterContext
*filter
= p
;
361 return filter
->filter
->name
;
364 AVFilterContext
*avfilter_open(AVFilter
*filter
, char *inst_name
)
366 AVFilterContext
*ret
;
371 ret
= av_malloc(sizeof(AVFilterContext
));
373 ret
->av_class
= av_mallocz(sizeof(AVClass
));
374 ret
->av_class
->item_name
= filter_name
;
375 ret
->filter
= filter
;
376 ret
->name
= inst_name ?
av_strdup(inst_name
) : NULL
;
377 ret
->priv
= av_mallocz(filter
->priv_size
);
379 ret
->input_count
= pad_count(filter
->inputs
);
380 ret
->input_pads
= av_malloc(sizeof(AVFilterPad
) * ret
->input_count
);
381 memcpy(ret
->input_pads
, filter
->inputs
, sizeof(AVFilterPad
)*ret
->input_count
);
382 ret
->inputs
= av_mallocz(sizeof(AVFilterLink
*) * ret
->input_count
);
384 ret
->output_count
= pad_count(filter
->outputs
);
385 ret
->output_pads
= av_malloc(sizeof(AVFilterPad
) * ret
->output_count
);
386 memcpy(ret
->output_pads
, filter
->outputs
, sizeof(AVFilterPad
)*ret
->output_count
);
387 ret
->outputs
= av_mallocz(sizeof(AVFilterLink
*) * ret
->output_count
);
392 void avfilter_destroy(AVFilterContext
*filter
)
396 if(filter
->filter
->uninit
)
397 filter
->filter
->uninit(filter
);
399 for(i
= 0; i
< filter
->input_count
; i
++) {
400 if(filter
->inputs
[i
])
401 filter
->inputs
[i
]->src
->outputs
[filter
->inputs
[i
]->srcpad
] = NULL
;
402 av_freep(&filter
->inputs
[i
]);
404 for(i
= 0; i
< filter
->output_count
; i
++) {
405 if(filter
->outputs
[i
])
406 filter
->outputs
[i
]->dst
->inputs
[filter
->outputs
[i
]->dstpad
] = NULL
;
407 av_freep(&filter
->outputs
[i
]);
410 av_freep(&filter
->name
);
411 av_freep(&filter
->input_pads
);
412 av_freep(&filter
->output_pads
);
413 av_freep(&filter
->inputs
);
414 av_freep(&filter
->outputs
);
415 av_freep(&filter
->priv
);
416 av_freep(&filter
->av_class
);
420 int avfilter_init_filter(AVFilterContext
*filter
, const char *args
, void *opaque
)
424 if(filter
->filter
->init
)
425 if((ret
= filter
->filter
->init(filter
, args
, opaque
))) return ret
;
429 int *avfilter_make_format_list(int len
, ...)
434 ret
= av_malloc(sizeof(int) * (len
+ 1));
436 for(i
= 0; i
< len
; i
++)
437 ret
[i
] = va_arg(vl
, int);