Flag added in a few simple filters. A bunch of other filters can likely use the feature as well.
Showing the changes to libavfilter/avfilter.c (1 of 21 files). Show all
Unified · Split
| @@ -23,6 +23,7 @@ · 22 unmodified lines | |||
| 23 | #include "libavutil/avstring.h" | 23 | #include "libavutil/avstring.h" |
| 24 | #include "libavutil/channel_layout.h" | 24 | #include "libavutil/channel_layout.h" |
| 25 | #include "libavutil/common.h" | 25 | #include "libavutil/common.h" |
| 26 | #include "libavutil/eval.h" | ||
| 26 | #include "libavutil/imgutils.h" | 27 | #include "libavutil/imgutils.h" |
| 27 | #include "libavutil/opt.h" | 28 | #include "libavutil/opt.h" |
| 28 | #include "libavutil/pixdesc.h" | 29 | #include "libavutil/pixdesc.h" |
| @@ -483,12 +484,20 @@ static const AVClass *filter_child_class_next(const AVClass *prev) · 454 unmodified lines | |||
| 483 | return NULL; | 484 | return NULL; |
| 484 | } | 485 | } |
| 485 | 486 | ||
| 487 | #define OFFSET(x) offsetof(AVFilterContext, x) | ||
| 488 | #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | ||
| 489 | static const AVOption filters_common_options[] = { | ||
| 490 | { "enable", "set enable expression", OFFSET(enable_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS }, | ||
| 491 | { NULL } | ||
| 492 | }; | ||
| 493 | |||
| 486 | static const AVClass avfilter_class = { | 494 | static const AVClass avfilter_class = { |
| 487 | .class_name = "AVFilter", | 495 | .class_name = "AVFilter", |
| 488 | .item_name = default_filter_name, | 496 | .item_name = default_filter_name, |
| 489 | .version = LIBAVUTIL_VERSION_INT, | 497 | .version = LIBAVUTIL_VERSION_INT, |
| 490 | .category = AV_CLASS_CATEGORY_FILTER, | 498 | .category = AV_CLASS_CATEGORY_FILTER, |
| 491 | .child_next = filter_child_next, | 499 | .child_next = filter_child_next, |
| 500 | .option = filters_common_options, | ||
| 492 | .child_class_next = filter_child_class_next, | 501 | .child_class_next = filter_child_class_next, |
| 493 | }; | 502 | }; |
| 494 | 503 | ||
| @@ -618,9 +627,16 @@ void avfilter_free(AVFilterContext *filter) · 123 unmodified lines | |||
| 618 | while(filter->command_queue){ | 627 | while(filter->command_queue){ |
| 619 | ff_command_queue_pop(filter); | 628 | ff_command_queue_pop(filter); |
| 620 | } | 629 | } |
| 630 | av_opt_free(filter); | ||
| 631 | av_expr_free(filter->enable); | ||
| 632 | filter->enable = NULL; | ||
| 633 | av_freep(&filter->var_values); | ||
| 621 | av_free(filter); | 634 | av_free(filter); |
| 622 | } | 635 | } |
| 623 | 636 | ||
| 637 | static const char *const var_names[] = { "t", "n", "pos", NULL }; | ||
| 638 | enum { VAR_T, VAR_N, VAR_POS, VAR_VARS_NB }; | ||
| 639 | |||
| 624 | static int process_options(AVFilterContext *ctx, AVDictionary **options, | 640 | static int process_options(AVFilterContext *ctx, AVDictionary **options, |
| 625 | const char *args) | 641 | const char *args) |
| 626 | { | 642 | { |
| @@ -630,6 +646,8 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options, · 3 unmodified lines | |||
| 630 | const char *key; | 646 | const char *key; |
| 631 | int offset= -1; | 647 | int offset= -1; |
| 632 | 648 | ||
| 649 | av_opt_set_defaults(ctx); | ||
| 650 | |||
| 633 | if (!args) | 651 | if (!args) |
| 634 | return 0; | 652 | return 0; |
| 635 | 653 | ||
| @@ -665,6 +683,12 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options, · 29 unmodified lines | |||
| 665 | } | 683 | } |
| 666 | 684 | ||
| 667 | av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value); | 685 | av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value); |
| 686 | |||
| 687 | if (av_opt_find(ctx, key, NULL, 0, 0)) { | ||
| 688 | ret = av_opt_set(ctx, key, value, 0); | ||
| 689 | if (ret < 0) | ||
| 690 | return ret; | ||
| 691 | } else { | ||
| 668 | av_dict_set(options, key, value, 0); | 692 | av_dict_set(options, key, value, 0); |
| 669 | if ((ret = av_opt_set(ctx->priv, key, value, 0)) < 0) { | 693 | if ((ret = av_opt_set(ctx->priv, key, value, 0)) < 0) { |
| 670 | if (!av_opt_find(ctx->priv, key, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) { | 694 | if (!av_opt_find(ctx->priv, key, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) { |
| @@ -675,11 +699,27 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options, · 4 unmodified lines | |||
| 675 | return ret; | 699 | return ret; |
| 676 | } | 700 | } |
| 677 | } | 701 | } |
| 702 | } | ||
| 678 | 703 | ||
| 679 | av_free(value); | 704 | av_free(value); |
| 680 | av_free(parsed_key); | 705 | av_free(parsed_key); |
| 681 | count++; | 706 | count++; |
| 682 | } | 707 | } |
| 708 | |||
| 709 | if (ctx->enable_str) { | ||
| 710 | if (!(ctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)) { | ||
| 711 | av_log(ctx, AV_LOG_ERROR, "Timeline ('enable' option) not supported " | ||
| 712 | "with filter '%s'\n", ctx->filter->name); | ||
| 713 | return AVERROR_PATCHWELCOME; | ||
| 714 | } | ||
| 715 | ctx->var_values = av_calloc(VAR_VARS_NB, sizeof(*ctx->var_values)); | ||
| 716 | if (!ctx->var_values) | ||
| 717 | return AVERROR(ENOMEM); | ||
| 718 | ret = av_expr_parse((AVExpr**)&ctx->enable, ctx->enable_str, var_names, | ||
| 719 | NULL, NULL, NULL, NULL, 0, ctx->priv); | ||
| 720 | if (ret < 0) | ||
| 721 | return ret; | ||
| 722 | } | ||
| 683 | return count; | 723 | return count; |
| 684 | } | 724 | } |
| 685 | 725 | ||
| @@ -852,6 +892,7 @@ static int default_filter_frame(AVFilterLink *link, AVFrame *frame) · 166 unmodified lines | |||
| 852 | static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame) | 892 | static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame) |
| 853 | { | 893 | { |
| 854 | int (*filter_frame)(AVFilterLink *, AVFrame *); | 894 | int (*filter_frame)(AVFilterLink *, AVFrame *); |
| 895 | AVFilterContext *dstctx = link->dst; | ||
| 855 | AVFilterPad *dst = link->dstpad; | 896 | AVFilterPad *dst = link->dstpad; |
| 856 | AVFrame *out; | 897 | AVFrame *out; |
| 857 | int ret; | 898 | int ret; |
| @@ -914,6 +955,15 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame) · 56 unmodified lines | |||
| 914 | } | 955 | } |
| 915 | 956 | ||
| 916 | pts = out->pts; | 957 | pts = out->pts; |
| 958 | if (dstctx->enable_str) { | ||
| 959 | int64_t pos = av_frame_get_pkt_pos(out); | ||
| 960 | dstctx->var_values[VAR_N] = link->frame_count; | ||
| 961 | dstctx->var_values[VAR_T] = pts == AV_NOPTS_VALUE ? NAN : pts * av_q2d(link->time_base); | ||
| 962 | dstctx->var_values[VAR_POS] = pos == -1 ? NAN : pos; | ||
| 963 | if (!av_expr_eval(dstctx->enable, dstctx->var_values, NULL)) | ||
| 964 | filter_frame = dst->passthrough_filter_frame ? dst->passthrough_filter_frame | ||
| 965 | : default_filter_frame; | ||
| 966 | } | ||
| 917 | ret = filter_frame(link, out); | 967 | ret = filter_frame(link, out); |
| 918 | link->frame_count++; | 968 | link->frame_count++; |
| 919 | link->frame_requested = 0; | 969 | link->frame_requested = 0; |