132static const char *
const var_names[] = {
"X",
"Y",
"W",
"H",
"A",
"B",
"PLANE",
"P",
NULL };
167#define OFFSET(x) offsetof(XFadeContext, x)
168#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
239#define CUSTOM_TRANSITION(name, type, div) \
240static void custom##name##_transition(AVFilterContext *ctx, \
241 const AVFrame *a, const AVFrame *b, AVFrame *out, \
243 int slice_start, int slice_end, int jobnr) \
245 XFadeContext *s = ctx->priv; \
246 const int height = slice_end - slice_start; \
247 const int width = out->width; \
249 double values[VAR_VARS_NB]; \
250 values[VAR_W] = width; \
251 values[VAR_H] = out->height; \
252 values[VAR_PROGRESS] = progress; \
254 for (int p = 0; p < s->nb_planes; p++) { \
255 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
256 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
257 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
259 values[VAR_PLANE] = p; \
261 for (int y = 0; y < height; y++) { \
262 values[VAR_Y] = slice_start + y; \
263 for (int x = 0; x < width; x++) { \
265 values[VAR_A] = xf0[x]; \
266 values[VAR_B] = xf1[x]; \
267 dst[x] = av_expr_eval(s->e, values, s); \
270 dst += out->linesize[p] / div; \
271 xf0 += a->linesize[p] / div; \
272 xf1 += b->linesize[p] / div; \
280static inline
float mix(
float a,
float b,
float mix)
290static inline float smoothstep(
float edge0,
float edge1,
float x)
294 t =
av_clipf((x - edge0) / (edge1 - edge0), 0.f, 1.f);
296 return t * t * (3.f - 2.f * t);
304#define FADE_TRANSITION(name, type, div) \
305static void fade##name##_transition(AVFilterContext *ctx, \
306 const AVFrame *a, const AVFrame *b, AVFrame *out, \
308 int slice_start, int slice_end, int jobnr) \
310 XFadeContext *s = ctx->priv; \
311 const int height = slice_end - slice_start; \
312 const int width = out->width; \
314 for (int p = 0; p < s->nb_planes; p++) { \
315 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
316 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
317 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
319 for (int y = 0; y < height; y++) { \
320 for (int x = 0; x < width; x++) { \
321 dst[x] = mix(xf0[x], xf1[x], progress); \
324 dst += out->linesize[p] / div; \
325 xf0 += a->linesize[p] / div; \
326 xf1 += b->linesize[p] / div; \
334#define WIPELEFT_TRANSITION(name, type, div) \
335static void wipeleft##name##_transition(AVFilterContext *ctx, \
336 const AVFrame *a, const AVFrame *b, AVFrame *out, \
338 int slice_start, int slice_end, int jobnr) \
340 XFadeContext *s = ctx->priv; \
341 const int height = slice_end - slice_start; \
342 const int width = out->width; \
343 const int z = width * progress; \
345 for (int p = 0; p < s->nb_planes; p++) { \
346 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
347 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
348 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
350 for (int y = 0; y < height; y++) { \
351 for (int x = 0; x < width; x++) { \
352 dst[x] = x > z ? xf1[x] : xf0[x]; \
355 dst += out->linesize[p] / div; \
356 xf0 += a->linesize[p] / div; \
357 xf1 += b->linesize[p] / div; \
365#define WIPERIGHT_TRANSITION(name, type, div) \
366static void wiperight##name##_transition(AVFilterContext *ctx, \
367 const AVFrame *a, const AVFrame *b, AVFrame *out, \
369 int slice_start, int slice_end, int jobnr) \
371 XFadeContext *s = ctx->priv; \
372 const int height = slice_end - slice_start; \
373 const int width = out->width; \
374 const int z = width * (1.f - progress); \
376 for (int p = 0; p < s->nb_planes; p++) { \
377 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
378 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
379 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
381 for (int y = 0; y < height; y++) { \
382 for (int x = 0; x < width; x++) { \
383 dst[x] = x > z ? xf0[x] : xf1[x]; \
386 dst += out->linesize[p] / div; \
387 xf0 += a->linesize[p] / div; \
388 xf1 += b->linesize[p] / div; \
396#define WIPEUP_TRANSITION(name, type, div) \
397static void wipeup##name##_transition(AVFilterContext *ctx, \
398 const AVFrame *a, const AVFrame *b, AVFrame *out, \
400 int slice_start, int slice_end, int jobnr) \
402 XFadeContext *s = ctx->priv; \
403 const int height = slice_end - slice_start; \
404 const int width = out->width; \
405 const int z = out->height * progress; \
407 for (int p = 0; p < s->nb_planes; p++) { \
408 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
409 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
410 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
412 for (int y = 0; y < height; y++) { \
413 for (int x = 0; x < width; x++) { \
414 dst[x] = slice_start + y > z ? xf1[x] : xf0[x]; \
417 dst += out->linesize[p] / div; \
418 xf0 += a->linesize[p] / div; \
419 xf1 += b->linesize[p] / div; \
427#define WIPEDOWN_TRANSITION(name, type, div) \
428static void wipedown##name##_transition(AVFilterContext *ctx, \
429 const AVFrame *a, const AVFrame *b, AVFrame *out, \
431 int slice_start, int slice_end, int jobnr) \
433 XFadeContext *s = ctx->priv; \
434 const int height = slice_end - slice_start; \
435 const int width = out->width; \
436 const int z = out->height * (1.f - progress); \
438 for (int p = 0; p < s->nb_planes; p++) { \
439 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
440 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
441 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
443 for (int y = 0; y < height; y++) { \
444 for (int x = 0; x < width; x++) { \
445 dst[x] = slice_start + y > z ? xf0[x] : xf1[x]; \
448 dst += out->linesize[p] / div; \
449 xf0 += a->linesize[p] / div; \
450 xf1 += b->linesize[p] / div; \
458#define SLIDELEFT_TRANSITION(name, type, div) \
459static void slideleft##name##_transition(AVFilterContext *ctx, \
460 const AVFrame *a, const AVFrame *b, AVFrame *out, \
462 int slice_start, int slice_end, int jobnr) \
464 XFadeContext *s = ctx->priv; \
465 const int height = slice_end - slice_start; \
466 const int width = out->width; \
467 const int z = -progress * width; \
469 for (int p = 0; p < s->nb_planes; p++) { \
470 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
471 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
472 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
474 for (int y = 0; y < height; y++) { \
475 for (int x = 0; x < width; x++) { \
476 const int zx = z + x; \
477 const int zz = zx % width + width * (zx % width < 0); \
478 dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \
481 dst += out->linesize[p] / div; \
482 xf0 += a->linesize[p] / div; \
483 xf1 += b->linesize[p] / div; \
491#define SLIDERIGHT_TRANSITION(name, type, div) \
492static void slideright##name##_transition(AVFilterContext *ctx, \
493 const AVFrame *a, const AVFrame *b, AVFrame *out, \
495 int slice_start, int slice_end, int jobnr) \
497 XFadeContext *s = ctx->priv; \
498 const int height = slice_end - slice_start; \
499 const int width = out->width; \
500 const int z = progress * width; \
502 for (int p = 0; p < s->nb_planes; p++) { \
503 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
504 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
505 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
507 for (int y = 0; y < height; y++) { \
508 for (int x = 0; x < width; x++) { \
509 const int zx = z + x; \
510 const int zz = zx % width + width * (zx % width < 0); \
511 dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \
514 dst += out->linesize[p] / div; \
515 xf0 += a->linesize[p] / div; \
516 xf1 += b->linesize[p] / div; \
524#define SLIDEUP_TRANSITION(name, type, div) \
525static void slideup##name##_transition(AVFilterContext *ctx, \
526 const AVFrame *a, const AVFrame *b, AVFrame *out, \
528 int slice_start, int slice_end, int jobnr) \
530 XFadeContext *s = ctx->priv; \
531 const int height = out->height; \
532 const int width = out->width; \
533 const int z = -progress * height; \
535 for (int p = 0; p < s->nb_planes; p++) { \
536 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
538 for (int y = slice_start; y < slice_end; y++) { \
539 const int zy = z + y; \
540 const int zz = zy % height + height * (zy % height < 0); \
541 const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
542 const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
544 for (int x = 0; x < width; x++) { \
545 dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
548 dst += out->linesize[p] / div; \
556#define SLIDEDOWN_TRANSITION(name, type, div) \
557static void slidedown##name##_transition(AVFilterContext *ctx, \
558 const AVFrame *a, const AVFrame *b, AVFrame *out, \
560 int slice_start, int slice_end, int jobnr) \
562 XFadeContext *s = ctx->priv; \
563 const int height = out->height; \
564 const int width = out->width; \
565 const int z = progress * height; \
567 for (int p = 0; p < s->nb_planes; p++) { \
568 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
570 for (int y = slice_start; y < slice_end; y++) { \
571 const int zy = z + y; \
572 const int zz = zy % height + height * (zy % height < 0); \
573 const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
574 const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
576 for (int x = 0; x < width; x++) { \
577 dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
580 dst += out->linesize[p] / div; \
588#define CIRCLECROP_TRANSITION(name, type, div) \
589static void circlecrop##name##_transition(AVFilterContext *ctx, \
590 const AVFrame *a, const AVFrame *b, AVFrame *out, \
592 int slice_start, int slice_end, int jobnr) \
594 XFadeContext *s = ctx->priv; \
595 const int width = out->width; \
596 const int height = out->height; \
597 float z = powf(2.f * fabsf(progress - 0.5f), 3.f) * hypotf(width/2, height/2); \
599 for (int p = 0; p < s->nb_planes; p++) { \
600 const int bg = s->black[p]; \
601 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
603 for (int y = slice_start; y < slice_end; y++) { \
604 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
605 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
607 for (int x = 0; x < width; x++) { \
608 float dist = hypotf(x - width / 2, y - height / 2); \
609 int val = progress < 0.5f ? xf1[x] : xf0[x]; \
610 dst[x] = (z < dist) ? bg : val; \
613 dst += out->linesize[p] / div; \
621#define RECTCROP_TRANSITION(name, type, div) \
622static void rectcrop##name##_transition(AVFilterContext *ctx, \
623 const AVFrame *a, const AVFrame *b, AVFrame *out, \
625 int slice_start, int slice_end, int jobnr) \
627 XFadeContext *s = ctx->priv; \
628 const int width = out->width; \
629 const int height = out->height; \
630 int zh = fabsf(progress - 0.5f) * height; \
631 int zw = fabsf(progress - 0.5f) * width; \
633 for (int p = 0; p < s->nb_planes; p++) { \
634 const int bg = s->black[p]; \
635 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
637 for (int y = slice_start; y < slice_end; y++) { \
638 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
639 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
641 for (int x = 0; x < width; x++) { \
642 int dist = FFABS(x - width / 2) < zw && \
643 FFABS(y - height / 2) < zh; \
644 int val = progress < 0.5f ? xf1[x] : xf0[x]; \
645 dst[x] = !dist ? bg : val; \
648 dst += out->linesize[p] / div; \
656#define DISTANCE_TRANSITION(name, type, div) \
657static void distance##name##_transition(AVFilterContext *ctx, \
658 const AVFrame *a, const AVFrame *b, AVFrame *out, \
660 int slice_start, int slice_end, int jobnr) \
662 XFadeContext *s = ctx->priv; \
663 const int width = out->width; \
664 const float max = s->max_value; \
666 for (int y = slice_start; y < slice_end; y++) { \
667 for (int x = 0; x < width; x++) { \
669 for (int p = 0; p < s->nb_planes; p++) { \
670 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
671 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
673 dist += (xf0[x] / max - xf1[x] / max) * \
674 (xf0[x] / max - xf1[x] / max); \
677 dist = sqrtf(dist) <= progress; \
678 for (int p = 0; p < s->nb_planes; p++) { \
679 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
680 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
681 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
682 dst[x] = mix(mix(xf0[x], xf1[x], dist), xf1[x], progress); \
691#define FADEBLACK_TRANSITION(name, type, div) \
692static void fadeblack##name##_transition(AVFilterContext *ctx, \
693 const AVFrame *a, const AVFrame *b, AVFrame *out, \
695 int slice_start, int slice_end, int jobnr) \
697 XFadeContext *s = ctx->priv; \
698 const int height = slice_end - slice_start; \
699 const int width = out->width; \
700 const float phase = 0.2f; \
702 for (int p = 0; p < s->nb_planes; p++) { \
703 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
704 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
705 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
706 const int bg = s->black[p]; \
708 for (int y = 0; y < height; y++) { \
709 for (int x = 0; x < width; x++) { \
710 dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \
711 mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \
715 dst += out->linesize[p] / div; \
716 xf0 += a->linesize[p] / div; \
717 xf1 += b->linesize[p] / div; \
725#define FADEWHITE_TRANSITION(name, type, div) \
726static void fadewhite##name##_transition(AVFilterContext *ctx, \
727 const AVFrame *a, const AVFrame *b, AVFrame *out, \
729 int slice_start, int slice_end, int jobnr) \
731 XFadeContext *s = ctx->priv; \
732 const int height = slice_end - slice_start; \
733 const int width = out->width; \
734 const float phase = 0.2f; \
736 for (int p = 0; p < s->nb_planes; p++) { \
737 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
738 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
739 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
740 const int bg = s->white[p]; \
742 for (int y = 0; y < height; y++) { \
743 for (int x = 0; x < width; x++) { \
744 dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \
745 mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \
749 dst += out->linesize[p] / div; \
750 xf0 += a->linesize[p] / div; \
751 xf1 += b->linesize[p] / div; \
759#define RADIAL_TRANSITION(name, type, div) \
760static void radial##name##_transition(AVFilterContext *ctx, \
761 const AVFrame *a, const AVFrame *b, AVFrame *out, \
763 int slice_start, int slice_end, int jobnr) \
765 XFadeContext *s = ctx->priv; \
766 const int width = out->width; \
767 const int height = out->height; \
769 for (int y = slice_start; y < slice_end; y++) { \
770 for (int x = 0; x < width; x++) { \
771 const float smooth = atan2f(x - width / 2, y - height / 2) - \
772 (progress - 0.5f) * (M_PI * 2.5f); \
773 for (int p = 0; p < s->nb_planes; p++) { \
774 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
775 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
776 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
778 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
787#define SMOOTHLEFT_TRANSITION(name, type, div) \
788static void smoothleft##name##_transition(AVFilterContext *ctx, \
789 const AVFrame *a, const AVFrame *b, AVFrame *out, \
791 int slice_start, int slice_end, int jobnr) \
793 XFadeContext *s = ctx->priv; \
794 const int width = out->width; \
795 const float w = width; \
797 for (int y = slice_start; y < slice_end; y++) { \
798 for (int x = 0; x < width; x++) { \
799 const float smooth = 1.f + x / w - progress * 2.f; \
801 for (int p = 0; p < s->nb_planes; p++) { \
802 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
803 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
804 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
806 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
815#define SMOOTHRIGHT_TRANSITION(name, type, div) \
816static void smoothright##name##_transition(AVFilterContext *ctx, \
817 const AVFrame *a, const AVFrame *b, AVFrame *out, \
819 int slice_start, int slice_end, int jobnr) \
821 XFadeContext *s = ctx->priv; \
822 const int width = out->width; \
823 const float w = width; \
825 for (int y = slice_start; y < slice_end; y++) { \
826 for (int x = 0; x < width; x++) { \
827 const float smooth = 1.f + (w - 1 - x) / w - progress * 2.f; \
829 for (int p = 0; p < s->nb_planes; p++) { \
830 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
831 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
832 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
834 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
843#define SMOOTHUP_TRANSITION(name, type, div) \
844static void smoothup##name##_transition(AVFilterContext *ctx, \
845 const AVFrame *a, const AVFrame *b, AVFrame *out, \
847 int slice_start, int slice_end, int jobnr) \
849 XFadeContext *s = ctx->priv; \
850 const int width = out->width; \
851 const float h = out->height; \
853 for (int y = slice_start; y < slice_end; y++) { \
854 const float smooth = 1.f + y / h - progress * 2.f; \
855 for (int x = 0; x < width; x++) { \
856 for (int p = 0; p < s->nb_planes; p++) { \
857 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
858 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
859 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
861 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
870#define SMOOTHDOWN_TRANSITION(name, type, div) \
871static void smoothdown##name##_transition(AVFilterContext *ctx, \
872 const AVFrame *a, const AVFrame *b, AVFrame *out, \
874 int slice_start, int slice_end, int jobnr) \
876 XFadeContext *s = ctx->priv; \
877 const int width = out->width; \
878 const float h = out->height; \
880 for (int y = slice_start; y < slice_end; y++) { \
881 const float smooth = 1.f + (h - 1 - y) / h - progress * 2.f; \
882 for (int x = 0; x < width; x++) { \
883 for (int p = 0; p < s->nb_planes; p++) { \
884 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
885 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
886 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
888 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
897#define CIRCLEOPEN_TRANSITION(name, type, div) \
898static void circleopen##name##_transition(AVFilterContext *ctx, \
899 const AVFrame *a, const AVFrame *b, AVFrame *out, \
901 int slice_start, int slice_end, int jobnr) \
903 XFadeContext *s = ctx->priv; \
904 const int width = out->width; \
905 const int height = out->height; \
906 const float z = hypotf(width / 2, height / 2); \
907 const float p = (progress - 0.5f) * 3.f; \
909 for (int y = slice_start; y < slice_end; y++) { \
910 for (int x = 0; x < width; x++) { \
911 const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \
912 for (int p = 0; p < s->nb_planes; p++) { \
913 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
914 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
915 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
917 dst[x] = mix(xf0[x], xf1[x], smoothstep(0.f, 1.f, smooth)); \
926#define CIRCLECLOSE_TRANSITION(name, type, div) \
927static void circleclose##name##_transition(AVFilterContext *ctx, \
928 const AVFrame *a, const AVFrame *b, AVFrame *out, \
930 int slice_start, int slice_end, int jobnr) \
932 XFadeContext *s = ctx->priv; \
933 const int width = out->width; \
934 const int height = out->height; \
935 const float z = hypotf(width / 2, height / 2); \
936 const float p = (1.f - progress - 0.5f) * 3.f; \
938 for (int y = slice_start; y < slice_end; y++) { \
939 for (int x = 0; x < width; x++) { \
940 const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \
941 for (int p = 0; p < s->nb_planes; p++) { \
942 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
943 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
944 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
946 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
955#define VERTOPEN_TRANSITION(name, type, div) \
956static void vertopen##name##_transition(AVFilterContext *ctx, \
957 const AVFrame *a, const AVFrame *b, AVFrame *out, \
959 int slice_start, int slice_end, int jobnr) \
961 XFadeContext *s = ctx->priv; \
962 const int width = out->width; \
963 const float w2 = out->width / 2.0; \
965 for (int y = slice_start; y < slice_end; y++) { \
966 for (int x = 0; x < width; x++) { \
967 const float smooth = 2.f - fabsf((x - w2) / w2) - progress * 2.f; \
968 for (int p = 0; p < s->nb_planes; p++) { \
969 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
970 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
971 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
973 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
982#define VERTCLOSE_TRANSITION(name, type, div) \
983static void vertclose##name##_transition(AVFilterContext *ctx, \
984 const AVFrame *a, const AVFrame *b, AVFrame *out, \
986 int slice_start, int slice_end, int jobnr) \
988 XFadeContext *s = ctx->priv; \
989 const int nb_planes = s->nb_planes; \
990 const int width = out->width; \
991 const float w2 = out->width / 2.0; \
993 for (int y = slice_start; y < slice_end; y++) { \
994 for (int x = 0; x < width; x++) { \
995 const float smooth = 1.f + fabsf((x - w2) / w2) - progress * 2.f; \
996 for (int p = 0; p < nb_planes; p++) { \
997 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
998 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
999 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1001 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1010#define HORZOPEN_TRANSITION(name, type, div) \
1011static void horzopen##name##_transition(AVFilterContext *ctx, \
1012 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1014 int slice_start, int slice_end, int jobnr) \
1016 XFadeContext *s = ctx->priv; \
1017 const int nb_planes = s->nb_planes; \
1018 const int width = out->width; \
1019 const float h2 = out->height / 2.0; \
1021 for (int y = slice_start; y < slice_end; y++) { \
1022 const float smooth = 2.f - fabsf((y - h2) / h2) - progress * 2.f; \
1023 for (int x = 0; x < width; x++) { \
1024 for (int p = 0; p < nb_planes; p++) { \
1025 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1026 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1027 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1029 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1038#define HORZCLOSE_TRANSITION(name, type, div) \
1039static void horzclose##name##_transition(AVFilterContext *ctx, \
1040 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1042 int slice_start, int slice_end, int jobnr) \
1044 XFadeContext *s = ctx->priv; \
1045 const int nb_planes = s->nb_planes; \
1046 const int width = out->width; \
1047 const float h2 = out->height / 2.0; \
1049 for (int y = slice_start; y < slice_end; y++) { \
1050 const float smooth = 1.f + fabsf((y - h2) / h2) - progress * 2.f; \
1051 for (int x = 0; x < width; x++) { \
1052 for (int p = 0; p < nb_planes; p++) { \
1053 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1054 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1055 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1057 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1068 const float r = sinf(x * 12.9898f + y * 78.233f) * 43758.545f;
1073#define DISSOLVE_TRANSITION(name, type, div) \
1074static void dissolve##name##_transition(AVFilterContext *ctx, \
1075 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1077 int slice_start, int slice_end, int jobnr) \
1079 XFadeContext *s = ctx->priv; \
1080 const int nb_planes = s->nb_planes; \
1081 const int width = out->width; \
1083 for (int y = slice_start; y < slice_end; y++) { \
1084 for (int x = 0; x < width; x++) { \
1085 const float smooth = frand(x, y) * 2.f + progress * 2.f - 1.5f; \
1086 for (int p = 0; p < nb_planes; p++) { \
1087 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1088 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1089 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1091 dst[x] = smooth >= 0.5f ? xf0[x] : xf1[x]; \
1100#define PIXELIZE_TRANSITION(name, type, div) \
1101static void pixelize##name##_transition(AVFilterContext *ctx, \
1102 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1104 int slice_start, int slice_end, int jobnr) \
1106 XFadeContext *s = ctx->priv; \
1107 const int nb_planes = s->nb_planes; \
1108 const int w = out->width; \
1109 const int h = out->height; \
1110 const float d = fminf(progress, 1.f - progress); \
1111 const float dist = ceilf(d * 50.f) / 50.f; \
1112 const float sqx = 2.f * dist * FFMIN(w, h) / 20.f; \
1113 const float sqy = 2.f * dist * FFMIN(w, h) / 20.f; \
1115 for (int y = slice_start; y < slice_end; y++) { \
1116 for (int x = 0; x < w; x++) { \
1117 int sx = dist > 0.f ? FFMIN((floorf(x / sqx) + .5f) * sqx, w - 1) : x; \
1118 int sy = dist > 0.f ? FFMIN((floorf(y / sqy) + .5f) * sqy, h - 1) : y; \
1119 for (int p = 0; p < nb_planes; p++) { \
1120 const type *xf0 = (const type *)(a->data[p] + sy * a->linesize[p]); \
1121 const type *xf1 = (const type *)(b->data[p] + sy * b->linesize[p]); \
1122 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1124 dst[x] = mix(xf0[sx], xf1[sx], progress); \
1133#define DIAGTL_TRANSITION(name, type, div) \
1134static void diagtl##name##_transition(AVFilterContext *ctx, \
1135 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1137 int slice_start, int slice_end, int jobnr) \
1139 XFadeContext *s = ctx->priv; \
1140 const int nb_planes = s->nb_planes; \
1141 const int width = out->width; \
1142 const float w = width; \
1143 const float h = out->height; \
1145 for (int y = slice_start; y < slice_end; y++) { \
1146 for (int x = 0; x < width; x++) { \
1147 const float smooth = 1.f + x / w * y / h - progress * 2.f; \
1149 for (int p = 0; p < nb_planes; p++) { \
1150 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1151 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1152 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1154 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1163#define DIAGTR_TRANSITION(name, type, div) \
1164static void diagtr##name##_transition(AVFilterContext *ctx, \
1165 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1167 int slice_start, int slice_end, int jobnr) \
1169 XFadeContext *s = ctx->priv; \
1170 const int nb_planes = s->nb_planes; \
1171 const int width = out->width; \
1172 const float w = width; \
1173 const float h = out->height; \
1175 for (int y = slice_start; y < slice_end; y++) { \
1176 for (int x = 0; x < width; x++) { \
1177 const float smooth = 1.f + (w - 1 - x) / w * y / h - progress * 2.f; \
1179 for (int p = 0; p < nb_planes; p++) { \
1180 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1181 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1182 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1184 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1193#define DIAGBL_TRANSITION(name, type, div) \
1194static void diagbl##name##_transition(AVFilterContext *ctx, \
1195 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1197 int slice_start, int slice_end, int jobnr) \
1199 XFadeContext *s = ctx->priv; \
1200 const int nb_planes = s->nb_planes; \
1201 const int width = out->width; \
1202 const float w = width; \
1203 const float h = out->height; \
1205 for (int y = slice_start; y < slice_end; y++) { \
1206 for (int x = 0; x < width; x++) { \
1207 const float smooth = 1.f + x / w * (h - 1 - y) / h - progress * 2.f; \
1209 for (int p = 0; p < nb_planes; p++) { \
1210 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1211 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1212 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1214 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1223#define DIAGBR_TRANSITION(name, type, div) \
1224static void diagbr##name##_transition(AVFilterContext *ctx, \
1225 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1227 int slice_start, int slice_end, int jobnr) \
1229 XFadeContext *s = ctx->priv; \
1230 const int nb_planes = s->nb_planes; \
1231 const int width = out->width; \
1232 const float w = width; \
1233 const float h = out->height; \
1235 for (int y = slice_start; y < slice_end; y++) { \
1236 for (int x = 0; x < width; x++) { \
1237 const float smooth = 1.f + (w - 1 - x) / w * (h - 1 - y) / h - \
1240 for (int p = 0; p < nb_planes; p++) { \
1241 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1242 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1243 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1245 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1254#define HLSLICE_TRANSITION(name, type, div) \
1255static void hlslice##name##_transition(AVFilterContext *ctx, \
1256 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1258 int slice_start, int slice_end, int jobnr) \
1260 XFadeContext *s = ctx->priv; \
1261 const int nb_planes = s->nb_planes; \
1262 const int width = out->width; \
1263 const float w = width; \
1265 for (int y = slice_start; y < slice_end; y++) { \
1266 for (int x = 0; x < width; x++) { \
1267 const float smooth = smoothstep(-0.5f, 0.f, x / w - progress * 1.5f); \
1268 const float ss = smooth <= fract(10.f * x / w) ? 0.f : 1.f; \
1270 for (int p = 0; p < nb_planes; p++) { \
1271 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1272 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1273 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1275 dst[x] = mix(xf1[x], xf0[x], ss); \
1284#define HRSLICE_TRANSITION(name, type, div) \
1285static void hrslice##name##_transition(AVFilterContext *ctx, \
1286 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1288 int slice_start, int slice_end, int jobnr) \
1290 XFadeContext *s = ctx->priv; \
1291 const int nb_planes = s->nb_planes; \
1292 const int width = out->width; \
1293 const float w = width; \
1295 for (int y = slice_start; y < slice_end; y++) { \
1296 for (int x = 0; x < width; x++) { \
1297 const float xx = (w - 1 - x) / w; \
1298 const float smooth = smoothstep(-0.5f, 0.f, xx - progress * 1.5f); \
1299 const float ss = smooth <= fract(10.f * xx) ? 0.f : 1.f; \
1301 for (int p = 0; p < nb_planes; p++) { \
1302 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1303 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1304 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1306 dst[x] = mix(xf1[x], xf0[x], ss); \
1315#define VUSLICE_TRANSITION(name, type, div) \
1316static void vuslice##name##_transition(AVFilterContext *ctx, \
1317 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1319 int slice_start, int slice_end, int jobnr) \
1321 XFadeContext *s = ctx->priv; \
1322 const int nb_planes = s->nb_planes; \
1323 const int width = out->width; \
1324 const float h = out->height; \
1326 for (int y = slice_start; y < slice_end; y++) { \
1327 const float smooth = smoothstep(-0.5f, 0.f, y / h - progress * 1.5f); \
1328 const float ss = smooth <= fract(10.f * y / h) ? 0.f : 1.f; \
1330 for (int x = 0; x < width; x++) { \
1331 for (int p = 0; p < 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]); \
1336 dst[x] = mix(xf1[x], xf0[x], ss); \
1345#define VDSLICE_TRANSITION(name, type, div) \
1346static void vdslice##name##_transition(AVFilterContext *ctx, \
1347 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1349 int slice_start, int slice_end, int jobnr) \
1351 XFadeContext *s = ctx->priv; \
1352 const int nb_planes = s->nb_planes; \
1353 const int width = out->width; \
1354 const float h = out->height; \
1356 for (int y = slice_start; y < slice_end; y++) { \
1357 const float yy = (h - 1 - y) / h; \
1358 const float smooth = smoothstep(-0.5f, 0.f, yy - progress * 1.5f); \
1359 const float ss = smooth <= fract(10.f * yy) ? 0.f : 1.f; \
1361 for (int x = 0; x < width; x++) { \
1362 for (int p = 0; p < nb_planes; p++) { \
1363 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1364 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1365 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1367 dst[x] = mix(xf1[x], xf0[x], ss); \
1376#define HBLUR_TRANSITION(name, type, div) \
1377static void hblur##name##_transition(AVFilterContext *ctx, \
1378 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1380 int slice_start, int slice_end, int jobnr) \
1382 XFadeContext *s = ctx->priv; \
1383 const int nb_planes = s->nb_planes; \
1384 const int width = out->width; \
1385 const float prog = progress <= 0.5f ? progress * 2.f : (1.f - progress) * 2.f; \
1386 const int size = 1 + (width / 2) * prog; \
1388 for (int y = slice_start; y < slice_end; y++) { \
1389 for (int p = 0; p < nb_planes; p++) { \
1390 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1391 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1392 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1397 for (int x = 0; x < size; x++) { \
1402 for (int x = 0; x < width; x++) { \
1403 dst[x] = mix(sum0 / cnt, sum1 / cnt, progress); \
1405 if (x + size < width) { \
1406 sum0 += xf0[x + size] - xf0[x]; \
1407 sum1 += xf1[x + size] - xf1[x]; \
1421#define FADEGRAYS_TRANSITION(name, type, div) \
1422static void fadegrays##name##_transition(AVFilterContext *ctx, \
1423 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1425 int slice_start, int slice_end, int jobnr) \
1427 XFadeContext *s = ctx->priv; \
1428 const int width = out->width; \
1429 const int is_rgb = s->is_rgb; \
1430 const int mid = (s->max_value + 1) / 2; \
1431 const float phase = 0.2f; \
1433 for (int y = slice_start; y < slice_end; y++) { \
1434 for (int x = 0; x < width; x++) { \
1437 bg[0][0] = bg[1][0] = 0; \
1438 for (int p = 0; p < s->nb_planes; p++) { \
1439 const type *xf0 = (const type *)(a->data[p] + \
1440 y * a->linesize[p]); \
1441 const type *xf1 = (const type *)(b->data[p] + \
1442 y * b->linesize[p]); \
1444 bg[0][3] = xf0[x]; \
1445 bg[1][3] = xf1[x]; \
1447 bg[0][0] += xf0[x]; \
1448 bg[1][0] += xf1[x]; \
1451 bg[0][0] = bg[0][0] / 3; \
1452 bg[1][0] = bg[1][0] / 3; \
1453 bg[0][1] = bg[0][2] = bg[0][0]; \
1454 bg[1][1] = bg[1][2] = bg[1][0]; \
1456 const type *yf0 = (const type *)(a->data[0] + \
1457 y * a->linesize[0]); \
1458 const type *yf1 = (const type *)(b->data[0] + \
1459 y * b->linesize[0]); \
1460 bg[0][0] = yf0[x]; \
1461 bg[1][0] = yf1[x]; \
1462 if (s->nb_planes == 4) { \
1463 const type *af0 = (const type *)(a->data[3] + \
1464 y * a->linesize[3]); \
1465 const type *af1 = (const type *)(b->data[3] + \
1466 y * b->linesize[3]); \
1467 bg[0][3] = af0[x]; \
1468 bg[1][3] = af1[x]; \
1470 bg[0][1] = bg[1][1] = mid; \
1471 bg[0][2] = bg[1][2] = mid; \
1474 for (int p = 0; p < s->nb_planes; p++) { \
1475 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1476 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1477 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1479 dst[x] = mix(mix(xf0[x], bg[0][p], \
1480 smoothstep(1.f-phase, 1.f, progress)), \
1481 mix(bg[1][p], xf1[x], smoothstep(phase, 1.f, progress)), \
1491#define WIPETL_TRANSITION(name, type, div) \
1492static void wipetl##name##_transition(AVFilterContext *ctx, \
1493 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1495 int slice_start, int slice_end, int jobnr) \
1497 XFadeContext *s = ctx->priv; \
1498 const int height = slice_end - slice_start; \
1499 const int width = out->width; \
1500 const int zw = out->width * progress; \
1501 const int zh = out->height * progress; \
1503 for (int p = 0; p < s->nb_planes; p++) { \
1504 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1505 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1506 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1508 for (int y = 0; y < height; y++) { \
1509 for (int x = 0; x < width; x++) { \
1510 dst[x] = slice_start + y <= zh && \
1511 x <= zw ? xf0[x] : xf1[x]; \
1514 dst += out->linesize[p] / div; \
1515 xf0 += a->linesize[p] / div; \
1516 xf1 += b->linesize[p] / div; \
1524#define WIPETR_TRANSITION(name, type, div) \
1525static void wipetr##name##_transition(AVFilterContext *ctx, \
1526 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1528 int slice_start, int slice_end, int jobnr) \
1530 XFadeContext *s = ctx->priv; \
1531 const int height = slice_end - slice_start; \
1532 const int width = out->width; \
1533 const int zw = width * (1.f - progress); \
1534 const int zh = out->height * progress; \
1536 for (int p = 0; p < s->nb_planes; p++) { \
1537 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1538 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1539 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1541 for (int y = 0; y < height; y++) { \
1542 for (int x = 0; x < width; x++) { \
1543 dst[x] = slice_start + y <= zh && \
1544 x > zw ? xf0[x] : xf1[x]; \
1547 dst += out->linesize[p] / div; \
1548 xf0 += a->linesize[p] / div; \
1549 xf1 += b->linesize[p] / div; \
1557#define WIPEBL_TRANSITION(name, type, div) \
1558static void wipebl##name##_transition(AVFilterContext *ctx, \
1559 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1561 int slice_start, int slice_end, int jobnr) \
1563 XFadeContext *s = ctx->priv; \
1564 const int height = slice_end - slice_start; \
1565 const int width = out->width; \
1566 const int zw = width * progress; \
1567 const int zh = out->height * (1.f - progress); \
1569 for (int p = 0; p < s->nb_planes; p++) { \
1570 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[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]); \
1574 for (int y = 0; y < height; y++) { \
1575 for (int x = 0; x < width; x++) { \
1576 dst[x] = slice_start + y > zh && \
1577 x <= zw ? xf0[x] : xf1[x]; \
1580 dst += out->linesize[p] / div; \
1581 xf0 += a->linesize[p] / div; \
1582 xf1 += b->linesize[p] / div; \
1590#define WIPEBR_TRANSITION(name, type, div) \
1591static void wipebr##name##_transition(AVFilterContext *ctx, \
1592 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1594 int slice_start, int slice_end, int jobnr) \
1596 XFadeContext *s = ctx->priv; \
1597 const int height = slice_end - slice_start; \
1598 const int zh = out->height * (1.f - progress); \
1599 const int width = out->width; \
1600 const int zw = width * (1.f - progress); \
1602 for (int p = 0; p < s->nb_planes; p++) { \
1603 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1604 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1605 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1607 for (int y = 0; y < height; y++) { \
1608 for (int x = 0; x < width; x++) { \
1609 dst[x] = slice_start + y > zh && \
1610 x > zw ? xf0[x] : xf1[x]; \
1613 dst += out->linesize[p] / div; \
1614 xf0 += a->linesize[p] / div; \
1615 xf1 += b->linesize[p] / div; \
1623#define SQUEEZEH_TRANSITION(name, type, div) \
1624static void squeezeh##name##_transition(AVFilterContext *ctx, \
1625 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1627 int slice_start, int slice_end, int jobnr) \
1629 XFadeContext *s = ctx->priv; \
1630 const float h = out->height; \
1631 const int height = slice_end - slice_start; \
1632 const int width = out->width; \
1634 for (int p = 0; p < s->nb_planes; p++) { \
1635 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1636 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1638 for (int y = 0; y < height; y++) { \
1639 const float z = progress > 0.f ? \
1640 .5f + ((slice_start + y) / h - .5f) / progress : -1.f; \
1642 if (z < 0.f || z > 1.f) { \
1643 for (int x = 0; x < width; x++) \
1646 const int yy = lrintf(z * (h - 1.f)); \
1647 const type *xf0 = (const type *)(a->data[p] + yy * a->linesize[p]); \
1649 for (int x = 0; x < width; x++) \
1653 dst += out->linesize[p] / div; \
1654 xf1 += b->linesize[p] / div; \
1662#define SQUEEZEV_TRANSITION(name, type, div) \
1663static void squeezev##name##_transition(AVFilterContext *ctx, \
1664 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1666 int slice_start, int slice_end, int jobnr) \
1668 XFadeContext *s = ctx->priv; \
1669 const int width = out->width; \
1670 const float w = width; \
1671 const int height = slice_end - slice_start; \
1673 for (int p = 0; p < s->nb_planes; p++) { \
1674 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1675 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1676 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1678 for (int y = 0; y < height; y++) { \
1679 for (int x = 0; x < width; x++) { \
1680 const float z = progress > 0.f ? \
1681 .5f + (x / w - .5f) / progress : -1.f; \
1683 if (z < 0.f || z > 1.f) { \
1686 const int xx = lrintf(z * (w - 1.f)); \
1692 dst += out->linesize[p] / div; \
1693 xf0 += a->linesize[p] / div; \
1694 xf1 += b->linesize[p] / div; \
1702static
void zoom(
float *
u,
float *v,
float amount)
1704 *
u = 0.5f + ((*
u - 0.5f) * amount);
1705 *v = 0.5f + ((*v - 0.5f) * amount);
1708#define ZOOMIN_TRANSITION(name, type, div) \
1709static void zoomin##name##_transition(AVFilterContext *ctx, \
1710 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1712 int slice_start, int slice_end, int jobnr) \
1714 XFadeContext *s = ctx->priv; \
1715 const int width = out->width; \
1716 const float w = width; \
1717 const float h = out->height; \
1718 const float zf = smoothstep(0.5f, 1.f, progress); \
1720 for (int p = 0; p < s->nb_planes; p++) { \
1721 const type *xf0 = (const type *)(a->data[p]); \
1722 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1723 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1725 for (int y = slice_start; y < slice_end; y++) { \
1726 for (int x = 0; x < width; x++) { \
1733 iu = ceilf(u * (w - 1)); \
1734 iv = ceilf(v * (h - 1)); \
1735 zv = xf0[iu + iv * a->linesize[p] / div]; \
1736 dst[x] = mix(zv, xf1[x], smoothstep(0.f, 0.5f, progress)); \
1738 dst += out->linesize[p] / div; \
1739 xf1 += b->linesize[p] / div; \
1747#define FADEFAST_TRANSITION(name, type, div) \
1748static void fadefast##name##_transition(AVFilterContext *ctx, \
1749 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1751 int slice_start, int slice_end, int jobnr) \
1753 XFadeContext *s = ctx->priv; \
1754 const int height = slice_end - slice_start; \
1755 const int width = out->width; \
1756 const float imax = 1.f / s->max_value; \
1758 for (int p = 0; p < s->nb_planes; p++) { \
1759 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1760 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1761 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1763 for (int y = 0; y < height; y++) { \
1764 for (int x = 0; x < width; x++) { \
1765 dst[x] = mix(xf0[x], xf1[x], powf(progress, 1.f + \
1766 logf(1.f+FFABS(xf0[x]-xf1[x])*imax)\
1770 dst += out->linesize[p] / div; \
1771 xf0 += a->linesize[p] / div; \
1772 xf1 += b->linesize[p] / div; \
1780#define FADESLOW_TRANSITION(name, type, div) \
1781static void fadeslow##name##_transition(AVFilterContext *ctx, \
1782 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1784 int slice_start, int slice_end, int jobnr) \
1786 XFadeContext *s = ctx->priv; \
1787 const int height = slice_end - slice_start; \
1788 const int width = out->width; \
1789 const float imax = 1.f / s->max_value; \
1791 for (int p = 0; p < s->nb_planes; p++) { \
1792 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1793 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1794 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1796 for (int y = 0; y < height; y++) { \
1797 for (int x = 0; x < width; x++) { \
1798 dst[x] = mix(xf0[x], xf1[x], powf(progress, 1.f + \
1799 logf(2.f-FFABS(xf0[x]-xf1[x])*imax)\
1803 dst += out->linesize[p] / div; \
1804 xf0 += a->linesize[p] / div; \
1805 xf1 += b->linesize[p] / div; \
1813#define HWIND_TRANSITION(name, z, type, div, expr) \
1814static void h##z##wind##name##_transition(AVFilterContext *ctx, \
1815 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1817 int slice_start, int slice_end, int jobnr) \
1819 XFadeContext *s = ctx->priv; \
1820 const int width = out->width; \
1822 for (int y = slice_start; y < slice_end; y++) { \
1823 const float r = frand(0, y); \
1824 for (int x = 0; x < width; x++) { \
1825 const float fx = expr x / (float)width; \
1826 for (int p = 0; p < s->nb_planes; p++) { \
1827 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1828 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1829 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1831 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f,-0.2f, fx * (1.f - 0.2f)\
1832 + 0.2f * r - (1.f - progress)\
1844#define VWIND_TRANSITION(name, z, type, div, expr) \
1845static void v##z##wind##name##_transition(AVFilterContext *ctx, \
1846 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1848 int slice_start, int slice_end, int jobnr) \
1850 XFadeContext *s = ctx->priv; \
1851 const int width = out->width; \
1853 for (int y = slice_start; y < slice_end; y++) { \
1854 const float fy = expr y / (float)out->height; \
1855 for (int x = 0; x < width; x++) { \
1856 const float r = frand(x, 0); \
1857 for (int p = 0; p < s->nb_planes; p++) { \
1858 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1859 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1860 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1862 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f,-0.2f, fy * (1.f - 0.2f) \
1863 + 0.2f * r - (1.f - progress)\
1875#define COVERH_TRANSITION(dir, name, type, div, expr) \
1876static void cover##dir##name##_transition(AVFilterContext *ctx, \
1877 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1879 int slice_start, int slice_end, int jobnr) \
1881 XFadeContext *s = ctx->priv; \
1882 const int height = slice_end - slice_start; \
1883 const int width = out->width; \
1884 const int z = (expr progress) * width; \
1886 for (int p = 0; p < s->nb_planes; p++) { \
1887 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1888 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1889 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1891 for (int y = 0; y < height; y++) { \
1892 for (int x = 0; x < width; x++) { \
1893 const int zx = z + x; \
1894 const int zz = wrap_once(zx, width); \
1895 dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[x]; \
1898 dst += out->linesize[p] / div; \
1899 xf0 += a->linesize[p] / div; \
1900 xf1 += b->linesize[p] / div; \
1910#define COVERV_TRANSITION(dir, name, type, div, expr) \
1911static void cover##dir##name##_transition(AVFilterContext *ctx, \
1912 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1914 int slice_start, int slice_end, int jobnr) \
1916 XFadeContext *s = ctx->priv; \
1917 const int height = out->height; \
1918 const int width = out->width; \
1919 const int z = (expr progress) * height; \
1921 for (int p = 0; p < s->nb_planes; p++) { \
1922 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1924 for (int y = slice_start; y < slice_end; y++) { \
1925 const int zy = z + y; \
1926 const int zz = wrap_once(zy, height); \
1927 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1928 const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
1930 for (int x = 0; x < width; x++) \
1931 dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
1933 dst += out->linesize[p] / div; \
1943#define REVEALH_TRANSITION(dir, name, type, div, expr) \
1944static void reveal##dir##name##_transition(AVFilterContext *ctx, \
1945 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1947 int slice_start, int slice_end, int jobnr) \
1949 XFadeContext *s = ctx->priv; \
1950 const int height = slice_end - slice_start; \
1951 const int width = out->width; \
1952 const int z = (expr progress) * width; \
1954 for (int p = 0; p < s->nb_planes; p++) { \
1955 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1956 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1957 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1959 for (int y = 0; y < height; y++) { \
1960 for (int x = 0; x < width; x++) { \
1961 const int zx = z + x; \
1962 const int zz = wrap_once(zx, width); \
1963 dst[x] = (zx >= 0) && (zx < width) ? xf1[x] : xf0[zz]; \
1966 dst += out->linesize[p] / div; \
1967 xf0 += a->linesize[p] / div; \
1968 xf1 += b->linesize[p] / div; \
1978#define REVEALV_TRANSITION(dir, name, type, div, expr) \
1979static void reveal##dir##name##_transition(AVFilterContext *ctx, \
1980 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1982 int slice_start, int slice_end, int jobnr) \
1984 XFadeContext *s = ctx->priv; \
1985 const int height = out->height; \
1986 const int width = out->width; \
1987 const int z = (expr progress) * height; \
1989 for (int p = 0; p < s->nb_planes; p++) { \
1990 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1992 for (int y = slice_start; y < slice_end; y++) { \
1993 const int zy = z + y; \
1994 const int zz = wrap_once(zy, height); \
1995 const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
1996 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1998 for (int x = 0; x < width; x++) \
1999 dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
2001 dst += out->linesize[p] / div; \
2011static inline
double getpix(
void *priv,
double x,
double y,
int plane,
int nb)
2015 const uint8_t *
src = in->
data[
FFMIN(plane,
s->nb_planes - 1)];
2026 const uint16_t *src16 = (
const uint16_t*)
src;
2029 return src16[
xi + yi * linesize];
2031 return src[
xi + yi * linesize];
2035static double a0(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 0, 0); }
2036static double a1(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 1, 0); }
2037static double a2(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 2, 0); }
2038static double a3(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 3, 0); }
2040static double b0(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 0, 1); }
2041static double b1(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 1, 1); }
2042static double b2(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 2, 1); }
2043static double b3(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 3, 1); }
2056 if (inlink0->
w != inlink1->
w || inlink0->
h != inlink1->
h) {
2058 "(size %dx%d) do not match the corresponding "
2059 "second input link %s parameters (size %dx%d)\n",
2060 ctx->input_pads[0].name, inlink0->
w, inlink0->
h,
2061 ctx->input_pads[1].name, inlink1->
w, inlink1->
h);
2068 "(%d/%d) do not match the corresponding "
2069 "second input link %s timebase (%d/%d)\n",
2084 "(%d/%d) do not match the corresponding "
2085 "second input link %s frame rate (%d/%d)\n",
2091 outlink->
w = inlink0->
w;
2092 outlink->
h = inlink0->
h;
2100 s->max_value = (1 <<
s->depth) - 1;
2102 s->black[1] =
s->black[2] =
s->is_rgb ? 0 :
s->max_value / 2;
2103 s->black[3] =
s->max_value;
2104 s->white[0] =
s->white[3] =
s->max_value;
2105 s->white[1] =
s->white[2] =
s->is_rgb ?
s->max_value :
s->max_value / 2;
2110 if (!
s->duration_pts)
2111 s->duration_pts = 1;
2113 switch (
s->transition) {
2114 case CUSTOM:
s->transitionf =
s->depth <= 8 ? custom8_transition : custom16_transition;
break;
2115 case FADE:
s->transitionf =
s->depth <= 8 ? fade8_transition : fade16_transition;
break;
2116 case WIPELEFT:
s->transitionf =
s->depth <= 8 ? wipeleft8_transition : wipeleft16_transition;
break;
2117 case WIPERIGHT:
s->transitionf =
s->depth <= 8 ? wiperight8_transition : wiperight16_transition;
break;
2118 case WIPEUP:
s->transitionf =
s->depth <= 8 ? wipeup8_transition : wipeup16_transition;
break;
2119 case WIPEDOWN:
s->transitionf =
s->depth <= 8 ? wipedown8_transition : wipedown16_transition;
break;
2120 case SLIDELEFT:
s->transitionf =
s->depth <= 8 ? slideleft8_transition : slideleft16_transition;
break;
2121 case SLIDERIGHT:
s->transitionf =
s->depth <= 8 ? slideright8_transition : slideright16_transition;
break;
2122 case SLIDEUP:
s->transitionf =
s->depth <= 8 ? slideup8_transition : slideup16_transition;
break;
2123 case SLIDEDOWN:
s->transitionf =
s->depth <= 8 ? slidedown8_transition : slidedown16_transition;
break;
2124 case CIRCLECROP:
s->transitionf =
s->depth <= 8 ? circlecrop8_transition : circlecrop16_transition;
break;
2125 case RECTCROP:
s->transitionf =
s->depth <= 8 ? rectcrop8_transition : rectcrop16_transition;
break;
2126 case DISTANCE:
s->transitionf =
s->depth <= 8 ? distance8_transition : distance16_transition;
break;
2127 case FADEBLACK:
s->transitionf =
s->depth <= 8 ? fadeblack8_transition : fadeblack16_transition;
break;
2128 case FADEWHITE:
s->transitionf =
s->depth <= 8 ? fadewhite8_transition : fadewhite16_transition;
break;
2129 case RADIAL:
s->transitionf =
s->depth <= 8 ? radial8_transition : radial16_transition;
break;
2130 case SMOOTHLEFT:
s->transitionf =
s->depth <= 8 ? smoothleft8_transition : smoothleft16_transition;
break;
2131 case SMOOTHRIGHT:
s->transitionf =
s->depth <= 8 ? smoothright8_transition: smoothright16_transition;
break;
2132 case SMOOTHUP:
s->transitionf =
s->depth <= 8 ? smoothup8_transition : smoothup16_transition;
break;
2133 case SMOOTHDOWN:
s->transitionf =
s->depth <= 8 ? smoothdown8_transition : smoothdown16_transition;
break;
2134 case CIRCLEOPEN:
s->transitionf =
s->depth <= 8 ? circleopen8_transition : circleopen16_transition;
break;
2135 case CIRCLECLOSE:
s->transitionf =
s->depth <= 8 ? circleclose8_transition: circleclose16_transition;
break;
2136 case VERTOPEN:
s->transitionf =
s->depth <= 8 ? vertopen8_transition : vertopen16_transition;
break;
2137 case VERTCLOSE:
s->transitionf =
s->depth <= 8 ? vertclose8_transition : vertclose16_transition;
break;
2138 case HORZOPEN:
s->transitionf =
s->depth <= 8 ? horzopen8_transition : horzopen16_transition;
break;
2139 case HORZCLOSE:
s->transitionf =
s->depth <= 8 ? horzclose8_transition : horzclose16_transition;
break;
2140 case DISSOLVE:
s->transitionf =
s->depth <= 8 ? dissolve8_transition : dissolve16_transition;
break;
2141 case PIXELIZE:
s->transitionf =
s->depth <= 8 ? pixelize8_transition : pixelize16_transition;
break;
2142 case DIAGTL:
s->transitionf =
s->depth <= 8 ? diagtl8_transition : diagtl16_transition;
break;
2143 case DIAGTR:
s->transitionf =
s->depth <= 8 ? diagtr8_transition : diagtr16_transition;
break;
2144 case DIAGBL:
s->transitionf =
s->depth <= 8 ? diagbl8_transition : diagbl16_transition;
break;
2145 case DIAGBR:
s->transitionf =
s->depth <= 8 ? diagbr8_transition : diagbr16_transition;
break;
2146 case HLSLICE:
s->transitionf =
s->depth <= 8 ? hlslice8_transition : hlslice16_transition;
break;
2147 case HRSLICE:
s->transitionf =
s->depth <= 8 ? hrslice8_transition : hrslice16_transition;
break;
2148 case VUSLICE:
s->transitionf =
s->depth <= 8 ? vuslice8_transition : vuslice16_transition;
break;
2149 case VDSLICE:
s->transitionf =
s->depth <= 8 ? vdslice8_transition : vdslice16_transition;
break;
2150 case HBLUR:
s->transitionf =
s->depth <= 8 ? hblur8_transition : hblur16_transition;
break;
2151 case FADEGRAYS:
s->transitionf =
s->depth <= 8 ? fadegrays8_transition : fadegrays16_transition;
break;
2152 case WIPETL:
s->transitionf =
s->depth <= 8 ? wipetl8_transition : wipetl16_transition;
break;
2153 case WIPETR:
s->transitionf =
s->depth <= 8 ? wipetr8_transition : wipetr16_transition;
break;
2154 case WIPEBL:
s->transitionf =
s->depth <= 8 ? wipebl8_transition : wipebl16_transition;
break;
2155 case WIPEBR:
s->transitionf =
s->depth <= 8 ? wipebr8_transition : wipebr16_transition;
break;
2156 case SQUEEZEH:
s->transitionf =
s->depth <= 8 ? squeezeh8_transition : squeezeh16_transition;
break;
2157 case SQUEEZEV:
s->transitionf =
s->depth <= 8 ? squeezev8_transition : squeezev16_transition;
break;
2158 case ZOOMIN:
s->transitionf =
s->depth <= 8 ? zoomin8_transition : zoomin16_transition;
break;
2159 case FADEFAST:
s->transitionf =
s->depth <= 8 ? fadefast8_transition : fadefast16_transition;
break;
2160 case FADESLOW:
s->transitionf =
s->depth <= 8 ? fadeslow8_transition : fadeslow16_transition;
break;
2161 case HLWIND:
s->transitionf =
s->depth <= 8 ? hlwind8_transition : hlwind16_transition;
break;
2162 case HRWIND:
s->transitionf =
s->depth <= 8 ? hrwind8_transition : hrwind16_transition;
break;
2163 case VUWIND:
s->transitionf =
s->depth <= 8 ? vuwind8_transition : vuwind16_transition;
break;
2164 case VDWIND:
s->transitionf =
s->depth <= 8 ? vdwind8_transition : vdwind16_transition;
break;
2165 case COVERLEFT:
s->transitionf =
s->depth <= 8 ? coverleft8_transition : coverleft16_transition;
break;
2166 case COVERRIGHT:
s->transitionf =
s->depth <= 8 ? coverright8_transition : coverright16_transition;
break;
2167 case COVERUP:
s->transitionf =
s->depth <= 8 ? coverup8_transition : coverup16_transition;
break;
2168 case COVERDOWN:
s->transitionf =
s->depth <= 8 ? coverdown8_transition : coverdown16_transition;
break;
2169 case REVEALLEFT:
s->transitionf =
s->depth <= 8 ? revealleft8_transition : revealleft16_transition;
break;
2170 case REVEALRIGHT:
s->transitionf =
s->depth <= 8 ? revealright8_transition: revealright16_transition;
break;
2171 case REVEALUP:
s->transitionf =
s->depth <= 8 ? revealup8_transition : revealup16_transition;
break;
2172 case REVEALDOWN:
s->transitionf =
s->depth <= 8 ? revealdown8_transition : revealdown16_transition;
break;
2176 if (
s->transition ==
CUSTOM) {
2178 "a0",
"a1",
"a2",
"a3",
2179 "b0",
"b1",
"b2",
"b3",
2216 float progress =
av_clipf(1.f - ((
float)(
s->pts -
s->start_pts) /
s->duration_pts), 0.f, 1.f);
2238 int ret = 0, status;
2249 s->inputs_offset_pts = -
frame->pts;
2252 frame->pts +=
s->inputs_offset_pts;
2259 s->inputs_offset_pts = -status_pts;
2285 if (
s->status[0] && !
s->status[1])
2292 s->pts = peeked_frame->
pts;
2300 if (
s->start_pts >
s->pts) {
2324 s->inputs_offset_pts =
s->pts -
s->xf[1]->pts;
2328 if (
s->pts -
s->start_pts >
s->duration_pts) {
2375 return s->passthrough ?
2404 .p.priv_class = &xfade_class,
static double(*const func2[])(void *, double, double)
static const char *const func2_names[]
const FFFilter ff_vf_xfade
static AVFormatContext * ctx
static AVFrame * get_video_buffer(AVFilterLink *inlink, int w, int h)
void ff_inlink_set_status(AVFilterLink *link, int status)
Set the status on an input link.
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
int ff_inlink_check_available_frame(AVFilterLink *link)
Test if a frame is available on the link.
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
int ff_outlink_frame_wanted(AVFilterLink *link)
Test if a frame is wanted on an output link.
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
AVFrame * ff_inlink_peek_frame(AVFilterLink *link, size_t idx)
Access a frame in the link fifo without consuming it.
void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
Mark a filter ready and schedule it for activation.
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Main libavfilter public API header.
static int BS_FUNC left(const BSCTX *bc)
Return the number of the bits left in a buffer.
#define xi(width, name, var, range_min, range_max, subs,...)
static __device__ float floorf(float a)
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with 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.
simple arithmetic expression evaluator
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_DURATION
Underlying C type is int64_t.
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
#define AVERROR_EOF
End of file.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
#define AV_NOPTS_VALUE
Undefined timestamp value.
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
static int config_output(AVBitStreamFilterLink *outlink)
static int mix(int c0, int c1)
#define u(width, name, range_min, range_max)
#define FILTER_INPUTS(array)
#define FILTER_OUTPUTS(array)
static int ff_slice_pos(int total, int jobnr, int nb_jobs)
Compute the boundary index for a slice when work of size total is split into nb_jobs slices.
#define FILTER_PIXFMTS_ARRAY(array)
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
#define FFERROR_NOT_READY
Filters implementation helper functions and internal structures.
#define FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, filter)
Forward the status on an output link to all input links.
static FilterLink * ff_filter_link(AVFilterLink *link)
#define AVFILTER_DEFINE_CLASS(fname)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static enum AVPixelFormat pix_fmts[]
static int slice_end(AVCodecContext *avctx, AVFrame *pict, int *got_output)
Handle slice ends.
static const char *const var_names[]
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
#define AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_YUV444P12
#define AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_YUVA444P10
#define AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GBRP12
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
#define AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_YUVA444P16
#define AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_YUV444P14
#define AV_PIX_FMT_YUVA444P9
#define AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_YUVA444P12
#define AV_PIX_FMT_YUV444P16
#define AV_PIX_FMT_YUV444P10
Describe the class of an AVClass context structure.
int depth
Number of bits in the component.
AVFilterLink ** inputs
array of pointers to input links
void * priv
private data for use by the filter
AVFilterLink ** outputs
array of pointers to output links
A link between two filters.
int w
agreed upon image width
int h
agreed upon image height
AVFilterContext * src
source filter
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link.
AVRational sample_aspect_ratio
agreed upon sample aspect ratio
AVFilterContext * dst
dest filter
int format
agreed upon media format
A filter pad used for either input or output.
This structure describes decoded (raw) audio or video data.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
uint64_t flags
Combination of AV_PIX_FMT_FLAG_... flags.
Link properties exposed to filter code, but not external callers.
AVRational frame_rate
Frame rate of the stream on the link, or 1/0 if unknown or variable.
Used for passing data between threads.
void(* transitionf)(AVFilterContext *ctx, const AVFrame *a, const AVFrame *b, AVFrame *out, float progress, int slice_start, int slice_end, int jobnr)
int64_t inputs_offset_pts
static float frand(int x, int y)
static double getpix(void *priv, double x, double y, int plane)
#define HWIND_TRANSITION(name, z, type, div, expr)
static int xfade_activate(AVFilterContext *avctx)
#define CIRCLEOPEN_TRANSITION(name, type, div)
#define SLIDERIGHT_TRANSITION(name, type, div)
static void zoom(float *u, float *v, float amount)
#define HORZCLOSE_TRANSITION(name, type, div)
#define WIPETR_TRANSITION(name, type, div)
#define SLIDEUP_TRANSITION(name, type, div)
static double b1(void *priv, double x, double y)
static double a0(void *priv, double x, double y)
static double b2(void *priv, double x, double y)
#define COVERV_TRANSITION(dir, name, type, div, expr)
#define CIRCLECROP_TRANSITION(name, type, div)
#define FADEWHITE_TRANSITION(name, type, div)
#define WIPELEFT_TRANSITION(name, type, div)
#define SMOOTHDOWN_TRANSITION(name, type, div)
#define WIPEUP_TRANSITION(name, type, div)
#define SMOOTHRIGHT_TRANSITION(name, type, div)
static const AVFilterPad xfade_inputs[]
#define FADEGRAYS_TRANSITION(name, type, div)
#define WIPETL_TRANSITION(name, type, div)
#define VDSLICE_TRANSITION(name, type, div)
#define CIRCLECLOSE_TRANSITION(name, type, div)
#define VERTOPEN_TRANSITION(name, type, div)
#define SLIDELEFT_TRANSITION(name, type, div)
static int forward_frame(XFadeContext *s, AVFilterLink *inlink, AVFilterLink *outlink)
#define FADEBLACK_TRANSITION(name, type, div)
#define DIAGTR_TRANSITION(name, type, div)
#define SMOOTHUP_TRANSITION(name, type, div)
#define CUSTOM_TRANSITION(name, type, div)
#define SQUEEZEV_TRANSITION(name, type, div)
#define WIPERIGHT_TRANSITION(name, type, div)
#define ZOOMIN_TRANSITION(name, type, div)
static float fract(float a)
static double b3(void *priv, double x, double y)
#define REVEALV_TRANSITION(dir, name, type, div, expr)
static const AVFilterPad xfade_outputs[]
static AVFrame * get_video_buffer(AVFilterLink *inlink, int w, int h)
static double a3(void *priv, double x, double y)
static int xfade_frame(AVFilterContext *ctx, AVFrame *a, AVFrame *b)
#define RADIAL_TRANSITION(name, type, div)
#define HORZOPEN_TRANSITION(name, type, div)
#define VERTCLOSE_TRANSITION(name, type, div)
#define WIPEDOWN_TRANSITION(name, type, div)
#define SQUEEZEH_TRANSITION(name, type, div)
#define HRSLICE_TRANSITION(name, type, div)
static float smoothstep(float edge0, float edge1, float x)
#define DIAGTL_TRANSITION(name, type, div)
static int wrap_once(int index, int size)
#define SLIDEDOWN_TRANSITION(name, type, div)
#define HBLUR_TRANSITION(name, type, div)
static double getpix(void *priv, double x, double y, int plane, int nb)
#define DIAGBL_TRANSITION(name, type, div)
static const AVOption xfade_options[]
#define DISTANCE_TRANSITION(name, type, div)
#define WIPEBL_TRANSITION(name, type, div)
static double b0(void *priv, double x, double y)
#define VWIND_TRANSITION(name, z, type, div, expr)
#define FADEFAST_TRANSITION(name, type, div)
static av_cold void uninit(AVFilterContext *ctx)
#define WIPEBR_TRANSITION(name, type, div)
static double a2(void *priv, double x, double y)
#define COVERH_TRANSITION(dir, name, type, div, expr)
#define HLSLICE_TRANSITION(name, type, div)
#define PIXELIZE_TRANSITION(name, type, div)
static int config_output(AVFilterLink *outlink)
#define FADESLOW_TRANSITION(name, type, div)
#define DISSOLVE_TRANSITION(name, type, div)
#define DIAGBR_TRANSITION(name, type, div)
#define FADE_TRANSITION(name, type, div)
#define SMOOTHLEFT_TRANSITION(name, type, div)
static double a1(void *priv, double x, double y)
#define RECTCROP_TRANSITION(name, type, div)
static int xfade_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define REVEALH_TRANSITION(dir, name, type, div, expr)
#define VUSLICE_TRANSITION(name, type, div)
AVFrame * ff_null_get_video_buffer(AVFilterLink *link, int w, int h)
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
AVFrame * ff_default_get_video_buffer(AVFilterLink *link, int w, int h)
static int slice_start(SliceContext *sc, VVCContext *s, VVCFrameContext *fc, const CodedBitstreamUnit *unit, const int is_first_slice)