FFmpeg
af_afade.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2015 Paul B Mahol
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file
23  * fade audio filter
24  */
25 
26 #include "config_components.h"
27 
28 #include "libavutil/opt.h"
29 #include "audio.h"
30 #include "avfilter.h"
31 #include "filters.h"
32 #include "internal.h"
33 
34 typedef struct AudioFadeContext {
35  const AVClass *class;
36  int type;
37  int curve, curve2;
38  int64_t nb_samples;
39  int64_t start_sample;
40  int64_t duration;
41  int64_t start_time;
42  int overlap;
43  int cf0_eof;
45  int64_t pts;
46 
47  void (*fade_samples)(uint8_t **dst, uint8_t * const *src,
48  int nb_samples, int channels, int direction,
49  int64_t start, int64_t range, int curve);
50  void (*crossfade_samples)(uint8_t **dst, uint8_t * const *cf0,
51  uint8_t * const *cf1,
52  int nb_samples, int channels,
53  int curve0, int curve1);
55 
57 
58 #define OFFSET(x) offsetof(AudioFadeContext, x)
59 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
60 #define TFLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
61 
62  static const enum AVSampleFormat sample_fmts[] = {
68  };
69 
70 static double fade_gain(int curve, int64_t index, int64_t range)
71 {
72 #define CUBE(a) ((a)*(a)*(a))
73  double gain;
74 
75  gain = av_clipd(1.0 * index / range, 0, 1.0);
76 
77  switch (curve) {
78  case QSIN:
79  gain = sin(gain * M_PI / 2.0);
80  break;
81  case IQSIN:
82  /* 0.6... = 2 / M_PI */
83  gain = 0.6366197723675814 * asin(gain);
84  break;
85  case ESIN:
86  gain = 1.0 - cos(M_PI / 4.0 * (CUBE(2.0*gain - 1) + 1));
87  break;
88  case HSIN:
89  gain = (1.0 - cos(gain * M_PI)) / 2.0;
90  break;
91  case IHSIN:
92  /* 0.3... = 1 / M_PI */
93  gain = 0.3183098861837907 * acos(1 - 2 * gain);
94  break;
95  case EXP:
96  /* -11.5... = 5*ln(0.1) */
97  gain = exp(-11.512925464970227 * (1 - gain));
98  break;
99  case LOG:
100  gain = av_clipd(1 + 0.2 * log10(gain), 0, 1.0);
101  break;
102  case PAR:
103  gain = 1 - sqrt(1 - gain);
104  break;
105  case IPAR:
106  gain = (1 - (1 - gain) * (1 - gain));
107  break;
108  case QUA:
109  gain *= gain;
110  break;
111  case CUB:
112  gain = CUBE(gain);
113  break;
114  case SQU:
115  gain = sqrt(gain);
116  break;
117  case CBR:
118  gain = cbrt(gain);
119  break;
120  case DESE:
121  gain = gain <= 0.5 ? cbrt(2 * gain) / 2: 1 - cbrt(2 * (1 - gain)) / 2;
122  break;
123  case DESI:
124  gain = gain <= 0.5 ? CUBE(2 * gain) / 2: 1 - CUBE(2 * (1 - gain)) / 2;
125  break;
126  case LOSI: {
127  const double a = 1. / (1. - 0.787) - 1;
128  double A = 1. / (1.0 + exp(0 -((gain-0.5) * a * 2.0)));
129  double B = 1. / (1.0 + exp(a));
130  double C = 1. / (1.0 + exp(0-a));
131  gain = (A - B) / (C - B);
132  }
133  break;
134  case SINC:
135  gain = gain >= 1.0 ? 1.0 : sin(M_PI * (1.0 - gain)) / (M_PI * (1.0 - gain));
136  break;
137  case ISINC:
138  gain = gain <= 0.0 ? 0.0 : 1.0 - sin(M_PI * gain) / (M_PI * gain);
139  break;
140  case NONE:
141  gain = 1.0;
142  break;
143  }
144 
145  return gain;
146 }
147 
148 #define FADE_PLANAR(name, type) \
149 static void fade_samples_## name ##p(uint8_t **dst, uint8_t * const *src, \
150  int nb_samples, int channels, int dir, \
151  int64_t start, int64_t range, int curve) \
152 { \
153  int i, c; \
154  \
155  for (i = 0; i < nb_samples; i++) { \
156  double gain = fade_gain(curve, start + i * dir, range); \
157  for (c = 0; c < channels; c++) { \
158  type *d = (type *)dst[c]; \
159  const type *s = (type *)src[c]; \
160  \
161  d[i] = s[i] * gain; \
162  } \
163  } \
164 }
165 
166 #define FADE(name, type) \
167 static void fade_samples_## name (uint8_t **dst, uint8_t * const *src, \
168  int nb_samples, int channels, int dir, \
169  int64_t start, int64_t range, int curve) \
170 { \
171  type *d = (type *)dst[0]; \
172  const type *s = (type *)src[0]; \
173  int i, c, k = 0; \
174  \
175  for (i = 0; i < nb_samples; i++) { \
176  double gain = fade_gain(curve, start + i * dir, range); \
177  for (c = 0; c < channels; c++, k++) \
178  d[k] = s[k] * gain; \
179  } \
180 }
181 
182 FADE_PLANAR(dbl, double)
183 FADE_PLANAR(flt, float)
184 FADE_PLANAR(s16, int16_t)
185 FADE_PLANAR(s32, int32_t)
186 
187 FADE(dbl, double)
188 FADE(flt, float)
189 FADE(s16, int16_t)
190 FADE(s32, int32_t)
191 
192 static int config_output(AVFilterLink *outlink)
193 {
194  AVFilterContext *ctx = outlink->src;
195  AudioFadeContext *s = ctx->priv;
196 
197  switch (outlink->format) {
198  case AV_SAMPLE_FMT_DBL: s->fade_samples = fade_samples_dbl; break;
199  case AV_SAMPLE_FMT_DBLP: s->fade_samples = fade_samples_dblp; break;
200  case AV_SAMPLE_FMT_FLT: s->fade_samples = fade_samples_flt; break;
201  case AV_SAMPLE_FMT_FLTP: s->fade_samples = fade_samples_fltp; break;
202  case AV_SAMPLE_FMT_S16: s->fade_samples = fade_samples_s16; break;
203  case AV_SAMPLE_FMT_S16P: s->fade_samples = fade_samples_s16p; break;
204  case AV_SAMPLE_FMT_S32: s->fade_samples = fade_samples_s32; break;
205  case AV_SAMPLE_FMT_S32P: s->fade_samples = fade_samples_s32p; break;
206  }
207 
208  if (s->duration)
209  s->nb_samples = av_rescale(s->duration, outlink->sample_rate, AV_TIME_BASE);
210  s->duration = 0;
211  if (s->start_time)
212  s->start_sample = av_rescale(s->start_time, outlink->sample_rate, AV_TIME_BASE);
213  s->start_time = 0;
214 
215  return 0;
216 }
217 
218 #if CONFIG_AFADE_FILTER
219 
220 static const AVOption afade_options[] = {
221  { "type", "set the fade direction", OFFSET(type), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, TFLAGS, "type" },
222  { "t", "set the fade direction", OFFSET(type), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, TFLAGS, "type" },
223  { "in", "fade-in", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, TFLAGS, "type" },
224  { "out", "fade-out", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, TFLAGS, "type" },
225  { "start_sample", "set number of first sample to start fading", OFFSET(start_sample), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, TFLAGS },
226  { "ss", "set number of first sample to start fading", OFFSET(start_sample), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, TFLAGS },
227  { "nb_samples", "set number of samples for fade duration", OFFSET(nb_samples), AV_OPT_TYPE_INT64, {.i64 = 44100}, 1, INT64_MAX, TFLAGS },
228  { "ns", "set number of samples for fade duration", OFFSET(nb_samples), AV_OPT_TYPE_INT64, {.i64 = 44100}, 1, INT64_MAX, TFLAGS },
229  { "start_time", "set time to start fading", OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, INT64_MAX, TFLAGS },
230  { "st", "set time to start fading", OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, INT64_MAX, TFLAGS },
231  { "duration", "set fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, INT64_MAX, TFLAGS },
232  { "d", "set fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, INT64_MAX, TFLAGS },
233  { "curve", "set fade curve type", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1, TFLAGS, "curve" },
234  { "c", "set fade curve type", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1, TFLAGS, "curve" },
235  { "nofade", "no fade; keep audio as-is", 0, AV_OPT_TYPE_CONST, {.i64 = NONE }, 0, 0, TFLAGS, "curve" },
236  { "tri", "linear slope", 0, AV_OPT_TYPE_CONST, {.i64 = TRI }, 0, 0, TFLAGS, "curve" },
237  { "qsin", "quarter of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = QSIN }, 0, 0, TFLAGS, "curve" },
238  { "esin", "exponential sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = ESIN }, 0, 0, TFLAGS, "curve" },
239  { "hsin", "half of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = HSIN }, 0, 0, TFLAGS, "curve" },
240  { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64 = LOG }, 0, 0, TFLAGS, "curve" },
241  { "ipar", "inverted parabola", 0, AV_OPT_TYPE_CONST, {.i64 = IPAR }, 0, 0, TFLAGS, "curve" },
242  { "qua", "quadratic", 0, AV_OPT_TYPE_CONST, {.i64 = QUA }, 0, 0, TFLAGS, "curve" },
243  { "cub", "cubic", 0, AV_OPT_TYPE_CONST, {.i64 = CUB }, 0, 0, TFLAGS, "curve" },
244  { "squ", "square root", 0, AV_OPT_TYPE_CONST, {.i64 = SQU }, 0, 0, TFLAGS, "curve" },
245  { "cbr", "cubic root", 0, AV_OPT_TYPE_CONST, {.i64 = CBR }, 0, 0, TFLAGS, "curve" },
246  { "par", "parabola", 0, AV_OPT_TYPE_CONST, {.i64 = PAR }, 0, 0, TFLAGS, "curve" },
247  { "exp", "exponential", 0, AV_OPT_TYPE_CONST, {.i64 = EXP }, 0, 0, TFLAGS, "curve" },
248  { "iqsin", "inverted quarter of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = IQSIN}, 0, 0, TFLAGS, "curve" },
249  { "ihsin", "inverted half of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = IHSIN}, 0, 0, TFLAGS, "curve" },
250  { "dese", "double-exponential seat", 0, AV_OPT_TYPE_CONST, {.i64 = DESE }, 0, 0, TFLAGS, "curve" },
251  { "desi", "double-exponential sigmoid", 0, AV_OPT_TYPE_CONST, {.i64 = DESI }, 0, 0, TFLAGS, "curve" },
252  { "losi", "logistic sigmoid", 0, AV_OPT_TYPE_CONST, {.i64 = LOSI }, 0, 0, TFLAGS, "curve" },
253  { "sinc", "sine cardinal function", 0, AV_OPT_TYPE_CONST, {.i64 = SINC }, 0, 0, TFLAGS, "curve" },
254  { "isinc", "inverted sine cardinal function", 0, AV_OPT_TYPE_CONST, {.i64 = ISINC}, 0, 0, TFLAGS, "curve" },
255  { NULL }
256 };
257 
258 AVFILTER_DEFINE_CLASS(afade);
259 
260 static av_cold int init(AVFilterContext *ctx)
261 {
262  AudioFadeContext *s = ctx->priv;
263 
264  if (INT64_MAX - s->nb_samples < s->start_sample)
265  return AVERROR(EINVAL);
266 
267  return 0;
268 }
269 
270 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
271 {
272  AudioFadeContext *s = inlink->dst->priv;
273  AVFilterLink *outlink = inlink->dst->outputs[0];
274  int nb_samples = buf->nb_samples;
275  AVFrame *out_buf;
276  int64_t cur_sample = av_rescale_q(buf->pts, inlink->time_base, (AVRational){1, inlink->sample_rate});
277 
278  if ((!s->type && (s->start_sample + s->nb_samples < cur_sample)) ||
279  ( s->type && (cur_sample + nb_samples < s->start_sample)))
280  return ff_filter_frame(outlink, buf);
281 
282  if (av_frame_is_writable(buf)) {
283  out_buf = buf;
284  } else {
285  out_buf = ff_get_audio_buffer(outlink, nb_samples);
286  if (!out_buf)
287  return AVERROR(ENOMEM);
288  av_frame_copy_props(out_buf, buf);
289  }
290 
291  if ((!s->type && (cur_sample + nb_samples < s->start_sample)) ||
292  ( s->type && (s->start_sample + s->nb_samples < cur_sample))) {
293  av_samples_set_silence(out_buf->extended_data, 0, nb_samples,
294  out_buf->ch_layout.nb_channels, out_buf->format);
295  } else {
296  int64_t start;
297 
298  if (!s->type)
299  start = cur_sample - s->start_sample;
300  else
301  start = s->start_sample + s->nb_samples - cur_sample;
302 
303  s->fade_samples(out_buf->extended_data, buf->extended_data,
304  nb_samples, buf->ch_layout.nb_channels,
305  s->type ? -1 : 1, start,
306  s->nb_samples, s->curve);
307  }
308 
309  if (buf != out_buf)
310  av_frame_free(&buf);
311 
312  return ff_filter_frame(outlink, out_buf);
313 }
314 
315 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
316  char *res, int res_len, int flags)
317 {
318  int ret;
319 
320  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
321  if (ret < 0)
322  return ret;
323 
324  return config_output(ctx->outputs[0]);
325 }
326 
327 static const AVFilterPad avfilter_af_afade_inputs[] = {
328  {
329  .name = "default",
330  .type = AVMEDIA_TYPE_AUDIO,
331  .filter_frame = filter_frame,
332  },
333 };
334 
335 static const AVFilterPad avfilter_af_afade_outputs[] = {
336  {
337  .name = "default",
338  .type = AVMEDIA_TYPE_AUDIO,
339  .config_props = config_output,
340  },
341 };
342 
343 const AVFilter ff_af_afade = {
344  .name = "afade",
345  .description = NULL_IF_CONFIG_SMALL("Fade in/out input audio."),
346  .priv_size = sizeof(AudioFadeContext),
347  .init = init,
348  FILTER_INPUTS(avfilter_af_afade_inputs),
349  FILTER_OUTPUTS(avfilter_af_afade_outputs),
351  .priv_class = &afade_class,
352  .process_command = process_command,
354 };
355 
356 #endif /* CONFIG_AFADE_FILTER */
357 
358 #if CONFIG_ACROSSFADE_FILTER
359 
360 static const AVOption acrossfade_options[] = {
361  { "nb_samples", "set number of samples for cross fade duration", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 44100}, 1, INT32_MAX/10, FLAGS },
362  { "ns", "set number of samples for cross fade duration", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 44100}, 1, INT32_MAX/10, FLAGS },
363  { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, 60000000, FLAGS },
364  { "d", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, 60000000, FLAGS },
365  { "overlap", "overlap 1st stream end with 2nd stream start", OFFSET(overlap), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, FLAGS },
366  { "o", "overlap 1st stream end with 2nd stream start", OFFSET(overlap), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, FLAGS },
367  { "curve1", "set fade curve type for 1st stream", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1, FLAGS, "curve" },
368  { "c1", "set fade curve type for 1st stream", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1, FLAGS, "curve" },
369  { "nofade", "no fade; keep audio as-is", 0, AV_OPT_TYPE_CONST, {.i64 = NONE }, 0, 0, FLAGS, "curve" },
370  { "tri", "linear slope", 0, AV_OPT_TYPE_CONST, {.i64 = TRI }, 0, 0, FLAGS, "curve" },
371  { "qsin", "quarter of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = QSIN }, 0, 0, FLAGS, "curve" },
372  { "esin", "exponential sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = ESIN }, 0, 0, FLAGS, "curve" },
373  { "hsin", "half of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = HSIN }, 0, 0, FLAGS, "curve" },
374  { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64 = LOG }, 0, 0, FLAGS, "curve" },
375  { "ipar", "inverted parabola", 0, AV_OPT_TYPE_CONST, {.i64 = IPAR }, 0, 0, FLAGS, "curve" },
376  { "qua", "quadratic", 0, AV_OPT_TYPE_CONST, {.i64 = QUA }, 0, 0, FLAGS, "curve" },
377  { "cub", "cubic", 0, AV_OPT_TYPE_CONST, {.i64 = CUB }, 0, 0, FLAGS, "curve" },
378  { "squ", "square root", 0, AV_OPT_TYPE_CONST, {.i64 = SQU }, 0, 0, FLAGS, "curve" },
379  { "cbr", "cubic root", 0, AV_OPT_TYPE_CONST, {.i64 = CBR }, 0, 0, FLAGS, "curve" },
380  { "par", "parabola", 0, AV_OPT_TYPE_CONST, {.i64 = PAR }, 0, 0, FLAGS, "curve" },
381  { "exp", "exponential", 0, AV_OPT_TYPE_CONST, {.i64 = EXP }, 0, 0, FLAGS, "curve" },
382  { "iqsin", "inverted quarter of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = IQSIN}, 0, 0, FLAGS, "curve" },
383  { "ihsin", "inverted half of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = IHSIN}, 0, 0, FLAGS, "curve" },
384  { "dese", "double-exponential seat", 0, AV_OPT_TYPE_CONST, {.i64 = DESE }, 0, 0, FLAGS, "curve" },
385  { "desi", "double-exponential sigmoid", 0, AV_OPT_TYPE_CONST, {.i64 = DESI }, 0, 0, FLAGS, "curve" },
386  { "losi", "logistic sigmoid", 0, AV_OPT_TYPE_CONST, {.i64 = LOSI }, 0, 0, FLAGS, "curve" },
387  { "sinc", "sine cardinal function", 0, AV_OPT_TYPE_CONST, {.i64 = SINC }, 0, 0, FLAGS, "curve" },
388  { "isinc", "inverted sine cardinal function", 0, AV_OPT_TYPE_CONST, {.i64 = ISINC}, 0, 0, FLAGS, "curve" },
389  { "curve2", "set fade curve type for 2nd stream", OFFSET(curve2), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1, FLAGS, "curve" },
390  { "c2", "set fade curve type for 2nd stream", OFFSET(curve2), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1, FLAGS, "curve" },
391  { NULL }
392 };
393 
394 AVFILTER_DEFINE_CLASS(acrossfade);
395 
396 #define CROSSFADE_PLANAR(name, type) \
397 static void crossfade_samples_## name ##p(uint8_t **dst, uint8_t * const *cf0, \
398  uint8_t * const *cf1, \
399  int nb_samples, int channels, \
400  int curve0, int curve1) \
401 { \
402  int i, c; \
403  \
404  for (i = 0; i < nb_samples; i++) { \
405  double gain0 = fade_gain(curve0, nb_samples - 1 - i, nb_samples); \
406  double gain1 = fade_gain(curve1, i, nb_samples); \
407  for (c = 0; c < channels; c++) { \
408  type *d = (type *)dst[c]; \
409  const type *s0 = (type *)cf0[c]; \
410  const type *s1 = (type *)cf1[c]; \
411  \
412  d[i] = s0[i] * gain0 + s1[i] * gain1; \
413  } \
414  } \
415 }
416 
417 #define CROSSFADE(name, type) \
418 static void crossfade_samples_## name (uint8_t **dst, uint8_t * const *cf0, \
419  uint8_t * const *cf1, \
420  int nb_samples, int channels, \
421  int curve0, int curve1) \
422 { \
423  type *d = (type *)dst[0]; \
424  const type *s0 = (type *)cf0[0]; \
425  const type *s1 = (type *)cf1[0]; \
426  int i, c, k = 0; \
427  \
428  for (i = 0; i < nb_samples; i++) { \
429  double gain0 = fade_gain(curve0, nb_samples - 1 - i, nb_samples); \
430  double gain1 = fade_gain(curve1, i, nb_samples); \
431  for (c = 0; c < channels; c++, k++) \
432  d[k] = s0[k] * gain0 + s1[k] * gain1; \
433  } \
434 }
435 
436 CROSSFADE_PLANAR(dbl, double)
437 CROSSFADE_PLANAR(flt, float)
438 CROSSFADE_PLANAR(s16, int16_t)
439 CROSSFADE_PLANAR(s32, int32_t)
440 
441 CROSSFADE(dbl, double)
442 CROSSFADE(flt, float)
443 CROSSFADE(s16, int16_t)
444 CROSSFADE(s32, int32_t)
445 
446 static int activate(AVFilterContext *ctx)
447 {
448  AudioFadeContext *s = ctx->priv;
449  AVFilterLink *outlink = ctx->outputs[0];
450  AVFrame *in = NULL, *out, *cf[2] = { NULL };
451  int ret = 0, nb_samples, status;
452  int64_t pts;
453 
455 
456  if (s->crossfade_is_over) {
457  ret = ff_inlink_consume_frame(ctx->inputs[1], &in);
458  if (ret > 0) {
459  in->pts = s->pts;
460  s->pts += av_rescale_q(in->nb_samples,
461  (AVRational){ 1, outlink->sample_rate }, outlink->time_base);
462  return ff_filter_frame(outlink, in);
463  } else if (ret < 0) {
464  return ret;
465  } else if (ff_inlink_acknowledge_status(ctx->inputs[1], &status, &pts)) {
466  ff_outlink_set_status(ctx->outputs[0], status, pts);
467  return 0;
468  } else if (!ret) {
469  if (ff_outlink_frame_wanted(ctx->outputs[0])) {
470  ff_inlink_request_frame(ctx->inputs[1]);
471  return 0;
472  }
473  }
474  }
475 
476  nb_samples = ff_inlink_queued_samples(ctx->inputs[0]);
477  if (nb_samples > s->nb_samples) {
478  nb_samples -= s->nb_samples;
479  ret = ff_inlink_consume_samples(ctx->inputs[0], nb_samples, nb_samples, &in);
480  if (ret < 0)
481  return ret;
482  in->pts = s->pts;
483  s->pts += av_rescale_q(in->nb_samples,
484  (AVRational){ 1, outlink->sample_rate }, outlink->time_base);
485  return ff_filter_frame(outlink, in);
486  } else if (s->cf0_eof && nb_samples >= s->nb_samples &&
487  ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples) {
488  if (s->overlap) {
489  out = ff_get_audio_buffer(outlink, s->nb_samples);
490  if (!out)
491  return AVERROR(ENOMEM);
492 
493  ret = ff_inlink_consume_samples(ctx->inputs[0], s->nb_samples, s->nb_samples, &cf[0]);
494  if (ret < 0) {
495  av_frame_free(&out);
496  return ret;
497  }
498 
499  ret = ff_inlink_consume_samples(ctx->inputs[1], s->nb_samples, s->nb_samples, &cf[1]);
500  if (ret < 0) {
501  av_frame_free(&out);
502  return ret;
503  }
504 
505  s->crossfade_samples(out->extended_data, cf[0]->extended_data,
506  cf[1]->extended_data,
507  s->nb_samples, out->ch_layout.nb_channels,
508  s->curve, s->curve2);
509  out->pts = s->pts;
510  s->pts += av_rescale_q(s->nb_samples,
511  (AVRational){ 1, outlink->sample_rate }, outlink->time_base);
512  s->crossfade_is_over = 1;
513  av_frame_free(&cf[0]);
514  av_frame_free(&cf[1]);
515  return ff_filter_frame(outlink, out);
516  } else {
517  out = ff_get_audio_buffer(outlink, s->nb_samples);
518  if (!out)
519  return AVERROR(ENOMEM);
520 
521  ret = ff_inlink_consume_samples(ctx->inputs[0], s->nb_samples, s->nb_samples, &cf[0]);
522  if (ret < 0) {
523  av_frame_free(&out);
524  return ret;
525  }
526 
527  s->fade_samples(out->extended_data, cf[0]->extended_data, s->nb_samples,
528  outlink->ch_layout.nb_channels, -1, s->nb_samples - 1, s->nb_samples, s->curve);
529  out->pts = s->pts;
530  s->pts += av_rescale_q(s->nb_samples,
531  (AVRational){ 1, outlink->sample_rate }, outlink->time_base);
532  av_frame_free(&cf[0]);
533  ret = ff_filter_frame(outlink, out);
534  if (ret < 0)
535  return ret;
536 
537  out = ff_get_audio_buffer(outlink, s->nb_samples);
538  if (!out)
539  return AVERROR(ENOMEM);
540 
541  ret = ff_inlink_consume_samples(ctx->inputs[1], s->nb_samples, s->nb_samples, &cf[1]);
542  if (ret < 0) {
543  av_frame_free(&out);
544  return ret;
545  }
546 
547  s->fade_samples(out->extended_data, cf[1]->extended_data, s->nb_samples,
548  outlink->ch_layout.nb_channels, 1, 0, s->nb_samples, s->curve2);
549  out->pts = s->pts;
550  s->pts += av_rescale_q(s->nb_samples,
551  (AVRational){ 1, outlink->sample_rate }, outlink->time_base);
552  s->crossfade_is_over = 1;
553  av_frame_free(&cf[1]);
554  return ff_filter_frame(outlink, out);
555  }
556  } else if (ff_outlink_frame_wanted(ctx->outputs[0])) {
557  if (!s->cf0_eof && ff_outlink_get_status(ctx->inputs[0])) {
558  s->cf0_eof = 1;
559  }
560  if (ff_outlink_get_status(ctx->inputs[1])) {
562  return 0;
563  }
564  if (!s->cf0_eof)
565  ff_inlink_request_frame(ctx->inputs[0]);
566  else
567  ff_inlink_request_frame(ctx->inputs[1]);
568  return 0;
569  }
570 
571  return ret;
572 }
573 
574 static int acrossfade_config_output(AVFilterLink *outlink)
575 {
576  AVFilterContext *ctx = outlink->src;
577  AudioFadeContext *s = ctx->priv;
578 
579  outlink->time_base = ctx->inputs[0]->time_base;
580 
581  switch (outlink->format) {
582  case AV_SAMPLE_FMT_DBL: s->crossfade_samples = crossfade_samples_dbl; break;
583  case AV_SAMPLE_FMT_DBLP: s->crossfade_samples = crossfade_samples_dblp; break;
584  case AV_SAMPLE_FMT_FLT: s->crossfade_samples = crossfade_samples_flt; break;
585  case AV_SAMPLE_FMT_FLTP: s->crossfade_samples = crossfade_samples_fltp; break;
586  case AV_SAMPLE_FMT_S16: s->crossfade_samples = crossfade_samples_s16; break;
587  case AV_SAMPLE_FMT_S16P: s->crossfade_samples = crossfade_samples_s16p; break;
588  case AV_SAMPLE_FMT_S32: s->crossfade_samples = crossfade_samples_s32; break;
589  case AV_SAMPLE_FMT_S32P: s->crossfade_samples = crossfade_samples_s32p; break;
590  }
591 
592  config_output(outlink);
593 
594  return 0;
595 }
596 
597 static const AVFilterPad avfilter_af_acrossfade_inputs[] = {
598  {
599  .name = "crossfade0",
600  .type = AVMEDIA_TYPE_AUDIO,
601  },
602  {
603  .name = "crossfade1",
604  .type = AVMEDIA_TYPE_AUDIO,
605  },
606 };
607 
608 static const AVFilterPad avfilter_af_acrossfade_outputs[] = {
609  {
610  .name = "default",
611  .type = AVMEDIA_TYPE_AUDIO,
612  .config_props = acrossfade_config_output,
613  },
614 };
615 
616 const AVFilter ff_af_acrossfade = {
617  .name = "acrossfade",
618  .description = NULL_IF_CONFIG_SMALL("Cross fade two input audio streams."),
619  .priv_size = sizeof(AudioFadeContext),
620  .activate = activate,
621  .priv_class = &acrossfade_class,
622  FILTER_INPUTS(avfilter_af_acrossfade_inputs),
623  FILTER_OUTPUTS(avfilter_af_acrossfade_outputs),
625 };
626 
627 #endif /* CONFIG_ACROSSFADE_FILTER */
ff_get_audio_buffer
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:100
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:66
status
they must not be accessed directly The fifo field contains the frames that are queued in the input for processing by the filter The status_in and status_out fields contains the queued status(EOF or error) of the link
AudioFadeContext::type
int type
Definition: af_afade.c:36
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
AudioFadeContext::curve2
int curve2
Definition: af_afade.c:37
ff_af_afade
const AVFilter ff_af_afade
out
FILE * out
Definition: movenc.c:54
NONE
@ NONE
Definition: af_afade.c:56
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:999
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
QUA
@ QUA
Definition: af_afade.c:56
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:111
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:325
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:432
AVOption
AVOption.
Definition: opt.h:251
IPAR
@ IPAR
Definition: af_afade.c:56
AV_SAMPLE_FMT_S32P
@ AV_SAMPLE_FMT_S32P
signed 32 bits, planar
Definition: samplefmt.h:65
AV_OPT_TYPE_DURATION
@ AV_OPT_TYPE_DURATION
Definition: opt.h:239
AudioFadeContext::fade_samples
void(* fade_samples)(uint8_t **dst, uint8_t *const *src, int nb_samples, int channels, int direction, int64_t start, int64_t range, int curve)
Definition: af_afade.c:47
config_output
static int config_output(AVFilterLink *outlink)
Definition: af_afade.c:192
NB_CURVES
@ NB_CURVES
Definition: af_afade.c:56
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:175
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:300
DESE
@ DESE
Definition: af_afade.c:56
DESI
@ DESI
Definition: af_afade.c:56
init
static int init
Definition: av_tx.c:47
A
#define A(x)
Definition: vp56_arith.h:28
ff_inlink_consume_frame
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition: avfilter.c:1394
FADE
#define FADE(name, type)
Definition: af_afade.c:166
FF_FILTER_FORWARD_STATUS_BACK_ALL
#define FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, filter)
Forward the status on an output link to all input links.
Definition: filters.h:212
ISINC
@ ISINC
Definition: af_afade.c:56
CUBE
#define CUBE(a)
AVFrame::ch_layout
AVChannelLayout ch_layout
Channel layout of the audio data.
Definition: frame.h:704
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
pts
static int64_t pts
Definition: transcode_aac.c:654
OFFSET
#define OFFSET(x)
Definition: af_afade.c:58
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:49
cbrt
#define cbrt
Definition: tablegen.h:35
C
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i you should get a foobar png with Lena edge detected That s your new playground is ready Some little details about what s going which in turn will define variables for the build system and the C
Definition: writing_filters.txt:58
ff_af_acrossfade
const AVFilter ff_af_acrossfade
AudioFadeContext::cf0_eof
int cf0_eof
Definition: af_afade.c:43
av_cold
#define av_cold
Definition: attributes.h:90
CUB
@ CUB
Definition: af_afade.c:56
QSIN
@ QSIN
Definition: af_afade.c:56
duration
int64_t duration
Definition: movenc.c:64
IHSIN
@ IHSIN
Definition: af_afade.c:56
ff_outlink_set_status
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition: filters.h:189
ff_inlink_request_frame
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Definition: avfilter.c:1511
s
#define s(width, name)
Definition: cbs_vp9.c:256
TRI
@ TRI
Definition: af_afade.c:56
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
HSIN
@ HSIN
Definition: af_afade.c:56
AV_OPT_TYPE_INT64
@ AV_OPT_TYPE_INT64
Definition: opt.h:226
filters.h
ctx
AVFormatContext * ctx
Definition: movenc.c:48
FLAGS
#define FLAGS
Definition: af_afade.c:59
channels
channels
Definition: aptx.h:32
IQSIN
@ IQSIN
Definition: af_afade.c:56
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
fade_gain
static double fade_gain(int curve, int64_t index, int64_t range)
Definition: af_afade.c:70
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:190
AudioFadeContext::crossfade_is_over
int crossfade_is_over
Definition: af_afade.c:44
AudioFadeContext::crossfade_samples
void(* crossfade_samples)(uint8_t **dst, uint8_t *const *cf0, uint8_t *const *cf1, int nb_samples, int channels, int curve0, int curve1)
Definition: af_afade.c:50
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
ff_inlink_consume_samples
int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, AVFrame **rframe)
Take samples from the link's FIFO and update the link's stats.
Definition: avfilter.c:1413
NULL
#define NULL
Definition: coverity.c:32
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:596
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AudioFadeContext::start_sample
int64_t start_sample
Definition: af_afade.c:39
activate
filter_frame For filters that do not use the activate() callback
filter_frame
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
Definition: dolby_e.c:1058
exp
int8_t exp
Definition: eval.c:72
ff_inlink_acknowledge_status
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition: avfilter.c:1348
index
int index
Definition: gxfenc.c:89
SQU
@ SQU
Definition: af_afade.c:56
CurveType
CurveType
Definition: af_afade.c:56
TFLAGS
#define TFLAGS
Definition: af_afade.c:60
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
process_command
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition: af_acrusher.c:306
start_time
static int64_t start_time
Definition: ffplay.c:331
AudioFadeContext::curve
int curve
Definition: af_afade.c:37
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:56
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
FILTER_SAMPLEFMTS_ARRAY
#define FILTER_SAMPLEFMTS_ARRAY(array)
Definition: internal.h:173
av_frame_is_writable
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:523
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:412
AudioFadeContext::duration
int64_t duration
Definition: af_afade.c:40
EXP
@ EXP
Definition: af_afade.c:56
ff_filter_process_command
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
Definition: avfilter.c:863
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
M_PI
#define M_PI
Definition: mathematics.h:52
AV_SAMPLE_FMT_S16P
@ AV_SAMPLE_FMT_S16P
signed 16 bits, planar
Definition: samplefmt.h:64
internal.h
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition: avfilter.h:152
AVFILTER_DEFINE_CLASS
#define AVFILTER_DEFINE_CLASS(fname)
Definition: internal.h:325
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:405
SINC
@ SINC
Definition: af_afade.c:56
AV_TIME_BASE
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:254
AVFrame::extended_data
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:386
AudioFadeContext::pts
int64_t pts
Definition: af_afade.c:45
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:55
AudioFadeContext::overlap
int overlap
Definition: af_afade.c:42
AV_SAMPLE_FMT_S16
@ AV_SAMPLE_FMT_S16
signed 16 bits
Definition: samplefmt.h:58
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:55
CBR
@ CBR
Definition: af_afade.c:56
ff_inlink_queued_samples
int ff_inlink_queued_samples(AVFilterLink *link)
Definition: avfilter.c:1373
av_rescale
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:129
AudioFadeContext::start_time
int64_t start_time
Definition: af_afade.c:41
av_samples_set_silence
int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples, int nb_channels, enum AVSampleFormat sample_fmt)
Fill an audio buffer with silence.
Definition: samplefmt.c:246
AVFilter
Filter definition.
Definition: avfilter.h:171
LOSI
@ LOSI
Definition: af_afade.c:56
ret
ret
Definition: filter_design.txt:187
B
#define B
Definition: huffyuvdsp.h:32
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
avfilter.h
AV_SAMPLE_FMT_DBLP
@ AV_SAMPLE_FMT_DBLP
double, planar
Definition: samplefmt.h:67
FADE_PLANAR
#define FADE_PLANAR(name, type)
Definition: af_afade.c:148
ff_outlink_get_status
int ff_outlink_get_status(AVFilterLink *link)
Get the status on an output link.
Definition: avfilter.c:1534
AVFilterContext
An instance of a filter.
Definition: avfilter.h:408
audio.h
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:191
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
int32_t
int32_t
Definition: audioconvert.c:56
ESIN
@ ESIN
Definition: af_afade.c:56
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
sample_fmts
static enum AVSampleFormat sample_fmts[]
Definition: af_afade.c:62
ff_outlink_frame_wanted
the definition of that something depends on the semantic of the filter The callback must examine the status of the filter s links and proceed accordingly The status of output links is stored in the status_in and status_out fields and tested by the ff_outlink_frame_wanted() function. If this function returns true
AV_SAMPLE_FMT_DBL
@ AV_SAMPLE_FMT_DBL
double
Definition: samplefmt.h:61
PAR
@ PAR
Definition: af_afade.c:56
AV_SAMPLE_FMT_S32
@ AV_SAMPLE_FMT_S32
signed 32 bits
Definition: samplefmt.h:59
AudioFadeContext::nb_samples
int64_t nb_samples
Definition: af_afade.c:38
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
AudioFadeContext
Definition: af_afade.c:34
AV_SAMPLE_FMT_FLT
@ AV_SAMPLE_FMT_FLT
float
Definition: samplefmt.h:60
av_clipd
av_clipd
Definition: af_crystalizer.c:132
LOG
@ LOG
Definition: af_afade.c:56