diff options
author | Brandon Mintern <bmintern@gmail.com> | 2011-02-21 12:02:57 +0100 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2011-04-03 08:47:16 +0200 |
commit | aadfc9ee747eeb37f9ea77c0cc56a88226b9d21b (patch) | |
tree | e7e9ddc9820ac3bcaf188c21790685dca299e116 | |
parent | 233ed6b314ee6b8d37d16a958f1bc309ae667393 (diff) | |
download | ffmpeg-aadfc9ee747eeb37f9ea77c0cc56a88226b9d21b.tar.gz |
lavfi: add fade filter
Port fade filter from libavfilter soc repo, with minor fixes by
Stefano.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Signed-off-by: Anton Khirnov <anton@khirnov.net>
-rw-r--r-- | doc/filters.texi | 33 | ||||
-rw-r--r-- | libavfilter/Makefile | 1 | ||||
-rw-r--r-- | libavfilter/allfilters.c | 1 | ||||
-rw-r--r-- | libavfilter/avfilter.h | 2 | ||||
-rw-r--r-- | libavfilter/vf_fade.c | 170 |
5 files changed, 206 insertions, 1 deletions
diff --git a/doc/filters.texi b/doc/filters.texi index 2bd7bf56ff..872afc6ca1 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -353,6 +353,39 @@ drawbox drawbox=10:20:200:60:red@@0.5" @end example +@section fade + +Apply fade-in/out effect to input video. + +It accepts the parameters: +@var{type}:@var{start_frame}:@var{nb_frames} + +@var{type} specifies if the effect type, can be either "in" for +fade-in, or "out" for a fade-out effect. + +@var{start_frame} specifies the number of the start frame for starting +to apply the fade effect. + +@var{nb_frames} specifies the number of frames for which the fade +effect has to last. At the end of the fade-in effect the output video +will have the same intensity as the input video, at the end of the +fade-out transition the output video will be completely black. + +A few usage examples follow, usable too as test scenarios. +@example +# fade in first 30 frames of video +fade=in:0:30 + +# fade out last 45 frames of a 200-frame video +fade=out:155:45 + +# fade in first 25 frames and fade out last 25 frames of a 1000-frame video +fade=in:0:25, fade=out:975:25 + +# make first 5 frames black, then fade in from frame 5-24 +fade=in:5:20 +@end example + @section fifo Buffer input images and send them when they are requested. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index bbd820238a..f7bc98df98 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -26,6 +26,7 @@ OBJS-$(CONFIG_COPY_FILTER) += vf_copy.o OBJS-$(CONFIG_CROP_FILTER) += vf_crop.o OBJS-$(CONFIG_CROPDETECT_FILTER) += vf_cropdetect.o OBJS-$(CONFIG_DRAWBOX_FILTER) += vf_drawbox.o +OBJS-$(CONFIG_FADE_FILTER) += vf_fade.o OBJS-$(CONFIG_FIFO_FILTER) += vf_fifo.o OBJS-$(CONFIG_FORMAT_FILTER) += vf_format.o OBJS-$(CONFIG_FREI0R_FILTER) += vf_frei0r.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 6afd1d7ec3..34e87f5fd9 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -45,6 +45,7 @@ void avfilter_register_all(void) REGISTER_FILTER (CROP, crop, vf); REGISTER_FILTER (CROPDETECT, cropdetect, vf); REGISTER_FILTER (DRAWBOX, drawbox, vf); + REGISTER_FILTER (FADE, fade, vf); REGISTER_FILTER (FIFO, fifo, vf); REGISTER_FILTER (FORMAT, format, vf); REGISTER_FILTER (FREI0R, frei0r, vf); diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index b4af4859d3..74435813fa 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -26,7 +26,7 @@ #include "libavutil/samplefmt.h" #define LIBAVFILTER_VERSION_MAJOR 1 -#define LIBAVFILTER_VERSION_MINOR 76 +#define LIBAVFILTER_VERSION_MINOR 77 #define LIBAVFILTER_VERSION_MICRO 0 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c new file mode 100644 index 0000000000..203a18656e --- /dev/null +++ b/libavfilter/vf_fade.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2010 Brandon Mintern + * Copyright (c) 2007 Bobby Bingham + * + * 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 + * video fade filter + * based heavily on vf_negate.c by Bobby Bingham + */ + +#include "libavutil/pixdesc.h" +#include "avfilter.h" + +typedef struct { + int factor, fade_per_frame; + unsigned int frame_index, start_frame, stop_frame; + int hsub, vsub, bpp; +} FadeContext; + +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) +{ + FadeContext *fade = ctx->priv; + unsigned int nb_frames; + char in_out[4]; + + if (!args || + sscanf(args, " %3[^:]:%u:%u", in_out, &fade->start_frame, &nb_frames) != 3) { + av_log(ctx, AV_LOG_ERROR, + "Expected 3 arguments '(in|out):#:#':'%s'\n", args); + return AVERROR(EINVAL); + } + + nb_frames = nb_frames ? nb_frames : 1; + fade->fade_per_frame = (1 << 16) / nb_frames; + if (!strcmp(in_out, "in")) + fade->factor = 0; + else if (!strcmp(in_out, "out")) { + fade->fade_per_frame = -fade->fade_per_frame; + fade->factor = (1 << 16); + } else { + av_log(ctx, AV_LOG_ERROR, + "first argument must be 'in' or 'out':'%s'\n", in_out); + return AVERROR(EINVAL); + } + fade->stop_frame = fade->start_frame + nb_frames; + + av_log(ctx, AV_LOG_INFO, + "type:%s start_frame:%d nb_frames:%d\n", + in_out, fade->start_frame, nb_frames); + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + const static enum PixelFormat pix_fmts[] = { + PIX_FMT_YUV444P, PIX_FMT_YUV422P, PIX_FMT_YUV420P, + PIX_FMT_YUV411P, PIX_FMT_YUV410P, + PIX_FMT_YUVJ444P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ420P, + PIX_FMT_YUV440P, PIX_FMT_YUVJ440P, + PIX_FMT_RGB24, PIX_FMT_BGR24, + PIX_FMT_NONE + }; + + avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); + return 0; +} + +static int config_props(AVFilterLink *inlink) +{ + FadeContext *fade = inlink->dst->priv; + const AVPixFmtDescriptor *pixdesc = &av_pix_fmt_descriptors[inlink->format]; + + fade->hsub = pixdesc->log2_chroma_w; + fade->vsub = pixdesc->log2_chroma_h; + + fade->bpp = av_get_bits_per_pixel(pixdesc) >> 3; + return 0; +} + +static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) +{ + FadeContext *fade = inlink->dst->priv; + AVFilterBufferRef *outpic = inlink->cur_buf; + uint8_t *p; + int i, j, plane; + + if (fade->factor < 65536) { + /* luma or rgb plane */ + for (i = 0; i < h; i++) { + p = outpic->data[0] + (y+i) * outpic->linesize[0]; + for (j = 0; j < inlink->w * fade->bpp; j++) { + /* fade->factor is using 16 lower-order bits for decimal + * places. 32768 = 1 << 15, it is an integer representation + * of 0.5 and is for rounding. */ + *p = (*p * fade->factor + 32768) >> 16; + p++; + } + } + + if (outpic->data[0] && outpic->data[1]) { + /* chroma planes */ + for (plane = 1; plane < 3; plane++) { + for (i = 0; i < h; i++) { + p = outpic->data[plane] + ((y+i) >> fade->vsub) * outpic->linesize[plane]; + for (j = 0; j < inlink->w >> fade->hsub; j++) { + /* 8421367 = ((128 << 1) + 1) << 15. It is an integer + * representation of 128.5. The .5 is for rounding + * purposes. */ + *p = ((*p - 128) * fade->factor + 8421367) >> 16; + p++; + } + } + } + } + } + + avfilter_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); +} + +static void end_frame(AVFilterLink *inlink) +{ + FadeContext *fade = inlink->dst->priv; + + avfilter_end_frame(inlink->dst->outputs[0]); + + if (fade->frame_index >= fade->start_frame && + fade->frame_index <= fade->stop_frame) + fade->factor += fade->fade_per_frame; + fade->factor = av_clip_uint16(fade->factor); + fade->frame_index++; +} + +AVFilter avfilter_vf_fade = { + .name = "fade", + .description = NULL_IF_CONFIG_SMALL("Fade in/out input video"), + .init = init, + .priv_size = sizeof(FadeContext), + .query_formats = query_formats, + + .inputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_props, + .get_video_buffer = avfilter_null_get_video_buffer, + .start_frame = avfilter_null_start_frame, + .draw_slice = draw_slice, + .end_frame = end_frame, + .min_perms = AV_PERM_READ | AV_PERM_WRITE, + .rej_perms = AV_PERM_PRESERVE, }, + { .name = NULL}}, + .outputs = (AVFilterPad[]) {{ .name = "default", + .type = AVMEDIA_TYPE_VIDEO, }, + { .name = NULL}}, +}; |