2 * Copyright (c) 2010 Brandon Mintern
3 * Copyright (c) 2007 Bobby Bingham
5 * This file is part of Libav.
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * based heavily on vf_negate.c by Bobby Bingham
28 #include "libavutil/common.h"
29 #include "libavutil/opt.h"
30 #include "libavutil/pixdesc.h"
42 int factor, fade_per_frame;
43 int start_frame, nb_frames;
44 unsigned int frame_index, stop_frame;
48 static av_cold int init(AVFilterContext *ctx, const char *args)
50 FadeContext *fade = ctx->priv;
52 fade->fade_per_frame = (1 << 16) / fade->nb_frames;
53 if (fade->type == FADE_IN) {
55 } else if (fade->type == FADE_OUT) {
56 fade->fade_per_frame = -fade->fade_per_frame;
57 fade->factor = (1 << 16);
59 fade->stop_frame = fade->start_frame + fade->nb_frames;
61 av_log(ctx, AV_LOG_VERBOSE,
62 "type:%s start_frame:%d nb_frames:%d\n",
63 fade->type == FADE_IN ? "in" : "out", fade->start_frame,
68 static int query_formats(AVFilterContext *ctx)
70 static const enum AVPixelFormat pix_fmts[] = {
71 AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P,
72 AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P,
73 AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P,
74 AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUVJ440P,
75 AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
79 ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
83 static int config_props(AVFilterLink *inlink)
85 FadeContext *fade = inlink->dst->priv;
86 const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(inlink->format);
88 fade->hsub = pixdesc->log2_chroma_w;
89 fade->vsub = pixdesc->log2_chroma_h;
91 fade->bpp = av_get_bits_per_pixel(pixdesc) >> 3;
95 static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
97 FadeContext *fade = inlink->dst->priv;
101 if (fade->factor < UINT16_MAX) {
102 /* luma or rgb plane */
103 for (i = 0; i < frame->height; i++) {
104 p = frame->data[0] + i * frame->linesize[0];
105 for (j = 0; j < inlink->w * fade->bpp; j++) {
106 /* fade->factor is using 16 lower-order bits for decimal
107 * places. 32768 = 1 << 15, it is an integer representation
108 * of 0.5 and is for rounding. */
109 *p = (*p * fade->factor + 32768) >> 16;
114 if (frame->data[1] && frame->data[2]) {
116 for (plane = 1; plane < 3; plane++) {
117 for (i = 0; i < frame->height; i++) {
118 p = frame->data[plane] + (i >> fade->vsub) * frame->linesize[plane];
119 for (j = 0; j < inlink->w >> fade->hsub; j++) {
120 /* 8421367 = ((128 << 1) + 1) << 15. It is an integer
121 * representation of 128.5. The .5 is for rounding
123 *p = ((*p - 128) * fade->factor + 8421367) >> 16;
131 if (fade->frame_index >= fade->start_frame &&
132 fade->frame_index <= fade->stop_frame)
133 fade->factor += fade->fade_per_frame;
134 fade->factor = av_clip_uint16(fade->factor);
137 return ff_filter_frame(inlink->dst->outputs[0], frame);
140 #define OFFSET(x) offsetof(FadeContext, x)
141 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM
142 static const AVOption options[] = {
143 { "type", "'in' or 'out' for fade-in/fade-out", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = FADE_IN }, FADE_IN, FADE_OUT, FLAGS, "type" },
144 { "in", "fade-in", 0, AV_OPT_TYPE_CONST, { .i64 = FADE_IN }, .unit = "type" },
145 { "out", "fade-out", 0, AV_OPT_TYPE_CONST, { .i64 = FADE_OUT }, .unit = "type" },
146 { "start_frame", "Number of the first frame to which to apply the effect.",
147 OFFSET(start_frame), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
148 { "nb_frames", "Number of frames to which the effect should be applied.",
149 OFFSET(nb_frames), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, FLAGS },
153 static const AVClass fade_class = {
154 .class_name = "fade",
155 .item_name = av_default_item_name,
157 .version = LIBAVUTIL_VERSION_INT,
160 static const AVFilterPad avfilter_vf_fade_inputs[] = {
163 .type = AVMEDIA_TYPE_VIDEO,
164 .config_props = config_props,
165 .get_video_buffer = ff_null_get_video_buffer,
166 .filter_frame = filter_frame,
172 static const AVFilterPad avfilter_vf_fade_outputs[] = {
175 .type = AVMEDIA_TYPE_VIDEO,
180 AVFilter avfilter_vf_fade = {
182 .description = NULL_IF_CONFIG_SMALL("Fade in/out input video"),
184 .priv_size = sizeof(FadeContext),
185 .priv_class = &fade_class,
186 .query_formats = query_formats,
188 .inputs = avfilter_vf_fade_inputs,
189 .outputs = avfilter_vf_fade_outputs,