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