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