diff --git a/doc/APIchanges b/doc/APIchanges index b023a6fc57..1c5f6d13c7 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2012-10-22 API changes, most recent first: +2013-05-12 - xxxxxxx - lavfi 3.65.100 + Add AVFILTER_FLAG_SUPPORT_TIMELINE* filter flags. + 2013-04-19 - xxxxxxx - lavc 55.4.100 Add AV_CODEC_PROP_TEXT_SUB property for text based subtitles codec. diff --git a/libavfilter/af_apad.c b/libavfilter/af_apad.c index 265b76a38d..710baaa104 100644 --- a/libavfilter/af_apad.c +++ b/libavfilter/af_apad.c @@ -131,7 +131,6 @@ static const AVFilterPad apad_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_AUDIO, .filter_frame = filter_frame, - .passthrough_filter_frame = filter_frame, }, { NULL }, }; @@ -153,5 +152,5 @@ AVFilter avfilter_af_apad = { .inputs = apad_inputs, .outputs = apad_outputs, .priv_class = &apad_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c index b7aec8d6fa..a2ac1e2f4e 100644 --- a/libavfilter/af_volume.c +++ b/libavfilter/af_volume.c @@ -296,5 +296,5 @@ AVFilter avfilter_af_volume = { .init = init, .inputs = avfilter_af_volume_inputs, .outputs = avfilter_af_volume_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 3f94dded2d..b61b7060a7 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -453,6 +453,9 @@ int avfilter_register(AVFilter *filter) AVFilter **f = &first_filter; int i; + /* the filter must select generic or internal exclusively */ + av_assert0((filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE) != AVFILTER_FLAG_SUPPORT_TIMELINE); + for(i=0; filter->inputs && filter->inputs[i].name; i++) { const AVFilterPad *input = &filter->inputs[i]; av_assert0( !input->filter_frame @@ -995,9 +998,9 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame) dstctx->var_values[VAR_POS] = pos == -1 ? NAN : pos; dstctx->is_disabled = !av_expr_eval(dstctx->enable, dstctx->var_values, NULL); - if (dstctx->is_disabled) - filter_frame = dst->passthrough_filter_frame ? dst->passthrough_filter_frame - : default_filter_frame; + if (dstctx->is_disabled && + (dstctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC)) + filter_frame = default_filter_frame; } ret = filter_frame(link, out); link->frame_count++; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index a79c86c2be..822eca7af2 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -385,19 +385,6 @@ struct AVFilterPad { int needs_fifo; int needs_writable; - - /** - * Passthrough filtering callback. - * - * If a filter supports timeline editing (in case - * AVFILTER_FLAG_SUPPORT_TIMELINE is enabled) then it can implement a - * custom passthrough callback to update its local context (for example to - * keep a frame reference, or simply send the filter to a custom outlink). - * The filter must not do any change to the frame in this callback. - * - * Input pads only. - */ - int (*passthrough_filter_frame)(AVFilterLink *link, AVFrame *frame); }; #endif @@ -444,9 +431,25 @@ enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx); /** * Some filters support a generic "enable" expression option that can be used * to enable or disable a filter in the timeline. Filters supporting this - * option have this flag set. + * option have this flag set. When the enable expression is false, the default + * no-op filter_frame() function is called in place of the filter_frame() + * callback defined on each input pad, thus the frame is passed unchanged to + * the next filters. */ -#define AVFILTER_FLAG_SUPPORT_TIMELINE (1 << 16) +#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC (1 << 16) +/** + * Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will + * have its filter_frame() callback(s) called as usual even when the enable + * expression is false. The filter will disable filtering within the + * filter_frame() callback(s) itself, for example executing code depending on + * the AVFilterContext->is_disabled value. + */ +#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL (1 << 17) +/** + * Handy mask to test whether the filter supports or no the timeline feature + * (internally or generically). + */ +#define AVFILTER_FLAG_SUPPORT_TIMELINE (AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL) /** * Filter definition. This defines the pads a filter contains, and all the diff --git a/libavfilter/version.h b/libavfilter/version.h index 74e8bcefbc..835bcf4029 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBAVFILTER_VERSION_MAJOR 3 -#define LIBAVFILTER_VERSION_MINOR 64 +#define LIBAVFILTER_VERSION_MINOR 65 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_boxblur.c b/libavfilter/vf_boxblur.c index a8a2014d61..c08559782c 100644 --- a/libavfilter/vf_boxblur.c +++ b/libavfilter/vf_boxblur.c @@ -383,5 +383,5 @@ AVFilter avfilter_vf_boxblur = { .inputs = avfilter_vf_boxblur_inputs, .outputs = avfilter_vf_boxblur_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_colorbalance.c b/libavfilter/vf_colorbalance.c index b09d17065f..74ee4d4409 100644 --- a/libavfilter/vf_colorbalance.c +++ b/libavfilter/vf_colorbalance.c @@ -209,5 +209,5 @@ AVFilter avfilter_vf_colorbalance = { .query_formats = query_formats, .inputs = colorbalance_inputs, .outputs = colorbalance_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_colorchannelmixer.c b/libavfilter/vf_colorchannelmixer.c index 343faace49..ff383f26c5 100644 --- a/libavfilter/vf_colorchannelmixer.c +++ b/libavfilter/vf_colorchannelmixer.c @@ -356,5 +356,5 @@ AVFilter avfilter_vf_colorchannelmixer = { .query_formats = query_formats, .inputs = colorchannelmixer_inputs, .outputs = colorchannelmixer_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_colormatrix.c b/libavfilter/vf_colormatrix.c index 8db5fcf8d1..7db0bd852e 100644 --- a/libavfilter/vf_colormatrix.c +++ b/libavfilter/vf_colormatrix.c @@ -385,5 +385,5 @@ AVFilter avfilter_vf_colormatrix = { .inputs = colormatrix_inputs, .outputs = colormatrix_outputs, .priv_class = &colormatrix_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_cropdetect.c b/libavfilter/vf_cropdetect.c index cb170d08fb..8f7d876ced 100644 --- a/libavfilter/vf_cropdetect.c +++ b/libavfilter/vf_cropdetect.c @@ -233,5 +233,5 @@ AVFilter avfilter_vf_cropdetect = { .query_formats = query_formats, .inputs = avfilter_vf_cropdetect_inputs, .outputs = avfilter_vf_cropdetect_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_curves.c b/libavfilter/vf_curves.c index faa4d66451..c5bbdfaad9 100644 --- a/libavfilter/vf_curves.c +++ b/libavfilter/vf_curves.c @@ -548,5 +548,5 @@ AVFilter avfilter_vf_curves = { .inputs = curves_inputs, .outputs = curves_outputs, .priv_class = &curves_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c index b644190b88..7acb01d894 100644 --- a/libavfilter/vf_delogo.c +++ b/libavfilter/vf_delogo.c @@ -271,5 +271,5 @@ AVFilter avfilter_vf_delogo = { .inputs = avfilter_vf_delogo_inputs, .outputs = avfilter_vf_delogo_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_drawbox.c b/libavfilter/vf_drawbox.c index c2ffbf3210..2747fbcd3e 100644 --- a/libavfilter/vf_drawbox.c +++ b/libavfilter/vf_drawbox.c @@ -181,5 +181,5 @@ AVFilter avfilter_vf_drawbox = { .query_formats = query_formats, .inputs = avfilter_vf_drawbox_inputs, .outputs = avfilter_vf_drawbox_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_edgedetect.c b/libavfilter/vf_edgedetect.c index b4698a8fe3..4c50d9f783 100644 --- a/libavfilter/vf_edgedetect.c +++ b/libavfilter/vf_edgedetect.c @@ -327,5 +327,5 @@ AVFilter avfilter_vf_edgedetect = { .inputs = edgedetect_inputs, .outputs = edgedetect_outputs, .priv_class = &edgedetect_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_gradfun.c b/libavfilter/vf_gradfun.c index 52c67ffedc..299cbf5e2e 100644 --- a/libavfilter/vf_gradfun.c +++ b/libavfilter/vf_gradfun.c @@ -260,5 +260,5 @@ AVFilter avfilter_vf_gradfun = { .query_formats = query_formats, .inputs = avfilter_vf_gradfun_inputs, .outputs = avfilter_vf_gradfun_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_histeq.c b/libavfilter/vf_histeq.c index a4166c674f..659b696dc7 100644 --- a/libavfilter/vf_histeq.c +++ b/libavfilter/vf_histeq.c @@ -279,5 +279,5 @@ AVFilter avfilter_vf_histeq = { .inputs = histeq_inputs, .outputs = histeq_outputs, .priv_class = &histeq_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_hue.c b/libavfilter/vf_hue.c index cba39d0002..cc8ac7842e 100644 --- a/libavfilter/vf_hue.c +++ b/libavfilter/vf_hue.c @@ -373,5 +373,5 @@ AVFilter avfilter_vf_hue = { .inputs = hue_inputs, .outputs = hue_outputs, .priv_class = &hue_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c index 070cf55244..f57c2845e6 100644 --- a/libavfilter/vf_lut.c +++ b/libavfilter/vf_lut.c @@ -354,7 +354,7 @@ static const AVFilterPad outputs[] = { \ .inputs = inputs, \ .outputs = outputs, \ - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, \ + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, \ } #if CONFIG_LUT_FILTER diff --git a/libavfilter/vf_noise.c b/libavfilter/vf_noise.c index da418fec9e..1651071dd5 100644 --- a/libavfilter/vf_noise.c +++ b/libavfilter/vf_noise.c @@ -471,5 +471,5 @@ AVFilter avfilter_vf_noise = { .inputs = noise_inputs, .outputs = noise_outputs, .priv_class = &noise_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index 6494bada3c..ec58dc4b66 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -88,7 +88,6 @@ enum var_name { typedef struct { const AVClass *class; int x, y; ///< position of overlayed picture - int enable; ///< tells if blending is enabled int allow_packed_rgb; uint8_t frame_requested; @@ -597,7 +596,7 @@ static int try_filter_frame(AVFilterContext *ctx, AVFrame *mainpic) over->var_values[VAR_X], over->x, over->var_values[VAR_Y], over->y); } - if (over->enable) + if (!ctx->is_disabled) blend_image(ctx, mainpic, over->overpicref, over->x, over->y); } @@ -663,20 +662,6 @@ static int filter_frame_over(AVFilterLink *inlink, AVFrame *inpicref) return ret == AVERROR(EAGAIN) ? 0 : ret; } -#define DEF_FILTER_FRAME(name, mode, enable_value) \ -static int filter_frame_##name##_##mode(AVFilterLink *inlink, AVFrame *frame) \ -{ \ - AVFilterContext *ctx = inlink->dst; \ - OverlayContext *over = ctx->priv; \ - over->enable = enable_value; \ - return filter_frame_##name(inlink, frame); \ -} - -DEF_FILTER_FRAME(main, enabled, 1); -DEF_FILTER_FRAME(main, disabled, 0); -DEF_FILTER_FRAME(over, enabled, 1); -DEF_FILTER_FRAME(over, disabled, 0); - static int request_frame(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -734,16 +719,14 @@ static const AVFilterPad avfilter_vf_overlay_inputs[] = { .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, .config_props = config_input_main, - .filter_frame = filter_frame_main_enabled, - .passthrough_filter_frame = filter_frame_main_disabled, + .filter_frame = filter_frame_main, .needs_writable = 1, }, { .name = "overlay", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_input_overlay, - .filter_frame = filter_frame_over_enabled, - .passthrough_filter_frame = filter_frame_over_disabled, + .filter_frame = filter_frame_over, }, { NULL } }; @@ -773,5 +756,5 @@ AVFilter avfilter_vf_overlay = { .inputs = avfilter_vf_overlay_inputs, .outputs = avfilter_vf_overlay_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; diff --git a/libavfilter/vf_pp.c b/libavfilter/vf_pp.c index 0571cfc1e7..3ab46b8abf 100644 --- a/libavfilter/vf_pp.c +++ b/libavfilter/vf_pp.c @@ -180,5 +180,5 @@ AVFilter avfilter_vf_pp = { .outputs = pp_outputs, .process_command = pp_process_command, .priv_class = &pp_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_removelogo.c b/libavfilter/vf_removelogo.c index 589c43a041..2b385fc533 100644 --- a/libavfilter/vf_removelogo.c +++ b/libavfilter/vf_removelogo.c @@ -578,5 +578,5 @@ AVFilter avfilter_vf_removelogo = { .inputs = removelogo_inputs, .outputs = removelogo_outputs, .priv_class = &removelogo_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_smartblur.c b/libavfilter/vf_smartblur.c index daf74513a7..a0013a2776 100644 --- a/libavfilter/vf_smartblur.c +++ b/libavfilter/vf_smartblur.c @@ -302,5 +302,5 @@ AVFilter avfilter_vf_smartblur = { .inputs = smartblur_inputs, .outputs = smartblur_outputs, .priv_class = &smartblur_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/vf_unsharp.c b/libavfilter/vf_unsharp.c index fc0628e379..c482d6b1bc 100644 --- a/libavfilter/vf_unsharp.c +++ b/libavfilter/vf_unsharp.c @@ -316,5 +316,5 @@ AVFilter avfilter_vf_unsharp = { .inputs = avfilter_vf_unsharp_inputs, .outputs = avfilter_vf_unsharp_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, };