X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Favfilter.c;h=0182e47018621613f7bbfa988f97124cbf505ce1;hb=8fb48e7c44feb1e6263228e0427ad66cf06fdc6e;hp=08007dc221d008ba0173fdcdbe5c5302373127d2;hpb=44b73497d31ffad6e0c89927006edeb58654fac3;p=ffmpeg diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 08007dc221d..0182e470186 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -1,5 +1,5 @@ /* - * Filter layer + * filter layer * copyright (c) 2007 Bobby Bingham * * This file is part of FFmpeg. @@ -19,13 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include -#include -#include - #include "avfilter.h" -#include "allfilters.h" +#include "imgconvert.h" /** list of registered filters */ struct FilterList @@ -49,7 +44,7 @@ AVFilterPicRef *avfilter_ref_pic(AVFilterPicRef *ref, int pmask) void avfilter_unref_pic(AVFilterPicRef *ref) { - if(-- ref->pic->refcount == 0) + if(!(--ref->pic->refcount)) ref->pic->free(ref->pic); av_free(ref); } @@ -72,7 +67,7 @@ void avfilter_insert_pad(unsigned idx, unsigned *count, size_t padidx_off, (*count) ++; for(i = idx+1; i < *count; i ++) if(*links[i]) - (*(unsigned *)((uint8_t *)(*links[i]) + padidx_off)) ++; + (*(unsigned *)((uint8_t *) *links[i] + padidx_off)) ++; } int avfilter_link(AVFilterContext *src, unsigned srcpad, @@ -85,7 +80,7 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, return -1; src->outputs[srcpad] = - dst->inputs[dstpad] = link = av_mallocz(sizeof(AVFilterLink)); + dst-> inputs[dstpad] = link = av_mallocz(sizeof(AVFilterLink)); link->src = src; link->dst = dst; @@ -96,43 +91,67 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, return 0; } -int avfilter_config_link(AVFilterLink *link) +int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, + unsigned in, unsigned out) +{ + av_log(link->dst, AV_LOG_INFO, "auto-inserting filter '%s'\n", + filt->filter->name); + + link->dst->inputs[link->dstpad] = NULL; + if(avfilter_link(filt, out, link->dst, link->dstpad)) { + /* failed to link output filter to new filter */ + link->dst->inputs[link->dstpad] = link; + return -1; + } + + /* re-hookup the link to the new destination filter we inserted */ + link->dst = filt; + link->dstpad = in; + filt->inputs[in] = link; + + /* if any information on supported colorspaces already exists on the + * link, we need to preserve that */ + if(link->out_formats) + avfilter_formats_changeref(&link->out_formats, + &filt->outputs[out]->out_formats); + + return 0; +} + +int avfilter_config_links(AVFilterContext *filter) { - int *fmts[2], i, j; int (*config_link)(AVFilterLink *); - int *(*query_formats)(AVFilterLink *link); + unsigned i; - if(!link) - return 0; + for(i = 0; i < filter->input_count; i ++) { + AVFilterLink *link = filter->inputs[i]; - /* find a format both filters support - TODO: auto-insert conversion filter */ - link->format = -1; - if(!(query_formats = link_spad(link).query_formats)) - query_formats = avfilter_default_query_output_formats; - fmts[0] = query_formats(link); - fmts[1] = link_dpad(link).query_formats(link); - for(i = 0; fmts[0][i] != -1; i ++) - for(j = 0; fmts[1][j] != -1; j ++) - if(fmts[0][i] == fmts[1][j]) { - link->format = fmts[0][i]; - goto format_done; - } + if(!link) continue; -format_done: - av_free(fmts[0]); - av_free(fmts[1]); - if(link->format == -1) - return -1; + switch(link->init_state) { + case AVLINK_INIT: + continue; + case AVLINK_STARTINIT: + av_log(filter, AV_LOG_INFO, "circular filter chain detected\n"); + return 0; + case AVLINK_UNINIT: + link->init_state = AVLINK_STARTINIT; - if(!(config_link = link_spad(link).config_props)) - config_link = avfilter_default_config_output_link; - if(config_link(link)) - return -1; + if(avfilter_config_links(link->src)) + return -1; - if(!(config_link = link_dpad(link).config_props)) - config_link = avfilter_default_config_input_link; - if(config_link(link)) - return -1; + if(!(config_link = link_spad(link).config_props)) + config_link = avfilter_default_config_output_link; + if(config_link(link)) + return -1; + + if((config_link = link_dpad(link).config_props)) + if(config_link(link)) + return -1; + + link->init_state = AVLINK_INIT; + } + } return 0; } @@ -159,25 +178,45 @@ int avfilter_request_frame(AVFilterLink *link) else return -1; } +int avfilter_poll_frame(AVFilterLink *link) +{ + int i, min=INT_MAX; + + if(link_spad(link).poll_frame) + return link_spad(link).poll_frame(link); + + for (i=0; isrc->input_count; i++) { + if(!link->src->inputs[i]) + return -1; + min = FFMIN(min, avfilter_poll_frame(link->src->inputs[i])); + } + + return min; +} + /* XXX: should we do the duplicating of the picture ref here, instead of * forcing the source filter to do it? */ void avfilter_start_frame(AVFilterLink *link, AVFilterPicRef *picref) { void (*start_frame)(AVFilterLink *, AVFilterPicRef *); + AVFilterPad *dst = &link_dpad(link); - if(!(start_frame = link_dpad(link).start_frame)) + if(!(start_frame = dst->start_frame)) start_frame = avfilter_default_start_frame; /* prepare to copy the picture if it has insufficient permissions */ - if((link_dpad(link).min_perms & picref->perms) != link_dpad(link).min_perms || - link_dpad(link).rej_perms & picref->perms) { + if((dst->min_perms & picref->perms) != dst->min_perms || + dst->rej_perms & picref->perms) { + /* av_log(link->dst, AV_LOG_INFO, "frame copy needed (have perms %x, need %x, reject %x)\n", picref->perms, link_dpad(link).min_perms, link_dpad(link).rej_perms); + */ - link->cur_pic = avfilter_default_get_video_buffer(link, link_dpad(link).min_perms); + link->cur_pic = avfilter_default_get_video_buffer(link, dst->min_perms); link->srcpic = picref; + link->cur_pic->pts = link->srcpic->pts; } else link->cur_pic = picref; @@ -189,6 +228,11 @@ void avfilter_end_frame(AVFilterLink *link) { void (*end_frame)(AVFilterLink *); + if(!(end_frame = link_dpad(link).end_frame)) + end_frame = avfilter_default_end_frame; + + end_frame(link); + /* unreference the source picture if we're feeding the destination filter * a copied version dues to permission issues */ if(link->srcpic) { @@ -196,10 +240,6 @@ void avfilter_end_frame(AVFilterLink *link) link->srcpic = NULL; } - if(!(end_frame = link_dpad(link).end_frame)) - end_frame = avfilter_default_end_frame; - - end_frame(link); } void avfilter_draw_slice(AVFilterLink *link, int y, int h) @@ -211,38 +251,35 @@ void avfilter_draw_slice(AVFilterLink *link, int y, int h) if(link->srcpic) { avcodec_get_chroma_sub_sample(link->format, &hsub, &vsub); - src[0] = link->srcpic-> data[0] + y * link->srcpic-> linesize[0]; - dst[0] = link->cur_pic->data[0] + y * link->cur_pic->linesize[0]; - for(i = 1; i < 4; i ++) { + for(i = 0; i < 4; i ++) { if(link->srcpic->data[i]) { - src[i] = link->srcpic-> data[i] + (y >> vsub) * link->srcpic-> linesize[i]; - dst[i] = link->cur_pic->data[i] + (y >> vsub) * link->cur_pic->linesize[i]; + src[i] = link->srcpic-> data[i] + + (y >> (i==0 ? 0 : vsub)) * link->srcpic-> linesize[i]; + dst[i] = link->cur_pic->data[i] + + (y >> (i==0 ? 0 : vsub)) * link->cur_pic->linesize[i]; } else src[i] = dst[i] = NULL; } - for(j = 0; j < h; j ++) { - memcpy(dst[0], src[0], link->cur_pic->linesize[0]); - src[0] += link->srcpic ->linesize[0]; - dst[0] += link->cur_pic->linesize[0]; - } - for(i = 1; i < 4; i ++) { + + for(i = 0; i < 4; i ++) { + int planew = + ff_get_plane_bytewidth(link->format, link->cur_pic->w, i); + if(!src[i]) continue; - for(j = 0; j < h >> vsub; j ++) { - memcpy(dst[i], src[i], link->cur_pic->linesize[i]); + for(j = 0; j < h >> (i==0 ? 0 : vsub); j ++) { + memcpy(dst[i], src[i], planew); src[i] += link->srcpic ->linesize[i]; dst[i] += link->cur_pic->linesize[i]; } } } - if(!link_dpad(link).draw_slice) - return; - - link_dpad(link).draw_slice(link, y, h); + if(link_dpad(link).draw_slice) + link_dpad(link).draw_slice(link, y, h); } -AVFilter *avfilter_get_by_name(char *name) +AVFilter *avfilter_get_by_name(const char *name) { struct FilterList *filt; @@ -253,7 +290,6 @@ AVFilter *avfilter_get_by_name(char *name) return NULL; } -/* FIXME: insert in order, rather than insert at end + resort */ void avfilter_register(AVFilter *filter) { struct FilterList *newfilt = av_malloc(sizeof(struct FilterList)); @@ -263,22 +299,6 @@ void avfilter_register(AVFilter *filter) filters = newfilt; } -void avfilter_init(void) -{ - avfilter_register(&vsrc_dummy); - avfilter_register(&vsrc_ppm); - avfilter_register(&vf_crop); - avfilter_register(&vf_fps); - avfilter_register(&vf_graph); - avfilter_register(&vf_graphdesc); - avfilter_register(&vf_graphfile); - avfilter_register(&vf_overlay); - avfilter_register(&vf_passthrough); - avfilter_register(&vf_rgb2bgr); - avfilter_register(&vf_slicify); - avfilter_register(&vf_vflip); -} - void avfilter_uninit(void) { struct FilterList *tmp; @@ -291,10 +311,9 @@ void avfilter_uninit(void) static int pad_count(const AVFilterPad *pads) { - AVFilterPad *p = (AVFilterPad *) pads; int count; - for(count = 0; p->name; count ++) p ++; + for(count = 0; pads->name; count ++) pads ++; return count; } @@ -304,9 +323,14 @@ static const char *filter_name(void *p) return filter->filter->name; } -AVFilterContext *avfilter_open(AVFilter *filter, char *inst_name) +AVFilterContext *avfilter_open(AVFilter *filter, const char *inst_name) { - AVFilterContext *ret = av_malloc(sizeof(AVFilterContext)); + AVFilterContext *ret; + + if (!filter) + return 0; + + ret = av_malloc(sizeof(AVFilterContext)); ret->av_class = av_mallocz(sizeof(AVClass)); ret->av_class->item_name = filter_name; @@ -337,45 +361,30 @@ void avfilter_destroy(AVFilterContext *filter) for(i = 0; i < filter->input_count; i ++) { if(filter->inputs[i]) filter->inputs[i]->src->outputs[filter->inputs[i]->srcpad] = NULL; - av_free(filter->inputs[i]); + av_freep(&filter->inputs[i]); } for(i = 0; i < filter->output_count; i ++) { if(filter->outputs[i]) filter->outputs[i]->dst->inputs[filter->outputs[i]->dstpad] = NULL; - av_free(filter->outputs[i]); + av_freep(&filter->outputs[i]); } - av_free(filter->name); - av_free(filter->input_pads); - av_free(filter->output_pads); - av_free(filter->inputs); - av_free(filter->outputs); - av_free(filter->priv); - av_free(filter->av_class); + av_freep(&filter->name); + av_freep(&filter->input_pads); + av_freep(&filter->output_pads); + av_freep(&filter->inputs); + av_freep(&filter->outputs); + av_freep(&filter->priv); + av_freep(&filter->av_class); av_free(filter); } int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque) { - int ret; + int ret=0; if(filter->filter->init) - if((ret = filter->filter->init(filter, args, opaque))) return ret; - return 0; -} - -int *avfilter_make_format_list(int len, ...) -{ - int *ret, i; - va_list vl; - - ret = av_malloc(sizeof(int) * (len + 1)); - va_start(vl, len); - for(i = 0; i < len; i ++) - ret[i] = va_arg(vl, int); - va_end(vl); - ret[len] = -1; - + ret = filter->filter->init(filter, args, opaque); return ret; }