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 /libavfilter/vf_fade.c | |
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>
Diffstat (limited to 'libavfilter/vf_fade.c')
-rw-r--r-- | libavfilter/vf_fade.c | 170 |
1 files changed, 170 insertions, 0 deletions
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}}, +}; |