FFmpeg
vf_xfade.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 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 #include "libavutil/imgutils.h"
22 #include "libavutil/eval.h"
23 #include "libavutil/opt.h"
24 #include "libavutil/pixfmt.h"
25 #include "avfilter.h"
26 #include "formats.h"
27 #include "internal.h"
28 #include "filters.h"
29 #include "video.h"
30 
32  CUSTOM = -1,
78 };
79 
80 typedef struct XFadeContext {
81  const AVClass *class;
82 
84  int64_t duration;
85  int64_t offset;
86  char *custom_str;
87 
88  int nb_planes;
89  int depth;
90  int is_rgb;
91 
92  int64_t duration_pts;
93  int64_t offset_pts;
94  int64_t first_pts;
95  int64_t last_pts;
96  int64_t pts;
99  int eof[2];
100  AVFrame *xf[2];
102  uint16_t black[4];
103  uint16_t white[4];
104 
105  void (*transitionf)(AVFilterContext *ctx, const AVFrame *a, const AVFrame *b, AVFrame *out, float progress,
106  int slice_start, int slice_end, int jobnr);
107 
109 } XFadeContext;
110 
111 static const char *const var_names[] = { "X", "Y", "W", "H", "A", "B", "PLANE", "P", NULL };
113 
114 typedef struct ThreadData {
115  const AVFrame *xf[2];
116  AVFrame *out;
117  float progress;
118 } ThreadData;
119 
121 {
122  static const enum AVPixelFormat pix_fmts[] = {
139  };
140 
142 }
143 
145 {
146  XFadeContext *s = ctx->priv;
147 
148  av_expr_free(s->e);
149 }
150 
151 #define OFFSET(x) offsetof(XFadeContext, x)
152 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
153 
154 static const AVOption xfade_options[] = {
155  { "transition", "set cross fade transition", OFFSET(transition), AV_OPT_TYPE_INT, {.i64=FADE}, -1, NB_TRANSITIONS-1, FLAGS, "transition" },
156  { "custom", "custom transition", 0, AV_OPT_TYPE_CONST, {.i64=CUSTOM}, 0, 0, FLAGS, "transition" },
157  { "fade", "fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADE}, 0, 0, FLAGS, "transition" },
158  { "wipeleft", "wipe left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPELEFT}, 0, 0, FLAGS, "transition" },
159  { "wiperight", "wipe right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPERIGHT}, 0, 0, FLAGS, "transition" },
160  { "wipeup", "wipe up transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEUP}, 0, 0, FLAGS, "transition" },
161  { "wipedown", "wipe down transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEDOWN}, 0, 0, FLAGS, "transition" },
162  { "slideleft", "slide left transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDELEFT}, 0, 0, FLAGS, "transition" },
163  { "slideright", "slide right transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDERIGHT}, 0, 0, FLAGS, "transition" },
164  { "slideup", "slide up transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEUP}, 0, 0, FLAGS, "transition" },
165  { "slidedown", "slide down transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEDOWN}, 0, 0, FLAGS, "transition" },
166  { "circlecrop", "circle crop transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLECROP}, 0, 0, FLAGS, "transition" },
167  { "rectcrop", "rect crop transition", 0, AV_OPT_TYPE_CONST, {.i64=RECTCROP}, 0, 0, FLAGS, "transition" },
168  { "distance", "distance transition", 0, AV_OPT_TYPE_CONST, {.i64=DISTANCE}, 0, 0, FLAGS, "transition" },
169  { "fadeblack", "fadeblack transition", 0, AV_OPT_TYPE_CONST, {.i64=FADEBLACK}, 0, 0, FLAGS, "transition" },
170  { "fadewhite", "fadewhite transition", 0, AV_OPT_TYPE_CONST, {.i64=FADEWHITE}, 0, 0, FLAGS, "transition" },
171  { "radial", "radial transition", 0, AV_OPT_TYPE_CONST, {.i64=RADIAL}, 0, 0, FLAGS, "transition" },
172  { "smoothleft", "smoothleft transition", 0, AV_OPT_TYPE_CONST, {.i64=SMOOTHLEFT}, 0, 0, FLAGS, "transition" },
173  { "smoothright","smoothright transition", 0, AV_OPT_TYPE_CONST, {.i64=SMOOTHRIGHT},0, 0, FLAGS, "transition" },
174  { "smoothup", "smoothup transition", 0, AV_OPT_TYPE_CONST, {.i64=SMOOTHUP}, 0, 0, FLAGS, "transition" },
175  { "smoothdown", "smoothdown transition", 0, AV_OPT_TYPE_CONST, {.i64=SMOOTHDOWN}, 0, 0, FLAGS, "transition" },
176  { "circleopen", "circleopen transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLEOPEN}, 0, 0, FLAGS, "transition" },
177  { "circleclose","circleclose transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLECLOSE},0, 0, FLAGS, "transition" },
178  { "vertopen", "vert open transition", 0, AV_OPT_TYPE_CONST, {.i64=VERTOPEN}, 0, 0, FLAGS, "transition" },
179  { "vertclose", "vert close transition", 0, AV_OPT_TYPE_CONST, {.i64=VERTCLOSE}, 0, 0, FLAGS, "transition" },
180  { "horzopen", "horz open transition", 0, AV_OPT_TYPE_CONST, {.i64=HORZOPEN}, 0, 0, FLAGS, "transition" },
181  { "horzclose", "horz close transition", 0, AV_OPT_TYPE_CONST, {.i64=HORZCLOSE}, 0, 0, FLAGS, "transition" },
182  { "dissolve", "dissolve transition", 0, AV_OPT_TYPE_CONST, {.i64=DISSOLVE}, 0, 0, FLAGS, "transition" },
183  { "pixelize", "pixelize transition", 0, AV_OPT_TYPE_CONST, {.i64=PIXELIZE}, 0, 0, FLAGS, "transition" },
184  { "diagtl", "diag tl transition", 0, AV_OPT_TYPE_CONST, {.i64=DIAGTL}, 0, 0, FLAGS, "transition" },
185  { "diagtr", "diag tr transition", 0, AV_OPT_TYPE_CONST, {.i64=DIAGTR}, 0, 0, FLAGS, "transition" },
186  { "diagbl", "diag bl transition", 0, AV_OPT_TYPE_CONST, {.i64=DIAGBL}, 0, 0, FLAGS, "transition" },
187  { "diagbr", "diag br transition", 0, AV_OPT_TYPE_CONST, {.i64=DIAGBR}, 0, 0, FLAGS, "transition" },
188  { "hlslice", "hl slice transition", 0, AV_OPT_TYPE_CONST, {.i64=HLSLICE}, 0, 0, FLAGS, "transition" },
189  { "hrslice", "hr slice transition", 0, AV_OPT_TYPE_CONST, {.i64=HRSLICE}, 0, 0, FLAGS, "transition" },
190  { "vuslice", "vu slice transition", 0, AV_OPT_TYPE_CONST, {.i64=VUSLICE}, 0, 0, FLAGS, "transition" },
191  { "vdslice", "vd slice transition", 0, AV_OPT_TYPE_CONST, {.i64=VDSLICE}, 0, 0, FLAGS, "transition" },
192  { "hblur", "hblur transition", 0, AV_OPT_TYPE_CONST, {.i64=HBLUR}, 0, 0, FLAGS, "transition" },
193  { "fadegrays", "fadegrays transition", 0, AV_OPT_TYPE_CONST, {.i64=FADEGRAYS}, 0, 0, FLAGS, "transition" },
194  { "wipetl", "wipe tl transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPETL}, 0, 0, FLAGS, "transition" },
195  { "wipetr", "wipe tr transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPETR}, 0, 0, FLAGS, "transition" },
196  { "wipebl", "wipe bl transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEBL}, 0, 0, FLAGS, "transition" },
197  { "wipebr", "wipe br transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEBR}, 0, 0, FLAGS, "transition" },
198  { "squeezeh", "squeeze h transition", 0, AV_OPT_TYPE_CONST, {.i64=SQUEEZEH}, 0, 0, FLAGS, "transition" },
199  { "squeezev", "squeeze v transition", 0, AV_OPT_TYPE_CONST, {.i64=SQUEEZEV}, 0, 0, FLAGS, "transition" },
200  { "zoomin", "zoom in transition", 0, AV_OPT_TYPE_CONST, {.i64=ZOOMIN}, 0, 0, FLAGS, "transition" },
201  { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=1000000}, 0, 60000000, FLAGS },
202  { "offset", "set cross fade start relative to first input stream", OFFSET(offset), AV_OPT_TYPE_DURATION, {.i64=0}, INT64_MIN, INT64_MAX, FLAGS },
203  { "expr", "set expression for custom transition", OFFSET(custom_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
204  { NULL }
205 };
206 
207 AVFILTER_DEFINE_CLASS(xfade);
208 
209 #define CUSTOM_TRANSITION(name, type, div) \
210 static void custom##name##_transition(AVFilterContext *ctx, \
211  const AVFrame *a, const AVFrame *b, AVFrame *out, \
212  float progress, \
213  int slice_start, int slice_end, int jobnr) \
214 { \
215  XFadeContext *s = ctx->priv; \
216  const int height = slice_end - slice_start; \
217  \
218  double values[VAR_VARS_NB]; \
219  values[VAR_W] = out->width; \
220  values[VAR_H] = out->height; \
221  values[VAR_PROGRESS] = progress; \
222  \
223  for (int p = 0; p < s->nb_planes; p++) { \
224  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
225  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
226  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
227  \
228  values[VAR_PLANE] = p; \
229  \
230  for (int y = 0; y < height; y++) { \
231  values[VAR_Y] = slice_start + y; \
232  for (int x = 0; x < out->width; x++) { \
233  values[VAR_X] = x; \
234  values[VAR_A] = xf0[x]; \
235  values[VAR_B] = xf1[x]; \
236  dst[x] = av_expr_eval(s->e, values, s); \
237  } \
238  \
239  dst += out->linesize[p] / div; \
240  xf0 += a->linesize[p] / div; \
241  xf1 += b->linesize[p] / div; \
242  } \
243  } \
244 }
245 
246 CUSTOM_TRANSITION(8, uint8_t, 1)
247 CUSTOM_TRANSITION(16, uint16_t, 2)
248 
249 static inline float mix(float a, float b, float mix)
250 {
251  return a * mix + b * (1.f - mix);
252 }
253 
254 static inline float fract(float a)
255 {
256  return a - floorf(a);
257 }
258 
259 static inline float smoothstep(float edge0, float edge1, float x)
260 {
261  float t;
262 
263  t = av_clipf((x - edge0) / (edge1 - edge0), 0.f, 1.f);
264 
265  return t * t * (3.f - 2.f * t);
266 }
267 
268 #define FADE_TRANSITION(name, type, div) \
269 static void fade##name##_transition(AVFilterContext *ctx, \
270  const AVFrame *a, const AVFrame *b, AVFrame *out, \
271  float progress, \
272  int slice_start, int slice_end, int jobnr) \
273 { \
274  XFadeContext *s = ctx->priv; \
275  const int height = slice_end - slice_start; \
276  \
277  for (int p = 0; p < s->nb_planes; p++) { \
278  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
279  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
280  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
281  \
282  for (int y = 0; y < height; y++) { \
283  for (int x = 0; x < out->width; x++) { \
284  dst[x] = mix(xf0[x], xf1[x], progress); \
285  } \
286  \
287  dst += out->linesize[p] / div; \
288  xf0 += a->linesize[p] / div; \
289  xf1 += b->linesize[p] / div; \
290  } \
291  } \
292 }
293 
294 FADE_TRANSITION(8, uint8_t, 1)
295 FADE_TRANSITION(16, uint16_t, 2)
296 
297 #define WIPELEFT_TRANSITION(name, type, div) \
298 static void wipeleft##name##_transition(AVFilterContext *ctx, \
299  const AVFrame *a, const AVFrame *b, AVFrame *out, \
300  float progress, \
301  int slice_start, int slice_end, int jobnr) \
302 { \
303  XFadeContext *s = ctx->priv; \
304  const int height = slice_end - slice_start; \
305  const int z = out->width * progress; \
306  \
307  for (int p = 0; p < s->nb_planes; p++) { \
308  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
309  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
310  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
311  \
312  for (int y = 0; y < height; y++) { \
313  for (int x = 0; x < out->width; x++) { \
314  dst[x] = x > z ? xf1[x] : xf0[x]; \
315  } \
316  \
317  dst += out->linesize[p] / div; \
318  xf0 += a->linesize[p] / div; \
319  xf1 += b->linesize[p] / div; \
320  } \
321  } \
322 }
323 
324 WIPELEFT_TRANSITION(8, uint8_t, 1)
325 WIPELEFT_TRANSITION(16, uint16_t, 2)
326 
327 #define WIPERIGHT_TRANSITION(name, type, div) \
328 static void wiperight##name##_transition(AVFilterContext *ctx, \
329  const AVFrame *a, const AVFrame *b, AVFrame *out, \
330  float progress, \
331  int slice_start, int slice_end, int jobnr) \
332 { \
333  XFadeContext *s = ctx->priv; \
334  const int height = slice_end - slice_start; \
335  const int z = out->width * (1.f - progress); \
336  \
337  for (int p = 0; p < s->nb_planes; p++) { \
338  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
339  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
340  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
341  \
342  for (int y = 0; y < height; y++) { \
343  for (int x = 0; x < out->width; x++) { \
344  dst[x] = x > z ? xf0[x] : xf1[x]; \
345  } \
346  \
347  dst += out->linesize[p] / div; \
348  xf0 += a->linesize[p] / div; \
349  xf1 += b->linesize[p] / div; \
350  } \
351  } \
352 }
353 
354 WIPERIGHT_TRANSITION(8, uint8_t, 1)
355 WIPERIGHT_TRANSITION(16, uint16_t, 2)
356 
357 #define WIPEUP_TRANSITION(name, type, div) \
358 static void wipeup##name##_transition(AVFilterContext *ctx, \
359  const AVFrame *a, const AVFrame *b, AVFrame *out, \
360  float progress, \
361  int slice_start, int slice_end, int jobnr) \
362 { \
363  XFadeContext *s = ctx->priv; \
364  const int height = slice_end - slice_start; \
365  const int z = out->height * progress; \
366  \
367  for (int p = 0; p < s->nb_planes; p++) { \
368  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
369  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
370  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
371  \
372  for (int y = 0; y < height; y++) { \
373  for (int x = 0; x < out->width; x++) { \
374  dst[x] = slice_start + y > z ? xf1[x] : xf0[x]; \
375  } \
376  \
377  dst += out->linesize[p] / div; \
378  xf0 += a->linesize[p] / div; \
379  xf1 += b->linesize[p] / div; \
380  } \
381  } \
382 }
383 
384 WIPEUP_TRANSITION(8, uint8_t, 1)
385 WIPEUP_TRANSITION(16, uint16_t, 2)
386 
387 #define WIPEDOWN_TRANSITION(name, type, div) \
388 static void wipedown##name##_transition(AVFilterContext *ctx, \
389  const AVFrame *a, const AVFrame *b, AVFrame *out, \
390  float progress, \
391  int slice_start, int slice_end, int jobnr) \
392 { \
393  XFadeContext *s = ctx->priv; \
394  const int height = slice_end - slice_start; \
395  const int z = out->height * (1.f - progress); \
396  \
397  for (int p = 0; p < s->nb_planes; p++) { \
398  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
399  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
400  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
401  \
402  for (int y = 0; y < height; y++) { \
403  for (int x = 0; x < out->width; x++) { \
404  dst[x] = slice_start + y > z ? xf0[x] : xf1[x]; \
405  } \
406  \
407  dst += out->linesize[p] / div; \
408  xf0 += a->linesize[p] / div; \
409  xf1 += b->linesize[p] / div; \
410  } \
411  } \
412 }
413 
414 WIPEDOWN_TRANSITION(8, uint8_t, 1)
415 WIPEDOWN_TRANSITION(16, uint16_t, 2)
416 
417 #define SLIDELEFT_TRANSITION(name, type, div) \
418 static void slideleft##name##_transition(AVFilterContext *ctx, \
419  const AVFrame *a, const AVFrame *b, AVFrame *out, \
420  float progress, \
421  int slice_start, int slice_end, int jobnr) \
422 { \
423  XFadeContext *s = ctx->priv; \
424  const int height = slice_end - slice_start; \
425  const int width = out->width; \
426  const int z = -progress * width; \
427  \
428  for (int p = 0; p < s->nb_planes; p++) { \
429  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
430  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
431  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
432  \
433  for (int y = 0; y < height; y++) { \
434  for (int x = 0; x < width; x++) { \
435  const int zx = z + x; \
436  const int zz = zx % width + width * (zx < 0); \
437  dst[x] = (zx > 0) && (zx < width) ? xf1[zz] : xf0[zz]; \
438  } \
439  \
440  dst += out->linesize[p] / div; \
441  xf0 += a->linesize[p] / div; \
442  xf1 += b->linesize[p] / div; \
443  } \
444  } \
445 }
446 
447 SLIDELEFT_TRANSITION(8, uint8_t, 1)
448 SLIDELEFT_TRANSITION(16, uint16_t, 2)
449 
450 #define SLIDERIGHT_TRANSITION(name, type, div) \
451 static void slideright##name##_transition(AVFilterContext *ctx, \
452  const AVFrame *a, const AVFrame *b, AVFrame *out, \
453  float progress, \
454  int slice_start, int slice_end, int jobnr) \
455 { \
456  XFadeContext *s = ctx->priv; \
457  const int height = slice_end - slice_start; \
458  const int width = out->width; \
459  const int z = progress * width; \
460  \
461  for (int p = 0; p < s->nb_planes; p++) { \
462  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
463  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
464  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
465  \
466  for (int y = 0; y < height; y++) { \
467  for (int x = 0; x < out->width; x++) { \
468  const int zx = z + x; \
469  const int zz = zx % width + width * (zx < 0); \
470  dst[x] = (zx > 0) && (zx < width) ? xf1[zz] : xf0[zz]; \
471  } \
472  \
473  dst += out->linesize[p] / div; \
474  xf0 += a->linesize[p] / div; \
475  xf1 += b->linesize[p] / div; \
476  } \
477  } \
478 }
479 
480 SLIDERIGHT_TRANSITION(8, uint8_t, 1)
481 SLIDERIGHT_TRANSITION(16, uint16_t, 2)
482 
483 #define SLIDEUP_TRANSITION(name, type, div) \
484 static void slideup##name##_transition(AVFilterContext *ctx, \
485  const AVFrame *a, const AVFrame *b, AVFrame *out, \
486  float progress, \
487  int slice_start, int slice_end, int jobnr) \
488 { \
489  XFadeContext *s = ctx->priv; \
490  const int height = out->height; \
491  const int z = -progress * height; \
492  \
493  for (int p = 0; p < s->nb_planes; p++) { \
494  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
495  \
496  for (int y = slice_start; y < slice_end; y++) { \
497  const int zy = z + y; \
498  const int zz = zy % height + height * (zy < 0); \
499  const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
500  const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
501  \
502  for (int x = 0; x < out->width; x++) { \
503  dst[x] = (zy > 0) && (zy < height) ? xf1[x] : xf0[x]; \
504  } \
505  \
506  dst += out->linesize[p] / div; \
507  } \
508  } \
509 }
510 
511 SLIDEUP_TRANSITION(8, uint8_t, 1)
512 SLIDEUP_TRANSITION(16, uint16_t, 2)
513 
514 #define SLIDEDOWN_TRANSITION(name, type, div) \
515 static void slidedown##name##_transition(AVFilterContext *ctx, \
516  const AVFrame *a, const AVFrame *b, AVFrame *out, \
517  float progress, \
518  int slice_start, int slice_end, int jobnr) \
519 { \
520  XFadeContext *s = ctx->priv; \
521  const int height = out->height; \
522  const int z = progress * height; \
523  \
524  for (int p = 0; p < s->nb_planes; p++) { \
525  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
526  \
527  for (int y = slice_start; y < slice_end; y++) { \
528  const int zy = z + y; \
529  const int zz = zy % height + height * (zy < 0); \
530  const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
531  const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
532  \
533  for (int x = 0; x < out->width; x++) { \
534  dst[x] = (zy > 0) && (zy < height) ? xf1[x] : xf0[x]; \
535  } \
536  \
537  dst += out->linesize[p] / div; \
538  } \
539  } \
540 }
541 
542 SLIDEDOWN_TRANSITION(8, uint8_t, 1)
543 SLIDEDOWN_TRANSITION(16, uint16_t, 2)
544 
545 #define CIRCLECROP_TRANSITION(name, type, div) \
546 static void circlecrop##name##_transition(AVFilterContext *ctx, \
547  const AVFrame *a, const AVFrame *b, AVFrame *out, \
548  float progress, \
549  int slice_start, int slice_end, int jobnr) \
550 { \
551  XFadeContext *s = ctx->priv; \
552  const int width = out->width; \
553  const int height = out->height; \
554  float z = powf(2.f * fabsf(progress - 0.5f), 3.f) * hypotf(width/2, height/2); \
555  \
556  for (int p = 0; p < s->nb_planes; p++) { \
557  const int bg = s->black[p]; \
558  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
559  \
560  for (int y = slice_start; y < slice_end; y++) { \
561  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
562  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
563  \
564  for (int x = 0; x < width; x++) { \
565  float dist = hypotf(x - width / 2, y - height / 2); \
566  int val = progress < 0.5f ? xf1[x] : xf0[x]; \
567  dst[x] = (z < dist) ? bg : val; \
568  } \
569  \
570  dst += out->linesize[p] / div; \
571  } \
572  } \
573 }
574 
575 CIRCLECROP_TRANSITION(8, uint8_t, 1)
576 CIRCLECROP_TRANSITION(16, uint16_t, 2)
577 
578 #define RECTCROP_TRANSITION(name, type, div) \
579 static void rectcrop##name##_transition(AVFilterContext *ctx, \
580  const AVFrame *a, const AVFrame *b, AVFrame *out, \
581  float progress, \
582  int slice_start, int slice_end, int jobnr) \
583 { \
584  XFadeContext *s = ctx->priv; \
585  const int width = out->width; \
586  const int height = out->height; \
587  int zh = fabsf(progress - 0.5f) * height; \
588  int zw = fabsf(progress - 0.5f) * width; \
589  \
590  for (int p = 0; p < s->nb_planes; p++) { \
591  const int bg = s->black[p]; \
592  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
593  \
594  for (int y = slice_start; y < slice_end; y++) { \
595  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
596  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
597  \
598  for (int x = 0; x < width; x++) { \
599  int dist = FFABS(x - width / 2) < zw && \
600  FFABS(y - height / 2) < zh; \
601  int val = progress < 0.5f ? xf1[x] : xf0[x]; \
602  dst[x] = !dist ? bg : val; \
603  } \
604  \
605  dst += out->linesize[p] / div; \
606  } \
607  } \
608 }
609 
610 RECTCROP_TRANSITION(8, uint8_t, 1)
611 RECTCROP_TRANSITION(16, uint16_t, 2)
612 
613 #define DISTANCE_TRANSITION(name, type, div) \
614 static void distance##name##_transition(AVFilterContext *ctx, \
615  const AVFrame *a, const AVFrame *b, AVFrame *out, \
616  float progress, \
617  int slice_start, int slice_end, int jobnr) \
618 { \
619  XFadeContext *s = ctx->priv; \
620  const int width = out->width; \
621  const float max = s->max_value; \
622  \
623  for (int y = slice_start; y < slice_end; y++) { \
624  for (int x = 0; x < width; x++) { \
625  float dist = 0.f; \
626  for (int p = 0; p < s->nb_planes; p++) { \
627  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
628  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
629  \
630  dist += (xf0[x] / max - xf1[x] / max) * \
631  (xf0[x] / max - xf1[x] / max); \
632  } \
633  \
634  dist = sqrtf(dist) <= progress; \
635  for (int p = 0; p < s->nb_planes; p++) { \
636  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
637  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
638  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
639  dst[x] = mix(mix(xf0[x], xf1[x], dist), xf1[x], progress); \
640  } \
641  } \
642  } \
643 }
644 
645 DISTANCE_TRANSITION(8, uint8_t, 1)
646 DISTANCE_TRANSITION(16, uint16_t, 2)
647 
648 #define FADEBLACK_TRANSITION(name, type, div) \
649 static void fadeblack##name##_transition(AVFilterContext *ctx, \
650  const AVFrame *a, const AVFrame *b, AVFrame *out, \
651  float progress, \
652  int slice_start, int slice_end, int jobnr) \
653 { \
654  XFadeContext *s = ctx->priv; \
655  const int height = slice_end - slice_start; \
656  const float phase = 0.2f; \
657  \
658  for (int p = 0; p < s->nb_planes; p++) { \
659  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
660  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
661  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
662  const int bg = s->black[p]; \
663  \
664  for (int y = 0; y < height; y++) { \
665  for (int x = 0; x < out->width; x++) { \
666  dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \
667  mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \
668  progress); \
669  } \
670  \
671  dst += out->linesize[p] / div; \
672  xf0 += a->linesize[p] / div; \
673  xf1 += b->linesize[p] / div; \
674  } \
675  } \
676 }
677 
678 FADEBLACK_TRANSITION(8, uint8_t, 1)
679 FADEBLACK_TRANSITION(16, uint16_t, 2)
680 
681 #define FADEWHITE_TRANSITION(name, type, div) \
682 static void fadewhite##name##_transition(AVFilterContext *ctx, \
683  const AVFrame *a, const AVFrame *b, AVFrame *out, \
684  float progress, \
685  int slice_start, int slice_end, int jobnr) \
686 { \
687  XFadeContext *s = ctx->priv; \
688  const int height = slice_end - slice_start; \
689  const float phase = 0.2f; \
690  \
691  for (int p = 0; p < s->nb_planes; p++) { \
692  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
693  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
694  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
695  const int bg = s->white[p]; \
696  \
697  for (int y = 0; y < height; y++) { \
698  for (int x = 0; x < out->width; x++) { \
699  dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \
700  mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \
701  progress); \
702  } \
703  \
704  dst += out->linesize[p] / div; \
705  xf0 += a->linesize[p] / div; \
706  xf1 += b->linesize[p] / div; \
707  } \
708  } \
709 }
710 
711 FADEWHITE_TRANSITION(8, uint8_t, 1)
712 FADEWHITE_TRANSITION(16, uint16_t, 2)
713 
714 #define RADIAL_TRANSITION(name, type, div) \
715 static void radial##name##_transition(AVFilterContext *ctx, \
716  const AVFrame *a, const AVFrame *b, AVFrame *out, \
717  float progress, \
718  int slice_start, int slice_end, int jobnr) \
719 { \
720  XFadeContext *s = ctx->priv; \
721  const int width = out->width; \
722  const int height = out->height; \
723  \
724  for (int y = slice_start; y < slice_end; y++) { \
725  for (int x = 0; x < width; x++) { \
726  const float smooth = atan2f(x - width / 2, y - height / 2) - \
727  (progress - 0.5f) * (M_PI * 2.5f); \
728  for (int p = 0; p < s->nb_planes; p++) { \
729  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
730  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
731  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
732  \
733  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
734  } \
735  } \
736  } \
737 }
738 
739 RADIAL_TRANSITION(8, uint8_t, 1)
740 RADIAL_TRANSITION(16, uint16_t, 2)
741 
742 #define SMOOTHLEFT_TRANSITION(name, type, div) \
743 static void smoothleft##name##_transition(AVFilterContext *ctx, \
744  const AVFrame *a, const AVFrame *b, AVFrame *out, \
745  float progress, \
746  int slice_start, int slice_end, int jobnr) \
747 { \
748  XFadeContext *s = ctx->priv; \
749  const int width = out->width; \
750  const float w = width; \
751  \
752  for (int y = slice_start; y < slice_end; y++) { \
753  for (int x = 0; x < width; x++) { \
754  const float smooth = 1.f + x / w - progress * 2.f; \
755  \
756  for (int p = 0; p < s->nb_planes; p++) { \
757  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
758  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
759  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
760  \
761  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
762  } \
763  } \
764  } \
765 }
766 
767 SMOOTHLEFT_TRANSITION(8, uint8_t, 1)
768 SMOOTHLEFT_TRANSITION(16, uint16_t, 2)
769 
770 #define SMOOTHRIGHT_TRANSITION(name, type, div) \
771 static void smoothright##name##_transition(AVFilterContext *ctx, \
772  const AVFrame *a, const AVFrame *b, AVFrame *out, \
773  float progress, \
774  int slice_start, int slice_end, int jobnr) \
775 { \
776  XFadeContext *s = ctx->priv; \
777  const int width = out->width; \
778  const float w = width; \
779  \
780  for (int y = slice_start; y < slice_end; y++) { \
781  for (int x = 0; x < width; x++) { \
782  const float smooth = 1.f + (w - 1 - x) / w - progress * 2.f; \
783  \
784  for (int p = 0; p < s->nb_planes; p++) { \
785  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
786  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
787  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
788  \
789  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
790  } \
791  } \
792  } \
793 }
794 
795 SMOOTHRIGHT_TRANSITION(8, uint8_t, 1)
796 SMOOTHRIGHT_TRANSITION(16, uint16_t, 2)
797 
798 #define SMOOTHUP_TRANSITION(name, type, div) \
799 static void smoothup##name##_transition(AVFilterContext *ctx, \
800  const AVFrame *a, const AVFrame *b, AVFrame *out, \
801  float progress, \
802  int slice_start, int slice_end, int jobnr) \
803 { \
804  XFadeContext *s = ctx->priv; \
805  const int width = out->width; \
806  const float h = out->height; \
807  \
808  for (int y = slice_start; y < slice_end; y++) { \
809  const float smooth = 1.f + y / h - progress * 2.f; \
810  for (int x = 0; x < width; x++) { \
811  for (int p = 0; p < s->nb_planes; p++) { \
812  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
813  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
814  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
815  \
816  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
817  } \
818  } \
819  } \
820 }
821 
822 SMOOTHUP_TRANSITION(8, uint8_t, 1)
823 SMOOTHUP_TRANSITION(16, uint16_t, 2)
824 
825 #define SMOOTHDOWN_TRANSITION(name, type, div) \
826 static void smoothdown##name##_transition(AVFilterContext *ctx, \
827  const AVFrame *a, const AVFrame *b, AVFrame *out, \
828  float progress, \
829  int slice_start, int slice_end, int jobnr) \
830 { \
831  XFadeContext *s = ctx->priv; \
832  const int width = out->width; \
833  const float h = out->height; \
834  \
835  for (int y = slice_start; y < slice_end; y++) { \
836  const float smooth = 1.f + (h - 1 - y) / h - progress * 2.f; \
837  for (int x = 0; x < width; x++) { \
838  for (int p = 0; p < s->nb_planes; p++) { \
839  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
840  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
841  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
842  \
843  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
844  } \
845  } \
846  } \
847 }
848 
849 SMOOTHDOWN_TRANSITION(8, uint8_t, 1)
850 SMOOTHDOWN_TRANSITION(16, uint16_t, 2)
851 
852 #define CIRCLEOPEN_TRANSITION(name, type, div) \
853 static void circleopen##name##_transition(AVFilterContext *ctx, \
854  const AVFrame *a, const AVFrame *b, AVFrame *out, \
855  float progress, \
856  int slice_start, int slice_end, int jobnr) \
857 { \
858  XFadeContext *s = ctx->priv; \
859  const int width = out->width; \
860  const int height = out->height; \
861  const float z = hypotf(width / 2, height / 2); \
862  const float p = (progress - 0.5f) * 3.f; \
863  \
864  for (int y = slice_start; y < slice_end; y++) { \
865  for (int x = 0; x < width; x++) { \
866  const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \
867  for (int p = 0; p < s->nb_planes; p++) { \
868  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
869  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
870  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
871  \
872  dst[x] = mix(xf0[x], xf1[x], smoothstep(0.f, 1.f, smooth)); \
873  } \
874  } \
875  } \
876 }
877 
878 CIRCLEOPEN_TRANSITION(8, uint8_t, 1)
879 CIRCLEOPEN_TRANSITION(16, uint16_t, 2)
880 
881 #define CIRCLECLOSE_TRANSITION(name, type, div) \
882 static void circleclose##name##_transition(AVFilterContext *ctx, \
883  const AVFrame *a, const AVFrame *b, AVFrame *out, \
884  float progress, \
885  int slice_start, int slice_end, int jobnr) \
886 { \
887  XFadeContext *s = ctx->priv; \
888  const int width = out->width; \
889  const int height = out->height; \
890  const float z = hypotf(width / 2, height / 2); \
891  const float p = (1.f - progress - 0.5f) * 3.f; \
892  \
893  for (int y = slice_start; y < slice_end; y++) { \
894  for (int x = 0; x < width; x++) { \
895  const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \
896  for (int p = 0; p < s->nb_planes; p++) { \
897  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
898  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
899  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
900  \
901  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
902  } \
903  } \
904  } \
905 }
906 
907 CIRCLECLOSE_TRANSITION(8, uint8_t, 1)
908 CIRCLECLOSE_TRANSITION(16, uint16_t, 2)
909 
910 #define VERTOPEN_TRANSITION(name, type, div) \
911 static void vertopen##name##_transition(AVFilterContext *ctx, \
912  const AVFrame *a, const AVFrame *b, AVFrame *out, \
913  float progress, \
914  int slice_start, int slice_end, int jobnr) \
915 { \
916  XFadeContext *s = ctx->priv; \
917  const int width = out->width; \
918  const float w2 = out->width / 2; \
919  \
920  for (int y = slice_start; y < slice_end; y++) { \
921  for (int x = 0; x < width; x++) { \
922  const float smooth = 2.f - fabsf((x - w2) / w2) - progress * 2.f; \
923  for (int p = 0; p < s->nb_planes; p++) { \
924  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
925  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
926  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
927  \
928  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
929  } \
930  } \
931  } \
932 }
933 
934 VERTOPEN_TRANSITION(8, uint8_t, 1)
935 VERTOPEN_TRANSITION(16, uint16_t, 2)
936 
937 #define VERTCLOSE_TRANSITION(name, type, div) \
938 static void vertclose##name##_transition(AVFilterContext *ctx, \
939  const AVFrame *a, const AVFrame *b, AVFrame *out, \
940  float progress, \
941  int slice_start, int slice_end, int jobnr) \
942 { \
943  XFadeContext *s = ctx->priv; \
944  const int width = out->width; \
945  const float w2 = out->width / 2; \
946  \
947  for (int y = slice_start; y < slice_end; y++) { \
948  for (int x = 0; x < width; x++) { \
949  const float smooth = 1.f + fabsf((x - w2) / w2) - progress * 2.f; \
950  for (int p = 0; p < s->nb_planes; p++) { \
951  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
952  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
953  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
954  \
955  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
956  } \
957  } \
958  } \
959 }
960 
961 VERTCLOSE_TRANSITION(8, uint8_t, 1)
962 VERTCLOSE_TRANSITION(16, uint16_t, 2)
963 
964 #define HORZOPEN_TRANSITION(name, type, div) \
965 static void horzopen##name##_transition(AVFilterContext *ctx, \
966  const AVFrame *a, const AVFrame *b, AVFrame *out, \
967  float progress, \
968  int slice_start, int slice_end, int jobnr) \
969 { \
970  XFadeContext *s = ctx->priv; \
971  const int width = out->width; \
972  const float h2 = out->height / 2; \
973  \
974  for (int y = slice_start; y < slice_end; y++) { \
975  const float smooth = 2.f - fabsf((y - h2) / h2) - progress * 2.f; \
976  for (int x = 0; x < width; x++) { \
977  for (int p = 0; p < s->nb_planes; p++) { \
978  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
979  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
980  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
981  \
982  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
983  } \
984  } \
985  } \
986 }
987 
988 HORZOPEN_TRANSITION(8, uint8_t, 1)
989 HORZOPEN_TRANSITION(16, uint16_t, 2)
990 
991 #define HORZCLOSE_TRANSITION(name, type, div) \
992 static void horzclose##name##_transition(AVFilterContext *ctx, \
993  const AVFrame *a, const AVFrame *b, AVFrame *out, \
994  float progress, \
995  int slice_start, int slice_end, int jobnr) \
996 { \
997  XFadeContext *s = ctx->priv; \
998  const int width = out->width; \
999  const float h2 = out->height / 2; \
1000  \
1001  for (int y = slice_start; y < slice_end; y++) { \
1002  const float smooth = 1.f + fabsf((y - h2) / h2) - progress * 2.f; \
1003  for (int x = 0; x < width; x++) { \
1004  for (int p = 0; p < s->nb_planes; p++) { \
1005  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1006  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1007  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1008  \
1009  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1010  } \
1011  } \
1012  } \
1013 }
1014 
1015 HORZCLOSE_TRANSITION(8, uint8_t, 1)
1016 HORZCLOSE_TRANSITION(16, uint16_t, 2)
1017 
1018 static float frand(int x, int y)
1019 {
1020  const float r = sinf(x * 12.9898f + y * 78.233f) * 43758.545f;
1021 
1022  return r - floorf(r);
1023 }
1024 
1025 #define DISSOLVE_TRANSITION(name, type, div) \
1026 static void dissolve##name##_transition(AVFilterContext *ctx, \
1027  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1028  float progress, \
1029  int slice_start, int slice_end, int jobnr) \
1030 { \
1031  XFadeContext *s = ctx->priv; \
1032  const int width = out->width; \
1033  \
1034  for (int y = slice_start; y < slice_end; y++) { \
1035  for (int x = 0; x < width; x++) { \
1036  const float smooth = frand(x, y) * 2.f + progress * 2.f - 1.5f; \
1037  for (int p = 0; p < s->nb_planes; p++) { \
1038  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1039  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1040  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1041  \
1042  dst[x] = smooth >= 0.5f ? xf0[x] : xf1[x]; \
1043  } \
1044  } \
1045  } \
1046 }
1047 
1048 DISSOLVE_TRANSITION(8, uint8_t, 1)
1049 DISSOLVE_TRANSITION(16, uint16_t, 2)
1050 
1051 #define PIXELIZE_TRANSITION(name, type, div) \
1052 static void pixelize##name##_transition(AVFilterContext *ctx, \
1053  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1054  float progress, \
1055  int slice_start, int slice_end, int jobnr) \
1056 { \
1057  XFadeContext *s = ctx->priv; \
1058  const int w = out->width; \
1059  const int h = out->height; \
1060  const float d = fminf(progress, 1.f - progress); \
1061  const float dist = ceilf(d * 50.f) / 50.f; \
1062  const float sqx = 2.f * dist * FFMIN(w, h) / 20.f; \
1063  const float sqy = 2.f * dist * FFMIN(w, h) / 20.f; \
1064  \
1065  for (int y = slice_start; y < slice_end; y++) { \
1066  for (int x = 0; x < w; x++) { \
1067  int sx = dist > 0.f ? FFMIN((floorf(x / sqx) + .5f) * sqx, w - 1) : x; \
1068  int sy = dist > 0.f ? FFMIN((floorf(y / sqy) + .5f) * sqy, h - 1) : y; \
1069  for (int p = 0; p < s->nb_planes; p++) { \
1070  const type *xf0 = (const type *)(a->data[p] + sy * a->linesize[p]); \
1071  const type *xf1 = (const type *)(b->data[p] + sy * b->linesize[p]); \
1072  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1073  \
1074  dst[x] = mix(xf0[sx], xf1[sx], progress); \
1075  } \
1076  } \
1077  } \
1078 }
1079 
1080 PIXELIZE_TRANSITION(8, uint8_t, 1)
1081 PIXELIZE_TRANSITION(16, uint16_t, 2)
1082 
1083 #define DIAGTL_TRANSITION(name, type, div) \
1084 static void diagtl##name##_transition(AVFilterContext *ctx, \
1085  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1086  float progress, \
1087  int slice_start, int slice_end, int jobnr) \
1088 { \
1089  XFadeContext *s = ctx->priv; \
1090  const int width = out->width; \
1091  const float w = width; \
1092  const float h = out->height; \
1093  \
1094  for (int y = slice_start; y < slice_end; y++) { \
1095  for (int x = 0; x < width; x++) { \
1096  const float smooth = 1.f + x / w * y / h - progress * 2.f; \
1097  \
1098  for (int p = 0; p < s->nb_planes; p++) { \
1099  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1100  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1101  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1102  \
1103  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1104  } \
1105  } \
1106  } \
1107 }
1108 
1109 DIAGTL_TRANSITION(8, uint8_t, 1)
1110 DIAGTL_TRANSITION(16, uint16_t, 2)
1111 
1112 #define DIAGTR_TRANSITION(name, type, div) \
1113 static void diagtr##name##_transition(AVFilterContext *ctx, \
1114  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1115  float progress, \
1116  int slice_start, int slice_end, int jobnr) \
1117 { \
1118  XFadeContext *s = ctx->priv; \
1119  const int width = out->width; \
1120  const float w = width; \
1121  const float h = out->height; \
1122  \
1123  for (int y = slice_start; y < slice_end; y++) { \
1124  for (int x = 0; x < width; x++) { \
1125  const float smooth = 1.f + (w - 1 - x) / w * y / h - progress * 2.f; \
1126  \
1127  for (int p = 0; p < s->nb_planes; p++) { \
1128  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1129  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1130  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1131  \
1132  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1133  } \
1134  } \
1135  } \
1136 }
1137 
1138 DIAGTR_TRANSITION(8, uint8_t, 1)
1139 DIAGTR_TRANSITION(16, uint16_t, 2)
1140 
1141 #define DIAGBL_TRANSITION(name, type, div) \
1142 static void diagbl##name##_transition(AVFilterContext *ctx, \
1143  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1144  float progress, \
1145  int slice_start, int slice_end, int jobnr) \
1146 { \
1147  XFadeContext *s = ctx->priv; \
1148  const int width = out->width; \
1149  const float w = width; \
1150  const float h = out->height; \
1151  \
1152  for (int y = slice_start; y < slice_end; y++) { \
1153  for (int x = 0; x < width; x++) { \
1154  const float smooth = 1.f + x / w * (h - 1 - y) / h - progress * 2.f; \
1155  \
1156  for (int p = 0; p < s->nb_planes; p++) { \
1157  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1158  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1159  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1160  \
1161  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1162  } \
1163  } \
1164  } \
1165 }
1166 
1167 DIAGBL_TRANSITION(8, uint8_t, 1)
1168 DIAGBL_TRANSITION(16, uint16_t, 2)
1169 
1170 #define DIAGBR_TRANSITION(name, type, div) \
1171 static void diagbr##name##_transition(AVFilterContext *ctx, \
1172  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1173  float progress, \
1174  int slice_start, int slice_end, int jobnr) \
1175 { \
1176  XFadeContext *s = ctx->priv; \
1177  const int width = out->width; \
1178  const float w = width; \
1179  const float h = out->height; \
1180  \
1181  for (int y = slice_start; y < slice_end; y++) { \
1182  for (int x = 0; x < width; x++) { \
1183  const float smooth = 1.f + (w - 1 - x) / w * (h - 1 - y) / h - \
1184  progress * 2.f; \
1185  \
1186  for (int p = 0; p < s->nb_planes; p++) { \
1187  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1188  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1189  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1190  \
1191  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1192  } \
1193  } \
1194  } \
1195 }
1196 
1197 DIAGBR_TRANSITION(8, uint8_t, 1)
1198 DIAGBR_TRANSITION(16, uint16_t, 2)
1199 
1200 #define HLSLICE_TRANSITION(name, type, div) \
1201 static void hlslice##name##_transition(AVFilterContext *ctx, \
1202  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1203  float progress, \
1204  int slice_start, int slice_end, int jobnr) \
1205 { \
1206  XFadeContext *s = ctx->priv; \
1207  const int width = out->width; \
1208  const float w = width; \
1209  \
1210  for (int y = slice_start; y < slice_end; y++) { \
1211  for (int x = 0; x < width; x++) { \
1212  const float smooth = smoothstep(-0.5f, 0.f, x / w - progress * 1.5f); \
1213  const float ss = smooth <= fract(10.f * x / w) ? 0.f : 1.f; \
1214  \
1215  for (int p = 0; p < s->nb_planes; p++) { \
1216  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1217  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1218  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1219  \
1220  dst[x] = mix(xf1[x], xf0[x], ss); \
1221  } \
1222  } \
1223  } \
1224 }
1225 
1226 HLSLICE_TRANSITION(8, uint8_t, 1)
1227 HLSLICE_TRANSITION(16, uint16_t, 2)
1228 
1229 #define HRSLICE_TRANSITION(name, type, div) \
1230 static void hrslice##name##_transition(AVFilterContext *ctx, \
1231  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1232  float progress, \
1233  int slice_start, int slice_end, int jobnr) \
1234 { \
1235  XFadeContext *s = ctx->priv; \
1236  const int width = out->width; \
1237  const float w = width; \
1238  \
1239  for (int y = slice_start; y < slice_end; y++) { \
1240  for (int x = 0; x < width; x++) { \
1241  const float xx = (w - 1 - x) / w; \
1242  const float smooth = smoothstep(-0.5f, 0.f, xx - progress * 1.5f); \
1243  const float ss = smooth <= fract(10.f * xx) ? 0.f : 1.f; \
1244  \
1245  for (int p = 0; p < s->nb_planes; p++) { \
1246  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1247  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1248  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1249  \
1250  dst[x] = mix(xf1[x], xf0[x], ss); \
1251  } \
1252  } \
1253  } \
1254 }
1255 
1256 HRSLICE_TRANSITION(8, uint8_t, 1)
1257 HRSLICE_TRANSITION(16, uint16_t, 2)
1258 
1259 #define VUSLICE_TRANSITION(name, type, div) \
1260 static void vuslice##name##_transition(AVFilterContext *ctx, \
1261  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1262  float progress, \
1263  int slice_start, int slice_end, int jobnr) \
1264 { \
1265  XFadeContext *s = ctx->priv; \
1266  const int width = out->width; \
1267  const float h = out->height; \
1268  \
1269  for (int y = slice_start; y < slice_end; y++) { \
1270  const float smooth = smoothstep(-0.5f, 0.f, y / h - progress * 1.5f); \
1271  const float ss = smooth <= fract(10.f * y / h) ? 0.f : 1.f; \
1272  \
1273  for (int x = 0; x < width; x++) { \
1274  for (int p = 0; p < s->nb_planes; p++) { \
1275  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1276  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1277  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1278  \
1279  dst[x] = mix(xf1[x], xf0[x], ss); \
1280  } \
1281  } \
1282  } \
1283 }
1284 
1285 VUSLICE_TRANSITION(8, uint8_t, 1)
1286 VUSLICE_TRANSITION(16, uint16_t, 2)
1287 
1288 #define VDSLICE_TRANSITION(name, type, div) \
1289 static void vdslice##name##_transition(AVFilterContext *ctx, \
1290  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1291  float progress, \
1292  int slice_start, int slice_end, int jobnr) \
1293 { \
1294  XFadeContext *s = ctx->priv; \
1295  const int width = out->width; \
1296  const float h = out->height; \
1297  \
1298  for (int y = slice_start; y < slice_end; y++) { \
1299  const float yy = (h - 1 - y) / h; \
1300  const float smooth = smoothstep(-0.5f, 0.f, yy - progress * 1.5f); \
1301  const float ss = smooth <= fract(10.f * yy) ? 0.f : 1.f; \
1302  \
1303  for (int x = 0; x < width; x++) { \
1304  for (int p = 0; p < s->nb_planes; p++) { \
1305  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1306  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1307  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1308  \
1309  dst[x] = mix(xf1[x], xf0[x], ss); \
1310  } \
1311  } \
1312  } \
1313 }
1314 
1315 VDSLICE_TRANSITION(8, uint8_t, 1)
1316 VDSLICE_TRANSITION(16, uint16_t, 2)
1317 
1318 #define HBLUR_TRANSITION(name, type, div) \
1319 static void hblur##name##_transition(AVFilterContext *ctx, \
1320  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1321  float progress, \
1322  int slice_start, int slice_end, int jobnr) \
1323 { \
1324  XFadeContext *s = ctx->priv; \
1325  const int width = out->width; \
1326  const float prog = progress <= 0.5f ? progress * 2.f : (1.f - progress) * 2.f; \
1327  const int size = 1 + (width / 2) * prog; \
1328  \
1329  for (int y = slice_start; y < slice_end; y++) { \
1330  for (int p = 0; p < s->nb_planes; p++) { \
1331  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1332  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1333  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1334  float sum0 = 0.f; \
1335  float sum1 = 0.f; \
1336  float cnt = size; \
1337  \
1338  for (int x = 0; x < size; x++) { \
1339  sum0 += xf0[x]; \
1340  sum1 += xf1[x]; \
1341  } \
1342  \
1343  for (int x = 0; x < width; x++) { \
1344  dst[x] = mix(sum0 / cnt, sum1 / cnt, progress); \
1345  \
1346  if (x + size < width) { \
1347  sum0 += xf0[x + size] - xf0[x]; \
1348  sum1 += xf1[x + size] - xf1[x]; \
1349  } else { \
1350  sum0 -= xf0[x]; \
1351  sum1 -= xf1[x]; \
1352  cnt--; \
1353  } \
1354  } \
1355  } \
1356  } \
1357 }
1358 
1359 HBLUR_TRANSITION(8, uint8_t, 1)
1360 HBLUR_TRANSITION(16, uint16_t, 2)
1361 
1362 #define FADEGRAYS_TRANSITION(name, type, div) \
1363 static void fadegrays##name##_transition(AVFilterContext *ctx, \
1364  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1365  float progress, \
1366  int slice_start, int slice_end, int jobnr) \
1367 { \
1368  XFadeContext *s = ctx->priv; \
1369  const int width = out->width; \
1370  const int is_rgb = s->is_rgb; \
1371  const int mid = (s->max_value + 1) / 2; \
1372  const float phase = 0.2f; \
1373  \
1374  for (int y = slice_start; y < slice_end; y++) { \
1375  for (int x = 0; x < width; x++) { \
1376  int bg[2][4]; \
1377  if (is_rgb) { \
1378  for (int p = 0; p < s->nb_planes; p++) { \
1379  const type *xf0 = (const type *)(a->data[p] + \
1380  y * a->linesize[p]); \
1381  const type *xf1 = (const type *)(b->data[p] + \
1382  y * b->linesize[p]); \
1383  if (p == 3) { \
1384  bg[0][3] = xf0[x]; \
1385  bg[1][3] = xf1[x]; \
1386  } else { \
1387  bg[0][0] += xf0[x]; \
1388  bg[1][0] += xf1[x]; \
1389  } \
1390  } \
1391  bg[0][0] = bg[0][0] / 3; \
1392  bg[1][0] = bg[1][0] / 3; \
1393  bg[0][1] = bg[0][2] = bg[0][0]; \
1394  bg[1][1] = bg[1][2] = bg[1][0]; \
1395  } else { \
1396  const type *yf0 = (const type *)(a->data[0] + \
1397  y * a->linesize[0]); \
1398  const type *yf1 = (const type *)(b->data[0] + \
1399  y * a->linesize[0]); \
1400  bg[0][0] = yf0[x]; \
1401  bg[1][0] = yf1[x]; \
1402  if (s->nb_planes == 4) { \
1403  const type *af0 = (const type *)(a->data[3] + \
1404  y * a->linesize[3]); \
1405  const type *af1 = (const type *)(b->data[3] + \
1406  y * a->linesize[3]); \
1407  bg[0][3] = af0[x]; \
1408  bg[1][3] = af1[x]; \
1409  } \
1410  bg[0][1] = bg[1][1] = mid; \
1411  bg[0][2] = bg[1][2] = mid; \
1412  } \
1413  \
1414  for (int p = 0; p < s->nb_planes; p++) { \
1415  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1416  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1417  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1418  \
1419  dst[x] = mix(mix(xf0[x], bg[0][p], \
1420  smoothstep(1.f-phase, 1.f, progress)), \
1421  mix(bg[1][p], xf1[x], smoothstep(phase, 1.f, progress)), \
1422  progress); \
1423  } \
1424  } \
1425  } \
1426 }
1427 
1428 FADEGRAYS_TRANSITION(8, uint8_t, 1)
1429 FADEGRAYS_TRANSITION(16, uint16_t, 2)
1430 
1431 #define WIPETL_TRANSITION(name, type, div) \
1432 static void wipetl##name##_transition(AVFilterContext *ctx, \
1433  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1434  float progress, \
1435  int slice_start, int slice_end, int jobnr) \
1436 { \
1437  XFadeContext *s = ctx->priv; \
1438  const int height = slice_end - slice_start; \
1439  const int zw = out->width * progress; \
1440  const int zh = out->height * progress; \
1441  \
1442  for (int p = 0; p < s->nb_planes; p++) { \
1443  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1444  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1445  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1446  \
1447  for (int y = 0; y < height; y++) { \
1448  for (int x = 0; x < out->width; x++) { \
1449  dst[x] = slice_start + y <= zh && \
1450  x <= zw ? xf0[x] : xf1[x]; \
1451  } \
1452  \
1453  dst += out->linesize[p] / div; \
1454  xf0 += a->linesize[p] / div; \
1455  xf1 += b->linesize[p] / div; \
1456  } \
1457  } \
1458 }
1459 
1460 WIPETL_TRANSITION(8, uint8_t, 1)
1461 WIPETL_TRANSITION(16, uint16_t, 2)
1462 
1463 #define WIPETR_TRANSITION(name, type, div) \
1464 static void wipetr##name##_transition(AVFilterContext *ctx, \
1465  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1466  float progress, \
1467  int slice_start, int slice_end, int jobnr) \
1468 { \
1469  XFadeContext *s = ctx->priv; \
1470  const int height = slice_end - slice_start; \
1471  const int zw = out->width * (1.f - progress); \
1472  const int zh = out->height * progress; \
1473  \
1474  for (int p = 0; p < s->nb_planes; p++) { \
1475  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1476  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1477  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1478  \
1479  for (int y = 0; y < height; y++) { \
1480  for (int x = 0; x < out->width; x++) { \
1481  dst[x] = slice_start + y <= zh && \
1482  x > zw ? xf0[x] : xf1[x]; \
1483  } \
1484  \
1485  dst += out->linesize[p] / div; \
1486  xf0 += a->linesize[p] / div; \
1487  xf1 += b->linesize[p] / div; \
1488  } \
1489  } \
1490 }
1491 
1492 WIPETR_TRANSITION(8, uint8_t, 1)
1493 WIPETR_TRANSITION(16, uint16_t, 2)
1494 
1495 #define WIPEBL_TRANSITION(name, type, div) \
1496 static void wipebl##name##_transition(AVFilterContext *ctx, \
1497  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1498  float progress, \
1499  int slice_start, int slice_end, int jobnr) \
1500 { \
1501  XFadeContext *s = ctx->priv; \
1502  const int height = slice_end - slice_start; \
1503  const int zw = out->width * progress; \
1504  const int zh = out->height * (1.f - progress); \
1505  \
1506  for (int p = 0; p < s->nb_planes; p++) { \
1507  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1508  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1509  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1510  \
1511  for (int y = 0; y < height; y++) { \
1512  for (int x = 0; x < out->width; x++) { \
1513  dst[x] = slice_start + y > zh && \
1514  x <= zw ? xf0[x] : xf1[x]; \
1515  } \
1516  \
1517  dst += out->linesize[p] / div; \
1518  xf0 += a->linesize[p] / div; \
1519  xf1 += b->linesize[p] / div; \
1520  } \
1521  } \
1522 }
1523 
1524 WIPEBL_TRANSITION(8, uint8_t, 1)
1525 WIPEBL_TRANSITION(16, uint16_t, 2)
1526 
1527 #define WIPEBR_TRANSITION(name, type, div) \
1528 static void wipebr##name##_transition(AVFilterContext *ctx, \
1529  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1530  float progress, \
1531  int slice_start, int slice_end, int jobnr) \
1532 { \
1533  XFadeContext *s = ctx->priv; \
1534  const int height = slice_end - slice_start; \
1535  const int zh = out->height * (1.f - progress); \
1536  const int zw = out->width * (1.f - progress); \
1537  \
1538  for (int p = 0; p < s->nb_planes; p++) { \
1539  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1540  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1541  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1542  \
1543  for (int y = 0; y < height; y++) { \
1544  for (int x = 0; x < out->width; x++) { \
1545  dst[x] = slice_start + y > zh && \
1546  x > zw ? xf0[x] : xf1[x]; \
1547  } \
1548  \
1549  dst += out->linesize[p] / div; \
1550  xf0 += a->linesize[p] / div; \
1551  xf1 += b->linesize[p] / div; \
1552  } \
1553  } \
1554 }
1555 
1556 WIPEBR_TRANSITION(8, uint8_t, 1)
1557 WIPEBR_TRANSITION(16, uint16_t, 2)
1558 
1559 #define SQUEEZEH_TRANSITION(name, type, div) \
1560 static void squeezeh##name##_transition(AVFilterContext *ctx, \
1561  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1562  float progress, \
1563  int slice_start, int slice_end, int jobnr) \
1564 { \
1565  XFadeContext *s = ctx->priv; \
1566  const float h = out->height; \
1567  const int height = slice_end - slice_start; \
1568  \
1569  for (int p = 0; p < s->nb_planes; p++) { \
1570  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1571  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1572  \
1573  for (int y = 0; y < height; y++) { \
1574  const float z = .5f + ((slice_start + y) / h - .5f) / progress; \
1575  \
1576  if (z < 0.f || z > 1.f) { \
1577  for (int x = 0; x < out->width; x++) \
1578  dst[x] = xf1[x]; \
1579  } else { \
1580  const int yy = lrintf(z * (h - 1.f)); \
1581  const type *xf0 = (const type *)(a->data[p] + yy * a->linesize[p]); \
1582  \
1583  for (int x = 0; x < out->width; x++) \
1584  dst[x] = xf0[x]; \
1585  } \
1586  \
1587  dst += out->linesize[p] / div; \
1588  xf1 += b->linesize[p] / div; \
1589  } \
1590  } \
1591 }
1592 
1593 SQUEEZEH_TRANSITION(8, uint8_t, 1)
1594 SQUEEZEH_TRANSITION(16, uint16_t, 2)
1595 
1596 #define SQUEEZEV_TRANSITION(name, type, div) \
1597 static void squeezev##name##_transition(AVFilterContext *ctx, \
1598  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1599  float progress, \
1600  int slice_start, int slice_end, int jobnr) \
1601 { \
1602  XFadeContext *s = ctx->priv; \
1603  const float w = out->width; \
1604  const int height = slice_end - slice_start; \
1605  \
1606  for (int p = 0; p < s->nb_planes; p++) { \
1607  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1608  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1609  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1610  \
1611  for (int y = 0; y < height; y++) { \
1612  for (int x = 0; x < out->width; x++) { \
1613  const float z = .5f + (x / w - .5f) / progress; \
1614  \
1615  if (z < 0.f || z > 1.f) { \
1616  dst[x] = xf1[x]; \
1617  } else { \
1618  const int xx = lrintf(z * (w - 1.f)); \
1619  \
1620  dst[x] = xf0[xx]; \
1621  } \
1622  } \
1623  \
1624  dst += out->linesize[p] / div; \
1625  xf0 += a->linesize[p] / div; \
1626  xf1 += b->linesize[p] / div; \
1627  } \
1628  } \
1629 }
1630 
1631 SQUEEZEV_TRANSITION(8, uint8_t, 1)
1632 SQUEEZEV_TRANSITION(16, uint16_t, 2)
1633 
1634 static void zoom(float *u, float *v, float amount)
1635 {
1636  *u = 0.5f + ((*u - 0.5f) * amount);
1637  *v = 0.5f + ((*v - 0.5f) * amount);
1638 }
1639 
1640 #define ZOOMIN_TRANSITION(name, type, div) \
1641 static void zoomin##name##_transition(AVFilterContext *ctx, \
1642  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1643  float progress, \
1644  int slice_start, int slice_end, int jobnr) \
1645 { \
1646  XFadeContext *s = ctx->priv; \
1647  const float w = out->width; \
1648  const float h = out->height; \
1649  const float zf = smoothstep(0.5f, 1.f, progress); \
1650  \
1651  for (int p = 0; p < s->nb_planes; p++) { \
1652  const type *xf0 = (const type *)(a->data[p]); \
1653  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1654  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1655  \
1656  for (int y = slice_start; y < slice_end; y++) { \
1657  for (int x = 0; x < w; x++) { \
1658  float zv, u, v; \
1659  int iu, iv; \
1660  \
1661  u = x / w; \
1662  v = y / h; \
1663  zoom(&u, &v, zf); \
1664  iu = ceilf(u * (w - 1)); \
1665  iv = ceilf(v * (h - 1)); \
1666  zv = xf0[iu + iv * a->linesize[p] / div]; \
1667  dst[x] = mix(zv, xf1[x], smoothstep(0.f, 0.5f, progress)); \
1668  } \
1669  dst += out->linesize[p] / div; \
1670  xf1 += b->linesize[p] / div; \
1671  } \
1672  } \
1673 }
1674 
1675 ZOOMIN_TRANSITION(8, uint8_t, 1)
1676 ZOOMIN_TRANSITION(16, uint16_t, 2)
1677 
1678 static inline double getpix(void *priv, double x, double y, int plane, int nb)
1679 {
1680  XFadeContext *s = priv;
1681  AVFrame *in = s->xf[nb];
1682  const uint8_t *src = in->data[FFMIN(plane, s->nb_planes - 1)];
1683  int linesize = in->linesize[FFMIN(plane, s->nb_planes - 1)];
1684  const int w = in->width;
1685  const int h = in->height;
1686 
1687  int xi, yi;
1688 
1689  xi = av_clipd(x, 0, w - 1);
1690  yi = av_clipd(y, 0, h - 1);
1691 
1692  if (s->depth > 8) {
1693  const uint16_t *src16 = (const uint16_t*)src;
1694 
1695  linesize /= 2;
1696  return src16[xi + yi * linesize];
1697  } else {
1698  return src[xi + yi * linesize];
1699  }
1700 }
1701 
1702 static double a0(void *priv, double x, double y) { return getpix(priv, x, y, 0, 0); }
1703 static double a1(void *priv, double x, double y) { return getpix(priv, x, y, 1, 0); }
1704 static double a2(void *priv, double x, double y) { return getpix(priv, x, y, 2, 0); }
1705 static double a3(void *priv, double x, double y) { return getpix(priv, x, y, 3, 0); }
1706 
1707 static double b0(void *priv, double x, double y) { return getpix(priv, x, y, 0, 1); }
1708 static double b1(void *priv, double x, double y) { return getpix(priv, x, y, 1, 1); }
1709 static double b2(void *priv, double x, double y) { return getpix(priv, x, y, 2, 1); }
1710 static double b3(void *priv, double x, double y) { return getpix(priv, x, y, 3, 1); }
1711 
1712 static int config_output(AVFilterLink *outlink)
1713 {
1714  AVFilterContext *ctx = outlink->src;
1715  AVFilterLink *inlink0 = ctx->inputs[0];
1716  AVFilterLink *inlink1 = ctx->inputs[1];
1717  XFadeContext *s = ctx->priv;
1718  const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink0->format);
1719 
1720  if (inlink0->format != inlink1->format) {
1721  av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n");
1722  return AVERROR(EINVAL);
1723  }
1724  if (inlink0->w != inlink1->w || inlink0->h != inlink1->h) {
1725  av_log(ctx, AV_LOG_ERROR, "First input link %s parameters "
1726  "(size %dx%d) do not match the corresponding "
1727  "second input link %s parameters (size %dx%d)\n",
1728  ctx->input_pads[0].name, inlink0->w, inlink0->h,
1729  ctx->input_pads[1].name, inlink1->w, inlink1->h);
1730  return AVERROR(EINVAL);
1731  }
1732 
1733  if (inlink0->time_base.num != inlink1->time_base.num ||
1734  inlink0->time_base.den != inlink1->time_base.den) {
1735  av_log(ctx, AV_LOG_ERROR, "First input link %s timebase "
1736  "(%d/%d) do not match the corresponding "
1737  "second input link %s timebase (%d/%d)\n",
1738  ctx->input_pads[0].name, inlink0->time_base.num, inlink0->time_base.den,
1739  ctx->input_pads[1].name, inlink1->time_base.num, inlink1->time_base.den);
1740  return AVERROR(EINVAL);
1741  }
1742 
1743  if (!inlink0->frame_rate.num || !inlink0->frame_rate.den) {
1744  av_log(ctx, AV_LOG_ERROR, "The inputs needs to be a constant frame rate; "
1745  "current rate of %d/%d is invalid\n", inlink0->frame_rate.num, inlink0->frame_rate.den);
1746  return AVERROR(EINVAL);
1747  }
1748 
1749  if (inlink0->frame_rate.num != inlink1->frame_rate.num ||
1750  inlink0->frame_rate.den != inlink1->frame_rate.den) {
1751  av_log(ctx, AV_LOG_ERROR, "First input link %s frame rate "
1752  "(%d/%d) do not match the corresponding "
1753  "second input link %s frame rate (%d/%d)\n",
1754  ctx->input_pads[0].name, inlink0->frame_rate.num, inlink0->frame_rate.den,
1755  ctx->input_pads[1].name, inlink1->frame_rate.num, inlink1->frame_rate.den);
1756  return AVERROR(EINVAL);
1757  }
1758 
1759  outlink->w = inlink0->w;
1760  outlink->h = inlink0->h;
1761  outlink->time_base = inlink0->time_base;
1762  outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio;
1763  outlink->frame_rate = inlink0->frame_rate;
1764 
1765  s->depth = pix_desc->comp[0].depth;
1766  s->is_rgb = !!(pix_desc->flags & AV_PIX_FMT_FLAG_RGB);
1767  s->nb_planes = av_pix_fmt_count_planes(inlink0->format);
1768  s->max_value = (1 << s->depth) - 1;
1769  s->black[0] = 0;
1770  s->black[1] = s->black[2] = s->is_rgb ? 0 : s->max_value / 2;
1771  s->black[3] = s->max_value;
1772  s->white[0] = s->white[3] = s->max_value;
1773  s->white[1] = s->white[2] = s->is_rgb ? s->max_value : s->max_value / 2;
1774 
1775  s->first_pts = s->last_pts = s->pts = AV_NOPTS_VALUE;
1776 
1777  if (s->duration)
1778  s->duration_pts = av_rescale_q(s->duration, AV_TIME_BASE_Q, outlink->time_base);
1779  if (s->offset)
1780  s->offset_pts = av_rescale_q(s->offset, AV_TIME_BASE_Q, outlink->time_base);
1781 
1782  switch (s->transition) {
1783  case CUSTOM: s->transitionf = s->depth <= 8 ? custom8_transition : custom16_transition; break;
1784  case FADE: s->transitionf = s->depth <= 8 ? fade8_transition : fade16_transition; break;
1785  case WIPELEFT: s->transitionf = s->depth <= 8 ? wipeleft8_transition : wipeleft16_transition; break;
1786  case WIPERIGHT: s->transitionf = s->depth <= 8 ? wiperight8_transition : wiperight16_transition; break;
1787  case WIPEUP: s->transitionf = s->depth <= 8 ? wipeup8_transition : wipeup16_transition; break;
1788  case WIPEDOWN: s->transitionf = s->depth <= 8 ? wipedown8_transition : wipedown16_transition; break;
1789  case SLIDELEFT: s->transitionf = s->depth <= 8 ? slideleft8_transition : slideleft16_transition; break;
1790  case SLIDERIGHT: s->transitionf = s->depth <= 8 ? slideright8_transition : slideright16_transition; break;
1791  case SLIDEUP: s->transitionf = s->depth <= 8 ? slideup8_transition : slideup16_transition; break;
1792  case SLIDEDOWN: s->transitionf = s->depth <= 8 ? slidedown8_transition : slidedown16_transition; break;
1793  case CIRCLECROP: s->transitionf = s->depth <= 8 ? circlecrop8_transition : circlecrop16_transition; break;
1794  case RECTCROP: s->transitionf = s->depth <= 8 ? rectcrop8_transition : rectcrop16_transition; break;
1795  case DISTANCE: s->transitionf = s->depth <= 8 ? distance8_transition : distance16_transition; break;
1796  case FADEBLACK: s->transitionf = s->depth <= 8 ? fadeblack8_transition : fadeblack16_transition; break;
1797  case FADEWHITE: s->transitionf = s->depth <= 8 ? fadewhite8_transition : fadewhite16_transition; break;
1798  case RADIAL: s->transitionf = s->depth <= 8 ? radial8_transition : radial16_transition; break;
1799  case SMOOTHLEFT: s->transitionf = s->depth <= 8 ? smoothleft8_transition : smoothleft16_transition; break;
1800  case SMOOTHRIGHT:s->transitionf = s->depth <= 8 ? smoothright8_transition: smoothright16_transition;break;
1801  case SMOOTHUP: s->transitionf = s->depth <= 8 ? smoothup8_transition : smoothup16_transition; break;
1802  case SMOOTHDOWN: s->transitionf = s->depth <= 8 ? smoothdown8_transition : smoothdown16_transition; break;
1803  case CIRCLEOPEN: s->transitionf = s->depth <= 8 ? circleopen8_transition : circleopen16_transition; break;
1804  case CIRCLECLOSE:s->transitionf = s->depth <= 8 ? circleclose8_transition: circleclose16_transition;break;
1805  case VERTOPEN: s->transitionf = s->depth <= 8 ? vertopen8_transition : vertopen16_transition; break;
1806  case VERTCLOSE: s->transitionf = s->depth <= 8 ? vertclose8_transition : vertclose16_transition; break;
1807  case HORZOPEN: s->transitionf = s->depth <= 8 ? horzopen8_transition : horzopen16_transition; break;
1808  case HORZCLOSE: s->transitionf = s->depth <= 8 ? horzclose8_transition : horzclose16_transition; break;
1809  case DISSOLVE: s->transitionf = s->depth <= 8 ? dissolve8_transition : dissolve16_transition; break;
1810  case PIXELIZE: s->transitionf = s->depth <= 8 ? pixelize8_transition : pixelize16_transition; break;
1811  case DIAGTL: s->transitionf = s->depth <= 8 ? diagtl8_transition : diagtl16_transition; break;
1812  case DIAGTR: s->transitionf = s->depth <= 8 ? diagtr8_transition : diagtr16_transition; break;
1813  case DIAGBL: s->transitionf = s->depth <= 8 ? diagbl8_transition : diagbl16_transition; break;
1814  case DIAGBR: s->transitionf = s->depth <= 8 ? diagbr8_transition : diagbr16_transition; break;
1815  case HLSLICE: s->transitionf = s->depth <= 8 ? hlslice8_transition : hlslice16_transition; break;
1816  case HRSLICE: s->transitionf = s->depth <= 8 ? hrslice8_transition : hrslice16_transition; break;
1817  case VUSLICE: s->transitionf = s->depth <= 8 ? vuslice8_transition : vuslice16_transition; break;
1818  case VDSLICE: s->transitionf = s->depth <= 8 ? vdslice8_transition : vdslice16_transition; break;
1819  case HBLUR: s->transitionf = s->depth <= 8 ? hblur8_transition : hblur16_transition; break;
1820  case FADEGRAYS: s->transitionf = s->depth <= 8 ? fadegrays8_transition : fadegrays16_transition; break;
1821  case WIPETL: s->transitionf = s->depth <= 8 ? wipetl8_transition : wipetl16_transition; break;
1822  case WIPETR: s->transitionf = s->depth <= 8 ? wipetr8_transition : wipetr16_transition; break;
1823  case WIPEBL: s->transitionf = s->depth <= 8 ? wipebl8_transition : wipebl16_transition; break;
1824  case WIPEBR: s->transitionf = s->depth <= 8 ? wipebr8_transition : wipebr16_transition; break;
1825  case SQUEEZEH: s->transitionf = s->depth <= 8 ? squeezeh8_transition : squeezeh16_transition; break;
1826  case SQUEEZEV: s->transitionf = s->depth <= 8 ? squeezev8_transition : squeezev16_transition; break;
1827  case ZOOMIN: s->transitionf = s->depth <= 8 ? zoomin8_transition : zoomin16_transition; break;
1828  default: return AVERROR_BUG;
1829  }
1830 
1831  if (s->transition == CUSTOM) {
1832  static const char *const func2_names[] = {
1833  "a0", "a1", "a2", "a3",
1834  "b0", "b1", "b2", "b3",
1835  NULL
1836  };
1837  double (*func2[])(void *, double, double) = {
1838  a0, a1, a2, a3,
1839  b0, b1, b2, b3,
1840  NULL };
1841  int ret;
1842 
1843  if (!s->custom_str)
1844  return AVERROR(EINVAL);
1845  ret = av_expr_parse(&s->e, s->custom_str, var_names,
1846  NULL, NULL, func2_names, func2, 0, ctx);
1847  if (ret < 0)
1848  return ret;
1849  }
1850 
1851  return 0;
1852 }
1853 
1854 static int xfade_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
1855 {
1856  XFadeContext *s = ctx->priv;
1857  AVFilterLink *outlink = ctx->outputs[0];
1858  ThreadData *td = arg;
1859  int slice_start = (outlink->h * jobnr ) / nb_jobs;
1860  int slice_end = (outlink->h * (jobnr+1)) / nb_jobs;
1861 
1862  s->transitionf(ctx, td->xf[0], td->xf[1], td->out, td->progress, slice_start, slice_end, jobnr);
1863 
1864  return 0;
1865 }
1866 
1868 {
1869  XFadeContext *s = ctx->priv;
1870  AVFilterLink *outlink = ctx->outputs[0];
1871  float progress = av_clipf(1.f - ((float)(s->pts - s->first_pts - s->offset_pts) / s->duration_pts), 0.f, 1.f);
1872  ThreadData td;
1873  AVFrame *out;
1874 
1875  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
1876  if (!out)
1877  return AVERROR(ENOMEM);
1879 
1880  td.xf[0] = a, td.xf[1] = b, td.out = out, td.progress = progress;
1882  FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
1883 
1884  out->pts = s->pts;
1885 
1886  return ff_filter_frame(outlink, out);
1887 }
1888 
1890 {
1891  XFadeContext *s = ctx->priv;
1892  AVFilterLink *outlink = ctx->outputs[0];
1893  AVFrame *in = NULL;
1894  int ret = 0, status;
1895  int64_t pts;
1896 
1898 
1899  if (s->xfade_is_over) {
1900  if (!s->eof[0]) {
1901  ret = ff_inlink_consume_frame(ctx->inputs[0], &in);
1902  if (ret > 0)
1903  av_frame_free(&in);
1904  }
1905  ret = ff_inlink_consume_frame(ctx->inputs[1], &in);
1906  if (ret < 0) {
1907  return ret;
1908  } else if (ret > 0) {
1909  in->pts = (in->pts - s->last_pts) + s->pts;
1910  return ff_filter_frame(outlink, in);
1911  } else if (ff_inlink_acknowledge_status(ctx->inputs[1], &status, &pts)) {
1912  ff_outlink_set_status(outlink, status, s->pts);
1913  return 0;
1914  } else if (!ret) {
1915  if (ff_outlink_frame_wanted(outlink))
1916  ff_inlink_request_frame(ctx->inputs[1]);
1917  return 0;
1918  }
1919  }
1920 
1921  if (ff_inlink_queued_frames(ctx->inputs[0]) > 0) {
1922  s->xf[0] = ff_inlink_peek_frame(ctx->inputs[0], 0);
1923  if (s->xf[0]) {
1924  if (s->first_pts == AV_NOPTS_VALUE) {
1925  s->first_pts = s->xf[0]->pts;
1926  }
1927  s->pts = s->xf[0]->pts;
1928  if (s->first_pts + s->offset_pts > s->xf[0]->pts) {
1929  s->xf[0] = NULL;
1930  s->need_second = 0;
1931  ff_inlink_consume_frame(ctx->inputs[0], &in);
1932  return ff_filter_frame(outlink, in);
1933  }
1934 
1935  s->need_second = 1;
1936  }
1937  }
1938 
1939  if (s->xf[0] && ff_inlink_queued_frames(ctx->inputs[1]) > 0) {
1940  ff_inlink_consume_frame(ctx->inputs[0], &s->xf[0]);
1941  ff_inlink_consume_frame(ctx->inputs[1], &s->xf[1]);
1942 
1943  s->last_pts = s->xf[1]->pts;
1944  s->pts = s->xf[0]->pts;
1945  if (s->xf[0]->pts - (s->first_pts + s->offset_pts) > s->duration_pts)
1946  s->xfade_is_over = 1;
1947  ret = xfade_frame(ctx, s->xf[0], s->xf[1]);
1948  av_frame_free(&s->xf[0]);
1949  av_frame_free(&s->xf[1]);
1950  return ret;
1951  }
1952 
1953  if (ff_inlink_queued_frames(ctx->inputs[0]) > 0 &&
1954  ff_inlink_queued_frames(ctx->inputs[1]) > 0) {
1955  ff_filter_set_ready(ctx, 100);
1956  return 0;
1957  }
1958 
1959  if (ff_outlink_frame_wanted(outlink)) {
1960  if (!s->eof[0] && ff_outlink_get_status(ctx->inputs[0])) {
1961  s->eof[0] = 1;
1962  s->xfade_is_over = 1;
1963  }
1964  if (!s->eof[1] && ff_outlink_get_status(ctx->inputs[1])) {
1965  s->eof[1] = 1;
1966  }
1967  if (!s->eof[0] && !s->xf[0] && ff_inlink_queued_frames(ctx->inputs[0]) == 0)
1968  ff_inlink_request_frame(ctx->inputs[0]);
1969  if (!s->eof[1] && (s->need_second || s->eof[0]) && ff_inlink_queued_frames(ctx->inputs[1]) == 0)
1970  ff_inlink_request_frame(ctx->inputs[1]);
1971  if (s->eof[0] && s->eof[1] && (
1972  ff_inlink_queued_frames(ctx->inputs[0]) <= 0 &&
1973  ff_inlink_queued_frames(ctx->inputs[1]) <= 0)) {
1975  } else if (s->xfade_is_over) {
1976  ff_filter_set_ready(ctx, 100);
1977  }
1978  return 0;
1979  }
1980 
1981  return FFERROR_NOT_READY;
1982 }
1983 
1984 static const AVFilterPad xfade_inputs[] = {
1985  {
1986  .name = "main",
1987  .type = AVMEDIA_TYPE_VIDEO,
1988  },
1989  {
1990  .name = "xfade",
1991  .type = AVMEDIA_TYPE_VIDEO,
1992  },
1993 };
1994 
1995 static const AVFilterPad xfade_outputs[] = {
1996  {
1997  .name = "default",
1998  .type = AVMEDIA_TYPE_VIDEO,
1999  .config_props = config_output,
2000  },
2001 };
2002 
2004  .name = "xfade",
2005  .description = NULL_IF_CONFIG_SMALL("Cross fade one video with another video."),
2006  .priv_size = sizeof(XFadeContext),
2007  .priv_class = &xfade_class,
2010  .uninit = uninit,
2013  .flags = AVFILTER_FLAG_SLICE_THREADS,
2014 };
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:98
AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:411
td
#define td
Definition: regdef.h:70
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
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
HORZOPEN_TRANSITION
#define HORZOPEN_TRANSITION(name, type, div)
Definition: vf_xfade.c:964
FADEBLACK_TRANSITION
#define FADEBLACK_TRANSITION(name, type, div)
Definition: vf_xfade.c:648
r
const char * r
Definition: vf_curves.c:116
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
SLIDERIGHT_TRANSITION
#define SLIDERIGHT_TRANSITION(name, type, div)
Definition: vf_xfade.c:450
xfade_activate
static int xfade_activate(AVFilterContext *ctx)
Definition: vf_xfade.c:1889
CIRCLECROP_TRANSITION
#define CIRCLECROP_TRANSITION(name, type, div)
Definition: vf_xfade.c:545
OFFSET
#define OFFSET(x)
Definition: vf_xfade.c:151
WIPELEFT
@ WIPELEFT
Definition: vf_xfade.c:34
out
FILE * out
Definition: movenc.c:54
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:264
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1017
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2540
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
FFERROR_NOT_READY
return FFERROR_NOT_READY
Definition: filter_design.txt:204
xfade_options
static const AVOption xfade_options[]
Definition: vf_xfade.c:154
floorf
static __device__ float floorf(float a)
Definition: cuda_runtime.h:172
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
XFadeContext::nb_planes
int nb_planes
Definition: vf_xfade.c:88
WIPEDOWN_TRANSITION
#define WIPEDOWN_TRANSITION(name, type, div)
Definition: vf_xfade.c:387
zoom
static void zoom(float *u, float *v, float amount)
Definition: vf_xfade.c:1634
RECTCROP_TRANSITION
#define RECTCROP_TRANSITION(name, type, div)
Definition: vf_xfade.c:578
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:112
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(xfade)
SMOOTHDOWN
@ SMOOTHDOWN
Definition: vf_xfade.c:51
WIPEBL_TRANSITION
#define WIPEBL_TRANSITION(name, type, div)
Definition: vf_xfade.c:1495
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:303
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:396
CIRCLECROP
@ CIRCLECROP
Definition: vf_xfade.c:42
AVFrame::width
int width
Definition: frame.h:361
w
uint8_t w
Definition: llviddspenc.c:38
SLIDELEFT_TRANSITION
#define SLIDELEFT_TRANSITION(name, type, div)
Definition: vf_xfade.c:417
AVComponentDescriptor::depth
int depth
Number of bits in the component.
Definition: pixdesc.h:57
VDSLICE_TRANSITION
#define VDSLICE_TRANSITION(name, type, div)
Definition: vf_xfade.c:1288
AVOption
AVOption.
Definition: opt.h:247
WIPERIGHT_TRANSITION
#define WIPERIGHT_TRANSITION(name, type, div)
Definition: vf_xfade.c:327
b
#define b
Definition: input.c:40
SLIDEDOWN
@ SLIDEDOWN
Definition: vf_xfade.c:41
AV_OPT_TYPE_DURATION
@ AV_OPT_TYPE_DURATION
Definition: opt.h:238
WIPEDOWN
@ WIPEDOWN
Definition: vf_xfade.c:37
DISSOLVE
@ DISSOLVE
Definition: vf_xfade.c:58
VUSLICE
@ VUSLICE
Definition: vf_xfade.c:66
XFadeContext::xfade_is_over
int xfade_is_over
Definition: vf_xfade.c:97
WIPETR
@ WIPETR
Definition: vf_xfade.c:71
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:153
SMOOTHDOWN_TRANSITION
#define SMOOTHDOWN_TRANSITION(name, type, div)
Definition: vf_xfade.c:825
ThreadData::out
AVFrame * out
Definition: af_adeclick.c:492
video.h
mix
static float mix(float a, float b, float mix)
Definition: vf_xfade.c:249
func2_names
static const char *const func2_names[]
Definition: af_afftfilt.c:122
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:317
DISTANCE
@ DISTANCE
Definition: vf_xfade.c:44
DIAGBR
@ DIAGBR
Definition: vf_xfade.c:63
XFadeContext::e
AVExpr * e
Definition: vf_xfade.c:108
formats.h
av_expr_parse
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
Definition: eval.c:685
XFadeContext::transition
int transition
Definition: vf_xfade.c:83
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:1416
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2580
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
AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:407
b1
static double b1(void *priv, double x, double y)
Definition: vf_xfade.c:1708
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:205
AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:405
AV_PIX_FMT_YUVA444P16
#define AV_PIX_FMT_YUVA444P16
Definition: pixfmt.h:433
VERTOPEN_TRANSITION
#define VERTOPEN_TRANSITION(name, type, div)
Definition: vf_xfade.c:910
xfade_frame
static int xfade_frame(AVFilterContext *ctx, AVFrame *a, AVFrame *b)
Definition: vf_xfade.c:1867
FADEGRAYS_TRANSITION
#define FADEGRAYS_TRANSITION(name, type, div)
Definition: vf_xfade.c:1362
SLIDEDOWN_TRANSITION
#define SLIDEDOWN_TRANSITION(name, type, div)
Definition: vf_xfade.c:514
PIXELIZE_TRANSITION
#define PIXELIZE_TRANSITION(name, type, div)
Definition: vf_xfade.c:1051
pts
static int64_t pts
Definition: transcode_aac.c:653
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:373
ThreadData::xf
const AVFrame * xf[2]
Definition: vf_xfade.c:115
a2
static double a2(void *priv, double x, double y)
Definition: vf_xfade.c:1704
av_expr_free
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:336
AVRational::num
int num
Numerator.
Definition: rational.h:59
HLSLICE_TRANSITION
#define HLSLICE_TRANSITION(name, type, div)
Definition: vf_xfade.c:1200
XFadeContext::offset
int64_t offset
Definition: vf_xfade.c:85
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:50
AV_PIX_FMT_YUV444P10
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:392
FADEWHITE
@ FADEWHITE
Definition: vf_xfade.c:46
WIPERIGHT
@ WIPERIGHT
Definition: vf_xfade.c:35
func2
static double(*const func2[])(void *, double, double)
Definition: af_afftfilt.c:123
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
DIAGTR_TRANSITION
#define DIAGTR_TRANSITION(name, type, div)
Definition: vf_xfade.c:1112
duration
int64_t duration
Definition: movenc.c:64
SMOOTHLEFT_TRANSITION
#define SMOOTHLEFT_TRANSITION(name, type, div)
Definition: vf_xfade.c:742
AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:409
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
XFadeContext::eof
int eof[2]
Definition: vf_xfade.c:99
ff_inlink_request_frame
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Definition: avfilter.c:1533
XFadeContext::is_rgb
int is_rgb
Definition: vf_xfade.c:90
b3
static double b3(void *priv, double x, double y)
Definition: vf_xfade.c:1710
ZOOMIN_TRANSITION
#define ZOOMIN_TRANSITION(name, type, div)
Definition: vf_xfade.c:1640
s
#define s(width, name)
Definition: cbs_vp9.c:257
AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:410
AV_PIX_FMT_YUV444P16
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:402
HBLUR
@ HBLUR
Definition: vf_xfade.c:68
smoothstep
static float smoothstep(float edge0, float edge1, float x)
Definition: vf_xfade.c:259
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2037
ff_set_common_formats_from_list
int ff_set_common_formats_from_list(AVFilterContext *ctx, const int *fmts)
Equivalent to ff_set_common_formats(ctx, ff_make_format_list(fmts))
Definition: formats.c:703
var_names
static const char *const var_names[]
Definition: vf_xfade.c:111
filters.h
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:290
DIAGTR
@ DIAGTR
Definition: vf_xfade.c:61
AV_PIX_FMT_YUVA444P12
#define AV_PIX_FMT_YUVA444P12
Definition: pixfmt.h:430
ctx
AVFormatContext * ctx
Definition: movenc.c:48
xi
#define xi(width, name, var, range_min, range_max, subs,...)
Definition: cbs_h2645.c:404
getpix
static double getpix(void *priv, double x, double y, int plane, int nb)
Definition: vf_xfade.c:1678
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:141
AVExpr
Definition: eval.c:157
VAR_X
@ VAR_X
Definition: vf_xfade.c:112
HORZCLOSE
@ HORZCLOSE
Definition: vf_xfade.c:57
CIRCLECLOSE_TRANSITION
#define CIRCLECLOSE_TRANSITION(name, type, div)
Definition: vf_xfade.c:881
DIAGBL_TRANSITION
#define DIAGBL_TRANSITION(name, type, div)
Definition: vf_xfade.c:1141
SLIDERIGHT
@ SLIDERIGHT
Definition: vf_xfade.c:39
XFadeContext::need_second
int need_second
Definition: vf_xfade.c:98
f
#define f(width, name)
Definition: cbs_vp9.c:255
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:152
WIPETR_TRANSITION
#define WIPETR_TRANSITION(name, type, div)
Definition: vf_xfade.c:1463
AV_PIX_FMT_YUVJ444P
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
arg
const char * arg
Definition: jacosubdec.c:67
AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:370
ff_inlink_peek_frame
AVFrame * ff_inlink_peek_frame(AVFilterLink *link, size_t idx)
Access a frame in the link fifo without consuming it.
Definition: avfilter.c:1455
XFadeContext::depth
int depth
Definition: vf_xfade.c:89
AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:408
SLIDEUP_TRANSITION
#define SLIDEUP_TRANSITION(name, type, div)
Definition: vf_xfade.c:483
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
HORZOPEN
@ HORZOPEN
Definition: vf_xfade.c:56
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:537
a3
static double a3(void *priv, double x, double y)
Definition: vf_xfade.c:1705
SMOOTHUP
@ SMOOTHUP
Definition: vf_xfade.c:50
FADE_TRANSITION
#define FADE_TRANSITION(name, type, div)
Definition: vf_xfade.c:268
activate
filter_frame For filters that do not use the activate() callback
NB_TRANSITIONS
@ NB_TRANSITIONS
Definition: vf_xfade.c:77
av_clipf
#define av_clipf
Definition: common.h:144
src
#define src
Definition: vp8dsp.c:255
PIXELIZE
@ PIXELIZE
Definition: vf_xfade.c:59
SMOOTHLEFT
@ SMOOTHLEFT
Definition: vf_xfade.c:48
RADIAL
@ RADIAL
Definition: vf_xfade.c:47
xfade_inputs
static const AVFilterPad xfade_inputs[]
Definition: vf_xfade.c:1984
ff_vf_xfade
const AVFilter ff_vf_xfade
Definition: vf_xfade.c:2003
sinf
#define sinf(x)
Definition: libm.h:419
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
AV_PIX_FMT_GBRP9
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:404
DISTANCE_TRANSITION
#define DISTANCE_TRANSITION(name, type, div)
Definition: vf_xfade.c:613
AVPixFmtDescriptor::flags
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:94
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:1370
xfade_outputs
static const AVFilterPad xfade_outputs[]
Definition: vf_xfade.c:1995
ff_inlink_queued_frames
size_t ff_inlink_queued_frames(AVFilterLink *link)
Get the number of frames available on the link.
Definition: avfilter.c:1385
XFadeContext
Definition: vf_xfade.c:80
eval.h
RADIAL_TRANSITION
#define RADIAL_TRANSITION(name, type, div)
Definition: vf_xfade.c:714
DIAGBL
@ DIAGBL
Definition: vf_xfade.c:62
WIPELEFT_TRANSITION
#define WIPELEFT_TRANSITION(name, type, div)
Definition: vf_xfade.c:297
RECTCROP
@ RECTCROP
Definition: vf_xfade.c:43
VAR_Y
@ VAR_Y
Definition: vf_xfade.c:112
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
CUSTOM_TRANSITION
#define CUSTOM_TRANSITION(name, type, div)
Definition: vf_xfade.c:209
XFadeContext::white
uint16_t white[4]
Definition: vf_xfade.c:103
AV_PIX_FMT_FLAG_RGB
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
Definition: pixdesc.h:136
HORZCLOSE_TRANSITION
#define HORZCLOSE_TRANSITION(name, type, div)
Definition: vf_xfade.c:991
av_clipd
#define av_clipd
Definition: common.h:147
XFadeContext::xf
AVFrame * xf[2]
Definition: vf_xfade.c:100
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_xfade.c:144
VDSLICE
@ VDSLICE
Definition: vf_xfade.c:67
VAR_VARS_NB
@ VAR_VARS_NB
Definition: vf_xfade.c:112
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
XFadeContext::offset_pts
int64_t offset_pts
Definition: vf_xfade.c:93
HBLUR_TRANSITION
#define HBLUR_TRANSITION(name, type, div)
Definition: vf_xfade.c:1318
AV_PIX_FMT_YUV444P12
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:396
CIRCLECLOSE
@ CIRCLECLOSE
Definition: vf_xfade.c:53
VUSLICE_TRANSITION
#define VUSLICE_TRANSITION(name, type, div)
Definition: vf_xfade.c:1259
b2
static double b2(void *priv, double x, double y)
Definition: vf_xfade.c:1709
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
XFadeContext::custom_str
char * custom_str
Definition: vf_xfade.c:86
AV_PIX_FMT_YUVA444P
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:167
a0
static double a0(void *priv, double x, double y)
Definition: vf_xfade.c:1702
AV_PIX_FMT_YUVA444P10
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:428
frand
static float frand(int x, int y)
Definition: vf_xfade.c:1018
offset
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 offset
Definition: writing_filters.txt:86
VAR_H
@ VAR_H
Definition: vf_xfade.c:112
SMOOTHRIGHT
@ SMOOTHRIGHT
Definition: vf_xfade.c:49
internal.h
WIPEUP_TRANSITION
#define WIPEUP_TRANSITION(name, type, div)
Definition: vf_xfade.c:357
WIPEUP
@ WIPEUP
Definition: vf_xfade.c:36
XFadeContext::duration_pts
int64_t duration_pts
Definition: vf_xfade.c:92
config_output
static int config_output(AVFilterLink *outlink)
Definition: vf_xfade.c:1712
SMOOTHRIGHT_TRANSITION
#define SMOOTHRIGHT_TRANSITION(name, type, div)
Definition: vf_xfade.c:770
VAR_PROGRESS
@ VAR_PROGRESS
Definition: vf_xfade.c:112
ThreadData::progress
float progress
Definition: vf_xfade.c:117
AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:406
FADEGRAYS
@ FADEGRAYS
Definition: vf_xfade.c:69
VERTCLOSE_TRANSITION
#define VERTCLOSE_TRANSITION(name, type, div)
Definition: vf_xfade.c:937
XFadeContext::first_pts
int64_t first_pts
Definition: vf_xfade.c:94
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:804
ThreadData
Used for passing data between threads.
Definition: dsddec.c:67
FADEBLACK
@ FADEBLACK
Definition: vf_xfade.c:45
WIPETL_TRANSITION
#define WIPETL_TRANSITION(name, type, div)
Definition: vf_xfade.c:1431
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
DIAGTL_TRANSITION
#define DIAGTL_TRANSITION(name, type, div)
Definition: vf_xfade.c:1083
VERTCLOSE
@ VERTCLOSE
Definition: vf_xfade.c:55
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:56
fract
static float fract(float a)
Definition: vf_xfade.c:254
WIPEBR
@ WIPEBR
Definition: vf_xfade.c:73
SQUEEZEH
@ SQUEEZEH
Definition: vf_xfade.c:74
AVFilter
Filter definition.
Definition: avfilter.h:149
XFadeContext::max_value
int max_value
Definition: vf_xfade.c:101
ret
ret
Definition: filter_design.txt:187
WIPETL
@ WIPETL
Definition: vf_xfade.c:70
pixfmt.h
SQUEEZEH_TRANSITION
#define SQUEEZEH_TRANSITION(name, type, div)
Definition: vf_xfade.c:1559
FLAGS
#define FLAGS
Definition: vf_xfade.c:152
CIRCLEOPEN_TRANSITION
#define CIRCLEOPEN_TRANSITION(name, type, div)
Definition: vf_xfade.c:852
AV_PIX_FMT_YUVA444P9
#define AV_PIX_FMT_YUVA444P9
Definition: pixfmt.h:425
SQUEEZEV_TRANSITION
#define SQUEEZEV_TRANSITION(name, type, div)
Definition: vf_xfade.c:1596
XFadeContext::black
uint16_t black[4]
Definition: vf_xfade.c:102
AVFrame::height
int height
Definition: frame.h:361
xfade_slice
static int xfade_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_xfade.c:1854
VERTOPEN
@ VERTOPEN
Definition: vf_xfade.c:54
SQUEEZEV
@ SQUEEZEV
Definition: vf_xfade.c:75
SLIDELEFT
@ SLIDELEFT
Definition: vf_xfade.c:38
ZOOMIN
@ ZOOMIN
Definition: vf_xfade.c:76
VAR_A
@ VAR_A
Definition: vf_xfade.c:112
AVRational::den
int den
Denominator.
Definition: rational.h:60
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:224
avfilter.h
FADEWHITE_TRANSITION
#define FADEWHITE_TRANSITION(name, type, div)
Definition: vf_xfade.c:681
VAR_B
@ VAR_B
Definition: vf_xfade.c:112
AVPixFmtDescriptor::comp
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:105
HLSLICE
@ HLSLICE
Definition: vf_xfade.c:64
DIAGTL
@ DIAGTL
Definition: vf_xfade.c:60
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
ff_outlink_get_status
int ff_outlink_get_status(AVFilterLink *link)
Get the status on an output link.
Definition: avfilter.c:1556
AVFilterContext
An instance of a filter.
Definition: avfilter.h:346
SMOOTHUP_TRANSITION
#define SMOOTHUP_TRANSITION(name, type, div)
Definition: vf_xfade.c:798
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:158
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:121
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
CIRCLEOPEN
@ CIRCLEOPEN
Definition: vf_xfade.c:52
CUSTOM
@ CUSTOM
Definition: vf_xfade.c:32
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
XFadeContext::transitionf
void(* transitionf)(AVFilterContext *ctx, const AVFrame *a, const AVFrame *b, AVFrame *out, float progress, int slice_start, int slice_end, int jobnr)
Definition: vf_xfade.c:105
XFadeTransitions
XFadeTransitions
Definition: vf_xfade.c:31
XFadeContext::last_pts
int64_t last_pts
Definition: vf_xfade.c:95
XFadeContext::duration
int64_t duration
Definition: vf_xfade.c:84
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:153
VAR_PLANE
@ VAR_PLANE
Definition: vf_xfade.c:112
SLIDEUP
@ SLIDEUP
Definition: vf_xfade.c:40
DIAGBR_TRANSITION
#define DIAGBR_TRANSITION(name, type, div)
Definition: vf_xfade.c:1170
imgutils.h
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:334
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
b0
static double b0(void *priv, double x, double y)
Definition: vf_xfade.c:1707
a1
static double a1(void *priv, double x, double y)
Definition: vf_xfade.c:1703
h
h
Definition: vp9dsp_template.c:2038
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
VAR_W
@ VAR_W
Definition: vf_xfade.c:112
AV_PIX_FMT_YUV444P14
#define AV_PIX_FMT_YUV444P14
Definition: pixfmt.h:399
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:228
AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:371
ff_filter_execute
static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: internal.h:143
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:233
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: vf_xfade.c:120
WIPEBR_TRANSITION
#define WIPEBR_TRANSITION(name, type, div)
Definition: vf_xfade.c:1527
WIPEBL
@ WIPEBL
Definition: vf_xfade.c:72
DISSOLVE_TRANSITION
#define DISSOLVE_TRANSITION(name, type, div)
Definition: vf_xfade.c:1025
XFadeContext::pts
int64_t pts
Definition: vf_xfade.c:96
FADE
@ FADE
Definition: vf_xfade.c:33
ff_filter_set_ready
void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
Mark a filter ready and schedule it for activation.
Definition: avfilter.c:212
HRSLICE
@ HRSLICE
Definition: vf_xfade.c:65
HRSLICE_TRANSITION
#define HRSLICE_TRANSITION(name, type, div)
Definition: vf_xfade.c:1229