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
22 #include "libavcodec/imgconvert.h"
25 unsigned avfilter_version(void) {
26 return LIBAVFILTER_VERSION_INT
;
29 /** list of registered filters */
33 struct FilterList
*next
;
36 /** helper macros to get the in/out pad on the dst/src filter */
37 #define link_dpad(link) link->dst-> input_pads[link->dstpad]
38 #define link_spad(link) link->src->output_pads[link->srcpad]
40 AVFilterPicRef
*avfilter_ref_pic(AVFilterPicRef
*ref
, int pmask
)
42 AVFilterPicRef
*ret
= av_malloc(sizeof(AVFilterPicRef
));
45 ret
->pic
->refcount
++;
49 void avfilter_unref_pic(AVFilterPicRef
*ref
)
51 if(!(--ref
->pic
->refcount
))
52 ref
->pic
->free(ref
->pic
);
56 void avfilter_insert_pad(unsigned idx
, unsigned *count
, size_t padidx_off
,
57 AVFilterPad
**pads
, AVFilterLink
***links
,
62 idx
= FFMIN(idx
, *count
);
64 *pads
= av_realloc(*pads
, sizeof(AVFilterPad
) * (*count
+ 1));
65 *links
= av_realloc(*links
, sizeof(AVFilterLink
*) * (*count
+ 1));
66 memmove(*pads
+idx
+1, *pads
+idx
, sizeof(AVFilterPad
) * (*count
-idx
));
67 memmove(*links
+idx
+1, *links
+idx
, sizeof(AVFilterLink
*) * (*count
-idx
));
68 memcpy(*pads
+idx
, newpad
, sizeof(AVFilterPad
));
72 for(i
= idx
+1; i
< *count
; i
++)
74 (*(unsigned *)((uint8_t *) *links
[i
] + padidx_off
)) ++;
77 int avfilter_link(AVFilterContext
*src
, unsigned srcpad
,
78 AVFilterContext
*dst
, unsigned dstpad
)
82 if(src
->output_count
<= srcpad
|| dst
->input_count
<= dstpad
||
83 src
->outputs
[srcpad
] || dst
->inputs
[dstpad
])
86 src
->outputs
[srcpad
] =
87 dst
-> inputs
[dstpad
] = link
= av_mallocz(sizeof(AVFilterLink
));
91 link
->srcpad
= srcpad
;
92 link
->dstpad
= dstpad
;
93 link
->format
= PIX_FMT_NONE
;
98 int avfilter_insert_filter(AVFilterLink
*link
, AVFilterContext
*filt
,
99 unsigned in
, unsigned out
)
101 av_log(link
->dst
, AV_LOG_INFO
, "auto-inserting filter '%s'\n",
104 link
->dst
->inputs
[link
->dstpad
] = NULL
;
105 if(avfilter_link(filt
, out
, link
->dst
, link
->dstpad
)) {
106 /* failed to link output filter to new filter */
107 link
->dst
->inputs
[link
->dstpad
] = link
;
111 /* re-hookup the link to the new destination filter we inserted */
114 filt
->inputs
[in
] = link
;
116 /* if any information on supported colorspaces already exists on the
117 * link, we need to preserve that */
118 if(link
->out_formats
)
119 avfilter_formats_changeref(&link
->out_formats
,
120 &filt
->outputs
[out
]->out_formats
);
125 int avfilter_config_links(AVFilterContext
*filter
)
127 int (*config_link
)(AVFilterLink
*);
130 for(i
= 0; i
< filter
->input_count
; i
++) {
131 AVFilterLink
*link
= filter
->inputs
[i
];
135 switch(link
->init_state
) {
138 case AVLINK_STARTINIT
:
139 av_log(filter
, AV_LOG_INFO
, "circular filter chain detected\n");
142 link
->init_state
= AVLINK_STARTINIT
;
144 if(avfilter_config_links(link
->src
))
147 if(!(config_link
= link_spad(link
).config_props
))
148 config_link
= avfilter_default_config_output_link
;
149 if(config_link(link
))
152 if((config_link
= link_dpad(link
).config_props
))
153 if(config_link(link
))
156 link
->init_state
= AVLINK_INIT
;
163 AVFilterPicRef
*avfilter_get_video_buffer(AVFilterLink
*link
, int perms
)
165 AVFilterPicRef
*ret
= NULL
;
167 if(link_dpad(link
).get_video_buffer
)
168 ret
= link_dpad(link
).get_video_buffer(link
, perms
);
171 ret
= avfilter_default_get_video_buffer(link
, perms
);
176 int avfilter_request_frame(AVFilterLink
*link
)
178 if(link_spad(link
).request_frame
)
179 return link_spad(link
).request_frame(link
);
180 else if(link
->src
->inputs
[0])
181 return avfilter_request_frame(link
->src
->inputs
[0]);
185 int avfilter_poll_frame(AVFilterLink
*link
)
189 if(link_spad(link
).poll_frame
)
190 return link_spad(link
).poll_frame(link
);
192 for (i
=0; i
<link
->src
->input_count
; i
++) {
193 if(!link
->src
->inputs
[i
])
195 min
= FFMIN(min
, avfilter_poll_frame(link
->src
->inputs
[i
]));
201 /* XXX: should we do the duplicating of the picture ref here, instead of
202 * forcing the source filter to do it? */
203 void avfilter_start_frame(AVFilterLink
*link
, AVFilterPicRef
*picref
)
205 void (*start_frame
)(AVFilterLink
*, AVFilterPicRef
*);
206 AVFilterPad
*dst
= &link_dpad(link
);
208 if(!(start_frame
= dst
->start_frame
))
209 start_frame
= avfilter_default_start_frame
;
211 /* prepare to copy the picture if it has insufficient permissions */
212 if((dst
->min_perms
& picref
->perms
) != dst
->min_perms
||
213 dst
->rej_perms
& picref
->perms
) {
215 av_log(link->dst, AV_LOG_INFO,
216 "frame copy needed (have perms %x, need %x, reject %x)\n",
218 link_dpad(link).min_perms, link_dpad(link).rej_perms);
221 link
->cur_pic
= avfilter_default_get_video_buffer(link
, dst
->min_perms
);
222 link
->srcpic
= picref
;
223 link
->cur_pic
->pts
= link
->srcpic
->pts
;
226 link
->cur_pic
= picref
;
228 start_frame(link
, link
->cur_pic
);
231 void avfilter_end_frame(AVFilterLink
*link
)
233 void (*end_frame
)(AVFilterLink
*);
235 if(!(end_frame
= link_dpad(link
).end_frame
))
236 end_frame
= avfilter_default_end_frame
;
240 /* unreference the source picture if we're feeding the destination filter
241 * a copied version dues to permission issues */
243 avfilter_unref_pic(link
->srcpic
);
249 void avfilter_draw_slice(AVFilterLink
*link
, int y
, int h
)
251 uint8_t *src
[4], *dst
[4];
252 int i
, j
, hsub
, vsub
;
254 /* copy the slice if needed for permission reasons */
256 avcodec_get_chroma_sub_sample(link
->format
, &hsub
, &vsub
);
258 for(i
= 0; i
< 4; i
++) {
259 if(link
->srcpic
->data
[i
]) {
260 src
[i
] = link
->srcpic
-> data
[i
] +
261 (y
>> (i
==0 ? 0 : vsub
)) * link
->srcpic
-> linesize
[i
];
262 dst
[i
] = link
->cur_pic
->data
[i
] +
263 (y
>> (i
==0 ? 0 : vsub
)) * link
->cur_pic
->linesize
[i
];
265 src
[i
] = dst
[i
] = NULL
;
268 for(i
= 0; i
< 4; i
++) {
270 ff_get_plane_bytewidth(link
->format
, link
->cur_pic
->w
, i
);
272 if(!src
[i
]) continue;
274 for(j
= 0; j
< h
>> (i
==0 ? 0 : vsub
); j
++) {
275 memcpy(dst
[i
], src
[i
], planew
);
276 src
[i
] += link
->srcpic
->linesize
[i
];
277 dst
[i
] += link
->cur_pic
->linesize
[i
];
282 if(link_dpad(link
).draw_slice
)
283 link_dpad(link
).draw_slice(link
, y
, h
);
286 AVFilter
*avfilter_get_by_name(const char *name
)
288 struct FilterList
*filt
;
290 for(filt
= filters
; filt
; filt
= filt
->next
)
291 if(!strcmp(filt
->filter
->name
, name
))
297 void avfilter_register(AVFilter
*filter
)
299 struct FilterList
*newfilt
= av_malloc(sizeof(struct FilterList
));
301 newfilt
->filter
= filter
;
302 newfilt
->next
= filters
;
306 void avfilter_uninit(void)
308 struct FilterList
*tmp
;
310 for(; filters
; filters
= tmp
) {
316 static int pad_count(const AVFilterPad
*pads
)
320 for(count
= 0; pads
->name
; count
++) pads
++;
324 static const char *filter_name(void *p
)
326 AVFilterContext
*filter
= p
;
327 return filter
->filter
->name
;
330 static const AVClass avfilter_class
= {
335 AVFilterContext
*avfilter_open(AVFilter
*filter
, const char *inst_name
)
337 AVFilterContext
*ret
;
342 ret
= av_malloc(sizeof(AVFilterContext
));
344 ret
->av_class
= &avfilter_class
;
345 ret
->filter
= filter
;
346 ret
->name
= inst_name
? av_strdup(inst_name
) : NULL
;
347 ret
->priv
= av_mallocz(filter
->priv_size
);
349 ret
->input_count
= pad_count(filter
->inputs
);
350 ret
->input_pads
= av_malloc(sizeof(AVFilterPad
) * ret
->input_count
);
351 memcpy(ret
->input_pads
, filter
->inputs
, sizeof(AVFilterPad
)*ret
->input_count
);
352 ret
->inputs
= av_mallocz(sizeof(AVFilterLink
*) * ret
->input_count
);
354 ret
->output_count
= pad_count(filter
->outputs
);
355 ret
->output_pads
= av_malloc(sizeof(AVFilterPad
) * ret
->output_count
);
356 memcpy(ret
->output_pads
, filter
->outputs
, sizeof(AVFilterPad
)*ret
->output_count
);
357 ret
->outputs
= av_mallocz(sizeof(AVFilterLink
*) * ret
->output_count
);
362 void avfilter_destroy(AVFilterContext
*filter
)
366 if(filter
->filter
->uninit
)
367 filter
->filter
->uninit(filter
);
369 for(i
= 0; i
< filter
->input_count
; i
++) {
370 if(filter
->inputs
[i
])
371 filter
->inputs
[i
]->src
->outputs
[filter
->inputs
[i
]->srcpad
] = NULL
;
372 av_freep(&filter
->inputs
[i
]);
374 for(i
= 0; i
< filter
->output_count
; i
++) {
375 if(filter
->outputs
[i
])
376 filter
->outputs
[i
]->dst
->inputs
[filter
->outputs
[i
]->dstpad
] = NULL
;
377 av_freep(&filter
->outputs
[i
]);
380 av_freep(&filter
->name
);
381 av_freep(&filter
->input_pads
);
382 av_freep(&filter
->output_pads
);
383 av_freep(&filter
->inputs
);
384 av_freep(&filter
->outputs
);
385 av_freep(&filter
->priv
);
389 int avfilter_init_filter(AVFilterContext
*filter
, const char *args
, void *opaque
)
393 if(filter
->filter
->init
)
394 ret
= filter
->filter
->init(filter
, args
, opaque
);