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/eval.h"
22 #include "libavutil/opt.h"
23 #include "libavutil/pixdesc.h"
24 #include "libavutil/pixfmt.h"
25 #include "avfilter.h"
26 #include "internal.h"
27 #include "filters.h"
28 #include "video.h"
29 
31  CUSTOM = -1,
91 };
92 
93 typedef struct XFadeContext {
94  const AVClass *class;
95 
97  int64_t duration;
98  int64_t offset;
99  char *custom_str;
100 
102  int depth;
103  int is_rgb;
104 
105  // PTS when the fade should start (in first inputs timebase)
106  int64_t start_pts;
107 
108  // PTS offset between first and second input
110 
111  // Duration of the transition
112  int64_t duration_pts;
113 
114  // Current PTS of the first input
115  int64_t pts;
116 
117  // If frames are currently just passed through unmodified,
118  // like before and after the actual transition.
120 
121  int status[2];
122  AVFrame *xf[2];
124  uint16_t black[4];
125  uint16_t white[4];
126 
127  void (*transitionf)(AVFilterContext *ctx, const AVFrame *a, const AVFrame *b, AVFrame *out, float progress,
128  int slice_start, int slice_end, int jobnr);
129 
131 } XFadeContext;
132 
133 static const char *const var_names[] = { "X", "Y", "W", "H", "A", "B", "PLANE", "P", NULL };
135 
136 typedef struct ThreadData {
137  const AVFrame *xf[2];
138  AVFrame *out;
139  float progress;
140 } ThreadData;
141 
142 static const enum AVPixelFormat pix_fmts[] = {
159 };
160 
162 {
163  XFadeContext *s = ctx->priv;
164 
165  av_expr_free(s->e);
166 }
167 
168 #define OFFSET(x) offsetof(XFadeContext, x)
169 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
170 
171 static const AVOption xfade_options[] = {
172  { "transition", "set cross fade transition", OFFSET(transition), AV_OPT_TYPE_INT, {.i64=FADE}, -1, NB_TRANSITIONS-1, FLAGS, "transition" },
173  { "custom", "custom transition", 0, AV_OPT_TYPE_CONST, {.i64=CUSTOM}, 0, 0, FLAGS, "transition" },
174  { "fade", "fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADE}, 0, 0, FLAGS, "transition" },
175  { "wipeleft", "wipe left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPELEFT}, 0, 0, FLAGS, "transition" },
176  { "wiperight", "wipe right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPERIGHT}, 0, 0, FLAGS, "transition" },
177  { "wipeup", "wipe up transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEUP}, 0, 0, FLAGS, "transition" },
178  { "wipedown", "wipe down transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEDOWN}, 0, 0, FLAGS, "transition" },
179  { "slideleft", "slide left transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDELEFT}, 0, 0, FLAGS, "transition" },
180  { "slideright", "slide right transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDERIGHT}, 0, 0, FLAGS, "transition" },
181  { "slideup", "slide up transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEUP}, 0, 0, FLAGS, "transition" },
182  { "slidedown", "slide down transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEDOWN}, 0, 0, FLAGS, "transition" },
183  { "circlecrop", "circle crop transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLECROP}, 0, 0, FLAGS, "transition" },
184  { "rectcrop", "rect crop transition", 0, AV_OPT_TYPE_CONST, {.i64=RECTCROP}, 0, 0, FLAGS, "transition" },
185  { "distance", "distance transition", 0, AV_OPT_TYPE_CONST, {.i64=DISTANCE}, 0, 0, FLAGS, "transition" },
186  { "fadeblack", "fadeblack transition", 0, AV_OPT_TYPE_CONST, {.i64=FADEBLACK}, 0, 0, FLAGS, "transition" },
187  { "fadewhite", "fadewhite transition", 0, AV_OPT_TYPE_CONST, {.i64=FADEWHITE}, 0, 0, FLAGS, "transition" },
188  { "radial", "radial transition", 0, AV_OPT_TYPE_CONST, {.i64=RADIAL}, 0, 0, FLAGS, "transition" },
189  { "smoothleft", "smoothleft transition", 0, AV_OPT_TYPE_CONST, {.i64=SMOOTHLEFT}, 0, 0, FLAGS, "transition" },
190  { "smoothright","smoothright transition", 0, AV_OPT_TYPE_CONST, {.i64=SMOOTHRIGHT},0, 0, FLAGS, "transition" },
191  { "smoothup", "smoothup transition", 0, AV_OPT_TYPE_CONST, {.i64=SMOOTHUP}, 0, 0, FLAGS, "transition" },
192  { "smoothdown", "smoothdown transition", 0, AV_OPT_TYPE_CONST, {.i64=SMOOTHDOWN}, 0, 0, FLAGS, "transition" },
193  { "circleopen", "circleopen transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLEOPEN}, 0, 0, FLAGS, "transition" },
194  { "circleclose","circleclose transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLECLOSE},0, 0, FLAGS, "transition" },
195  { "vertopen", "vert open transition", 0, AV_OPT_TYPE_CONST, {.i64=VERTOPEN}, 0, 0, FLAGS, "transition" },
196  { "vertclose", "vert close transition", 0, AV_OPT_TYPE_CONST, {.i64=VERTCLOSE}, 0, 0, FLAGS, "transition" },
197  { "horzopen", "horz open transition", 0, AV_OPT_TYPE_CONST, {.i64=HORZOPEN}, 0, 0, FLAGS, "transition" },
198  { "horzclose", "horz close transition", 0, AV_OPT_TYPE_CONST, {.i64=HORZCLOSE}, 0, 0, FLAGS, "transition" },
199  { "dissolve", "dissolve transition", 0, AV_OPT_TYPE_CONST, {.i64=DISSOLVE}, 0, 0, FLAGS, "transition" },
200  { "pixelize", "pixelize transition", 0, AV_OPT_TYPE_CONST, {.i64=PIXELIZE}, 0, 0, FLAGS, "transition" },
201  { "diagtl", "diag tl transition", 0, AV_OPT_TYPE_CONST, {.i64=DIAGTL}, 0, 0, FLAGS, "transition" },
202  { "diagtr", "diag tr transition", 0, AV_OPT_TYPE_CONST, {.i64=DIAGTR}, 0, 0, FLAGS, "transition" },
203  { "diagbl", "diag bl transition", 0, AV_OPT_TYPE_CONST, {.i64=DIAGBL}, 0, 0, FLAGS, "transition" },
204  { "diagbr", "diag br transition", 0, AV_OPT_TYPE_CONST, {.i64=DIAGBR}, 0, 0, FLAGS, "transition" },
205  { "hlslice", "hl slice transition", 0, AV_OPT_TYPE_CONST, {.i64=HLSLICE}, 0, 0, FLAGS, "transition" },
206  { "hrslice", "hr slice transition", 0, AV_OPT_TYPE_CONST, {.i64=HRSLICE}, 0, 0, FLAGS, "transition" },
207  { "vuslice", "vu slice transition", 0, AV_OPT_TYPE_CONST, {.i64=VUSLICE}, 0, 0, FLAGS, "transition" },
208  { "vdslice", "vd slice transition", 0, AV_OPT_TYPE_CONST, {.i64=VDSLICE}, 0, 0, FLAGS, "transition" },
209  { "hblur", "hblur transition", 0, AV_OPT_TYPE_CONST, {.i64=HBLUR}, 0, 0, FLAGS, "transition" },
210  { "fadegrays", "fadegrays transition", 0, AV_OPT_TYPE_CONST, {.i64=FADEGRAYS}, 0, 0, FLAGS, "transition" },
211  { "wipetl", "wipe tl transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPETL}, 0, 0, FLAGS, "transition" },
212  { "wipetr", "wipe tr transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPETR}, 0, 0, FLAGS, "transition" },
213  { "wipebl", "wipe bl transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEBL}, 0, 0, FLAGS, "transition" },
214  { "wipebr", "wipe br transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEBR}, 0, 0, FLAGS, "transition" },
215  { "squeezeh", "squeeze h transition", 0, AV_OPT_TYPE_CONST, {.i64=SQUEEZEH}, 0, 0, FLAGS, "transition" },
216  { "squeezev", "squeeze v transition", 0, AV_OPT_TYPE_CONST, {.i64=SQUEEZEV}, 0, 0, FLAGS, "transition" },
217  { "zoomin", "zoom in transition", 0, AV_OPT_TYPE_CONST, {.i64=ZOOMIN}, 0, 0, FLAGS, "transition" },
218  { "fadefast", "fast fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADEFAST}, 0, 0, FLAGS, "transition" },
219  { "fadeslow", "slow fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADESLOW}, 0, 0, FLAGS, "transition" },
220  { "hlwind", "hl wind transition", 0, AV_OPT_TYPE_CONST, {.i64=HLWIND}, 0, 0, FLAGS, "transition" },
221  { "hrwind", "hr wind transition", 0, AV_OPT_TYPE_CONST, {.i64=HRWIND}, 0, 0, FLAGS, "transition" },
222  { "vuwind", "vu wind transition", 0, AV_OPT_TYPE_CONST, {.i64=VUWIND}, 0, 0, FLAGS, "transition" },
223  { "vdwind", "vd wind transition", 0, AV_OPT_TYPE_CONST, {.i64=VDWIND}, 0, 0, FLAGS, "transition" },
224  { "coverleft", "cover left transition", 0, AV_OPT_TYPE_CONST, {.i64=COVERLEFT}, 0, 0, FLAGS, "transition" },
225  { "coverright", "cover right transition", 0, AV_OPT_TYPE_CONST, {.i64=COVERRIGHT}, 0, 0, FLAGS, "transition" },
226  { "coverup", "cover up transition", 0, AV_OPT_TYPE_CONST, {.i64=COVERUP}, 0, 0, FLAGS, "transition" },
227  { "coverdown", "cover down transition", 0, AV_OPT_TYPE_CONST, {.i64=COVERDOWN}, 0, 0, FLAGS, "transition" },
228  { "revealleft", "reveal left transition", 0, AV_OPT_TYPE_CONST, {.i64=REVEALLEFT}, 0, 0, FLAGS, "transition" },
229  { "revealright","reveal right transition",0, AV_OPT_TYPE_CONST, {.i64=REVEALRIGHT},0, 0, FLAGS, "transition" },
230  { "revealup", "reveal up transition", 0, AV_OPT_TYPE_CONST, {.i64=REVEALUP}, 0, 0, FLAGS, "transition" },
231  { "revealdown", "reveal down transition", 0, AV_OPT_TYPE_CONST, {.i64=REVEALDOWN}, 0, 0, FLAGS, "transition" },
232  { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=1000000}, 0, 60000000, FLAGS },
233  { "offset", "set cross fade start relative to first input stream", OFFSET(offset), AV_OPT_TYPE_DURATION, {.i64=0}, INT64_MIN, INT64_MAX, FLAGS },
234  { "expr", "set expression for custom transition", OFFSET(custom_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
235  { NULL }
236 };
237 
238 AVFILTER_DEFINE_CLASS(xfade);
239 
240 #define CUSTOM_TRANSITION(name, type, div) \
241 static void custom##name##_transition(AVFilterContext *ctx, \
242  const AVFrame *a, const AVFrame *b, AVFrame *out, \
243  float progress, \
244  int slice_start, int slice_end, int jobnr) \
245 { \
246  XFadeContext *s = ctx->priv; \
247  const int height = slice_end - slice_start; \
248  const int width = out->width; \
249  \
250  double values[VAR_VARS_NB]; \
251  values[VAR_W] = width; \
252  values[VAR_H] = out->height; \
253  values[VAR_PROGRESS] = progress; \
254  \
255  for (int p = 0; p < s->nb_planes; p++) { \
256  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
257  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
258  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
259  \
260  values[VAR_PLANE] = p; \
261  \
262  for (int y = 0; y < height; y++) { \
263  values[VAR_Y] = slice_start + y; \
264  for (int x = 0; x < width; x++) { \
265  values[VAR_X] = x; \
266  values[VAR_A] = xf0[x]; \
267  values[VAR_B] = xf1[x]; \
268  dst[x] = av_expr_eval(s->e, values, s); \
269  } \
270  \
271  dst += out->linesize[p] / div; \
272  xf0 += a->linesize[p] / div; \
273  xf1 += b->linesize[p] / div; \
274  } \
275  } \
276 }
277 
278 CUSTOM_TRANSITION(8, uint8_t, 1)
279 CUSTOM_TRANSITION(16, uint16_t, 2)
280 
281 static inline float mix(float a, float b, float mix)
282 {
283  return a * mix + b * (1.f - mix);
284 }
285 
286 static inline float fract(float a)
287 {
288  return a - floorf(a);
289 }
290 
291 static inline float smoothstep(float edge0, float edge1, float x)
292 {
293  float t;
294 
295  t = av_clipf((x - edge0) / (edge1 - edge0), 0.f, 1.f);
296 
297  return t * t * (3.f - 2.f * t);
298 }
299 
300 #define FADE_TRANSITION(name, type, div) \
301 static void fade##name##_transition(AVFilterContext *ctx, \
302  const AVFrame *a, const AVFrame *b, AVFrame *out, \
303  float progress, \
304  int slice_start, int slice_end, int jobnr) \
305 { \
306  XFadeContext *s = ctx->priv; \
307  const int height = slice_end - slice_start; \
308  const int width = out->width; \
309  \
310  for (int p = 0; p < s->nb_planes; p++) { \
311  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
312  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
313  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
314  \
315  for (int y = 0; y < height; y++) { \
316  for (int x = 0; x < width; x++) { \
317  dst[x] = mix(xf0[x], xf1[x], progress); \
318  } \
319  \
320  dst += out->linesize[p] / div; \
321  xf0 += a->linesize[p] / div; \
322  xf1 += b->linesize[p] / div; \
323  } \
324  } \
325 }
326 
327 FADE_TRANSITION(8, uint8_t, 1)
328 FADE_TRANSITION(16, uint16_t, 2)
329 
330 #define WIPELEFT_TRANSITION(name, type, div) \
331 static void wipeleft##name##_transition(AVFilterContext *ctx, \
332  const AVFrame *a, const AVFrame *b, AVFrame *out, \
333  float progress, \
334  int slice_start, int slice_end, int jobnr) \
335 { \
336  XFadeContext *s = ctx->priv; \
337  const int height = slice_end - slice_start; \
338  const int width = out->width; \
339  const int z = width * progress; \
340  \
341  for (int p = 0; p < s->nb_planes; p++) { \
342  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
343  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
344  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
345  \
346  for (int y = 0; y < height; y++) { \
347  for (int x = 0; x < width; x++) { \
348  dst[x] = x > z ? xf1[x] : xf0[x]; \
349  } \
350  \
351  dst += out->linesize[p] / div; \
352  xf0 += a->linesize[p] / div; \
353  xf1 += b->linesize[p] / div; \
354  } \
355  } \
356 }
357 
358 WIPELEFT_TRANSITION(8, uint8_t, 1)
359 WIPELEFT_TRANSITION(16, uint16_t, 2)
360 
361 #define WIPERIGHT_TRANSITION(name, type, div) \
362 static void wiperight##name##_transition(AVFilterContext *ctx, \
363  const AVFrame *a, const AVFrame *b, AVFrame *out, \
364  float progress, \
365  int slice_start, int slice_end, int jobnr) \
366 { \
367  XFadeContext *s = ctx->priv; \
368  const int height = slice_end - slice_start; \
369  const int width = out->width; \
370  const int z = width * (1.f - progress); \
371  \
372  for (int p = 0; p < s->nb_planes; p++) { \
373  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
374  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
375  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
376  \
377  for (int y = 0; y < height; y++) { \
378  for (int x = 0; x < width; x++) { \
379  dst[x] = x > z ? xf0[x] : xf1[x]; \
380  } \
381  \
382  dst += out->linesize[p] / div; \
383  xf0 += a->linesize[p] / div; \
384  xf1 += b->linesize[p] / div; \
385  } \
386  } \
387 }
388 
389 WIPERIGHT_TRANSITION(8, uint8_t, 1)
390 WIPERIGHT_TRANSITION(16, uint16_t, 2)
391 
392 #define WIPEUP_TRANSITION(name, type, div) \
393 static void wipeup##name##_transition(AVFilterContext *ctx, \
394  const AVFrame *a, const AVFrame *b, AVFrame *out, \
395  float progress, \
396  int slice_start, int slice_end, int jobnr) \
397 { \
398  XFadeContext *s = ctx->priv; \
399  const int height = slice_end - slice_start; \
400  const int width = out->width; \
401  const int z = out->height * progress; \
402  \
403  for (int p = 0; p < s->nb_planes; p++) { \
404  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
405  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
406  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
407  \
408  for (int y = 0; y < height; y++) { \
409  for (int x = 0; x < width; x++) { \
410  dst[x] = slice_start + y > z ? xf1[x] : xf0[x]; \
411  } \
412  \
413  dst += out->linesize[p] / div; \
414  xf0 += a->linesize[p] / div; \
415  xf1 += b->linesize[p] / div; \
416  } \
417  } \
418 }
419 
420 WIPEUP_TRANSITION(8, uint8_t, 1)
421 WIPEUP_TRANSITION(16, uint16_t, 2)
422 
423 #define WIPEDOWN_TRANSITION(name, type, div) \
424 static void wipedown##name##_transition(AVFilterContext *ctx, \
425  const AVFrame *a, const AVFrame *b, AVFrame *out, \
426  float progress, \
427  int slice_start, int slice_end, int jobnr) \
428 { \
429  XFadeContext *s = ctx->priv; \
430  const int height = slice_end - slice_start; \
431  const int width = out->width; \
432  const int z = out->height * (1.f - progress); \
433  \
434  for (int p = 0; p < s->nb_planes; p++) { \
435  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
436  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
437  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
438  \
439  for (int y = 0; y < height; y++) { \
440  for (int x = 0; x < width; x++) { \
441  dst[x] = slice_start + y > z ? xf0[x] : xf1[x]; \
442  } \
443  \
444  dst += out->linesize[p] / div; \
445  xf0 += a->linesize[p] / div; \
446  xf1 += b->linesize[p] / div; \
447  } \
448  } \
449 }
450 
451 WIPEDOWN_TRANSITION(8, uint8_t, 1)
452 WIPEDOWN_TRANSITION(16, uint16_t, 2)
453 
454 #define SLIDELEFT_TRANSITION(name, type, div) \
455 static void slideleft##name##_transition(AVFilterContext *ctx, \
456  const AVFrame *a, const AVFrame *b, AVFrame *out, \
457  float progress, \
458  int slice_start, int slice_end, int jobnr) \
459 { \
460  XFadeContext *s = ctx->priv; \
461  const int height = slice_end - slice_start; \
462  const int width = out->width; \
463  const int z = -progress * width; \
464  \
465  for (int p = 0; p < s->nb_planes; p++) { \
466  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
467  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
468  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
469  \
470  for (int y = 0; y < height; y++) { \
471  for (int x = 0; x < width; x++) { \
472  const int zx = z + x; \
473  const int zz = zx % width + width * (zx < 0); \
474  dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \
475  } \
476  \
477  dst += out->linesize[p] / div; \
478  xf0 += a->linesize[p] / div; \
479  xf1 += b->linesize[p] / div; \
480  } \
481  } \
482 }
483 
484 SLIDELEFT_TRANSITION(8, uint8_t, 1)
485 SLIDELEFT_TRANSITION(16, uint16_t, 2)
486 
487 #define SLIDERIGHT_TRANSITION(name, type, div) \
488 static void slideright##name##_transition(AVFilterContext *ctx, \
489  const AVFrame *a, const AVFrame *b, AVFrame *out, \
490  float progress, \
491  int slice_start, int slice_end, int jobnr) \
492 { \
493  XFadeContext *s = ctx->priv; \
494  const int height = slice_end - slice_start; \
495  const int width = out->width; \
496  const int z = progress * width; \
497  \
498  for (int p = 0; p < s->nb_planes; p++) { \
499  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
500  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
501  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
502  \
503  for (int y = 0; y < height; y++) { \
504  for (int x = 0; x < width; x++) { \
505  const int zx = z + x; \
506  const int zz = zx % width + width * (zx < 0); \
507  dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \
508  } \
509  \
510  dst += out->linesize[p] / div; \
511  xf0 += a->linesize[p] / div; \
512  xf1 += b->linesize[p] / div; \
513  } \
514  } \
515 }
516 
517 SLIDERIGHT_TRANSITION(8, uint8_t, 1)
518 SLIDERIGHT_TRANSITION(16, uint16_t, 2)
519 
520 #define SLIDEUP_TRANSITION(name, type, div) \
521 static void slideup##name##_transition(AVFilterContext *ctx, \
522  const AVFrame *a, const AVFrame *b, AVFrame *out, \
523  float progress, \
524  int slice_start, int slice_end, int jobnr) \
525 { \
526  XFadeContext *s = ctx->priv; \
527  const int height = out->height; \
528  const int width = out->width; \
529  const int z = -progress * height; \
530  \
531  for (int p = 0; p < s->nb_planes; p++) { \
532  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
533  \
534  for (int y = slice_start; y < slice_end; y++) { \
535  const int zy = z + y; \
536  const int zz = zy % height + height * (zy < 0); \
537  const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
538  const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
539  \
540  for (int x = 0; x < width; x++) { \
541  dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
542  } \
543  \
544  dst += out->linesize[p] / div; \
545  } \
546  } \
547 }
548 
549 SLIDEUP_TRANSITION(8, uint8_t, 1)
550 SLIDEUP_TRANSITION(16, uint16_t, 2)
551 
552 #define SLIDEDOWN_TRANSITION(name, type, div) \
553 static void slidedown##name##_transition(AVFilterContext *ctx, \
554  const AVFrame *a, const AVFrame *b, AVFrame *out, \
555  float progress, \
556  int slice_start, int slice_end, int jobnr) \
557 { \
558  XFadeContext *s = ctx->priv; \
559  const int height = out->height; \
560  const int width = out->width; \
561  const int z = progress * height; \
562  \
563  for (int p = 0; p < s->nb_planes; p++) { \
564  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
565  \
566  for (int y = slice_start; y < slice_end; y++) { \
567  const int zy = z + y; \
568  const int zz = zy % height + height * (zy < 0); \
569  const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
570  const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
571  \
572  for (int x = 0; x < width; x++) { \
573  dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
574  } \
575  \
576  dst += out->linesize[p] / div; \
577  } \
578  } \
579 }
580 
581 SLIDEDOWN_TRANSITION(8, uint8_t, 1)
582 SLIDEDOWN_TRANSITION(16, uint16_t, 2)
583 
584 #define CIRCLECROP_TRANSITION(name, type, div) \
585 static void circlecrop##name##_transition(AVFilterContext *ctx, \
586  const AVFrame *a, const AVFrame *b, AVFrame *out, \
587  float progress, \
588  int slice_start, int slice_end, int jobnr) \
589 { \
590  XFadeContext *s = ctx->priv; \
591  const int width = out->width; \
592  const int height = out->height; \
593  float z = powf(2.f * fabsf(progress - 0.5f), 3.f) * hypotf(width/2, height/2); \
594  \
595  for (int p = 0; p < s->nb_planes; p++) { \
596  const int bg = s->black[p]; \
597  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
598  \
599  for (int y = slice_start; y < slice_end; y++) { \
600  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
601  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
602  \
603  for (int x = 0; x < width; x++) { \
604  float dist = hypotf(x - width / 2, y - height / 2); \
605  int val = progress < 0.5f ? xf1[x] : xf0[x]; \
606  dst[x] = (z < dist) ? bg : val; \
607  } \
608  \
609  dst += out->linesize[p] / div; \
610  } \
611  } \
612 }
613 
614 CIRCLECROP_TRANSITION(8, uint8_t, 1)
615 CIRCLECROP_TRANSITION(16, uint16_t, 2)
616 
617 #define RECTCROP_TRANSITION(name, type, div) \
618 static void rectcrop##name##_transition(AVFilterContext *ctx, \
619  const AVFrame *a, const AVFrame *b, AVFrame *out, \
620  float progress, \
621  int slice_start, int slice_end, int jobnr) \
622 { \
623  XFadeContext *s = ctx->priv; \
624  const int width = out->width; \
625  const int height = out->height; \
626  int zh = fabsf(progress - 0.5f) * height; \
627  int zw = fabsf(progress - 0.5f) * width; \
628  \
629  for (int p = 0; p < s->nb_planes; p++) { \
630  const int bg = s->black[p]; \
631  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
632  \
633  for (int y = slice_start; y < slice_end; y++) { \
634  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
635  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
636  \
637  for (int x = 0; x < width; x++) { \
638  int dist = FFABS(x - width / 2) < zw && \
639  FFABS(y - height / 2) < zh; \
640  int val = progress < 0.5f ? xf1[x] : xf0[x]; \
641  dst[x] = !dist ? bg : val; \
642  } \
643  \
644  dst += out->linesize[p] / div; \
645  } \
646  } \
647 }
648 
649 RECTCROP_TRANSITION(8, uint8_t, 1)
650 RECTCROP_TRANSITION(16, uint16_t, 2)
651 
652 #define DISTANCE_TRANSITION(name, type, div) \
653 static void distance##name##_transition(AVFilterContext *ctx, \
654  const AVFrame *a, const AVFrame *b, AVFrame *out, \
655  float progress, \
656  int slice_start, int slice_end, int jobnr) \
657 { \
658  XFadeContext *s = ctx->priv; \
659  const int width = out->width; \
660  const float max = s->max_value; \
661  \
662  for (int y = slice_start; y < slice_end; y++) { \
663  for (int x = 0; x < width; x++) { \
664  float dist = 0.f; \
665  for (int p = 0; p < s->nb_planes; p++) { \
666  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
667  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
668  \
669  dist += (xf0[x] / max - xf1[x] / max) * \
670  (xf0[x] / max - xf1[x] / max); \
671  } \
672  \
673  dist = sqrtf(dist) <= progress; \
674  for (int p = 0; p < s->nb_planes; p++) { \
675  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
676  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
677  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
678  dst[x] = mix(mix(xf0[x], xf1[x], dist), xf1[x], progress); \
679  } \
680  } \
681  } \
682 }
683 
684 DISTANCE_TRANSITION(8, uint8_t, 1)
685 DISTANCE_TRANSITION(16, uint16_t, 2)
686 
687 #define FADEBLACK_TRANSITION(name, type, div) \
688 static void fadeblack##name##_transition(AVFilterContext *ctx, \
689  const AVFrame *a, const AVFrame *b, AVFrame *out, \
690  float progress, \
691  int slice_start, int slice_end, int jobnr) \
692 { \
693  XFadeContext *s = ctx->priv; \
694  const int height = slice_end - slice_start; \
695  const int width = out->width; \
696  const float phase = 0.2f; \
697  \
698  for (int p = 0; p < s->nb_planes; p++) { \
699  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
700  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
701  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
702  const int bg = s->black[p]; \
703  \
704  for (int y = 0; y < height; y++) { \
705  for (int x = 0; x < width; x++) { \
706  dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \
707  mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \
708  progress); \
709  } \
710  \
711  dst += out->linesize[p] / div; \
712  xf0 += a->linesize[p] / div; \
713  xf1 += b->linesize[p] / div; \
714  } \
715  } \
716 }
717 
718 FADEBLACK_TRANSITION(8, uint8_t, 1)
719 FADEBLACK_TRANSITION(16, uint16_t, 2)
720 
721 #define FADEWHITE_TRANSITION(name, type, div) \
722 static void fadewhite##name##_transition(AVFilterContext *ctx, \
723  const AVFrame *a, const AVFrame *b, AVFrame *out, \
724  float progress, \
725  int slice_start, int slice_end, int jobnr) \
726 { \
727  XFadeContext *s = ctx->priv; \
728  const int height = slice_end - slice_start; \
729  const int width = out->width; \
730  const float phase = 0.2f; \
731  \
732  for (int p = 0; p < s->nb_planes; p++) { \
733  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
734  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
735  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
736  const int bg = s->white[p]; \
737  \
738  for (int y = 0; y < height; y++) { \
739  for (int x = 0; x < width; x++) { \
740  dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \
741  mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \
742  progress); \
743  } \
744  \
745  dst += out->linesize[p] / div; \
746  xf0 += a->linesize[p] / div; \
747  xf1 += b->linesize[p] / div; \
748  } \
749  } \
750 }
751 
752 FADEWHITE_TRANSITION(8, uint8_t, 1)
753 FADEWHITE_TRANSITION(16, uint16_t, 2)
754 
755 #define RADIAL_TRANSITION(name, type, div) \
756 static void radial##name##_transition(AVFilterContext *ctx, \
757  const AVFrame *a, const AVFrame *b, AVFrame *out, \
758  float progress, \
759  int slice_start, int slice_end, int jobnr) \
760 { \
761  XFadeContext *s = ctx->priv; \
762  const int width = out->width; \
763  const int height = out->height; \
764  \
765  for (int y = slice_start; y < slice_end; y++) { \
766  for (int x = 0; x < width; x++) { \
767  const float smooth = atan2f(x - width / 2, y - height / 2) - \
768  (progress - 0.5f) * (M_PI * 2.5f); \
769  for (int p = 0; p < s->nb_planes; p++) { \
770  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
771  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
772  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
773  \
774  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
775  } \
776  } \
777  } \
778 }
779 
780 RADIAL_TRANSITION(8, uint8_t, 1)
781 RADIAL_TRANSITION(16, uint16_t, 2)
782 
783 #define SMOOTHLEFT_TRANSITION(name, type, div) \
784 static void smoothleft##name##_transition(AVFilterContext *ctx, \
785  const AVFrame *a, const AVFrame *b, AVFrame *out, \
786  float progress, \
787  int slice_start, int slice_end, int jobnr) \
788 { \
789  XFadeContext *s = ctx->priv; \
790  const int width = out->width; \
791  const float w = width; \
792  \
793  for (int y = slice_start; y < slice_end; y++) { \
794  for (int x = 0; x < width; x++) { \
795  const float smooth = 1.f + x / w - progress * 2.f; \
796  \
797  for (int p = 0; p < s->nb_planes; p++) { \
798  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
799  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
800  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
801  \
802  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
803  } \
804  } \
805  } \
806 }
807 
808 SMOOTHLEFT_TRANSITION(8, uint8_t, 1)
809 SMOOTHLEFT_TRANSITION(16, uint16_t, 2)
810 
811 #define SMOOTHRIGHT_TRANSITION(name, type, div) \
812 static void smoothright##name##_transition(AVFilterContext *ctx, \
813  const AVFrame *a, const AVFrame *b, AVFrame *out, \
814  float progress, \
815  int slice_start, int slice_end, int jobnr) \
816 { \
817  XFadeContext *s = ctx->priv; \
818  const int width = out->width; \
819  const float w = width; \
820  \
821  for (int y = slice_start; y < slice_end; y++) { \
822  for (int x = 0; x < width; x++) { \
823  const float smooth = 1.f + (w - 1 - x) / w - progress * 2.f; \
824  \
825  for (int p = 0; p < s->nb_planes; p++) { \
826  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
827  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
828  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
829  \
830  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
831  } \
832  } \
833  } \
834 }
835 
836 SMOOTHRIGHT_TRANSITION(8, uint8_t, 1)
837 SMOOTHRIGHT_TRANSITION(16, uint16_t, 2)
838 
839 #define SMOOTHUP_TRANSITION(name, type, div) \
840 static void smoothup##name##_transition(AVFilterContext *ctx, \
841  const AVFrame *a, const AVFrame *b, AVFrame *out, \
842  float progress, \
843  int slice_start, int slice_end, int jobnr) \
844 { \
845  XFadeContext *s = ctx->priv; \
846  const int width = out->width; \
847  const float h = out->height; \
848  \
849  for (int y = slice_start; y < slice_end; y++) { \
850  const float smooth = 1.f + y / h - progress * 2.f; \
851  for (int x = 0; x < width; x++) { \
852  for (int p = 0; p < s->nb_planes; p++) { \
853  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
854  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
855  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
856  \
857  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
858  } \
859  } \
860  } \
861 }
862 
863 SMOOTHUP_TRANSITION(8, uint8_t, 1)
864 SMOOTHUP_TRANSITION(16, uint16_t, 2)
865 
866 #define SMOOTHDOWN_TRANSITION(name, type, div) \
867 static void smoothdown##name##_transition(AVFilterContext *ctx, \
868  const AVFrame *a, const AVFrame *b, AVFrame *out, \
869  float progress, \
870  int slice_start, int slice_end, int jobnr) \
871 { \
872  XFadeContext *s = ctx->priv; \
873  const int width = out->width; \
874  const float h = out->height; \
875  \
876  for (int y = slice_start; y < slice_end; y++) { \
877  const float smooth = 1.f + (h - 1 - y) / h - progress * 2.f; \
878  for (int x = 0; x < width; x++) { \
879  for (int p = 0; p < s->nb_planes; p++) { \
880  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
881  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
882  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
883  \
884  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
885  } \
886  } \
887  } \
888 }
889 
890 SMOOTHDOWN_TRANSITION(8, uint8_t, 1)
891 SMOOTHDOWN_TRANSITION(16, uint16_t, 2)
892 
893 #define CIRCLEOPEN_TRANSITION(name, type, div) \
894 static void circleopen##name##_transition(AVFilterContext *ctx, \
895  const AVFrame *a, const AVFrame *b, AVFrame *out, \
896  float progress, \
897  int slice_start, int slice_end, int jobnr) \
898 { \
899  XFadeContext *s = ctx->priv; \
900  const int width = out->width; \
901  const int height = out->height; \
902  const float z = hypotf(width / 2, height / 2); \
903  const float p = (progress - 0.5f) * 3.f; \
904  \
905  for (int y = slice_start; y < slice_end; y++) { \
906  for (int x = 0; x < width; x++) { \
907  const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \
908  for (int p = 0; p < s->nb_planes; p++) { \
909  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
910  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
911  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
912  \
913  dst[x] = mix(xf0[x], xf1[x], smoothstep(0.f, 1.f, smooth)); \
914  } \
915  } \
916  } \
917 }
918 
919 CIRCLEOPEN_TRANSITION(8, uint8_t, 1)
920 CIRCLEOPEN_TRANSITION(16, uint16_t, 2)
921 
922 #define CIRCLECLOSE_TRANSITION(name, type, div) \
923 static void circleclose##name##_transition(AVFilterContext *ctx, \
924  const AVFrame *a, const AVFrame *b, AVFrame *out, \
925  float progress, \
926  int slice_start, int slice_end, int jobnr) \
927 { \
928  XFadeContext *s = ctx->priv; \
929  const int width = out->width; \
930  const int height = out->height; \
931  const float z = hypotf(width / 2, height / 2); \
932  const float p = (1.f - progress - 0.5f) * 3.f; \
933  \
934  for (int y = slice_start; y < slice_end; y++) { \
935  for (int x = 0; x < width; x++) { \
936  const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \
937  for (int p = 0; p < s->nb_planes; p++) { \
938  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
939  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
940  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
941  \
942  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
943  } \
944  } \
945  } \
946 }
947 
948 CIRCLECLOSE_TRANSITION(8, uint8_t, 1)
949 CIRCLECLOSE_TRANSITION(16, uint16_t, 2)
950 
951 #define VERTOPEN_TRANSITION(name, type, div) \
952 static void vertopen##name##_transition(AVFilterContext *ctx, \
953  const AVFrame *a, const AVFrame *b, AVFrame *out, \
954  float progress, \
955  int slice_start, int slice_end, int jobnr) \
956 { \
957  XFadeContext *s = ctx->priv; \
958  const int width = out->width; \
959  const float w2 = out->width / 2; \
960  \
961  for (int y = slice_start; y < slice_end; y++) { \
962  for (int x = 0; x < width; x++) { \
963  const float smooth = 2.f - fabsf((x - w2) / w2) - progress * 2.f; \
964  for (int p = 0; p < s->nb_planes; p++) { \
965  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
966  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
967  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
968  \
969  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
970  } \
971  } \
972  } \
973 }
974 
975 VERTOPEN_TRANSITION(8, uint8_t, 1)
976 VERTOPEN_TRANSITION(16, uint16_t, 2)
977 
978 #define VERTCLOSE_TRANSITION(name, type, div) \
979 static void vertclose##name##_transition(AVFilterContext *ctx, \
980  const AVFrame *a, const AVFrame *b, AVFrame *out, \
981  float progress, \
982  int slice_start, int slice_end, int jobnr) \
983 { \
984  XFadeContext *s = ctx->priv; \
985  const int nb_planes = s->nb_planes; \
986  const int width = out->width; \
987  const float w2 = out->width / 2; \
988  \
989  for (int y = slice_start; y < slice_end; y++) { \
990  for (int x = 0; x < width; x++) { \
991  const float smooth = 1.f + fabsf((x - w2) / w2) - progress * 2.f; \
992  for (int p = 0; p < nb_planes; p++) { \
993  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
994  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
995  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
996  \
997  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
998  } \
999  } \
1000  } \
1001 }
1002 
1003 VERTCLOSE_TRANSITION(8, uint8_t, 1)
1004 VERTCLOSE_TRANSITION(16, uint16_t, 2)
1005 
1006 #define HORZOPEN_TRANSITION(name, type, div) \
1007 static void horzopen##name##_transition(AVFilterContext *ctx, \
1008  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1009  float progress, \
1010  int slice_start, int slice_end, int jobnr) \
1011 { \
1012  XFadeContext *s = ctx->priv; \
1013  const int nb_planes = s->nb_planes; \
1014  const int width = out->width; \
1015  const float h2 = out->height / 2; \
1016  \
1017  for (int y = slice_start; y < slice_end; y++) { \
1018  const float smooth = 2.f - fabsf((y - h2) / h2) - progress * 2.f; \
1019  for (int x = 0; x < width; x++) { \
1020  for (int p = 0; p < nb_planes; p++) { \
1021  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1022  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1023  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1024  \
1025  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1026  } \
1027  } \
1028  } \
1029 }
1030 
1031 HORZOPEN_TRANSITION(8, uint8_t, 1)
1032 HORZOPEN_TRANSITION(16, uint16_t, 2)
1033 
1034 #define HORZCLOSE_TRANSITION(name, type, div) \
1035 static void horzclose##name##_transition(AVFilterContext *ctx, \
1036  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1037  float progress, \
1038  int slice_start, int slice_end, int jobnr) \
1039 { \
1040  XFadeContext *s = ctx->priv; \
1041  const int nb_planes = s->nb_planes; \
1042  const int width = out->width; \
1043  const float h2 = out->height / 2; \
1044  \
1045  for (int y = slice_start; y < slice_end; y++) { \
1046  const float smooth = 1.f + fabsf((y - h2) / h2) - progress * 2.f; \
1047  for (int x = 0; x < width; x++) { \
1048  for (int p = 0; p < nb_planes; p++) { \
1049  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1050  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1051  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1052  \
1053  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1054  } \
1055  } \
1056  } \
1057 }
1058 
1059 HORZCLOSE_TRANSITION(8, uint8_t, 1)
1060 HORZCLOSE_TRANSITION(16, uint16_t, 2)
1061 
1062 static float frand(int x, int y)
1063 {
1064  const float r = sinf(x * 12.9898f + y * 78.233f) * 43758.545f;
1065 
1066  return r - floorf(r);
1067 }
1068 
1069 #define DISSOLVE_TRANSITION(name, type, div) \
1070 static void dissolve##name##_transition(AVFilterContext *ctx, \
1071  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1072  float progress, \
1073  int slice_start, int slice_end, int jobnr) \
1074 { \
1075  XFadeContext *s = ctx->priv; \
1076  const int nb_planes = s->nb_planes; \
1077  const int width = out->width; \
1078  \
1079  for (int y = slice_start; y < slice_end; y++) { \
1080  for (int x = 0; x < width; x++) { \
1081  const float smooth = frand(x, y) * 2.f + progress * 2.f - 1.5f; \
1082  for (int p = 0; p < nb_planes; p++) { \
1083  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1084  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1085  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1086  \
1087  dst[x] = smooth >= 0.5f ? xf0[x] : xf1[x]; \
1088  } \
1089  } \
1090  } \
1091 }
1092 
1093 DISSOLVE_TRANSITION(8, uint8_t, 1)
1094 DISSOLVE_TRANSITION(16, uint16_t, 2)
1095 
1096 #define PIXELIZE_TRANSITION(name, type, div) \
1097 static void pixelize##name##_transition(AVFilterContext *ctx, \
1098  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1099  float progress, \
1100  int slice_start, int slice_end, int jobnr) \
1101 { \
1102  XFadeContext *s = ctx->priv; \
1103  const int nb_planes = s->nb_planes; \
1104  const int w = out->width; \
1105  const int h = out->height; \
1106  const float d = fminf(progress, 1.f - progress); \
1107  const float dist = ceilf(d * 50.f) / 50.f; \
1108  const float sqx = 2.f * dist * FFMIN(w, h) / 20.f; \
1109  const float sqy = 2.f * dist * FFMIN(w, h) / 20.f; \
1110  \
1111  for (int y = slice_start; y < slice_end; y++) { \
1112  for (int x = 0; x < w; x++) { \
1113  int sx = dist > 0.f ? FFMIN((floorf(x / sqx) + .5f) * sqx, w - 1) : x; \
1114  int sy = dist > 0.f ? FFMIN((floorf(y / sqy) + .5f) * sqy, h - 1) : y; \
1115  for (int p = 0; p < nb_planes; p++) { \
1116  const type *xf0 = (const type *)(a->data[p] + sy * a->linesize[p]); \
1117  const type *xf1 = (const type *)(b->data[p] + sy * b->linesize[p]); \
1118  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1119  \
1120  dst[x] = mix(xf0[sx], xf1[sx], progress); \
1121  } \
1122  } \
1123  } \
1124 }
1125 
1126 PIXELIZE_TRANSITION(8, uint8_t, 1)
1127 PIXELIZE_TRANSITION(16, uint16_t, 2)
1128 
1129 #define DIAGTL_TRANSITION(name, type, div) \
1130 static void diagtl##name##_transition(AVFilterContext *ctx, \
1131  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1132  float progress, \
1133  int slice_start, int slice_end, int jobnr) \
1134 { \
1135  XFadeContext *s = ctx->priv; \
1136  const int nb_planes = s->nb_planes; \
1137  const int width = out->width; \
1138  const float w = width; \
1139  const float h = out->height; \
1140  \
1141  for (int y = slice_start; y < slice_end; y++) { \
1142  for (int x = 0; x < width; x++) { \
1143  const float smooth = 1.f + x / w * y / h - progress * 2.f; \
1144  \
1145  for (int p = 0; p < nb_planes; p++) { \
1146  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1147  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1148  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1149  \
1150  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1151  } \
1152  } \
1153  } \
1154 }
1155 
1156 DIAGTL_TRANSITION(8, uint8_t, 1)
1157 DIAGTL_TRANSITION(16, uint16_t, 2)
1158 
1159 #define DIAGTR_TRANSITION(name, type, div) \
1160 static void diagtr##name##_transition(AVFilterContext *ctx, \
1161  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1162  float progress, \
1163  int slice_start, int slice_end, int jobnr) \
1164 { \
1165  XFadeContext *s = ctx->priv; \
1166  const int nb_planes = s->nb_planes; \
1167  const int width = out->width; \
1168  const float w = width; \
1169  const float h = out->height; \
1170  \
1171  for (int y = slice_start; y < slice_end; y++) { \
1172  for (int x = 0; x < width; x++) { \
1173  const float smooth = 1.f + (w - 1 - x) / w * y / h - progress * 2.f; \
1174  \
1175  for (int p = 0; p < nb_planes; p++) { \
1176  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1177  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1178  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1179  \
1180  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1181  } \
1182  } \
1183  } \
1184 }
1185 
1186 DIAGTR_TRANSITION(8, uint8_t, 1)
1187 DIAGTR_TRANSITION(16, uint16_t, 2)
1188 
1189 #define DIAGBL_TRANSITION(name, type, div) \
1190 static void diagbl##name##_transition(AVFilterContext *ctx, \
1191  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1192  float progress, \
1193  int slice_start, int slice_end, int jobnr) \
1194 { \
1195  XFadeContext *s = ctx->priv; \
1196  const int nb_planes = s->nb_planes; \
1197  const int width = out->width; \
1198  const float w = width; \
1199  const float h = out->height; \
1200  \
1201  for (int y = slice_start; y < slice_end; y++) { \
1202  for (int x = 0; x < width; x++) { \
1203  const float smooth = 1.f + x / w * (h - 1 - y) / h - progress * 2.f; \
1204  \
1205  for (int p = 0; p < nb_planes; p++) { \
1206  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1207  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1208  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1209  \
1210  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1211  } \
1212  } \
1213  } \
1214 }
1215 
1216 DIAGBL_TRANSITION(8, uint8_t, 1)
1217 DIAGBL_TRANSITION(16, uint16_t, 2)
1218 
1219 #define DIAGBR_TRANSITION(name, type, div) \
1220 static void diagbr##name##_transition(AVFilterContext *ctx, \
1221  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1222  float progress, \
1223  int slice_start, int slice_end, int jobnr) \
1224 { \
1225  XFadeContext *s = ctx->priv; \
1226  const int nb_planes = s->nb_planes; \
1227  const int width = out->width; \
1228  const float w = width; \
1229  const float h = out->height; \
1230  \
1231  for (int y = slice_start; y < slice_end; y++) { \
1232  for (int x = 0; x < width; x++) { \
1233  const float smooth = 1.f + (w - 1 - x) / w * (h - 1 - y) / h - \
1234  progress * 2.f; \
1235  \
1236  for (int p = 0; p < nb_planes; p++) { \
1237  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1238  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1239  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1240  \
1241  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1242  } \
1243  } \
1244  } \
1245 }
1246 
1247 DIAGBR_TRANSITION(8, uint8_t, 1)
1248 DIAGBR_TRANSITION(16, uint16_t, 2)
1249 
1250 #define HLSLICE_TRANSITION(name, type, div) \
1251 static void hlslice##name##_transition(AVFilterContext *ctx, \
1252  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1253  float progress, \
1254  int slice_start, int slice_end, int jobnr) \
1255 { \
1256  XFadeContext *s = ctx->priv; \
1257  const int nb_planes = s->nb_planes; \
1258  const int width = out->width; \
1259  const float w = width; \
1260  \
1261  for (int y = slice_start; y < slice_end; y++) { \
1262  for (int x = 0; x < width; x++) { \
1263  const float smooth = smoothstep(-0.5f, 0.f, x / w - progress * 1.5f); \
1264  const float ss = smooth <= fract(10.f * x / w) ? 0.f : 1.f; \
1265  \
1266  for (int p = 0; p < nb_planes; p++) { \
1267  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1268  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1269  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1270  \
1271  dst[x] = mix(xf1[x], xf0[x], ss); \
1272  } \
1273  } \
1274  } \
1275 }
1276 
1277 HLSLICE_TRANSITION(8, uint8_t, 1)
1278 HLSLICE_TRANSITION(16, uint16_t, 2)
1279 
1280 #define HRSLICE_TRANSITION(name, type, div) \
1281 static void hrslice##name##_transition(AVFilterContext *ctx, \
1282  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1283  float progress, \
1284  int slice_start, int slice_end, int jobnr) \
1285 { \
1286  XFadeContext *s = ctx->priv; \
1287  const int nb_planes = s->nb_planes; \
1288  const int width = out->width; \
1289  const float w = width; \
1290  \
1291  for (int y = slice_start; y < slice_end; y++) { \
1292  for (int x = 0; x < width; x++) { \
1293  const float xx = (w - 1 - x) / w; \
1294  const float smooth = smoothstep(-0.5f, 0.f, xx - progress * 1.5f); \
1295  const float ss = smooth <= fract(10.f * xx) ? 0.f : 1.f; \
1296  \
1297  for (int p = 0; p < nb_planes; p++) { \
1298  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1299  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1300  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1301  \
1302  dst[x] = mix(xf1[x], xf0[x], ss); \
1303  } \
1304  } \
1305  } \
1306 }
1307 
1308 HRSLICE_TRANSITION(8, uint8_t, 1)
1309 HRSLICE_TRANSITION(16, uint16_t, 2)
1310 
1311 #define VUSLICE_TRANSITION(name, type, div) \
1312 static void vuslice##name##_transition(AVFilterContext *ctx, \
1313  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1314  float progress, \
1315  int slice_start, int slice_end, int jobnr) \
1316 { \
1317  XFadeContext *s = ctx->priv; \
1318  const int nb_planes = s->nb_planes; \
1319  const int width = out->width; \
1320  const float h = out->height; \
1321  \
1322  for (int y = slice_start; y < slice_end; y++) { \
1323  const float smooth = smoothstep(-0.5f, 0.f, y / h - progress * 1.5f); \
1324  const float ss = smooth <= fract(10.f * y / h) ? 0.f : 1.f; \
1325  \
1326  for (int x = 0; x < width; x++) { \
1327  for (int p = 0; p < nb_planes; p++) { \
1328  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1329  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1330  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1331  \
1332  dst[x] = mix(xf1[x], xf0[x], ss); \
1333  } \
1334  } \
1335  } \
1336 }
1337 
1338 VUSLICE_TRANSITION(8, uint8_t, 1)
1339 VUSLICE_TRANSITION(16, uint16_t, 2)
1340 
1341 #define VDSLICE_TRANSITION(name, type, div) \
1342 static void vdslice##name##_transition(AVFilterContext *ctx, \
1343  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1344  float progress, \
1345  int slice_start, int slice_end, int jobnr) \
1346 { \
1347  XFadeContext *s = ctx->priv; \
1348  const int nb_planes = s->nb_planes; \
1349  const int width = out->width; \
1350  const float h = out->height; \
1351  \
1352  for (int y = slice_start; y < slice_end; y++) { \
1353  const float yy = (h - 1 - y) / h; \
1354  const float smooth = smoothstep(-0.5f, 0.f, yy - progress * 1.5f); \
1355  const float ss = smooth <= fract(10.f * yy) ? 0.f : 1.f; \
1356  \
1357  for (int x = 0; x < width; x++) { \
1358  for (int p = 0; p < nb_planes; p++) { \
1359  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1360  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1361  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1362  \
1363  dst[x] = mix(xf1[x], xf0[x], ss); \
1364  } \
1365  } \
1366  } \
1367 }
1368 
1369 VDSLICE_TRANSITION(8, uint8_t, 1)
1370 VDSLICE_TRANSITION(16, uint16_t, 2)
1371 
1372 #define HBLUR_TRANSITION(name, type, div) \
1373 static void hblur##name##_transition(AVFilterContext *ctx, \
1374  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1375  float progress, \
1376  int slice_start, int slice_end, int jobnr) \
1377 { \
1378  XFadeContext *s = ctx->priv; \
1379  const int nb_planes = s->nb_planes; \
1380  const int width = out->width; \
1381  const float prog = progress <= 0.5f ? progress * 2.f : (1.f - progress) * 2.f; \
1382  const int size = 1 + (width / 2) * prog; \
1383  \
1384  for (int y = slice_start; y < slice_end; y++) { \
1385  for (int p = 0; p < nb_planes; p++) { \
1386  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1387  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1388  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1389  float sum0 = 0.f; \
1390  float sum1 = 0.f; \
1391  float cnt = size; \
1392  \
1393  for (int x = 0; x < size; x++) { \
1394  sum0 += xf0[x]; \
1395  sum1 += xf1[x]; \
1396  } \
1397  \
1398  for (int x = 0; x < width; x++) { \
1399  dst[x] = mix(sum0 / cnt, sum1 / cnt, progress); \
1400  \
1401  if (x + size < width) { \
1402  sum0 += xf0[x + size] - xf0[x]; \
1403  sum1 += xf1[x + size] - xf1[x]; \
1404  } else { \
1405  sum0 -= xf0[x]; \
1406  sum1 -= xf1[x]; \
1407  cnt--; \
1408  } \
1409  } \
1410  } \
1411  } \
1412 }
1413 
1414 HBLUR_TRANSITION(8, uint8_t, 1)
1415 HBLUR_TRANSITION(16, uint16_t, 2)
1416 
1417 #define FADEGRAYS_TRANSITION(name, type, div) \
1418 static void fadegrays##name##_transition(AVFilterContext *ctx, \
1419  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1420  float progress, \
1421  int slice_start, int slice_end, int jobnr) \
1422 { \
1423  XFadeContext *s = ctx->priv; \
1424  const int width = out->width; \
1425  const int is_rgb = s->is_rgb; \
1426  const int mid = (s->max_value + 1) / 2; \
1427  const float phase = 0.2f; \
1428  \
1429  for (int y = slice_start; y < slice_end; y++) { \
1430  for (int x = 0; x < width; x++) { \
1431  int bg[2][4]; \
1432  if (is_rgb) { \
1433  bg[0][0] = bg[1][0] = 0; \
1434  for (int p = 0; p < s->nb_planes; p++) { \
1435  const type *xf0 = (const type *)(a->data[p] + \
1436  y * a->linesize[p]); \
1437  const type *xf1 = (const type *)(b->data[p] + \
1438  y * b->linesize[p]); \
1439  if (p == 3) { \
1440  bg[0][3] = xf0[x]; \
1441  bg[1][3] = xf1[x]; \
1442  } else { \
1443  bg[0][0] += xf0[x]; \
1444  bg[1][0] += xf1[x]; \
1445  } \
1446  } \
1447  bg[0][0] = bg[0][0] / 3; \
1448  bg[1][0] = bg[1][0] / 3; \
1449  bg[0][1] = bg[0][2] = bg[0][0]; \
1450  bg[1][1] = bg[1][2] = bg[1][0]; \
1451  } else { \
1452  const type *yf0 = (const type *)(a->data[0] + \
1453  y * a->linesize[0]); \
1454  const type *yf1 = (const type *)(b->data[0] + \
1455  y * a->linesize[0]); \
1456  bg[0][0] = yf0[x]; \
1457  bg[1][0] = yf1[x]; \
1458  if (s->nb_planes == 4) { \
1459  const type *af0 = (const type *)(a->data[3] + \
1460  y * a->linesize[3]); \
1461  const type *af1 = (const type *)(b->data[3] + \
1462  y * a->linesize[3]); \
1463  bg[0][3] = af0[x]; \
1464  bg[1][3] = af1[x]; \
1465  } \
1466  bg[0][1] = bg[1][1] = mid; \
1467  bg[0][2] = bg[1][2] = mid; \
1468  } \
1469  \
1470  for (int p = 0; p < s->nb_planes; p++) { \
1471  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1472  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1473  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1474  \
1475  dst[x] = mix(mix(xf0[x], bg[0][p], \
1476  smoothstep(1.f-phase, 1.f, progress)), \
1477  mix(bg[1][p], xf1[x], smoothstep(phase, 1.f, progress)), \
1478  progress); \
1479  } \
1480  } \
1481  } \
1482 }
1483 
1484 FADEGRAYS_TRANSITION(8, uint8_t, 1)
1485 FADEGRAYS_TRANSITION(16, uint16_t, 2)
1486 
1487 #define WIPETL_TRANSITION(name, type, div) \
1488 static void wipetl##name##_transition(AVFilterContext *ctx, \
1489  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1490  float progress, \
1491  int slice_start, int slice_end, int jobnr) \
1492 { \
1493  XFadeContext *s = ctx->priv; \
1494  const int height = slice_end - slice_start; \
1495  const int width = out->width; \
1496  const int zw = out->width * progress; \
1497  const int zh = out->height * progress; \
1498  \
1499  for (int p = 0; p < s->nb_planes; p++) { \
1500  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1501  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1502  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1503  \
1504  for (int y = 0; y < height; y++) { \
1505  for (int x = 0; x < width; x++) { \
1506  dst[x] = slice_start + y <= zh && \
1507  x <= zw ? xf0[x] : xf1[x]; \
1508  } \
1509  \
1510  dst += out->linesize[p] / div; \
1511  xf0 += a->linesize[p] / div; \
1512  xf1 += b->linesize[p] / div; \
1513  } \
1514  } \
1515 }
1516 
1517 WIPETL_TRANSITION(8, uint8_t, 1)
1518 WIPETL_TRANSITION(16, uint16_t, 2)
1519 
1520 #define WIPETR_TRANSITION(name, type, div) \
1521 static void wipetr##name##_transition(AVFilterContext *ctx, \
1522  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1523  float progress, \
1524  int slice_start, int slice_end, int jobnr) \
1525 { \
1526  XFadeContext *s = ctx->priv; \
1527  const int height = slice_end - slice_start; \
1528  const int width = out->width; \
1529  const int zw = width * (1.f - progress); \
1530  const int zh = out->height * progress; \
1531  \
1532  for (int p = 0; p < s->nb_planes; p++) { \
1533  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1534  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1535  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1536  \
1537  for (int y = 0; y < height; y++) { \
1538  for (int x = 0; x < width; x++) { \
1539  dst[x] = slice_start + y <= zh && \
1540  x > zw ? xf0[x] : xf1[x]; \
1541  } \
1542  \
1543  dst += out->linesize[p] / div; \
1544  xf0 += a->linesize[p] / div; \
1545  xf1 += b->linesize[p] / div; \
1546  } \
1547  } \
1548 }
1549 
1550 WIPETR_TRANSITION(8, uint8_t, 1)
1551 WIPETR_TRANSITION(16, uint16_t, 2)
1552 
1553 #define WIPEBL_TRANSITION(name, type, div) \
1554 static void wipebl##name##_transition(AVFilterContext *ctx, \
1555  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1556  float progress, \
1557  int slice_start, int slice_end, int jobnr) \
1558 { \
1559  XFadeContext *s = ctx->priv; \
1560  const int height = slice_end - slice_start; \
1561  const int width = out->width; \
1562  const int zw = width * progress; \
1563  const int zh = out->height * (1.f - progress); \
1564  \
1565  for (int p = 0; p < s->nb_planes; p++) { \
1566  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1567  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1568  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1569  \
1570  for (int y = 0; y < height; y++) { \
1571  for (int x = 0; x < width; x++) { \
1572  dst[x] = slice_start + y > zh && \
1573  x <= zw ? xf0[x] : xf1[x]; \
1574  } \
1575  \
1576  dst += out->linesize[p] / div; \
1577  xf0 += a->linesize[p] / div; \
1578  xf1 += b->linesize[p] / div; \
1579  } \
1580  } \
1581 }
1582 
1583 WIPEBL_TRANSITION(8, uint8_t, 1)
1584 WIPEBL_TRANSITION(16, uint16_t, 2)
1585 
1586 #define WIPEBR_TRANSITION(name, type, div) \
1587 static void wipebr##name##_transition(AVFilterContext *ctx, \
1588  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1589  float progress, \
1590  int slice_start, int slice_end, int jobnr) \
1591 { \
1592  XFadeContext *s = ctx->priv; \
1593  const int height = slice_end - slice_start; \
1594  const int zh = out->height * (1.f - progress); \
1595  const int width = out->width; \
1596  const int zw = width * (1.f - progress); \
1597  \
1598  for (int p = 0; p < s->nb_planes; p++) { \
1599  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1600  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1601  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1602  \
1603  for (int y = 0; y < height; y++) { \
1604  for (int x = 0; x < width; x++) { \
1605  dst[x] = slice_start + y > zh && \
1606  x > zw ? xf0[x] : xf1[x]; \
1607  } \
1608  \
1609  dst += out->linesize[p] / div; \
1610  xf0 += a->linesize[p] / div; \
1611  xf1 += b->linesize[p] / div; \
1612  } \
1613  } \
1614 }
1615 
1616 WIPEBR_TRANSITION(8, uint8_t, 1)
1617 WIPEBR_TRANSITION(16, uint16_t, 2)
1618 
1619 #define SQUEEZEH_TRANSITION(name, type, div) \
1620 static void squeezeh##name##_transition(AVFilterContext *ctx, \
1621  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1622  float progress, \
1623  int slice_start, int slice_end, int jobnr) \
1624 { \
1625  XFadeContext *s = ctx->priv; \
1626  const float h = out->height; \
1627  const int height = slice_end - slice_start; \
1628  const int width = out->width; \
1629  \
1630  for (int p = 0; p < s->nb_planes; p++) { \
1631  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1632  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1633  \
1634  for (int y = 0; y < height; y++) { \
1635  const float z = .5f + ((slice_start + y) / h - .5f) / progress; \
1636  \
1637  if (z < 0.f || z > 1.f) { \
1638  for (int x = 0; x < width; x++) \
1639  dst[x] = xf1[x]; \
1640  } else { \
1641  const int yy = lrintf(z * (h - 1.f)); \
1642  const type *xf0 = (const type *)(a->data[p] + yy * a->linesize[p]); \
1643  \
1644  for (int x = 0; x < width; x++) \
1645  dst[x] = xf0[x]; \
1646  } \
1647  \
1648  dst += out->linesize[p] / div; \
1649  xf1 += b->linesize[p] / div; \
1650  } \
1651  } \
1652 }
1653 
1654 SQUEEZEH_TRANSITION(8, uint8_t, 1)
1655 SQUEEZEH_TRANSITION(16, uint16_t, 2)
1656 
1657 #define SQUEEZEV_TRANSITION(name, type, div) \
1658 static void squeezev##name##_transition(AVFilterContext *ctx, \
1659  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1660  float progress, \
1661  int slice_start, int slice_end, int jobnr) \
1662 { \
1663  XFadeContext *s = ctx->priv; \
1664  const int width = out->width; \
1665  const float w = width; \
1666  const int height = slice_end - slice_start; \
1667  \
1668  for (int p = 0; p < s->nb_planes; p++) { \
1669  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1670  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1671  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1672  \
1673  for (int y = 0; y < height; y++) { \
1674  for (int x = 0; x < width; x++) { \
1675  const float z = .5f + (x / w - .5f) / progress; \
1676  \
1677  if (z < 0.f || z > 1.f) { \
1678  dst[x] = xf1[x]; \
1679  } else { \
1680  const int xx = lrintf(z * (w - 1.f)); \
1681  \
1682  dst[x] = xf0[xx]; \
1683  } \
1684  } \
1685  \
1686  dst += out->linesize[p] / div; \
1687  xf0 += a->linesize[p] / div; \
1688  xf1 += b->linesize[p] / div; \
1689  } \
1690  } \
1691 }
1692 
1693 SQUEEZEV_TRANSITION(8, uint8_t, 1)
1694 SQUEEZEV_TRANSITION(16, uint16_t, 2)
1695 
1696 static void zoom(float *u, float *v, float amount)
1697 {
1698  *u = 0.5f + ((*u - 0.5f) * amount);
1699  *v = 0.5f + ((*v - 0.5f) * amount);
1700 }
1701 
1702 #define ZOOMIN_TRANSITION(name, type, div) \
1703 static void zoomin##name##_transition(AVFilterContext *ctx, \
1704  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1705  float progress, \
1706  int slice_start, int slice_end, int jobnr) \
1707 { \
1708  XFadeContext *s = ctx->priv; \
1709  const int width = out->width; \
1710  const float w = width; \
1711  const float h = out->height; \
1712  const float zf = smoothstep(0.5f, 1.f, progress); \
1713  \
1714  for (int p = 0; p < s->nb_planes; p++) { \
1715  const type *xf0 = (const type *)(a->data[p]); \
1716  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1717  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1718  \
1719  for (int y = slice_start; y < slice_end; y++) { \
1720  for (int x = 0; x < width; x++) { \
1721  float zv, u, v; \
1722  int iu, iv; \
1723  \
1724  u = x / w; \
1725  v = y / h; \
1726  zoom(&u, &v, zf); \
1727  iu = ceilf(u * (w - 1)); \
1728  iv = ceilf(v * (h - 1)); \
1729  zv = xf0[iu + iv * a->linesize[p] / div]; \
1730  dst[x] = mix(zv, xf1[x], smoothstep(0.f, 0.5f, progress)); \
1731  } \
1732  dst += out->linesize[p] / div; \
1733  xf1 += b->linesize[p] / div; \
1734  } \
1735  } \
1736 }
1737 
1738 ZOOMIN_TRANSITION(8, uint8_t, 1)
1739 ZOOMIN_TRANSITION(16, uint16_t, 2)
1740 
1741 #define FADEFAST_TRANSITION(name, type, div) \
1742 static void fadefast##name##_transition(AVFilterContext *ctx, \
1743  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1744  float progress, \
1745  int slice_start, int slice_end, int jobnr) \
1746 { \
1747  XFadeContext *s = ctx->priv; \
1748  const int height = slice_end - slice_start; \
1749  const int width = out->width; \
1750  const float imax = 1.f / s->max_value; \
1751  \
1752  for (int p = 0; p < s->nb_planes; p++) { \
1753  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1754  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1755  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1756  \
1757  for (int y = 0; y < height; y++) { \
1758  for (int x = 0; x < width; x++) { \
1759  dst[x] = mix(xf0[x], xf1[x], powf(progress, 1.f + \
1760  logf(1.f+FFABS(xf0[x]-xf1[x])*imax)\
1761  )); \
1762  } \
1763  \
1764  dst += out->linesize[p] / div; \
1765  xf0 += a->linesize[p] / div; \
1766  xf1 += b->linesize[p] / div; \
1767  } \
1768  } \
1769 }
1770 
1771 FADEFAST_TRANSITION(8, uint8_t, 1)
1772 FADEFAST_TRANSITION(16, uint16_t, 2)
1773 
1774 #define FADESLOW_TRANSITION(name, type, div) \
1775 static void fadeslow##name##_transition(AVFilterContext *ctx, \
1776  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1777  float progress, \
1778  int slice_start, int slice_end, int jobnr) \
1779 { \
1780  XFadeContext *s = ctx->priv; \
1781  const int height = slice_end - slice_start; \
1782  const int width = out->width; \
1783  const float imax = 1.f / s->max_value; \
1784  \
1785  for (int p = 0; p < s->nb_planes; p++) { \
1786  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1787  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1788  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1789  \
1790  for (int y = 0; y < height; y++) { \
1791  for (int x = 0; x < width; x++) { \
1792  dst[x] = mix(xf0[x], xf1[x], powf(progress, 1.f + \
1793  logf(2.f-FFABS(xf0[x]-xf1[x])*imax)\
1794  )); \
1795  } \
1796  \
1797  dst += out->linesize[p] / div; \
1798  xf0 += a->linesize[p] / div; \
1799  xf1 += b->linesize[p] / div; \
1800  } \
1801  } \
1802 }
1803 
1804 FADESLOW_TRANSITION(8, uint8_t, 1)
1805 FADESLOW_TRANSITION(16, uint16_t, 2)
1806 
1807 #define HWIND_TRANSITION(name, z, type, div, expr) \
1808 static void h##z##wind##name##_transition(AVFilterContext *ctx, \
1809  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1810  float progress, \
1811  int slice_start, int slice_end, int jobnr) \
1812 { \
1813  XFadeContext *s = ctx->priv; \
1814  const int width = out->width; \
1815  \
1816  for (int y = slice_start; y < slice_end; y++) { \
1817  const float r = frand(0, y); \
1818  for (int x = 0; x < width; x++) { \
1819  const float fx = expr x / (float)width; \
1820  for (int p = 0; p < s->nb_planes; p++) { \
1821  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1822  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1823  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1824  \
1825  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f,-0.2f, fx * (1.f - 0.2f)\
1826  + 0.2f * r - (1.f - progress)\
1827  * (1.f + 0.2f))); \
1828  } \
1829  } \
1830  } \
1831 }
1832 
1833 HWIND_TRANSITION(8, l, uint8_t, 1, 1.f - )
1834 HWIND_TRANSITION(16, l, uint16_t, 2, 1.f - )
1835 HWIND_TRANSITION(8, r, uint8_t, 1, )
1836 HWIND_TRANSITION(16, r, uint16_t, 2, )
1837 
1838 #define VWIND_TRANSITION(name, z, type, div, expr) \
1839 static void v##z##wind##name##_transition(AVFilterContext *ctx, \
1840  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1841  float progress, \
1842  int slice_start, int slice_end, int jobnr) \
1843 { \
1844  XFadeContext *s = ctx->priv; \
1845  const int width = out->width; \
1846  \
1847  for (int y = slice_start; y < slice_end; y++) { \
1848  const float fy = expr y / (float)out->height; \
1849  for (int x = 0; x < width; x++) { \
1850  const float r = frand(x, 0); \
1851  for (int p = 0; p < s->nb_planes; p++) { \
1852  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1853  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1854  type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1855  \
1856  dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f,-0.2f, fy * (1.f - 0.2f) \
1857  + 0.2f * r - (1.f - progress)\
1858  * (1.f + 0.2f))); \
1859  } \
1860  } \
1861  } \
1862 }
1863 
1864 VWIND_TRANSITION(8, u, uint8_t, 1, 1.f - )
1865 VWIND_TRANSITION(16, u, uint16_t, 2, 1.f - )
1866 VWIND_TRANSITION(8, d, uint8_t, 1, )
1867 VWIND_TRANSITION(16, d, uint16_t, 2, )
1868 
1869 #define COVERH_TRANSITION(dir, name, type, div, expr) \
1870 static void cover##dir##name##_transition(AVFilterContext *ctx, \
1871  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1872  float progress, \
1873  int slice_start, int slice_end, int jobnr) \
1874 { \
1875  XFadeContext *s = ctx->priv; \
1876  const int height = slice_end - slice_start; \
1877  const int width = out->width; \
1878  const int z = (expr progress) * width; \
1879  \
1880  for (int p = 0; p < s->nb_planes; p++) { \
1881  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1882  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1883  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1884  \
1885  for (int y = 0; y < height; y++) { \
1886  for (int x = 0; x < width; x++) { \
1887  const int zx = z + x; \
1888  const int zz = zx % width + width * (zx < 0); \
1889  dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[x]; \
1890  } \
1891  \
1892  dst += out->linesize[p] / div; \
1893  xf0 += a->linesize[p] / div; \
1894  xf1 += b->linesize[p] / div; \
1895  } \
1896  } \
1897 }
1898 
1899 COVERH_TRANSITION(left, 8, uint8_t, 1, -)
1900 COVERH_TRANSITION(left, 16, uint16_t, 2, -)
1901 COVERH_TRANSITION(right, 8, uint8_t, 1, )
1902 COVERH_TRANSITION(right, 16, uint16_t, 2, )
1903 
1904 #define COVERV_TRANSITION(dir, name, type, div, expr) \
1905 static void cover##dir##name##_transition(AVFilterContext *ctx, \
1906  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1907  float progress, \
1908  int slice_start, int slice_end, int jobnr) \
1909 { \
1910  XFadeContext *s = ctx->priv; \
1911  const int height = out->height; \
1912  const int width = out->width; \
1913  const int z = (expr progress) * height; \
1914  \
1915  for (int p = 0; p < s->nb_planes; p++) { \
1916  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1917  \
1918  for (int y = slice_start; y < slice_end; y++) { \
1919  const int zy = z + y; \
1920  const int zz = zy % height + height * (zy < 0); \
1921  const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1922  const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
1923  \
1924  for (int x = 0; x < width; x++) \
1925  dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
1926  \
1927  dst += out->linesize[p] / div; \
1928  } \
1929  } \
1930 }
1931 
1932 COVERV_TRANSITION(up, 8, uint8_t, 1, -)
1933 COVERV_TRANSITION(up, 16, uint16_t, 2, -)
1934 COVERV_TRANSITION(down, 8, uint8_t, 1, )
1935 COVERV_TRANSITION(down, 16, uint16_t, 2, )
1936 
1937 #define REVEALH_TRANSITION(dir, name, type, div, expr) \
1938 static void reveal##dir##name##_transition(AVFilterContext *ctx, \
1939  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1940  float progress, \
1941  int slice_start, int slice_end, int jobnr) \
1942 { \
1943  XFadeContext *s = ctx->priv; \
1944  const int height = slice_end - slice_start; \
1945  const int width = out->width; \
1946  const int z = (expr progress) * width; \
1947  \
1948  for (int p = 0; p < s->nb_planes; p++) { \
1949  const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1950  const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1951  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1952  \
1953  for (int y = 0; y < height; y++) { \
1954  for (int x = 0; x < width; x++) { \
1955  const int zx = z + x; \
1956  const int zz = zx % width + width * (zx < 0); \
1957  dst[x] = (zx >= 0) && (zx < width) ? xf1[x] : xf0[zz]; \
1958  } \
1959  \
1960  dst += out->linesize[p] / div; \
1961  xf0 += a->linesize[p] / div; \
1962  xf1 += b->linesize[p] / div; \
1963  } \
1964  } \
1965 }
1966 
1967 REVEALH_TRANSITION(left, 8, uint8_t, 1, -)
1968 REVEALH_TRANSITION(left, 16, uint16_t, 2, -)
1969 REVEALH_TRANSITION(right, 8, uint8_t, 1, )
1970 REVEALH_TRANSITION(right, 16, uint16_t, 2, )
1971 
1972 #define REVEALV_TRANSITION(dir, name, type, div, expr) \
1973 static void reveal##dir##name##_transition(AVFilterContext *ctx, \
1974  const AVFrame *a, const AVFrame *b, AVFrame *out, \
1975  float progress, \
1976  int slice_start, int slice_end, int jobnr) \
1977 { \
1978  XFadeContext *s = ctx->priv; \
1979  const int height = out->height; \
1980  const int width = out->width; \
1981  const int z = (expr progress) * height; \
1982  \
1983  for (int p = 0; p < s->nb_planes; p++) { \
1984  type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1985  \
1986  for (int y = slice_start; y < slice_end; y++) { \
1987  const int zy = z + y; \
1988  const int zz = zy % height + height * (zy < 0); \
1989  const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
1990  const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1991  \
1992  for (int x = 0; x < width; x++) \
1993  dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
1994  \
1995  dst += out->linesize[p] / div; \
1996  } \
1997  } \
1998 }
1999 
2000 REVEALV_TRANSITION(up, 8, uint8_t, 1, -)
2001 REVEALV_TRANSITION(up, 16, uint16_t, 2, -)
2002 REVEALV_TRANSITION(down, 8, uint8_t, 1, )
2003 REVEALV_TRANSITION(down, 16, uint16_t, 2, )
2004 
2005 static inline double getpix(void *priv, double x, double y, int plane, int nb)
2006 {
2007  XFadeContext *s = priv;
2008  AVFrame *in = s->xf[nb];
2009  const uint8_t *src = in->data[FFMIN(plane, s->nb_planes - 1)];
2010  int linesize = in->linesize[FFMIN(plane, s->nb_planes - 1)];
2011  const int w = in->width;
2012  const int h = in->height;
2013 
2014  int xi, yi;
2015 
2016  xi = av_clipd(x, 0, w - 1);
2017  yi = av_clipd(y, 0, h - 1);
2018 
2019  if (s->depth > 8) {
2020  const uint16_t *src16 = (const uint16_t*)src;
2021 
2022  linesize /= 2;
2023  return src16[xi + yi * linesize];
2024  } else {
2025  return src[xi + yi * linesize];
2026  }
2027 }
2028 
2029 static double a0(void *priv, double x, double y) { return getpix(priv, x, y, 0, 0); }
2030 static double a1(void *priv, double x, double y) { return getpix(priv, x, y, 1, 0); }
2031 static double a2(void *priv, double x, double y) { return getpix(priv, x, y, 2, 0); }
2032 static double a3(void *priv, double x, double y) { return getpix(priv, x, y, 3, 0); }
2033 
2034 static double b0(void *priv, double x, double y) { return getpix(priv, x, y, 0, 1); }
2035 static double b1(void *priv, double x, double y) { return getpix(priv, x, y, 1, 1); }
2036 static double b2(void *priv, double x, double y) { return getpix(priv, x, y, 2, 1); }
2037 static double b3(void *priv, double x, double y) { return getpix(priv, x, y, 3, 1); }
2038 
2039 static int config_output(AVFilterLink *outlink)
2040 {
2041  AVFilterContext *ctx = outlink->src;
2042  AVFilterLink *inlink0 = ctx->inputs[0];
2043  AVFilterLink *inlink1 = ctx->inputs[1];
2044  XFadeContext *s = ctx->priv;
2045  const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink0->format);
2046 
2047  if (inlink0->w != inlink1->w || inlink0->h != inlink1->h) {
2048  av_log(ctx, AV_LOG_ERROR, "First input link %s parameters "
2049  "(size %dx%d) do not match the corresponding "
2050  "second input link %s parameters (size %dx%d)\n",
2051  ctx->input_pads[0].name, inlink0->w, inlink0->h,
2052  ctx->input_pads[1].name, inlink1->w, inlink1->h);
2053  return AVERROR(EINVAL);
2054  }
2055 
2056  if (inlink0->time_base.num != inlink1->time_base.num ||
2057  inlink0->time_base.den != inlink1->time_base.den) {
2058  av_log(ctx, AV_LOG_ERROR, "First input link %s timebase "
2059  "(%d/%d) do not match the corresponding "
2060  "second input link %s timebase (%d/%d)\n",
2061  ctx->input_pads[0].name, inlink0->time_base.num, inlink0->time_base.den,
2062  ctx->input_pads[1].name, inlink1->time_base.num, inlink1->time_base.den);
2063  return AVERROR(EINVAL);
2064  }
2065 
2066  if (!inlink0->frame_rate.num || !inlink0->frame_rate.den) {
2067  av_log(ctx, AV_LOG_ERROR, "The inputs needs to be a constant frame rate; "
2068  "current rate of %d/%d is invalid\n", inlink0->frame_rate.num, inlink0->frame_rate.den);
2069  return AVERROR(EINVAL);
2070  }
2071 
2072  if (inlink0->frame_rate.num != inlink1->frame_rate.num ||
2073  inlink0->frame_rate.den != inlink1->frame_rate.den) {
2074  av_log(ctx, AV_LOG_ERROR, "First input link %s frame rate "
2075  "(%d/%d) do not match the corresponding "
2076  "second input link %s frame rate (%d/%d)\n",
2077  ctx->input_pads[0].name, inlink0->frame_rate.num, inlink0->frame_rate.den,
2078  ctx->input_pads[1].name, inlink1->frame_rate.num, inlink1->frame_rate.den);
2079  return AVERROR(EINVAL);
2080  }
2081 
2082  outlink->w = inlink0->w;
2083  outlink->h = inlink0->h;
2084  outlink->time_base = inlink0->time_base;
2085  outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio;
2086  outlink->frame_rate = inlink0->frame_rate;
2087 
2088  s->depth = pix_desc->comp[0].depth;
2089  s->is_rgb = !!(pix_desc->flags & AV_PIX_FMT_FLAG_RGB);
2090  s->nb_planes = av_pix_fmt_count_planes(inlink0->format);
2091  s->max_value = (1 << s->depth) - 1;
2092  s->black[0] = 0;
2093  s->black[1] = s->black[2] = s->is_rgb ? 0 : s->max_value / 2;
2094  s->black[3] = s->max_value;
2095  s->white[0] = s->white[3] = s->max_value;
2096  s->white[1] = s->white[2] = s->is_rgb ? s->max_value : s->max_value / 2;
2097 
2098  s->start_pts = s->inputs_offset_pts = AV_NOPTS_VALUE;
2099 
2100  if (s->duration)
2101  s->duration_pts = av_rescale_q(s->duration, AV_TIME_BASE_Q, outlink->time_base);
2102 
2103  switch (s->transition) {
2104  case CUSTOM: s->transitionf = s->depth <= 8 ? custom8_transition : custom16_transition; break;
2105  case FADE: s->transitionf = s->depth <= 8 ? fade8_transition : fade16_transition; break;
2106  case WIPELEFT: s->transitionf = s->depth <= 8 ? wipeleft8_transition : wipeleft16_transition; break;
2107  case WIPERIGHT: s->transitionf = s->depth <= 8 ? wiperight8_transition : wiperight16_transition; break;
2108  case WIPEUP: s->transitionf = s->depth <= 8 ? wipeup8_transition : wipeup16_transition; break;
2109  case WIPEDOWN: s->transitionf = s->depth <= 8 ? wipedown8_transition : wipedown16_transition; break;
2110  case SLIDELEFT: s->transitionf = s->depth <= 8 ? slideleft8_transition : slideleft16_transition; break;
2111  case SLIDERIGHT: s->transitionf = s->depth <= 8 ? slideright8_transition : slideright16_transition; break;
2112  case SLIDEUP: s->transitionf = s->depth <= 8 ? slideup8_transition : slideup16_transition; break;
2113  case SLIDEDOWN: s->transitionf = s->depth <= 8 ? slidedown8_transition : slidedown16_transition; break;
2114  case CIRCLECROP: s->transitionf = s->depth <= 8 ? circlecrop8_transition : circlecrop16_transition; break;
2115  case RECTCROP: s->transitionf = s->depth <= 8 ? rectcrop8_transition : rectcrop16_transition; break;
2116  case DISTANCE: s->transitionf = s->depth <= 8 ? distance8_transition : distance16_transition; break;
2117  case FADEBLACK: s->transitionf = s->depth <= 8 ? fadeblack8_transition : fadeblack16_transition; break;
2118  case FADEWHITE: s->transitionf = s->depth <= 8 ? fadewhite8_transition : fadewhite16_transition; break;
2119  case RADIAL: s->transitionf = s->depth <= 8 ? radial8_transition : radial16_transition; break;
2120  case SMOOTHLEFT: s->transitionf = s->depth <= 8 ? smoothleft8_transition : smoothleft16_transition; break;
2121  case SMOOTHRIGHT:s->transitionf = s->depth <= 8 ? smoothright8_transition: smoothright16_transition;break;
2122  case SMOOTHUP: s->transitionf = s->depth <= 8 ? smoothup8_transition : smoothup16_transition; break;
2123  case SMOOTHDOWN: s->transitionf = s->depth <= 8 ? smoothdown8_transition : smoothdown16_transition; break;
2124  case CIRCLEOPEN: s->transitionf = s->depth <= 8 ? circleopen8_transition : circleopen16_transition; break;
2125  case CIRCLECLOSE:s->transitionf = s->depth <= 8 ? circleclose8_transition: circleclose16_transition;break;
2126  case VERTOPEN: s->transitionf = s->depth <= 8 ? vertopen8_transition : vertopen16_transition; break;
2127  case VERTCLOSE: s->transitionf = s->depth <= 8 ? vertclose8_transition : vertclose16_transition; break;
2128  case HORZOPEN: s->transitionf = s->depth <= 8 ? horzopen8_transition : horzopen16_transition; break;
2129  case HORZCLOSE: s->transitionf = s->depth <= 8 ? horzclose8_transition : horzclose16_transition; break;
2130  case DISSOLVE: s->transitionf = s->depth <= 8 ? dissolve8_transition : dissolve16_transition; break;
2131  case PIXELIZE: s->transitionf = s->depth <= 8 ? pixelize8_transition : pixelize16_transition; break;
2132  case DIAGTL: s->transitionf = s->depth <= 8 ? diagtl8_transition : diagtl16_transition; break;
2133  case DIAGTR: s->transitionf = s->depth <= 8 ? diagtr8_transition : diagtr16_transition; break;
2134  case DIAGBL: s->transitionf = s->depth <= 8 ? diagbl8_transition : diagbl16_transition; break;
2135  case DIAGBR: s->transitionf = s->depth <= 8 ? diagbr8_transition : diagbr16_transition; break;
2136  case HLSLICE: s->transitionf = s->depth <= 8 ? hlslice8_transition : hlslice16_transition; break;
2137  case HRSLICE: s->transitionf = s->depth <= 8 ? hrslice8_transition : hrslice16_transition; break;
2138  case VUSLICE: s->transitionf = s->depth <= 8 ? vuslice8_transition : vuslice16_transition; break;
2139  case VDSLICE: s->transitionf = s->depth <= 8 ? vdslice8_transition : vdslice16_transition; break;
2140  case HBLUR: s->transitionf = s->depth <= 8 ? hblur8_transition : hblur16_transition; break;
2141  case FADEGRAYS: s->transitionf = s->depth <= 8 ? fadegrays8_transition : fadegrays16_transition; break;
2142  case WIPETL: s->transitionf = s->depth <= 8 ? wipetl8_transition : wipetl16_transition; break;
2143  case WIPETR: s->transitionf = s->depth <= 8 ? wipetr8_transition : wipetr16_transition; break;
2144  case WIPEBL: s->transitionf = s->depth <= 8 ? wipebl8_transition : wipebl16_transition; break;
2145  case WIPEBR: s->transitionf = s->depth <= 8 ? wipebr8_transition : wipebr16_transition; break;
2146  case SQUEEZEH: s->transitionf = s->depth <= 8 ? squeezeh8_transition : squeezeh16_transition; break;
2147  case SQUEEZEV: s->transitionf = s->depth <= 8 ? squeezev8_transition : squeezev16_transition; break;
2148  case ZOOMIN: s->transitionf = s->depth <= 8 ? zoomin8_transition : zoomin16_transition; break;
2149  case FADEFAST: s->transitionf = s->depth <= 8 ? fadefast8_transition : fadefast16_transition; break;
2150  case FADESLOW: s->transitionf = s->depth <= 8 ? fadeslow8_transition : fadeslow16_transition; break;
2151  case HLWIND: s->transitionf = s->depth <= 8 ? hlwind8_transition : hlwind16_transition; break;
2152  case HRWIND: s->transitionf = s->depth <= 8 ? hrwind8_transition : hrwind16_transition; break;
2153  case VUWIND: s->transitionf = s->depth <= 8 ? vuwind8_transition : vuwind16_transition; break;
2154  case VDWIND: s->transitionf = s->depth <= 8 ? vdwind8_transition : vdwind16_transition; break;
2155  case COVERLEFT: s->transitionf = s->depth <= 8 ? coverleft8_transition : coverleft16_transition; break;
2156  case COVERRIGHT: s->transitionf = s->depth <= 8 ? coverright8_transition : coverright16_transition; break;
2157  case COVERUP: s->transitionf = s->depth <= 8 ? coverup8_transition : coverup16_transition; break;
2158  case COVERDOWN: s->transitionf = s->depth <= 8 ? coverdown8_transition : coverdown16_transition; break;
2159  case REVEALLEFT: s->transitionf = s->depth <= 8 ? revealleft8_transition : revealleft16_transition; break;
2160  case REVEALRIGHT:s->transitionf = s->depth <= 8 ? revealright8_transition: revealright16_transition;break;
2161  case REVEALUP: s->transitionf = s->depth <= 8 ? revealup8_transition : revealup16_transition; break;
2162  case REVEALDOWN: s->transitionf = s->depth <= 8 ? revealdown8_transition : revealdown16_transition; break;
2163  default: return AVERROR_BUG;
2164  }
2165 
2166  if (s->transition == CUSTOM) {
2167  static const char *const func2_names[] = {
2168  "a0", "a1", "a2", "a3",
2169  "b0", "b1", "b2", "b3",
2170  NULL
2171  };
2172  double (*func2[])(void *, double, double) = {
2173  a0, a1, a2, a3,
2174  b0, b1, b2, b3,
2175  NULL };
2176  int ret;
2177 
2178  if (!s->custom_str)
2179  return AVERROR(EINVAL);
2180  ret = av_expr_parse(&s->e, s->custom_str, var_names,
2181  NULL, NULL, func2_names, func2, 0, ctx);
2182  if (ret < 0)
2183  return ret;
2184  }
2185 
2186  return 0;
2187 }
2188 
2189 static int xfade_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
2190 {
2191  XFadeContext *s = ctx->priv;
2192  AVFilterLink *outlink = ctx->outputs[0];
2193  ThreadData *td = arg;
2194  int slice_start = (outlink->h * jobnr ) / nb_jobs;
2195  int slice_end = (outlink->h * (jobnr+1)) / nb_jobs;
2196 
2197  s->transitionf(ctx, td->xf[0], td->xf[1], td->out, td->progress, slice_start, slice_end, jobnr);
2198 
2199  return 0;
2200 }
2201 
2203 {
2204  XFadeContext *s = ctx->priv;
2205  AVFilterLink *outlink = ctx->outputs[0];
2206  float progress = av_clipf(1.f - ((float)(s->pts - s->start_pts) / s->duration_pts), 0.f, 1.f);
2207  ThreadData td;
2208  AVFrame *out;
2209 
2210  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
2211  if (!out)
2212  return AVERROR(ENOMEM);
2214 
2215  td.xf[0] = a, td.xf[1] = b, td.out = out, td.progress = progress;
2217  FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
2218 
2219  out->pts = s->pts;
2220 
2221  return ff_filter_frame(outlink, out);
2222 }
2223 
2225  AVFilterLink *inlink, AVFilterLink *outlink)
2226 {
2227  int64_t status_pts;
2228  int ret = 0, status;
2229  AVFrame *frame = NULL;
2230 
2232  if (ret < 0)
2233  return ret;
2234 
2235  if (ret > 0) {
2236  // If we do not have an offset yet, it's because we
2237  // never got a first input. Just offset to 0
2238  if (s->inputs_offset_pts == AV_NOPTS_VALUE)
2239  s->inputs_offset_pts = -frame->pts;
2240 
2241  // We got a frame, nothing to do other than adjusting the timestamp
2242  frame->pts += s->inputs_offset_pts;
2243  return ff_filter_frame(outlink, frame);
2244  }
2245 
2246  // Forward status with our timestamp
2247  if (ff_inlink_acknowledge_status(inlink, &status, &status_pts)) {
2248  if (s->inputs_offset_pts == AV_NOPTS_VALUE)
2249  s->inputs_offset_pts = -status_pts;
2250 
2251  ff_outlink_set_status(outlink, status, status_pts + s->inputs_offset_pts);
2252  return 0;
2253  }
2254 
2255  // No frame available, request one if needed
2256  if (ff_outlink_frame_wanted(outlink))
2258 
2259  return 0;
2260 }
2261 
2263 {
2264  XFadeContext *s = avctx->priv;
2265  AVFilterLink *in_a = avctx->inputs[0];
2266  AVFilterLink *in_b = avctx->inputs[1];
2267  AVFilterLink *outlink = avctx->outputs[0];
2268  int64_t status_pts;
2269 
2270  FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, avctx);
2271 
2272  // Check if we already transitioned or first input ended prematurely,
2273  // in which case just forward the frames from second input with adjusted
2274  // timestamps until EOF.
2275  if (s->status[0] && !s->status[1])
2276  return forward_frame(s, in_b, outlink);
2277 
2278  // We did not finish transitioning yet and the first stream
2279  // did not end either, so check if there are more frames to consume.
2280  if (ff_inlink_check_available_frame(in_a)) {
2281  AVFrame *peeked_frame = ff_inlink_peek_frame(in_a, 0);
2282  s->pts = peeked_frame->pts;
2283 
2284  if (s->start_pts == AV_NOPTS_VALUE)
2285  s->start_pts =
2286  s->pts + av_rescale_q(s->offset, AV_TIME_BASE_Q, in_a->time_base);
2287 
2288  // Check if we are not yet transitioning, in which case
2289  // just request and forward the input frame.
2290  if (s->start_pts > s->pts) {
2291  s->passthrough = 1;
2292  ff_inlink_consume_frame(in_a, &s->xf[0]);
2293  return ff_filter_frame(outlink, s->xf[0]);
2294  }
2295  s->passthrough = 0;
2296 
2297  // We are transitioning, so we need a frame from second input
2298  if (ff_inlink_check_available_frame(in_b)) {
2299  int ret;
2300  ff_inlink_consume_frame(avctx->inputs[0], &s->xf[0]);
2301  ff_inlink_consume_frame(avctx->inputs[1], &s->xf[1]);
2302 
2303  // Calculate PTS offset to first input
2304  if (s->inputs_offset_pts == AV_NOPTS_VALUE)
2305  s->inputs_offset_pts = s->pts - s->xf[1]->pts;
2306 
2307  // Check if we finished transitioning, in which case we
2308  // report back EOF to first input as it is no longer needed.
2309  if (s->pts - s->start_pts > s->duration_pts) {
2310  s->status[0] = AVERROR_EOF;
2312  s->passthrough = 1;
2313  }
2314  ret = xfade_frame(avctx, s->xf[0], s->xf[1]);
2315  av_frame_free(&s->xf[0]);
2316  av_frame_free(&s->xf[1]);
2317  return ret;
2318  }
2319 
2320  // We did not get a frame from second input, check its status.
2321  if (ff_inlink_acknowledge_status(in_b, &s->status[1], &status_pts)) {
2322  // We should transition, but second input is EOF so just report EOF output now.
2323  ff_outlink_set_status(outlink, s->status[1], s->pts);
2324  return 0;
2325  }
2326 
2327  // We did not get a frame for second input but no EOF either, so just request more.
2328  if (ff_outlink_frame_wanted(outlink)) {
2330  return 0;
2331  }
2332  }
2333 
2334  // We did not get a frame from first input, check its status.
2335  if (ff_inlink_acknowledge_status(in_a, &s->status[0], &status_pts)) {
2336  // No more frames from first input, do not report EOF though, we will just
2337  // forward the second input frames in the next activate calls.
2338  s->passthrough = 1;
2339  ff_filter_set_ready(avctx, 100);
2340  return 0;
2341  }
2342 
2343  // We have no frames yet from first input and no EOF, so request some.
2344  if (ff_outlink_frame_wanted(outlink)) {
2346  return 0;
2347  }
2348 
2349  return FFERROR_NOT_READY;
2350 }
2351 
2353 {
2354  XFadeContext *s = inlink->dst->priv;
2355 
2356  return s->passthrough ?
2359 }
2360 
2361 static const AVFilterPad xfade_inputs[] = {
2362  {
2363  .name = "main",
2364  .type = AVMEDIA_TYPE_VIDEO,
2365  .get_buffer.video = get_video_buffer,
2366  },
2367  {
2368  .name = "xfade",
2369  .type = AVMEDIA_TYPE_VIDEO,
2370  .get_buffer.video = get_video_buffer,
2371  },
2372 };
2373 
2374 static const AVFilterPad xfade_outputs[] = {
2375  {
2376  .name = "default",
2377  .type = AVMEDIA_TYPE_VIDEO,
2378  .config_props = config_output,
2379  },
2380 };
2381 
2383  .name = "xfade",
2384  .description = NULL_IF_CONFIG_SMALL("Cross fade one video with another video."),
2385  .priv_size = sizeof(XFadeContext),
2386  .priv_class = &xfade_class,
2388  .uninit = uninit,
2392  .flags = AVFILTER_FLAG_SLICE_THREADS,
2393 };
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:108
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: vf_xfade.c:142
AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:491
td
#define td
Definition: regdef.h:70
VAR_PROGRESS
@ VAR_PROGRESS
Definition: vf_xfade.c:134
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
HORZOPEN_TRANSITION
#define HORZOPEN_TRANSITION(name, type, div)
Definition: vf_xfade.c:1006
FADEBLACK_TRANSITION
#define FADEBLACK_TRANSITION(name, type, div)
Definition: vf_xfade.c:687
VDWIND
@ VDWIND
Definition: vf_xfade.c:81
r
const char * r
Definition: vf_curves.c:126
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:487
CIRCLECROP_TRANSITION
#define CIRCLECROP_TRANSITION(name, type, div)
Definition: vf_xfade.c:584
OFFSET
#define OFFSET(x)
Definition: vf_xfade.c:168
REVEALLEFT
@ REVEALLEFT
Definition: vf_xfade.c:86
WIPELEFT
@ WIPELEFT
Definition: vf_xfade.c:33
out
FILE * out
Definition: movenc.c:54
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:250
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:978
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2964
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:171
FILTER_PIXFMTS_ARRAY
#define FILTER_PIXFMTS_ARRAY(array)
Definition: internal.h:172
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:264
XFadeContext::nb_planes
int nb_planes
Definition: vf_xfade.c:101
WIPEDOWN_TRANSITION
#define WIPEDOWN_TRANSITION(name, type, div)
Definition: vf_xfade.c:423
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
VWIND_TRANSITION
#define VWIND_TRANSITION(name, z, type, div, expr)
Definition: vf_xfade.c:1838
zoom
static void zoom(float *u, float *v, float amount)
Definition: vf_xfade.c:1696
xfade_activate
static int xfade_activate(AVFilterContext *avctx)
Definition: vf_xfade.c:2262
RECTCROP_TRANSITION
#define RECTCROP_TRANSITION(name, type, div)
Definition: vf_xfade.c:617
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:100
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(xfade)
SMOOTHDOWN
@ SMOOTHDOWN
Definition: vf_xfade.c:50
WIPEBL_TRANSITION
#define WIPEBL_TRANSITION(name, type, div)
Definition: vf_xfade.c:1553
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
pixdesc.h
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:452
CIRCLECROP
@ CIRCLECROP
Definition: vf_xfade.c:41
AVFrame::width
int width
Definition: frame.h:412
w
uint8_t w
Definition: llviddspenc.c:38
SLIDELEFT_TRANSITION
#define SLIDELEFT_TRANSITION(name, type, div)
Definition: vf_xfade.c:454
get_video_buffer
static AVFrame * get_video_buffer(AVFilterLink *inlink, int w, int h)
Definition: vf_xfade.c:2352
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:1341
AVOption
AVOption.
Definition: opt.h:251
WIPERIGHT_TRANSITION
#define WIPERIGHT_TRANSITION(name, type, div)
Definition: vf_xfade.c:361
b
#define b
Definition: input.c:41
SLIDEDOWN
@ SLIDEDOWN
Definition: vf_xfade.c:40
AV_OPT_TYPE_DURATION
@ AV_OPT_TYPE_DURATION
Definition: opt.h:239
WIPEDOWN
@ WIPEDOWN
Definition: vf_xfade.c:36
VAR_A
@ VAR_A
Definition: vf_xfade.c:134
DISSOLVE
@ DISSOLVE
Definition: vf_xfade.c:57
VUSLICE
@ VUSLICE
Definition: vf_xfade.c:65
WIPETR
@ WIPETR
Definition: vf_xfade.c:70
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:170
SMOOTHDOWN_TRANSITION
#define SMOOTHDOWN_TRANSITION(name, type, div)
Definition: vf_xfade.c:866
ThreadData::out
AVFrame * out
Definition: af_adeclick.c:526
video.h
mix
static float mix(float a, float b, float mix)
Definition: vf_xfade.c:281
func2_names
static const char *const func2_names[]
Definition: af_afftfilt.c:98
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:361
DISTANCE
@ DISTANCE
Definition: vf_xfade.c:43
DIAGBR
@ DIAGBR
Definition: vf_xfade.c:62
XFadeContext::e
AVExpr * e
Definition: vf_xfade.c:130
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:96
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:1383
ff_default_get_video_buffer
AVFrame * ff_default_get_video_buffer(AVFilterLink *link, int w, int h)
Definition: video.c:103
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3004
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:486
b1
static double b1(void *priv, double x, double y)
Definition: vf_xfade.c:2035
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:205
AVFilterContext::priv
void * priv
private data for use by the filter
Definition: avfilter.h:412
AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:484
AV_PIX_FMT_YUVA444P16
#define AV_PIX_FMT_YUVA444P16
Definition: pixfmt.h:513
VERTOPEN_TRANSITION
#define VERTOPEN_TRANSITION(name, type, div)
Definition: vf_xfade.c:951
HRWIND
@ HRWIND
Definition: vf_xfade.c:79
xfade_frame
static int xfade_frame(AVFilterContext *ctx, AVFrame *a, AVFrame *b)
Definition: vf_xfade.c:2202
FADEGRAYS_TRANSITION
#define FADEGRAYS_TRANSITION(name, type, div)
Definition: vf_xfade.c:1417
SLIDEDOWN_TRANSITION
#define SLIDEDOWN_TRANSITION(name, type, div)
Definition: vf_xfade.c:552
PIXELIZE_TRANSITION
#define PIXELIZE_TRANSITION(name, type, div)
Definition: vf_xfade.c:1096
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:452
ThreadData::xf
const AVFrame * xf[2]
Definition: vf_xfade.c:137
REVEALUP
@ REVEALUP
Definition: vf_xfade.c:88
VAR_B
@ VAR_B
Definition: vf_xfade.c:134
a2
static double a2(void *priv, double x, double y)
Definition: vf_xfade.c:2031
XFadeContext::status
int status[2]
Definition: vf_xfade.c:121
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:1250
XFadeContext::offset
int64_t offset
Definition: vf_xfade.c:98
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:47
AV_PIX_FMT_YUV444P10
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:471
FADEWHITE
@ FADEWHITE
Definition: vf_xfade.c:45
WIPERIGHT
@ WIPERIGHT
Definition: vf_xfade.c:34
func2
static double(*const func2[])(void *, double, double)
Definition: af_afftfilt.c:99
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:1159
duration
int64_t duration
Definition: movenc.c:64
SMOOTHLEFT_TRANSITION
#define SMOOTHLEFT_TRANSITION(name, type, div)
Definition: vf_xfade.c:783
AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:488
ff_outlink_set_status
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition: filters.h:189
ff_inlink_request_frame
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Definition: avfilter.c:1506
XFadeContext::is_rgb
int is_rgb
Definition: vf_xfade.c:103
b3
static double b3(void *priv, double x, double y)
Definition: vf_xfade.c:2037
ZOOMIN_TRANSITION
#define ZOOMIN_TRANSITION(name, type, div)
Definition: vf_xfade.c:1702
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:489
XFadeContext::start_pts
int64_t start_pts
Definition: vf_xfade.c:106
AV_PIX_FMT_YUV444P16
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:481
HBLUR
@ HBLUR
Definition: vf_xfade.c:67
smoothstep
static float smoothstep(float edge0, float edge1, float x)
Definition: vf_xfade.c:291
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:1979
var_names
static const char *const var_names[]
Definition: vf_xfade.c:133
filters.h
DIAGTR
@ DIAGTR
Definition: vf_xfade.c:60
AV_PIX_FMT_YUVA444P12
#define AV_PIX_FMT_YUVA444P12
Definition: pixfmt.h:510
ctx
AVFormatContext * ctx
Definition: movenc.c:48
xi
#define xi(width, name, var, range_min, range_max, subs,...)
Definition: cbs_h2645.c:417
getpix
static double getpix(void *priv, double x, double y, int plane, int nb)
Definition: vf_xfade.c:2005
HWIND_TRANSITION
#define HWIND_TRANSITION(name, z, type, div, expr)
Definition: vf_xfade.c:1807
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
AVExpr
Definition: eval.c:157
HORZCLOSE
@ HORZCLOSE
Definition: vf_xfade.c:56
CIRCLECLOSE_TRANSITION
#define CIRCLECLOSE_TRANSITION(name, type, div)
Definition: vf_xfade.c:922
XFadeContext::inputs_offset_pts
int64_t inputs_offset_pts
Definition: vf_xfade.c:109
DIAGBL_TRANSITION
#define DIAGBL_TRANSITION(name, type, div)
Definition: vf_xfade.c:1189
SLIDERIGHT
@ SLIDERIGHT
Definition: vf_xfade.c:38
HLWIND
@ HLWIND
Definition: vf_xfade.c:78
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:192
WIPETR_TRANSITION
#define WIPETR_TRANSITION(name, type, div)
Definition: vf_xfade.c:1520
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
frame
static AVFrame * frame
Definition: demux_decode.c:54
arg
const char * arg
Definition: jacosubdec.c:67
VAR_H
@ VAR_H
Definition: vf_xfade.c:134
AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:449
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:1422
XFadeContext::depth
int depth
Definition: vf_xfade.c:102
AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:487
SLIDEUP_TRANSITION
#define SLIDEUP_TRANSITION(name, type, div)
Definition: vf_xfade.c:520
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:55
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:736
a3
static double a3(void *priv, double x, double y)
Definition: vf_xfade.c:2032
SMOOTHUP
@ SMOOTHUP
Definition: vf_xfade.c:49
COVERDOWN
@ COVERDOWN
Definition: vf_xfade.c:85
FADE_TRANSITION
#define FADE_TRANSITION(name, type, div)
Definition: vf_xfade.c:300
activate
filter_frame For filters that do not use the activate() callback
NB_TRANSITIONS
@ NB_TRANSITIONS
Definition: vf_xfade.c:90
AVFilterContext::inputs
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:405
VAR_X
@ VAR_X
Definition: vf_xfade.c:134
PIXELIZE
@ PIXELIZE
Definition: vf_xfade.c:58
SMOOTHLEFT
@ SMOOTHLEFT
Definition: vf_xfade.c:47
RADIAL
@ RADIAL
Definition: vf_xfade.c:46
double
double
Definition: af_crystalizer.c:131
xfade_inputs
static const AVFilterPad xfade_inputs[]
Definition: vf_xfade.c:2361
ff_vf_xfade
const AVFilter ff_vf_xfade
Definition: vf_xfade.c:2382
sinf
#define sinf(x)
Definition: libm.h:419
av_clipf
av_clipf
Definition: af_crystalizer.c:121
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:483
DISTANCE_TRANSITION
#define DISTANCE_TRANSITION(name, type, div)
Definition: vf_xfade.c:652
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:1337
xfade_outputs
static const AVFilterPad xfade_outputs[]
Definition: vf_xfade.c:2374
FADESLOW
@ FADESLOW
Definition: vf_xfade.c:77
REVEALV_TRANSITION
#define REVEALV_TRANSITION(dir, name, type, div, expr)
Definition: vf_xfade.c:1972
XFadeContext
Definition: vf_xfade.c:93
VAR_VARS_NB
@ VAR_VARS_NB
Definition: vf_xfade.c:134
eval.h
REVEALRIGHT
@ REVEALRIGHT
Definition: vf_xfade.c:87
RADIAL_TRANSITION
#define RADIAL_TRANSITION(name, type, div)
Definition: vf_xfade.c:755
f
f
Definition: af_crystalizer.c:121
DIAGBL
@ DIAGBL
Definition: vf_xfade.c:61
WIPELEFT_TRANSITION
#define WIPELEFT_TRANSITION(name, type, div)
Definition: vf_xfade.c:330
RECTCROP
@ RECTCROP
Definition: vf_xfade.c:42
ff_inlink_set_status
void ff_inlink_set_status(AVFilterLink *link, int status)
Set the status on an input link.
Definition: avfilter.c:1514
ff_inlink_check_available_frame
int ff_inlink_check_available_frame(AVFilterLink *link)
Test if a frame is available on the link.
Definition: avfilter.c:1357
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:106
CUSTOM_TRANSITION
#define CUSTOM_TRANSITION(name, type, div)
Definition: vf_xfade.c:240
FADESLOW_TRANSITION
#define FADESLOW_TRANSITION(name, type, div)
Definition: vf_xfade.c:1774
XFadeContext::white
uint16_t white[4]
Definition: vf_xfade.c:125
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:1034
XFadeContext::xf
AVFrame * xf[2]
Definition: vf_xfade.c:122
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_xfade.c:161
VDSLICE
@ VDSLICE
Definition: vf_xfade.c:66
VAR_W
@ VAR_W
Definition: vf_xfade.c:134
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
HBLUR_TRANSITION
#define HBLUR_TRANSITION(name, type, div)
Definition: vf_xfade.c:1372
AV_PIX_FMT_YUV444P12
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:475
CIRCLECLOSE
@ CIRCLECLOSE
Definition: vf_xfade.c:52
VUSLICE_TRANSITION
#define VUSLICE_TRANSITION(name, type, div)
Definition: vf_xfade.c:1311
b2
static double b2(void *priv, double x, double y)
Definition: vf_xfade.c:2036
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:99
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:2029
AV_PIX_FMT_YUVA444P10
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:508
frand
static float frand(int x, int y)
Definition: vf_xfade.c:1062
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
SMOOTHRIGHT
@ SMOOTHRIGHT
Definition: vf_xfade.c:48
ff_null_get_video_buffer
AVFrame * ff_null_get_video_buffer(AVFilterLink *link, int w, int h)
Definition: video.c:43
internal.h
WIPEUP_TRANSITION
#define WIPEUP_TRANSITION(name, type, div)
Definition: vf_xfade.c:392
WIPEUP
@ WIPEUP
Definition: vf_xfade.c:35
REVEALH_TRANSITION
#define REVEALH_TRANSITION(dir, name, type, div, expr)
Definition: vf_xfade.c:1937
XFadeContext::duration_pts
int64_t duration_pts
Definition: vf_xfade.c:112
config_output
static int config_output(AVFilterLink *outlink)
Definition: vf_xfade.c:2039
REVEALDOWN
@ REVEALDOWN
Definition: vf_xfade.c:89
SMOOTHRIGHT_TRANSITION
#define SMOOTHRIGHT_TRANSITION(name, type, div)
Definition: vf_xfade.c:811
ThreadData::progress
float progress
Definition: vf_xfade.c:139
AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:485
FADEGRAYS
@ FADEGRAYS
Definition: vf_xfade.c:68
VERTCLOSE_TRANSITION
#define VERTCLOSE_TRANSITION(name, type, div)
Definition: vf_xfade.c:978
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:786
ThreadData
Used for passing data between threads.
Definition: dsddec.c:69
FADEBLACK
@ FADEBLACK
Definition: vf_xfade.c:44
WIPETL_TRANSITION
#define WIPETL_TRANSITION(name, type, div)
Definition: vf_xfade.c:1487
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
DIAGTL_TRANSITION
#define DIAGTL_TRANSITION(name, type, div)
Definition: vf_xfade.c:1129
VERTCLOSE
@ VERTCLOSE
Definition: vf_xfade.c:54
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:53
COVERV_TRANSITION
#define COVERV_TRANSITION(dir, name, type, div, expr)
Definition: vf_xfade.c:1904
fract
static float fract(float a)
Definition: vf_xfade.c:286
WIPEBR
@ WIPEBR
Definition: vf_xfade.c:72
SQUEEZEH
@ SQUEEZEH
Definition: vf_xfade.c:73
AVFilter
Filter definition.
Definition: avfilter.h:166
XFadeContext::max_value
int max_value
Definition: vf_xfade.c:123
ret
ret
Definition: filter_design.txt:187
WIPETL
@ WIPETL
Definition: vf_xfade.c:69
pixfmt.h
SQUEEZEH_TRANSITION
#define SQUEEZEH_TRANSITION(name, type, div)
Definition: vf_xfade.c:1619
FLAGS
#define FLAGS
Definition: vf_xfade.c:169
CIRCLEOPEN_TRANSITION
#define CIRCLEOPEN_TRANSITION(name, type, div)
Definition: vf_xfade.c:893
AV_PIX_FMT_YUVA444P9
#define AV_PIX_FMT_YUVA444P9
Definition: pixfmt.h:505
SQUEEZEV_TRANSITION
#define SQUEEZEV_TRANSITION(name, type, div)
Definition: vf_xfade.c:1657
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
XFadeContext::black
uint16_t black[4]
Definition: vf_xfade.c:124
AVFrame::height
int height
Definition: frame.h:412
xfade_slice
static int xfade_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_xfade.c:2189
status
ov_status_e status
Definition: dnn_backend_openvino.c:119
VERTOPEN
@ VERTOPEN
Definition: vf_xfade.c:53
COVERH_TRANSITION
#define COVERH_TRANSITION(dir, name, type, div, expr)
Definition: vf_xfade.c:1869
COVERRIGHT
@ COVERRIGHT
Definition: vf_xfade.c:83
SQUEEZEV
@ SQUEEZEV
Definition: vf_xfade.c:74
SLIDELEFT
@ SLIDELEFT
Definition: vf_xfade.c:37
ZOOMIN
@ ZOOMIN
Definition: vf_xfade.c:75
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:225
avfilter.h
FADEWHITE_TRANSITION
#define FADEWHITE_TRANSITION(name, type, div)
Definition: vf_xfade.c:721
AVPixFmtDescriptor::comp
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:105
FADEFAST_TRANSITION
#define FADEFAST_TRANSITION(name, type, div)
Definition: vf_xfade.c:1741
HLSLICE
@ HLSLICE
Definition: vf_xfade.c:63
DIAGTL
@ DIAGTL
Definition: vf_xfade.c:59
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
XFadeContext::passthrough
int passthrough
Definition: vf_xfade.c:119
AVFilterContext
An instance of a filter.
Definition: avfilter.h:397
SMOOTHUP_TRANSITION
#define SMOOTHUP_TRANSITION(name, type, div)
Definition: vf_xfade.c:839
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:117
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
CIRCLEOPEN
@ CIRCLEOPEN
Definition: vf_xfade.c:51
CUSTOM
@ CUSTOM
Definition: vf_xfade.c:31
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:127
XFadeTransitions
XFadeTransitions
Definition: vf_xfade.c:30
COVERUP
@ COVERUP
Definition: vf_xfade.c:84
XFadeContext::duration
int64_t duration
Definition: vf_xfade.c:97
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:193
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
SLIDEUP
@ SLIDEUP
Definition: vf_xfade.c:39
DIAGBR_TRANSITION
#define DIAGBR_TRANSITION(name, type, div)
Definition: vf_xfade.c:1219
d
d
Definition: ffmpeg_filter.c:368
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:385
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
VAR_PLANE
@ VAR_PLANE
Definition: vf_xfade.c:134
b0
static double b0(void *priv, double x, double y)
Definition: vf_xfade.c:2034
a1
static double a1(void *priv, double x, double y)
Definition: vf_xfade.c:2030
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:478
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:450
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:144
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
FADEFAST
@ FADEFAST
Definition: vf_xfade.c:76
COVERLEFT
@ COVERLEFT
Definition: vf_xfade.c:82
WIPEBR_TRANSITION
#define WIPEBR_TRANSITION(name, type, div)
Definition: vf_xfade.c:1586
WIPEBL
@ WIPEBL
Definition: vf_xfade.c:71
DISSOLVE_TRANSITION
#define DISSOLVE_TRANSITION(name, type, div)
Definition: vf_xfade.c:1069
VAR_Y
@ VAR_Y
Definition: vf_xfade.c:134
forward_frame
static int forward_frame(XFadeContext *s, AVFilterLink *inlink, AVFilterLink *outlink)
Definition: vf_xfade.c:2224
av_clipd
av_clipd
Definition: af_crystalizer.c:131
XFadeContext::pts
int64_t pts
Definition: vf_xfade.c:115
FADE
@ FADE
Definition: vf_xfade.c:32
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:216
HRSLICE
@ HRSLICE
Definition: vf_xfade.c:64
HRSLICE_TRANSITION
#define HRSLICE_TRANSITION(name, type, div)
Definition: vf_xfade.c:1280
VUWIND
@ VUWIND
Definition: vf_xfade.c:80
AVFilterContext::outputs
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:409