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
24 #include "libavcodec/imgconvert.h"
25 #include "libavutil/pixdesc.h"
28 unsigned avfilter_version(void) {
29 return LIBAVFILTER_VERSION_INT
;
32 const char *avfilter_configuration(void)
34 return FFMPEG_CONFIGURATION
;
37 const char *avfilter_license(void)
39 #define LICENSE_PREFIX "libavfilter license: "
40 return LICENSE_PREFIX FFMPEG_LICENSE
+ sizeof(LICENSE_PREFIX
) - 1;
43 /** helper macros to get the in/out pad on the dst/src filter */
44 #define link_dpad(link) link->dst-> input_pads[link->dstpad]
45 #define link_spad(link) link->src->output_pads[link->srcpad]
47 AVFilterPicRef
*avfilter_ref_pic(AVFilterPicRef
*ref
, int pmask
)
49 AVFilterPicRef
*ret
= av_malloc(sizeof(AVFilterPicRef
));
52 ret
->pic
->refcount
++;
56 void avfilter_unref_pic(AVFilterPicRef
*ref
)
58 if(!(--ref
->pic
->refcount
))
59 ref
->pic
->free(ref
->pic
);
63 void avfilter_insert_pad(unsigned idx
, unsigned *count
, size_t padidx_off
,
64 AVFilterPad
**pads
, AVFilterLink
***links
,
69 idx
= FFMIN(idx
, *count
);
71 *pads
= av_realloc(*pads
, sizeof(AVFilterPad
) * (*count
+ 1));
72 *links
= av_realloc(*links
, sizeof(AVFilterLink
*) * (*count
+ 1));
73 memmove(*pads
+idx
+1, *pads
+idx
, sizeof(AVFilterPad
) * (*count
-idx
));
74 memmove(*links
+idx
+1, *links
+idx
, sizeof(AVFilterLink
*) * (*count
-idx
));
75 memcpy(*pads
+idx
, newpad
, sizeof(AVFilterPad
));
79 for(i
= idx
+1; i
< *count
; i
++)
81 (*(unsigned *)((uint8_t *) *links
[i
] + padidx_off
)) ++;
84 int avfilter_link(AVFilterContext
*src
, unsigned srcpad
,
85 AVFilterContext
*dst
, unsigned dstpad
)
89 if(src
->output_count
<= srcpad
|| dst
->input_count
<= dstpad
||
90 src
->outputs
[srcpad
] || dst
->inputs
[dstpad
])
93 src
->outputs
[srcpad
] =
94 dst
-> inputs
[dstpad
] = link
= av_mallocz(sizeof(AVFilterLink
));
98 link
->srcpad
= srcpad
;
99 link
->dstpad
= dstpad
;
100 link
->format
= PIX_FMT_NONE
;
105 int avfilter_insert_filter(AVFilterLink
*link
, AVFilterContext
*filt
,
106 unsigned in
, unsigned out
)
108 av_log(link
->dst
, AV_LOG_INFO
, "auto-inserting filter '%s' "
109 "between the filter '%s' and the filter '%s'\n",
110 filt
->name
, link
->src
->name
, link
->dst
->name
);
112 link
->dst
->inputs
[link
->dstpad
] = NULL
;
113 if(avfilter_link(filt
, out
, link
->dst
, link
->dstpad
)) {
114 /* failed to link output filter to new filter */
115 link
->dst
->inputs
[link
->dstpad
] = link
;
119 /* re-hookup the link to the new destination filter we inserted */
122 filt
->inputs
[in
] = link
;
124 /* if any information on supported colorspaces already exists on the
125 * link, we need to preserve that */
126 if(link
->out_formats
)
127 avfilter_formats_changeref(&link
->out_formats
,
128 &filt
->outputs
[out
]->out_formats
);
133 int avfilter_config_links(AVFilterContext
*filter
)
135 int (*config_link
)(AVFilterLink
*);
138 for(i
= 0; i
< filter
->input_count
; i
++) {
139 AVFilterLink
*link
= filter
->inputs
[i
];
143 switch(link
->init_state
) {
146 case AVLINK_STARTINIT
:
147 av_log(filter
, AV_LOG_INFO
, "circular filter chain detected\n");
150 link
->init_state
= AVLINK_STARTINIT
;
152 if(avfilter_config_links(link
->src
))
155 if(!(config_link
= link_spad(link
).config_props
))
156 config_link
= avfilter_default_config_output_link
;
157 if(config_link(link
))
160 if((config_link
= link_dpad(link
).config_props
))
161 if(config_link(link
))
164 link
->init_state
= AVLINK_INIT
;
171 static void dprintf_picref(void *ctx
, AVFilterPicRef
*picref
, int end
)
174 "picref[%p data[%p, %p, %p, %p] linesize[%d, %d, %d, %d] pts:%"PRId64
" pos:%"PRId64
" a:%d/%d s:%dx%d]%s",
176 picref
->data
[0], picref
->data
[1], picref
->data
[2], picref
->data
[3],
177 picref
->linesize
[0], picref
->linesize
[1], picref
->linesize
[2], picref
->linesize
[3],
178 picref
->pts
, picref
->pos
,
179 picref
->pixel_aspect
.num
, picref
->pixel_aspect
.den
, picref
->w
, picref
->h
,
183 static void dprintf_link(void *ctx
, AVFilterLink
*link
, int end
)
186 "link[%p s:%dx%d fmt:%-16s %-16s->%-16s]%s",
187 link
, link
->w
, link
->h
,
188 av_pix_fmt_descriptors
[link
->format
].name
,
189 link
->src ? link
->src
->filter
->name
: "",
190 link
->dst ? link
->dst
->filter
->name
: "",
194 #define DPRINTF_START(ctx, func) dprintf(NULL, "%-16s: ", #func)
196 AVFilterPicRef
*avfilter_get_video_buffer(AVFilterLink
*link
, int perms
, int w
, int h
)
198 AVFilterPicRef
*ret
= NULL
;
200 DPRINTF_START(NULL
, get_video_buffer
); dprintf_link(NULL
, link
, 0); dprintf(NULL
, " perms:%d w:%d h:%d\n", perms
, w
, h
);
202 if(link_dpad(link
).get_video_buffer
)
203 ret
= link_dpad(link
).get_video_buffer(link
, perms
, w
, h
);
206 ret
= avfilter_default_get_video_buffer(link
, perms
, w
, h
);
208 DPRINTF_START(NULL
, get_video_buffer
); dprintf_link(NULL
, link
, 0); dprintf(NULL
, " returning "); dprintf_picref(NULL
, ret
, 1);
213 int avfilter_request_frame(AVFilterLink
*link
)
215 DPRINTF_START(NULL
, request_frame
); dprintf_link(NULL
, link
, 1);
217 if(link_spad(link
).request_frame
)
218 return link_spad(link
).request_frame(link
);
219 else if(link
->src
->inputs
[0])
220 return avfilter_request_frame(link
->src
->inputs
[0]);
224 int avfilter_poll_frame(AVFilterLink
*link
)
228 if(link_spad(link
).poll_frame
)
229 return link_spad(link
).poll_frame(link
);
231 for (i
=0; i
<link
->src
->input_count
; i
++) {
233 if(!link
->src
->inputs
[i
])
235 val
= avfilter_poll_frame(link
->src
->inputs
[i
]);
236 min
= FFMIN(min
, val
);
242 /* XXX: should we do the duplicating of the picture ref here, instead of
243 * forcing the source filter to do it? */
244 void avfilter_start_frame(AVFilterLink
*link
, AVFilterPicRef
*picref
)
246 void (*start_frame
)(AVFilterLink
*, AVFilterPicRef
*);
247 AVFilterPad
*dst
= &link_dpad(link
);
249 DPRINTF_START(NULL
, start_frame
); dprintf_link(NULL
, link
, 0); dprintf(NULL
, " "); dprintf_picref(NULL
, picref
, 1);
251 if(!(start_frame
= dst
->start_frame
))
252 start_frame
= avfilter_default_start_frame
;
254 /* prepare to copy the picture if it has insufficient permissions */
255 if((dst
->min_perms
& picref
->perms
) != dst
->min_perms
||
256 dst
->rej_perms
& picref
->perms
) {
258 av_log(link->dst, AV_LOG_INFO,
259 "frame copy needed (have perms %x, need %x, reject %x)\n",
261 link_dpad(link).min_perms, link_dpad(link).rej_perms);
264 link
->cur_pic
= avfilter_default_get_video_buffer(link
, dst
->min_perms
, link
->w
, link
->h
);
265 link
->srcpic
= picref
;
266 link
->cur_pic
->pts
= link
->srcpic
->pts
;
267 link
->cur_pic
->pos
= link
->srcpic
->pos
;
268 link
->cur_pic
->pixel_aspect
= link
->srcpic
->pixel_aspect
;
271 link
->cur_pic
= picref
;
273 start_frame(link
, link
->cur_pic
);
276 void avfilter_end_frame(AVFilterLink
*link
)
278 void (*end_frame
)(AVFilterLink
*);
280 if(!(end_frame
= link_dpad(link
).end_frame
))
281 end_frame
= avfilter_default_end_frame
;
285 /* unreference the source picture if we're feeding the destination filter
286 * a copied version dues to permission issues */
288 avfilter_unref_pic(link
->srcpic
);
294 void avfilter_draw_slice(AVFilterLink
*link
, int y
, int h
, int slice_dir
)
296 uint8_t *src
[4], *dst
[4];
298 void (*draw_slice
)(AVFilterLink
*, int, int, int);
300 DPRINTF_START(NULL
, draw_slice
); dprintf_link(NULL
, link
, 0); dprintf(NULL
, " y:%d h:%d dir:%d\n", y
, h
, slice_dir
);
302 /* copy the slice if needed for permission reasons */
304 vsub
= av_pix_fmt_descriptors
[link
->format
].log2_chroma_h
;
306 for(i
= 0; i
< 4; i
++) {
307 if(link
->srcpic
->data
[i
]) {
308 src
[i
] = link
->srcpic
-> data
[i
] +
309 (y
>> (i
==0 ?
0 : vsub
)) * link
->srcpic
-> linesize
[i
];
310 dst
[i
] = link
->cur_pic
->data
[i
] +
311 (y
>> (i
==0 ?
0 : vsub
)) * link
->cur_pic
->linesize
[i
];
313 src
[i
] = dst
[i
] = NULL
;
316 for(i
= 0; i
< 4; i
++) {
318 ff_get_plane_bytewidth(link
->format
, link
->cur_pic
->w
, i
);
320 if(!src
[i
]) continue;
322 for(j
= 0; j
< h
>> (i
==0 ?
0 : vsub
); j
++) {
323 memcpy(dst
[i
], src
[i
], planew
);
324 src
[i
] += link
->srcpic
->linesize
[i
];
325 dst
[i
] += link
->cur_pic
->linesize
[i
];
330 if(!(draw_slice
= link_dpad(link
).draw_slice
))
331 draw_slice
= avfilter_default_draw_slice
;
332 draw_slice(link
, y
, h
, slice_dir
);
335 #define MAX_REGISTERED_AVFILTERS_NB 64
337 static AVFilter
*registered_avfilters
[MAX_REGISTERED_AVFILTERS_NB
+ 1];
339 static int next_registered_avfilter_idx
= 0;
341 AVFilter
*avfilter_get_by_name(const char *name
)
345 for (i
= 0; registered_avfilters
[i
]; i
++)
346 if (!strcmp(registered_avfilters
[i
]->name
, name
))
347 return registered_avfilters
[i
];
352 int avfilter_register(AVFilter
*filter
)
354 if (next_registered_avfilter_idx
== MAX_REGISTERED_AVFILTERS_NB
)
357 registered_avfilters
[next_registered_avfilter_idx
++] = filter
;
361 AVFilter
**av_filter_next(AVFilter
**filter
)
363 return filter ?
++filter
: ®istered_avfilters
[0];
366 void avfilter_uninit(void)
368 memset(registered_avfilters
, 0, sizeof(registered_avfilters
));
369 next_registered_avfilter_idx
= 0;
372 static int pad_count(const AVFilterPad
*pads
)
376 for(count
= 0; pads
->name
; count
++) pads
++;
380 static const char *filter_name(void *p
)
382 AVFilterContext
*filter
= p
;
383 return filter
->filter
->name
;
386 static const AVClass avfilter_class
= {
390 LIBAVUTIL_VERSION_INT
,
393 AVFilterContext
*avfilter_open(AVFilter
*filter
, const char *inst_name
)
395 AVFilterContext
*ret
;
400 ret
= av_mallocz(sizeof(AVFilterContext
));
402 ret
->av_class
= &avfilter_class
;
403 ret
->filter
= filter
;
404 ret
->name
= inst_name ?
av_strdup(inst_name
) : NULL
;
405 ret
->priv
= av_mallocz(filter
->priv_size
);
407 ret
->input_count
= pad_count(filter
->inputs
);
408 if (ret
->input_count
) {
409 ret
->input_pads
= av_malloc(sizeof(AVFilterPad
) * ret
->input_count
);
410 memcpy(ret
->input_pads
, filter
->inputs
, sizeof(AVFilterPad
) * ret
->input_count
);
411 ret
->inputs
= av_mallocz(sizeof(AVFilterLink
*) * ret
->input_count
);
414 ret
->output_count
= pad_count(filter
->outputs
);
415 if (ret
->output_count
) {
416 ret
->output_pads
= av_malloc(sizeof(AVFilterPad
) * ret
->output_count
);
417 memcpy(ret
->output_pads
, filter
->outputs
, sizeof(AVFilterPad
) * ret
->output_count
);
418 ret
->outputs
= av_mallocz(sizeof(AVFilterLink
*) * ret
->output_count
);
424 void avfilter_destroy(AVFilterContext
*filter
)
428 if(filter
->filter
->uninit
)
429 filter
->filter
->uninit(filter
);
431 for(i
= 0; i
< filter
->input_count
; i
++) {
432 if(filter
->inputs
[i
])
433 filter
->inputs
[i
]->src
->outputs
[filter
->inputs
[i
]->srcpad
] = NULL
;
434 av_freep(&filter
->inputs
[i
]);
436 for(i
= 0; i
< filter
->output_count
; i
++) {
437 if(filter
->outputs
[i
])
438 filter
->outputs
[i
]->dst
->inputs
[filter
->outputs
[i
]->dstpad
] = NULL
;
439 av_freep(&filter
->outputs
[i
]);
442 av_freep(&filter
->name
);
443 av_freep(&filter
->input_pads
);
444 av_freep(&filter
->output_pads
);
445 av_freep(&filter
->inputs
);
446 av_freep(&filter
->outputs
);
447 av_freep(&filter
->priv
);
451 int avfilter_init_filter(AVFilterContext
*filter
, const char *args
, void *opaque
)
455 if(filter
->filter
->init
)
456 ret
= filter
->filter
->init(filter
, args
, opaque
);