1 /*
2 * Copyright (c) 2010 Brandon Mintern
3 * Copyright (c) 2007 Bobby Bingham
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg 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.
11 *
12 * FFmpeg 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.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * video fade filter
25 * based heavily on vf_negate.c by Bobby Bingham
26 */
27
39
44
48
51
67
69 {
71
74
76 // If duration (seconds) is non-zero, assume that we are not fading based on frames
77 s->
nb_frames = 0;
// Mostly to clean up logging
78 }
79
80 // Choose what to log. If both time-based and frame-based options, both lines will be in the log
83 "type:%s start_frame:%d nb_frames:%d alpha:%d\n",
86 }
89 "type:%s start_time:%f duration:%f alpha:%d\n",
92 }
93
95 return 0;
96 }
97
99 {
111 };
117 };
118
121 else
123 return 0;
124 }
125
131 };
132
134 {
137
140
142 1 :
146
147 /* use CCIR601/709 black level for studio-level pixel non-alpha components */
150 /* 32768 = 1 << 15, it is an integer representation
151 * of 0.5 and is for rounding. */
153 return 0;
154 }
155
158 int do_alpha, int step)
159 {
160 int i, j;
166
167 for (i = slice_start; i <
slice_end; i++) {
169 for (j = 0; j < frame->
width; j++) {
170 #define INTERP(c_name, c_idx) av_clip_uint8(((c[c_idx]<<16) + ((int)p[c_name] - (int)c[c_idx]) * s->factor + (1<<15)) >> 16)
171 p[r_idx] =
INTERP(r_idx, 0);
172 p[g_idx] =
INTERP(g_idx, 1);
173 p[b_idx] =
INTERP(b_idx, 2);
174 if (do_alpha)
175 p[a_idx] =
INTERP(a_idx, 3);
176 p += step;
177 }
178 }
179 }
180
182 int nb_jobs)
183 {
186 int slice_start = (frame->
height * jobnr ) / nb_jobs;
188
190 else if (s->
bpp == 3)
filter_rgb(s, frame, slice_start, slice_end, 0, 3);
191 else if (s->
bpp == 4)
filter_rgb(s, frame, slice_start, slice_end, 0, 4);
193
194 return 0;
195 }
196
198 int nb_jobs)
199 {
202 int slice_start = (frame->
height * jobnr ) / nb_jobs;
204 int i, j;
205
206 for (i = slice_start; i <
slice_end; i++) {
208 for (j = 0; j < frame->
width * s->
bpp; j++) {
209 /* s->factor is using 16 lower-order bits for decimal
210 * places. 32768 = 1 << 15, it is an integer representation
211 * of 0.5 and is for rounding. */
213 p++;
214 }
215 }
216
217 return 0;
218 }
219
221 int nb_jobs)
222 {
225 int i, j, plane;
228 int slice_start = (height * jobnr ) / nb_jobs;
229 int slice_end = (height * (jobnr+1)) / nb_jobs;
230
231 for (plane = 1; plane < 3; plane++) {
232 for (i = slice_start; i <
slice_end; i++) {
234 for (j = 0; j <
width; j++) {
235 /* 8421367 = ((128 << 1) + 1) << 15. It is an integer
236 * representation of 128.5. The .5 is for rounding
237 * purposes. */
238 *p = ((*p - 128) * s->
factor + 8421367) >> 16;
239 p++;
240 }
241 }
242 }
243
244 return 0;
245 }
246
248 int nb_jobs)
249 {
253 int slice_start = (frame->
height * jobnr ) / nb_jobs;
255 int i, j;
256
257 for (i = slice_start; i <
slice_end; i++) {
260 for (j = 0; j < frame->
width; j++) {
261 /* s->factor is using 16 lower-order bits for decimal
262 * places. 32768 = 1 << 15, it is an integer representation
263 * of 0.5 and is for rounding. */
265 p += step;
266 }
267 }
268
269 return 0;
270 }
271
273 {
277
278 // Calculate Fade assuming this is a Fade In
283 // Time to start fading
285
286 // Save start time in case we are starting based on frames and fading based on time
289 }
290
291 // Save start frame in case we are starting based on time and fading based on frames
294 }
295 }
296 }
299 // Fading based on frame count
303 }
304
305 } else {
306 // Fading based on duration
312 }
313 }
314 }
317 }
318
320
321 // Invert fade_factor if Fading Out
324 }
325
326 if (s->
factor < UINT16_MAX) {
333 } else {
334 /* luma, or rgb plane in case of black */
337
338 if (frame->
data[1] && frame->
data[2]) {
339 /* chroma planes */
342 }
343 }
344 }
345
347 }
348
349
350 #define OFFSET(x) offsetof(FadeContext, x)
351 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
352
358 { "start_frame", "Number of the first frame to which to apply the effect.",
360 { "s", "Number of the first frame to which to apply the effect.",
362 { "nb_frames", "Number of frames to which the effect should be applied.",
364 { "n", "Number of frames to which the effect should be applied.",
367 { "start_time", "Number of seconds of the beginning of the effect.",
369 { "st", "Number of seconds of the beginning of the effect.",
371 { "duration", "Duration of the effect in seconds.",
373 { "d", "Duration of the effect in seconds.",
378 };
379
381
383 {
388 .needs_writable = 1,
389 },
391 };
392
394 {
397 },
399 };
400
406 .priv_class = &fade_class,
408 .
inputs = avfilter_vf_fade_inputs,
409 .
outputs = avfilter_vf_fade_outputs,
411 };