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 int avfilter_config_link(AVFilterLink
*link
)
102 int (*config_link
)(AVFilterLink
*);
103 int *(*query_formats
)(AVFilterLink
*link
);
108 /* find a format both filters support - TODO: auto-insert conversion filter */
110 if(!(query_formats
= link_spad(link
).query_formats
))
111 query_formats
= avfilter_default_query_output_formats
;
112 fmts
[0] = query_formats(link
);
113 fmts
[1] = link_dpad(link
).query_formats(link
);
114 for(i
= 0; fmts
[0][i
] != -1; i
++)
115 for(j
= 0; fmts
[1][j
] != -1; j
++)
116 if(fmts
[0][i
] == fmts
[1][j
]) {
117 link
->format
= fmts
[0][i
];
124 if(link
->format
== -1)
127 if(!(config_link
= link_spad(link
).config_props
))
128 config_link
= avfilter_default_config_output_link
;
129 if(config_link(link
))
132 if(!(config_link
= link_dpad(link
).config_props
))
133 config_link
= avfilter_default_config_input_link
;
134 if(config_link(link
))
140 AVFilterPicRef
*avfilter_get_video_buffer(AVFilterLink
*link
, int perms
)
142 AVFilterPicRef
*ret
= NULL
;
144 if(link_dpad(link
).get_video_buffer
)
145 ret
= link_dpad(link
).get_video_buffer(link
, perms
);
148 ret
= avfilter_default_get_video_buffer(link
, perms
);
153 int avfilter_request_frame(AVFilterLink
*link
)
155 if(link_spad(link
).request_frame
)
156 return link_spad(link
).request_frame(link
);
157 else if(link
->src
->inputs
[0])
158 return avfilter_request_frame(link
->src
->inputs
[0]);
162 /* XXX: should we do the duplicating of the picture ref here, instead of
163 * forcing the source filter to do it? */
164 void avfilter_start_frame(AVFilterLink
*link
, AVFilterPicRef
*picref
)
166 void (*start_frame
)(AVFilterLink
*, AVFilterPicRef
*);
168 if(!(start_frame
= link_dpad(link
).start_frame
))
169 start_frame
= avfilter_default_start_frame
;
171 /* prepare to copy the picture if it has insufficient permissions */
172 if((link_dpad(link
).min_perms
& picref
->perms
) != link_dpad(link
).min_perms
||
173 link_dpad(link
).rej_perms
& picref
->perms
) {
174 av_log(link
->dst
, AV_LOG_INFO
,
175 "frame copy needed (have perms %x, need %x, reject %x)\n",
177 link_dpad(link
).min_perms
, link_dpad(link
).rej_perms
);
179 link
->cur_pic
= avfilter_default_get_video_buffer(link
, link_dpad(link
).min_perms
);
180 link
->srcpic
= picref
;
183 link
->cur_pic
= picref
;
185 start_frame(link
, link
->cur_pic
);
188 void avfilter_end_frame(AVFilterLink
*link
)
190 void (*end_frame
)(AVFilterLink
*);
192 /* unreference the source picture if we're feeding the destination filter
193 * a copied version dues to permission issues */
195 avfilter_unref_pic(link
->srcpic
);
199 if(!(end_frame
= link_dpad(link
).end_frame
))
200 end_frame
= avfilter_default_end_frame
;
205 void avfilter_draw_slice(AVFilterLink
*link
, int y
, int h
)
207 uint8_t *src
[4], *dst
[4];
208 int i
, j
, hsub
, vsub
;
210 /* copy the slice if needed for permission reasons */
212 avcodec_get_chroma_sub_sample(link
->format
, &hsub
, &vsub
);
214 src
[0] = link
->srcpic
-> data
[0] + y
* link
->srcpic
-> linesize
[0];
215 dst
[0] = link
->cur_pic
->data
[0] + y
* link
->cur_pic
->linesize
[0];
216 for(i
= 1; i
< 4; i
++) {
217 if(link
->srcpic
->data
[i
]) {
218 src
[i
] = link
->srcpic
-> data
[i
] + (y
>> vsub
) * link
->srcpic
-> linesize
[i
];
219 dst
[i
] = link
->cur_pic
->data
[i
] + (y
>> vsub
) * link
->cur_pic
->linesize
[i
];
221 src
[i
] = dst
[i
] = NULL
;
223 for(j
= 0; j
< h
; j
++) {
224 memcpy(dst
[0], src
[0], link
->cur_pic
->linesize
[0]);
225 src
[0] += link
->srcpic
->linesize
[0];
226 dst
[0] += link
->cur_pic
->linesize
[0];
228 for(i
= 1; i
< 4; i
++) {
229 if(!src
[i
]) continue;
231 for(j
= 0; j
< h
>> vsub
; j
++) {
232 memcpy(dst
[i
], src
[i
], link
->cur_pic
->linesize
[i
]);
233 src
[i
] += link
->srcpic
->linesize
[i
];
234 dst
[i
] += link
->cur_pic
->linesize
[i
];
239 if(!link_dpad(link
).draw_slice
)
242 link_dpad(link
).draw_slice(link
, y
, h
);
245 AVFilter
*avfilter_get_by_name(char *name
)
247 struct FilterList
*filt
;
249 for(filt
= filters
; filt
; filt
= filt
->next
)
250 if(!strcmp(filt
->filter
->name
, name
))
256 /* FIXME: insert in order, rather than insert at end + resort */
257 void avfilter_register(AVFilter
*filter
)
259 struct FilterList
*newfilt
= av_malloc(sizeof(struct FilterList
));
261 newfilt
->filter
= filter
;
262 newfilt
->next
= filters
;
266 void avfilter_init(void)
268 avfilter_register(&vsrc_dummy
);
269 avfilter_register(&vsrc_ppm
);
270 avfilter_register(&vf_buffer
);
271 avfilter_register(&vf_crop
);
272 avfilter_register(&vf_fps
);
273 avfilter_register(&vf_graph
);
274 avfilter_register(&vf_graphdesc
);
275 avfilter_register(&vf_graphfile
);
276 avfilter_register(&vf_overlay
);
277 avfilter_register(&vf_passthrough
);
278 avfilter_register(&vf_rgb2bgr
);
279 avfilter_register(&vf_slicify
);
280 avfilter_register(&vf_vflip
);
283 void avfilter_uninit(void)
285 struct FilterList
*tmp
;
287 for(; filters
; filters
= tmp
) {
293 static int pad_count(const AVFilterPad
*pads
)
295 AVFilterPad
*p
= (AVFilterPad
*) pads
;
298 for(count
= 0; p
->name
; count
++) p
++;
302 static const char *filter_name(void *p
)
304 AVFilterContext
*filter
= p
;
305 return filter
->filter
->name
;
308 AVFilterContext
*avfilter_open(AVFilter
*filter
, char *inst_name
)
310 AVFilterContext
*ret
= av_malloc(sizeof(AVFilterContext
));
312 ret
->av_class
= av_mallocz(sizeof(AVClass
));
313 ret
->av_class
->item_name
= filter_name
;
314 ret
->filter
= filter
;
315 ret
->name
= inst_name ?
av_strdup(inst_name
) : NULL
;
316 ret
->priv
= av_mallocz(filter
->priv_size
);
318 ret
->input_count
= pad_count(filter
->inputs
);
319 ret
->input_pads
= av_malloc(sizeof(AVFilterPad
) * ret
->input_count
);
320 memcpy(ret
->input_pads
, filter
->inputs
, sizeof(AVFilterPad
)*ret
->input_count
);
321 ret
->inputs
= av_mallocz(sizeof(AVFilterLink
*) * ret
->input_count
);
323 ret
->output_count
= pad_count(filter
->outputs
);
324 ret
->output_pads
= av_malloc(sizeof(AVFilterPad
) * ret
->output_count
);
325 memcpy(ret
->output_pads
, filter
->outputs
, sizeof(AVFilterPad
)*ret
->output_count
);
326 ret
->outputs
= av_mallocz(sizeof(AVFilterLink
*) * ret
->output_count
);
331 void avfilter_destroy(AVFilterContext
*filter
)
335 if(filter
->filter
->uninit
)
336 filter
->filter
->uninit(filter
);
338 for(i
= 0; i
< filter
->input_count
; i
++) {
339 if(filter
->inputs
[i
])
340 filter
->inputs
[i
]->src
->outputs
[filter
->inputs
[i
]->srcpad
] = NULL
;
341 av_freep(&filter
->inputs
[i
]);
343 for(i
= 0; i
< filter
->output_count
; i
++) {
344 if(filter
->outputs
[i
])
345 filter
->outputs
[i
]->dst
->inputs
[filter
->outputs
[i
]->dstpad
] = NULL
;
346 av_freep(&filter
->outputs
[i
]);
349 av_freep(&filter
->name
);
350 av_freep(&filter
->input_pads
);
351 av_freep(&filter
->output_pads
);
352 av_freep(&filter
->inputs
);
353 av_freep(&filter
->outputs
);
354 av_freep(&filter
->priv
);
355 av_freep(&filter
->av_class
);
359 int avfilter_init_filter(AVFilterContext
*filter
, const char *args
, void *opaque
)
363 if(filter
->filter
->init
)
364 if((ret
= filter
->filter
->init(filter
, args
, opaque
))) return ret
;
368 int *avfilter_make_format_list(int len
, ...)
373 ret
= av_malloc(sizeof(int) * (len
+ 1));
375 for(i
= 0; i
< len
; i
++)
376 ret
[i
] = va_arg(vl
, int);