[FFmpeg-devel] [PATCH] lavfi: add tdiff filter
Paul B Mahol
onemda at gmail.com
Thu Dec 11 11:18:51 CET 2014
On 12/10/14, Clement Boesch <u at pkh.me> wrote:
> Oups, sorry about the delay, I forgot that one.
>
> On Thu, Dec 04, 2014 at 12:36:43PM +0100, Stefano Sabatini wrote:
>> On date Sunday 2014-11-23 14:57:41 +0100, Clement Boesch encoded:
>> > On Sun, Nov 23, 2014 at 02:50:51PM +0100, Stefano Sabatini wrote:
>> > > On date Sunday 2014-11-23 02:01:16 +0100, Clement Boesch encoded:
>> > > > On Sat, Nov 22, 2014 at 11:44:29PM +0100, Stefano Sabatini wrote:
>> > > > > TODO: bump minor
>> > > > > ---
>> > > > > Changelog | 1 +
>> > > > > doc/filters.texi | 4 ++
>> > > > > libavfilter/Makefile | 1 +
>> > > > > libavfilter/allfilters.c | 1 +
>> > > > > libavfilter/vf_tdiff.c | 131
>> > > > > +++++++++++++++++++++++++++++++++++++++++++++++
>> > > > > 5 files changed, 138 insertions(+)
>> > > > > create mode 100644 libavfilter/vf_tdiff.c
>> > > > >
>> > > >
>> > >
>> > > > What about adding a tblend in vf_blend.c instead?
>> > >
>> > > What do you exactly mean? tdiff works with a single input, blend with
>> > > two inputs.
>> >
>> > That's the point: make another filter with temporal dimension in blend.
>> > Blend filter has many features such as doing something more than diff
>> > and having threading. The main function takes 2 frames so just add the
>> > glue code around to take the previous and the current frame instead.
>> >
>> > That's just a suggestion, maybe the other functions don't make much
>> > sense.
>> > Feel free to ignore.
>>
>> Uh, what about this?
>
> Yeah, I kind of like that much better :)
>
>> --
>> FFmpeg = Frightening Faithless Martial Powerful Evil Goblin
>
>> From c805460ceb04ec2da3f607e69067f4cc710c0613 Mon Sep 17 00:00:00 2001
>> From: Stefano Sabatini <stefasab at gmail.com>
>> Date: Thu, 4 Dec 2014 12:27:53 +0100
>> Subject: [PATCH] lavfi: add tblend filter
>>
>> ---
>> libavfilter/Makefile | 1 +
>> libavfilter/allfilters.c | 1 +
>> libavfilter/vf_blend.c | 73
>> +++++++++++++++++++++++++++++++++++++++++++++++-
>> 3 files changed, 74 insertions(+), 1 deletion(-)
>>
>> diff --git a/libavfilter/Makefile b/libavfilter/Makefile
>> index d41a52e..d1be7e3 100644
>> --- a/libavfilter/Makefile
>> +++ b/libavfilter/Makefile
>> @@ -187,6 +187,7 @@ OBJS-$(CONFIG_STEREO3D_FILTER) +=
>> vf_stereo3d.o
>> OBJS-$(CONFIG_SUBTITLES_FILTER) += vf_subtitles.o
>> OBJS-$(CONFIG_SUPER2XSAI_FILTER) += vf_super2xsai.o
>> OBJS-$(CONFIG_SWAPUV_FILTER) += vf_swapuv.o
>> +OBJS-$(CONFIG_TBLEND_FILTER) += vf_blend.o
>> OBJS-$(CONFIG_TDIFF_FILTER) += vf_tdiff.o
>> OBJS-$(CONFIG_TELECINE_FILTER) += vf_telecine.o
>> OBJS-$(CONFIG_THUMBNAIL_FILTER) += vf_thumbnail.o
>> diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
>> index f13f82d..e8914cc 100644
>> --- a/libavfilter/allfilters.c
>> +++ b/libavfilter/allfilters.c
>> @@ -202,6 +202,7 @@ void avfilter_register_all(void)
>> REGISTER_FILTER(SUBTITLES, subtitles, vf);
>> REGISTER_FILTER(SUPER2XSAI, super2xsai, vf);
>> REGISTER_FILTER(SWAPUV, swapuv, vf);
>> + REGISTER_FILTER(TBLEND, tblend, vf);
>> REGISTER_FILTER(TDIFF, tdiff, vf);
>> REGISTER_FILTER(TELECINE, telecine, vf);
>> REGISTER_FILTER(THUMBNAIL, thumbnail, vf);
>> diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c
>> index 8bf19ff..3c1572c 100644
>> --- a/libavfilter/vf_blend.c
>> +++ b/libavfilter/vf_blend.c
>> @@ -95,6 +95,8 @@ typedef struct {
>> double all_opacity;
>>
>> FilterParams params[4];
>> + int tblend;
>> + AVFrame *prev_frame; /* only used with tblend */
>> } BlendContext;
>>
>> #define OFFSET(x) offsetof(BlendContext, x)
>> @@ -285,7 +287,8 @@ static AVFrame *blend_frame(AVFilterContext *ctx,
>> AVFrame *top_buf,
>> ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(outh,
>> ctx->graph->nb_threads));
>> }
>>
>> - av_frame_free(&top_buf);
>> + if (!b->tblend)
>> + av_frame_free(&top_buf);
>>
>> return dst_buf;
>> }
>> @@ -295,6 +298,8 @@ static av_cold int init(AVFilterContext *ctx)
>> BlendContext *b = ctx->priv;
>> int ret, plane;
>>
>> + b->tblend = !strcmp(ctx->filter->name, "tblend");
>> +
>> for (plane = 0; plane < FF_ARRAY_ELEMS(b->params); plane++) {
>> FilterParams *param = &b->params[plane];
>>
>> @@ -412,6 +417,8 @@ static av_cold void uninit(AVFilterContext *ctx)
>> int i;
>>
>> ff_dualinput_uninit(&b->dinput);
>> + av_freep(&b->prev_frame);
>> +
>> for (i = 0; i < FF_ARRAY_ELEMS(b->params); i++)
>> av_expr_free(b->params[i].e);
>> }
>> @@ -463,3 +470,67 @@ AVFilter ff_vf_blend = {
>> .priv_class = &blend_class,
>> .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
>> AVFILTER_FLAG_SLICE_THREADS,
>> };
>> +
>> +static int tblend_config_output(AVFilterLink *outlink)
>> +{
>> + AVFilterContext *ctx = outlink->src;
>> + AVFilterLink *inlink = ctx->inputs[0];
>> + BlendContext *b = ctx->priv;
>> + const AVPixFmtDescriptor *pix_desc =
>> av_pix_fmt_desc_get(inlink->format);
>> +
>> + b->hsub = pix_desc->log2_chroma_w;
>> + b->vsub = pix_desc->log2_chroma_h;
>> + b->nb_planes = av_pix_fmt_count_planes(inlink->format);
>
>> + outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
>
> Do you need that? (it's single input)
>
>> +
>> + return 0;
>> +}
>> +
>> +static int tblend_filter_frame(AVFilterLink *inlink, AVFrame *frame)
>> +{
>> + BlendContext *b = inlink->dst->priv;
>> + AVFilterLink *outlink = inlink->dst->outputs[0];
>> +
>> + if (b->prev_frame) {
>> + AVFrame *out = blend_frame(inlink->dst, frame, b->prev_frame);
>> + av_frame_free(&b->prev_frame);
>> + b->prev_frame = frame;
>> + return ff_filter_frame(outlink, out);
>> + }
>> + b->prev_frame = frame;
>> + return 0;
>> +}
>> +
>> +#define tblend_options blend_options
>> +AVFILTER_DEFINE_CLASS(tblend);
>> +
>
> You probably want to sort out the shortest/repeatlast options
>
>> +static const AVFilterPad tblend_inputs[] = {
>> + {
>> + .name = "default",
>> + .type = AVMEDIA_TYPE_VIDEO,
>> + .filter_frame = tblend_filter_frame,
>> + },
>> + { NULL }
>> +};
>> +
>> +static const AVFilterPad tblend_outputs[] = {
>> + {
>> + .name = "default",
>> + .type = AVMEDIA_TYPE_VIDEO,
>> + .config_props = tblend_config_output,
>> + },
>> + { NULL }
>> +};
>> +
>> +AVFilter ff_vf_tblend = {
>> + .name = "tblend",
>> + .description = NULL_IF_CONFIG_SMALL("Blend successive frames."),
>> + .priv_size = sizeof(BlendContext),
>> + .priv_class = &blend_class,
>> + .query_formats = query_formats,
>> + .init = init,
>> + .uninit = uninit,
>> + .inputs = tblend_inputs,
>> + .outputs = tblend_outputs,
>
>> + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
>> AVFILTER_FLAG_SLICE_THREADS,
>
> Does the timeline works as expected? Like, is it caching the previous
> frame even when skipping segment?
>
>> +};
>> --
>> 1.8.3.2
>>
>
>> From 65455601f502dd148bcd140f8d70eef104b1bdbe Mon Sep 17 00:00:00 2001
>> From: Stefano Sabatini <stefasab at gmail.com>
>> Date: Thu, 4 Dec 2014 12:34:30 +0100
>> Subject: [PATCH] lavfi/blend: add difference128 mode
>>
>> ---
>> libavfilter/vf_blend.c | 4 ++++
>> 1 file changed, 4 insertions(+)
>>
>> diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c
>> index 3c1572c..e73ea35 100644
>> --- a/libavfilter/vf_blend.c
>> +++ b/libavfilter/vf_blend.c
>> @@ -41,6 +41,7 @@ enum BlendMode {
>> BLEND_BURN,
>> BLEND_DARKEN,
>> BLEND_DIFFERENCE,
>> + BLEND_DIFFERENCE128,
>> BLEND_DIVIDE,
>> BLEND_DODGE,
>> BLEND_EXCLUSION,
>> @@ -114,6 +115,7 @@ static const AVOption blend_options[] = {
>> { "burn", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_BURN}, 0,
>> 0, FLAGS, "mode" },
>> { "darken", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DARKEN}, 0,
>> 0, FLAGS, "mode" },
>> { "difference", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DIFFERENCE}, 0,
>> 0, FLAGS, "mode" },
>> + { "difference128", "", 0, AV_OPT_TYPE_CONST,
>> {.i64=BLEND_DIFFERENCE128}, 0, 0, FLAGS, "mode" },
>> { "divide", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DIVIDE}, 0,
>> 0, FLAGS, "mode" },
>> { "dodge", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DODGE}, 0,
>> 0, FLAGS, "mode" },
>> { "exclusion", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_EXCLUSION}, 0,
>> 0, FLAGS, "mode" },
>> @@ -192,6 +194,7 @@ DEFINE_BLEND(subtract, FFMAX(0, A - B))
>> DEFINE_BLEND(multiply, MULTIPLY(1, A, B))
>> DEFINE_BLEND(negation, 255 - FFABS(255 - A - B))
>> DEFINE_BLEND(difference, FFABS(A - B))
>> +DEFINE_BLEND(difference128, av_clip_uint8(128 + A - B))
>> DEFINE_BLEND(screen, SCREEN(1, A, B))
>> DEFINE_BLEND(overlay, (A < 128) ? MULTIPLY(2, A, B) : SCREEN(2, A,
>> B))
>> DEFINE_BLEND(hardlight, (B < 128) ? MULTIPLY(2, B, A) : SCREEN(2, B,
>> A))
>> @@ -315,6 +318,7 @@ static av_cold int init(AVFilterContext *ctx)
>> case BLEND_BURN: param->blend = blend_burn; break;
>> case BLEND_DARKEN: param->blend = blend_darken; break;
>> case BLEND_DIFFERENCE: param->blend = blend_difference; break;
>> + case BLEND_DIFFERENCE128: param->blend = blend_difference128;
>> break;
>> case BLEND_DIVIDE: param->blend = blend_divide; break;
>> case BLEND_DODGE: param->blend = blend_dodge; break;
>> case BLEND_EXCLUSION: param->blend = blend_exclusion; break;
>
> I'm not a maintainer of blend but it looks OK (assuming previous comments
> are honored).
The new difference mode is useful, thanks.
>
> Would be nice to complete doc but I suppose you won't forget them.
>
> Thank you.
>
> [...]
>
> --
> Clement B.
>
More information about the ffmpeg-devel
mailing list