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/pixdesc.h"
36 int factor
, fade_per_frame
;
37 unsigned int frame_index
, start_frame
, stop_frame
;
41 static av_cold
int init(AVFilterContext
*ctx
, const char *args
)
43 FadeContext
*fade
= ctx
->priv
;
44 unsigned int nb_frames
;
48 sscanf(args
, " %3[^:]:%u:%u", in_out
, &fade
->start_frame
, &nb_frames
) != 3) {
49 av_log(ctx
, AV_LOG_ERROR
,
50 "Expected 3 arguments '(in|out):#:#':'%s'\n", args
);
51 return AVERROR(EINVAL
);
54 nb_frames
= nb_frames
? nb_frames
: 1;
55 fade
->fade_per_frame
= (1 << 16) / nb_frames
;
56 if (!strcmp(in_out
, "in"))
58 else if (!strcmp(in_out
, "out")) {
59 fade
->fade_per_frame
= -fade
->fade_per_frame
;
60 fade
->factor
= (1 << 16);
62 av_log(ctx
, AV_LOG_ERROR
,
63 "first argument must be 'in' or 'out':'%s'\n", in_out
);
64 return AVERROR(EINVAL
);
66 fade
->stop_frame
= fade
->start_frame
+ nb_frames
;
68 av_log(ctx
, AV_LOG_VERBOSE
,
69 "type:%s start_frame:%d nb_frames:%d\n",
70 in_out
, fade
->start_frame
, nb_frames
);
74 static int query_formats(AVFilterContext
*ctx
)
76 static const enum AVPixelFormat pix_fmts
[] = {
77 AV_PIX_FMT_YUV444P
, AV_PIX_FMT_YUV422P
, AV_PIX_FMT_YUV420P
,
78 AV_PIX_FMT_YUV411P
, AV_PIX_FMT_YUV410P
,
79 AV_PIX_FMT_YUVJ444P
, AV_PIX_FMT_YUVJ422P
, AV_PIX_FMT_YUVJ420P
,
80 AV_PIX_FMT_YUV440P
, AV_PIX_FMT_YUVJ440P
,
81 AV_PIX_FMT_RGB24
, AV_PIX_FMT_BGR24
,
85 ff_set_common_formats(ctx
, ff_make_format_list(pix_fmts
));
89 static int config_props(AVFilterLink
*inlink
)
91 FadeContext
*fade
= inlink
->dst
->priv
;
92 const AVPixFmtDescriptor
*pixdesc
= av_pix_fmt_desc_get(inlink
->format
);
94 fade
->hsub
= pixdesc
->log2_chroma_w
;
95 fade
->vsub
= pixdesc
->log2_chroma_h
;
97 fade
->bpp
= av_get_bits_per_pixel(pixdesc
) >> 3;
101 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*frame
)
103 FadeContext
*fade
= inlink
->dst
->priv
;
107 if (fade
->factor
< UINT16_MAX
) {
108 /* luma or rgb plane */
109 for (i
= 0; i
< frame
->height
; i
++) {
110 p
= frame
->data
[0] + i
* frame
->linesize
[0];
111 for (j
= 0; j
< inlink
->w
* fade
->bpp
; j
++) {
112 /* fade->factor is using 16 lower-order bits for decimal
113 * places. 32768 = 1 << 15, it is an integer representation
114 * of 0.5 and is for rounding. */
115 *p
= (*p
* fade
->factor
+ 32768) >> 16;
120 if (frame
->data
[1] && frame
->data
[2]) {
122 for (plane
= 1; plane
< 3; plane
++) {
123 for (i
= 0; i
< frame
->height
; i
++) {
124 p
= frame
->data
[plane
] + (i
>> fade
->vsub
) * frame
->linesize
[plane
];
125 for (j
= 0; j
< inlink
->w
>> fade
->hsub
; j
++) {
126 /* 8421367 = ((128 << 1) + 1) << 15. It is an integer
127 * representation of 128.5. The .5 is for rounding
129 *p
= ((*p
- 128) * fade
->factor
+ 8421367) >> 16;
137 if (fade
->frame_index
>= fade
->start_frame
&&
138 fade
->frame_index
<= fade
->stop_frame
)
139 fade
->factor
+= fade
->fade_per_frame
;
140 fade
->factor
= av_clip_uint16(fade
->factor
);
143 return ff_filter_frame(inlink
->dst
->outputs
[0], frame
);
146 static const AVFilterPad avfilter_vf_fade_inputs
[] = {
149 .type
= AVMEDIA_TYPE_VIDEO
,
150 .config_props
= config_props
,
151 .get_video_buffer
= ff_null_get_video_buffer
,
152 .filter_frame
= filter_frame
,
158 static const AVFilterPad avfilter_vf_fade_outputs
[] = {
161 .type
= AVMEDIA_TYPE_VIDEO
,
166 AVFilter avfilter_vf_fade
= {
168 .description
= NULL_IF_CONFIG_SMALL("Fade in/out input video"),
170 .priv_size
= sizeof(FadeContext
),
171 .query_formats
= query_formats
,
173 .inputs
= avfilter_vf_fade_inputs
,
174 .outputs
= avfilter_vf_fade_outputs
,