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