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
diff --git a/Changelog b/Changelog index 5f38aea..41fdf18 100644 --- a/Changelog +++ b/Changelog @@ -15,6 +15,7 @@ version <next>: - ffserver supports codec private options - creating DASH compatible fragmented MP4, MPEG-DASH segmenting muxer - WebP muxer with animated WebP support +- tdiff filter version 2.4: diff --git a/doc/filters.texi b/doc/filters.texi index 8c16c7a..9882da7 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -8394,6 +8394,10 @@ Useful for enlarging pixel art images without reducing sharpness. @section swapuv Swap U & V plane. +@section tdiff + +Show difference between consecutive frames. + @section telecine Apply telecine process to the video. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 2c56e38..3217c99 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -97,6 +97,7 @@ OBJS-$(CONFIG_BLACKDETECT_FILTER) += vf_blackdetect.o OBJS-$(CONFIG_BLACKFRAME_FILTER) += vf_blackframe.o OBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o dualinput.o framesync.o OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o +OBJS-$(CONFIG_CDIFF_FILTER) += vf_cdiff.o OBJS-$(CONFIG_CODECVIEW_FILTER) += vf_codecview.o OBJS-$(CONFIG_COLORBALANCE_FILTER) += vf_colorbalance.o OBJS-$(CONFIG_COLORCHANNELMIXER_FILTER) += vf_colorchannelmixer.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 2352d44..4d065a9 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -201,6 +201,7 @@ void avfilter_register_all(void) REGISTER_FILTER(SUBTITLES, subtitles, vf); REGISTER_FILTER(SUPER2XSAI, super2xsai, vf); REGISTER_FILTER(SWAPUV, swapuv, vf); + REGISTER_FILTER(TDIFF, tdiff, vf); REGISTER_FILTER(TELECINE, telecine, vf); REGISTER_FILTER(THUMBNAIL, thumbnail, vf); REGISTER_FILTER(TILE, tile, vf); diff --git a/libavfilter/vf_tdiff.c b/libavfilter/vf_tdiff.c new file mode 100644 index 0000000..82dceef --- /dev/null +++ b/libavfilter/vf_tdiff.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2014 Stefano Sabatini + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Consecutive frames diff filter. + */ + +#include "libavutil/colorspace.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" +#include "libavutil/eval.h" +#include "libavutil/pixdesc.h" +#include "libavutil/parseutils.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct { + const AVClass *class; + AVFrame *prev_frame; +} TDiffContext; + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE + }; + + ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP; + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + TDiffContext *tdiff = inlink->dst->priv; + AVFilterLink *outlink = inlink->dst->outputs[0]; + + if (tdiff->prev_frame) { + int i, j; + + AVFrame *diff = ff_get_video_buffer(outlink, outlink->w, outlink->h); + av_frame_copy_props(frame, diff); + if (!diff) { + av_frame_free(&frame); + return AVERROR(ENOMEM); + } + + /* compute difference with previous frame */ + for (i = 0; i < frame->height; i++) { + uint8_t *pdiff = diff ->data[0] + i * diff ->linesize[0]; + uint8_t *pprev = tdiff->prev_frame->data[0] + i * tdiff->prev_frame->linesize[0]; + uint8_t *pthis = frame ->data[0] + i * frame ->linesize[0]; + for (j = 0; j < frame->width; j++) { + *pdiff++ = abs(*pthis++ - *pprev++); + } + } + + av_frame_free(&tdiff->prev_frame); + tdiff->prev_frame = frame; + return ff_filter_frame(outlink, diff); + } + tdiff->prev_frame = frame; + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + TDiffContext *tdiff = ctx->priv; + av_freep(&tdiff->prev_frame); +} + +static const AVOption tdiff_options[] = { + { NULL } +}; + +AVFILTER_DEFINE_CLASS(tdiff); + +static const AVFilterPad tdiff_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .needs_writable = 0, + }, + { NULL } +}; + +static const AVFilterPad tdiff_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vf_tdiff = { + .name = "tdiff", + .description = NULL_IF_CONFIG_SMALL("Show difference with previous frame."), + .priv_size = sizeof(TDiffContext), + .priv_class = &tdiff_class, + .query_formats = query_formats, + .uninit = uninit, + .inputs = tdiff_inputs, + .outputs = tdiff_outputs, +}; -- 1.8.3.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel