X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Favfilter.c;h=8ff22c71e3957f041921f822899a6572d67dc1f4;hb=191f68aec1a5d3a5d61e14c9653189ffd7b55f3b;hp=7553f7c36a22f9b806c5193e3f3bea6dcefb661a;hpb=9a15af48284b951701b7e6b9dcc81b4212c6ca95;p=ffmpeg diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 7553f7c36a2..8ff22c71e39 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -88,7 +88,7 @@ const char *avfilter_configuration(void) const char *avfilter_license(void) { #define LICENSE_PREFIX "libavfilter license: " - return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; } void ff_command_queue_pop(AVFilterContext *filter) @@ -261,15 +261,15 @@ int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, /* 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); - if (link->out_samplerates) - ff_formats_changeref(&link->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); + if (link->outcfg.formats) + ff_formats_changeref(&link->outcfg.formats, + &filt->outputs[filt_dstpad_idx]->outcfg.formats); + if (link->outcfg.samplerates) + ff_formats_changeref(&link->outcfg.samplerates, + &filt->outputs[filt_dstpad_idx]->outcfg.samplerates); + if (link->outcfg.channel_layouts) + ff_channel_layouts_changeref(&link->outcfg.channel_layouts, + &filt->outputs[filt_dstpad_idx]->outcfg.channel_layouts); return 0; } @@ -467,24 +467,6 @@ static int ff_request_frame_to_filter(AVFilterLink *link) return ret; } -int ff_poll_frame(AVFilterLink *link) -{ - int i, min = INT_MAX; - - if (link->srcpad->poll_frame) - return link->srcpad->poll_frame(link); - - for (i = 0; i < link->src->nb_inputs; i++) { - int val; - if (!link->src->inputs[i]) - return AVERROR(EINVAL); - val = ff_poll_frame(link->src->inputs[i]); - min = FFMIN(min, val); - } - - return min; -} - static const char *const var_names[] = { "t", "n", @@ -575,51 +557,6 @@ int avfilter_process_command(AVFilterContext *filter, const char *cmd, const cha return AVERROR(ENOSYS); } -static AVFilter *first_filter; -static AVFilter **last_filter = &first_filter; - -const AVFilter *avfilter_get_by_name(const char *name) -{ - const AVFilter *f = NULL; - - if (!name) - return NULL; - - while ((f = avfilter_next(f))) - if (!strcmp(f->name, name)) - return (AVFilter *)f; - - return NULL; -} - -static AVMutex filter_register_mutex = AV_MUTEX_INITIALIZER; - -int avfilter_register(AVFilter *filter) -{ - AVFilter **f; - - /* the filter must select generic or internal exclusively */ - av_assert0((filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE) != AVFILTER_FLAG_SUPPORT_TIMELINE); - - ff_mutex_lock(&filter_register_mutex); - f = last_filter; - - while (*f) - f = &(*f)->next; - *f = filter; - filter->next = NULL; - last_filter = &filter->next; - - ff_mutex_unlock(&filter_register_mutex); - - return 0; -} - -const AVFilter *avfilter_next(const AVFilter *prev) -{ - return prev ? prev->next : first_filter; -} - int avfilter_pad_count(const AVFilterPad *pads) { int count; @@ -646,12 +583,14 @@ static void *filter_child_next(void *obj, void *prev) return NULL; } +#if FF_API_CHILD_CLASS_NEXT static const AVClass *filter_child_class_next(const AVClass *prev) { + void *opaque = NULL; const AVFilter *f = NULL; /* find the filter that corresponds to prev */ - while (prev && (f = avfilter_next(f))) + while (prev && (f = av_filter_iterate(&opaque))) if (f->priv_class == prev) break; @@ -660,7 +599,19 @@ static const AVClass *filter_child_class_next(const AVClass *prev) return NULL; /* find next filter with specific options */ - while ((f = avfilter_next(f))) + while ((f = av_filter_iterate(&opaque))) + if (f->priv_class) + return f->priv_class; + + return NULL; +} +#endif + +static const AVClass *filter_child_class_iterate(void **iter) +{ + const AVFilter *f; + + while ((f = av_filter_iterate(iter))) if (f->priv_class) return f->priv_class; @@ -672,7 +623,7 @@ static const AVClass *filter_child_class_next(const AVClass *prev) 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" }, + { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .flags = FLAGS, .unit = "thread_type" }, { "enable", "set enable expression", OFFSET(enable_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS }, { "threads", "Allowed number of threads", OFFSET(nb_threads), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, @@ -687,7 +638,10 @@ static const AVClass avfilter_class = { .version = LIBAVUTIL_VERSION_INT, .category = AV_CLASS_CATEGORY_FILTER, .child_next = filter_child_next, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = filter_child_class_next, +#endif + .child_class_iterate = filter_child_class_iterate, .option = avfilter_options, }; @@ -792,12 +746,12 @@ static void free_link(AVFilterLink *link) av_buffer_unref(&link->hw_frames_ctx); - 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); + ff_formats_unref(&link->incfg.formats); + ff_formats_unref(&link->outcfg.formats); + ff_formats_unref(&link->incfg.samplerates); + ff_formats_unref(&link->outcfg.samplerates); + ff_channel_layouts_unref(&link->incfg.channel_layouts); + ff_channel_layouts_unref(&link->outcfg.channel_layouts); avfilter_link_free(&link); } @@ -845,9 +799,9 @@ void avfilter_free(AVFilterContext *filter) int ff_filter_get_nb_threads(AVFilterContext *ctx) { - if (ctx->nb_threads > 0) - return FFMIN(ctx->nb_threads, ctx->graph->nb_threads); - return ctx->graph->nb_threads; + if (ctx->nb_threads > 0) + return FFMIN(ctx->nb_threads, ctx->graph->nb_threads); + return ctx->graph->nb_threads; } static int process_options(AVFilterContext *ctx, AVDictionary **options, @@ -903,17 +857,17 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options, return ret; } } else { - av_dict_set(options, key, value, 0); - if ((ret = av_opt_set(ctx->priv, key, value, AV_OPT_SEARCH_CHILDREN)) < 0) { - if (!av_opt_find(ctx->priv, key, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) { - if (ret == AVERROR_OPTION_NOT_FOUND) - av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key); - av_free(value); - av_free(parsed_key); - return ret; + av_dict_set(options, key, value, 0); + if ((ret = av_opt_set(ctx->priv, key, value, AV_OPT_SEARCH_CHILDREN)) < 0) { + if (!av_opt_find(ctx->priv, key, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) { + if (ret == AVERROR_OPTION_NOT_FOUND) + av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key); + av_free(value); + av_free(parsed_key); + return ret; + } } } - } av_free(value); av_free(parsed_key); @@ -928,6 +882,19 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options, return count; } +int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, + const char *arg, char *res, int res_len, int flags) +{ + const AVOption *o; + + if (!ctx->filter->priv_class) + return 0; + o = av_opt_find2(ctx->priv, cmd, NULL, AV_OPT_FLAG_RUNTIME_PARAM | AV_OPT_FLAG_FILTERING_PARAM, AV_OPT_SEARCH_CHILDREN, NULL); + if (!o) + return AVERROR(ENOSYS); + return av_opt_set(ctx->priv, cmd, arg, 0); +} + int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options) { int ret = 0; @@ -1414,7 +1381,7 @@ static int ff_filter_activate_default(AVFilterContext *filter) and request_frame() to acknowledge status changes), to run once more and check if enough input was present for several frames. - Exemples of scenarios to consider: + Examples of scenarios to consider: - buffersrc: activate if frame_wanted_out to notify the application; activate when the application adds a frame to push it immediately. @@ -1440,7 +1407,7 @@ static int ff_filter_activate_default(AVFilterContext *filter) - If an input has frames in fifo and frame_wanted_out == 0, dequeue a frame and call filter_frame(). - Ratinale: filter frames as soon as possible instead of leaving them + Rationale: filter frames as soon as possible instead of leaving them queued; frame_wanted_out < 0 is not possible since the old API does not set it nor provides any similar feedback; frame_wanted_out > 0 happens when min_samples > 0 and there are not enough samples queued. @@ -1457,9 +1424,6 @@ static int ff_filter_activate_default(AVFilterContext *filter) Rationale: checking frame_blocked_in is necessary to avoid requesting repeatedly on a blocked input if another is not blocked (example: [buffersrc1][testsrc1][buffersrc2][testsrc2]concat=v=2). - - TODO: respect needs_fifo and remove auto-inserted fifos. - */ int ff_filter_activate(AVFilterContext *filter) @@ -1492,11 +1456,21 @@ int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts return 1; } +size_t ff_inlink_queued_frames(AVFilterLink *link) +{ + return ff_framequeue_queued_frames(&link->fifo); +} + int ff_inlink_check_available_frame(AVFilterLink *link) { return ff_framequeue_queued_frames(&link->fifo) > 0; } +int ff_inlink_queued_samples(AVFilterLink *link) +{ + return ff_framequeue_queued_samples(&link->fifo); +} + int ff_inlink_check_available_samples(AVFilterLink *link, unsigned min) { uint64_t samples = ff_framequeue_queued_samples(&link->fifo); @@ -1551,6 +1525,11 @@ int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, return 1; } +AVFrame *ff_inlink_peek_frame(AVFilterLink *link, size_t idx) +{ + return ff_framequeue_peek(&link->fifo, idx); +} + int ff_inlink_make_frame_writable(AVFilterLink *link, AVFrame **rframe) { AVFrame *frame = *rframe;