X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Favfilter.c;h=c9617dc2ff339eead83eb4104a8434f8f58e6cec;hb=b396bbad100a7493691d09b8dceba91e3cd28e2e;hp=1ba91d9821ad829c28ac597aaf0d5970971aa701;hpb=62549f9655c48f0ec061087fa33a96040ce01145;p=ffmpeg diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 1ba91d9821a..c9617dc2ff3 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -19,12 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* #define DEBUG */ - #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "libavutil/imgutils.h" +#include "libavutil/internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/rational.h" @@ -36,7 +35,8 @@ #include "internal.h" #include "video.h" -unsigned avfilter_version(void) { +unsigned avfilter_version(void) +{ return LIBAVFILTER_VERSION_INT; } @@ -61,13 +61,13 @@ void ff_insert_pad(unsigned idx, unsigned *count, size_t padidx_off, *pads = av_realloc(*pads, sizeof(AVFilterPad) * (*count + 1)); *links = av_realloc(*links, sizeof(AVFilterLink*) * (*count + 1)); - memmove(*pads +idx+1, *pads +idx, sizeof(AVFilterPad) * (*count-idx)); - memmove(*links+idx+1, *links+idx, sizeof(AVFilterLink*) * (*count-idx)); - memcpy(*pads+idx, newpad, sizeof(AVFilterPad)); + memmove(*pads + idx + 1, *pads + idx, sizeof(AVFilterPad) * (*count - idx)); + memmove(*links + idx + 1, *links + idx, sizeof(AVFilterLink*) * (*count - idx)); + memcpy(*pads + idx, newpad, sizeof(AVFilterPad)); (*links)[idx] = NULL; (*count)++; - for (i = idx+1; i < *count; i++) + for (i = idx + 1; i < *count; i++) if (*links[i]) (*(unsigned *)((uint8_t *) *links[i] + padidx_off))++; } @@ -88,8 +88,11 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, return AVERROR(EINVAL); } - src->outputs[srcpad] = - dst-> inputs[dstpad] = link = av_mallocz(sizeof(AVFilterLink)); + link = av_mallocz(sizeof(*link)); + if (!link) + return AVERROR(ENOMEM); + + src->outputs[srcpad] = dst->inputs[dstpad] = link; link->src = src; link->dst = dst; @@ -120,18 +123,18 @@ int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, } /* re-hookup the link to the new destination filter we inserted */ - link->dst = filt; - link->dstpad = &filt->input_pads[filt_srcpad_idx]; + link->dst = filt; + link->dstpad = &filt->input_pads[filt_srcpad_idx]; filt->inputs[filt_srcpad_idx] = link; /* if any information on supported media formats already exists on the * link, we need to preserve that */ if (link->out_formats) ff_formats_changeref(&link->out_formats, - &filt->outputs[filt_dstpad_idx]->out_formats); + &filt->outputs[filt_dstpad_idx]->out_formats); if (link->out_samplerates) ff_formats_changeref(&link->out_samplerates, - &filt->outputs[filt_dstpad_idx]->out_samplerates); + &filt->outputs[filt_dstpad_idx]->out_samplerates); if (link->out_channel_layouts) ff_channel_layouts_changeref(&link->out_channel_layouts, &filt->outputs[filt_dstpad_idx]->out_channel_layouts); @@ -201,7 +204,7 @@ int avfilter_config_links(AVFilterContext *filter) if ((config_link = link->dstpad->config_props)) if ((ret = config_link(link)) < 0) { - av_log(link->src, AV_LOG_ERROR, + av_log(link->dst, AV_LOG_ERROR, "Failed to configure input pad on %s\n", link->dst->name); return ret; @@ -267,51 +270,60 @@ int ff_poll_frame(AVFilterLink *link) return min; } -#define MAX_REGISTERED_AVFILTERS_NB 64 - -static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1]; - -static int next_registered_avfilter_idx = 0; +static AVFilter *first_filter; +#if !FF_API_NOCONST_GET_NAME +const +#endif AVFilter *avfilter_get_by_name(const char *name) { - int i; + const AVFilter *f = NULL; - for (i = 0; registered_avfilters[i]; i++) - if (!strcmp(registered_avfilters[i]->name, name)) - return registered_avfilters[i]; + if (!name) + return NULL; + + while ((f = avfilter_next(f))) + if (!strcmp(f->name, name)) + return f; return NULL; } int avfilter_register(AVFilter *filter) { - if (next_registered_avfilter_idx == MAX_REGISTERED_AVFILTERS_NB) - return -1; - - registered_avfilters[next_registered_avfilter_idx++] = filter; + AVFilter **f = &first_filter; + while (*f) + f = &(*f)->next; + *f = filter; + filter->next = NULL; return 0; } +const AVFilter *avfilter_next(const AVFilter *prev) +{ + return prev ? prev->next : first_filter; +} + +#if FF_API_OLD_FILTER_REGISTER AVFilter **av_filter_next(AVFilter **filter) { - return filter ? ++filter : ®istered_avfilters[0]; + return filter ? &(*filter)->next : &first_filter; } void avfilter_uninit(void) { - memset(registered_avfilters, 0, sizeof(registered_avfilters)); - next_registered_avfilter_idx = 0; } +#endif -static int pad_count(const AVFilterPad *pads) +int avfilter_pad_count(const AVFilterPad *pads) { int count; if (!pads) return 0; - for(count = 0; pads->name; count ++) pads ++; + for (count = 0; pads->name; count++) + pads++; return count; } @@ -321,23 +333,70 @@ static const char *filter_name(void *p) return filter->filter->name; } +static void *filter_child_next(void *obj, void *prev) +{ + AVFilterContext *ctx = obj; + if (!prev && ctx->filter && ctx->filter->priv_class && ctx->priv) + return ctx->priv; + return NULL; +} + +static const AVClass *filter_child_class_next(const AVClass *prev) +{ + const AVFilter *f = NULL; + + while (prev && (f = avfilter_next(f))) + if (f->priv_class == prev) + break; + + while ((f = avfilter_next(f))) + if (f->priv_class) + return f->priv_class; + + return NULL; +} + +#define OFFSET(x) offsetof(AVFilterContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM +static const AVOption avfilter_options[] = { + { "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, + { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, "thread_type" }, + { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .unit = "thread_type" }, + { NULL }, +}; + static const AVClass avfilter_class = { .class_name = "AVFilter", .item_name = filter_name, .version = LIBAVUTIL_VERSION_INT, + .child_next = filter_child_next, + .child_class_next = filter_child_class_next, + .option = avfilter_options, }; -int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name) +static int default_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, + int *ret, int nb_jobs) +{ + int i; + + for (i = 0; i < nb_jobs; i++) { + int r = func(ctx, arg, i, nb_jobs); + if (ret) + ret[i] = r; + } + return 0; +} + +AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name) { AVFilterContext *ret; - *filter_ctx = NULL; if (!filter) - return AVERROR(EINVAL); + return NULL; ret = av_mallocz(sizeof(AVFilterContext)); if (!ret) - return AVERROR(ENOMEM); + return NULL; ret->av_class = &avfilter_class; ret->filter = filter; @@ -348,12 +407,18 @@ int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *in goto err; } + av_opt_set_defaults(ret); if (filter->priv_class) { *(const AVClass**)ret->priv = filter->priv_class; av_opt_set_defaults(ret->priv); } - ret->nb_inputs = pad_count(filter->inputs); + ret->internal = av_mallocz(sizeof(*ret->internal)); + if (!ret->internal) + goto err; + ret->internal->execute = default_execute; + + ret->nb_inputs = avfilter_pad_count(filter->inputs); if (ret->nb_inputs ) { ret->input_pads = av_malloc(sizeof(AVFilterPad) * ret->nb_inputs); if (!ret->input_pads) @@ -364,7 +429,7 @@ int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *in goto err; } - ret->nb_outputs = pad_count(filter->outputs); + ret->nb_outputs = avfilter_pad_count(filter->outputs); if (ret->nb_outputs) { ret->output_pads = av_malloc(sizeof(AVFilterPad) * ret->nb_outputs); if (!ret->output_pads) @@ -375,12 +440,13 @@ int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *in goto err; } #if FF_API_FOO_COUNT +FF_DISABLE_DEPRECATION_WARNINGS ret->output_count = ret->nb_outputs; ret->input_count = ret->nb_inputs; +FF_ENABLE_DEPRECATION_WARNINGS #endif - *filter_ctx = ret; - return 0; + return ret; err: av_freep(&ret->inputs); @@ -390,43 +456,53 @@ err: av_freep(&ret->output_pads); ret->nb_outputs = 0; av_freep(&ret->priv); + av_freep(&ret->internal); av_free(ret); - return AVERROR(ENOMEM); + return NULL; +} + +#if FF_API_AVFILTER_OPEN +int avfilter_open(AVFilterContext **filter_ctx, AVFilter *filter, const char *inst_name) +{ + *filter_ctx = ff_filter_alloc(filter, inst_name); + return *filter_ctx ? 0 : AVERROR(ENOMEM); +} +#endif + +static void free_link(AVFilterLink *link) +{ + if (!link) + return; + + if (link->src) + link->src->outputs[link->srcpad - link->src->output_pads] = NULL; + if (link->dst) + link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL; + + ff_formats_unref(&link->in_formats); + ff_formats_unref(&link->out_formats); + ff_formats_unref(&link->in_samplerates); + ff_formats_unref(&link->out_samplerates); + ff_channel_layouts_unref(&link->in_channel_layouts); + ff_channel_layouts_unref(&link->out_channel_layouts); + av_freep(&link); } void avfilter_free(AVFilterContext *filter) { int i; - AVFilterLink *link; + + if (filter->graph) + ff_filter_graph_remove_filter(filter->graph, filter); if (filter->filter->uninit) filter->filter->uninit(filter); for (i = 0; i < filter->nb_inputs; i++) { - if ((link = filter->inputs[i])) { - if (link->src) - link->src->outputs[link->srcpad - link->src->output_pads] = NULL; - ff_formats_unref(&link->in_formats); - ff_formats_unref(&link->out_formats); - ff_formats_unref(&link->in_samplerates); - ff_formats_unref(&link->out_samplerates); - ff_channel_layouts_unref(&link->in_channel_layouts); - ff_channel_layouts_unref(&link->out_channel_layouts); - } - av_freep(&link); + free_link(filter->inputs[i]); } for (i = 0; i < filter->nb_outputs; i++) { - if ((link = filter->outputs[i])) { - if (link->dst) - link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL; - ff_formats_unref(&link->in_formats); - ff_formats_unref(&link->out_formats); - ff_formats_unref(&link->in_samplerates); - ff_formats_unref(&link->out_samplerates); - ff_channel_layouts_unref(&link->in_channel_layouts); - ff_channel_layouts_unref(&link->out_channel_layouts); - } - av_freep(&link); + free_link(filter->outputs[i]); } if (filter->filter->priv_class) @@ -438,6 +514,7 @@ void avfilter_free(AVFilterContext *filter) av_freep(&filter->inputs); av_freep(&filter->outputs); av_freep(&filter->priv); + av_freep(&filter->internal); av_free(filter); } @@ -474,11 +551,53 @@ static int process_unnamed_options(AVFilterContext *ctx, AVDictionary **options, return 0; } +#if FF_API_AVFILTER_INIT_FILTER int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque) +{ + return avfilter_init_str(filter, args); +} +#endif + +int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options) +{ + int ret = 0; + + ret = av_opt_set_dict(ctx, options); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Error applying generic filter options.\n"); + return ret; + } + + if (ctx->filter->flags & AVFILTER_FLAG_SLICE_THREADS && + ctx->thread_type & ctx->graph->thread_type & AVFILTER_THREAD_SLICE && + ctx->graph->internal->thread_execute) { + ctx->thread_type = AVFILTER_THREAD_SLICE; + ctx->internal->execute = ctx->graph->internal->thread_execute; + } else { + ctx->thread_type = 0; + } + + if (ctx->filter->priv_class) { + ret = av_opt_set_dict(ctx->priv, options); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Error applying options to the filter.\n"); + return ret; + } + } + + if (ctx->filter->init) + ret = ctx->filter->init(ctx); + else if (ctx->filter->init_dict) + ret = ctx->filter->init_dict(ctx, options); + + return ret; +} + +int avfilter_init_str(AVFilterContext *filter, const char *args) { AVDictionary *options = NULL; AVDictionaryEntry *e; - int ret=0; + int ret = 0; if (args && *args) { if (!filter->filter->priv_class) { @@ -489,7 +608,7 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque #if FF_API_OLD_FILTER_OPTS if (!strcmp(filter->filter->name, "scale") && - strchr(args, ':') < strchr(args, '=')) { + strchr(args, ':') && strchr(args, ':') < strchr(args, '=')) { /* old w:h:flags= syntax */ char *copy = av_strdup(args); char *p; @@ -575,18 +694,7 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque } } - if (filter->filter->priv_class) { - ret = av_opt_set_dict(filter->priv, &options); - if (ret < 0) { - av_log(filter, AV_LOG_ERROR, "Error applying options to the filter.\n"); - goto fail; - } - } - - if (filter->filter->init) - ret = filter->filter->init(filter); - else if (filter->filter->init_dict) - ret = filter->filter->init_dict(filter, &options); + ret = avfilter_init_dict(filter, &options); if (ret < 0) goto fail; @@ -602,12 +710,12 @@ fail: return ret; } -const char *avfilter_pad_get_name(AVFilterPad *pads, int pad_idx) +const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx) { return pads[pad_idx].name; } -enum AVMediaType avfilter_pad_get_type(AVFilterPad *pads, int pad_idx) +enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx) { return pads[pad_idx].type; } @@ -621,7 +729,8 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame) { int (*filter_frame)(AVFilterLink *, AVFrame *); AVFilterPad *dst = link->dstpad; - AVFrame *out; + AVFrame *out = NULL; + int ret; FF_DPRINTF_START(NULL, filter_frame); ff_dlog_link(NULL, link, 1); @@ -640,13 +749,18 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame) case AVMEDIA_TYPE_AUDIO: out = ff_get_audio_buffer(link, frame->nb_samples); break; - default: return AVERROR(EINVAL); + default: + ret = AVERROR(EINVAL); + goto fail; } if (!out) { - av_frame_free(&frame); - return AVERROR(ENOMEM); + ret = AVERROR(ENOMEM); + goto fail; } - av_frame_copy_props(out, frame); + + ret = av_frame_copy_props(out, frame); + if (ret < 0) + goto fail; switch (link->type) { case AVMEDIA_TYPE_VIDEO: @@ -659,7 +773,9 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame) av_get_channel_layout_nb_channels(frame->channel_layout), frame->format); break; - default: return AVERROR(EINVAL); + default: + ret = AVERROR(EINVAL); + goto fail; } av_frame_free(&frame); @@ -667,4 +783,14 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame) out = frame; return filter_frame(link, out); + +fail: + av_frame_free(&out); + av_frame_free(&frame); + return ret; +} + +const AVClass *avfilter_get_class(void) +{ + return &avfilter_class; }