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