Go to the documentation of this file.
132 static 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) \
240 static 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; \
280 static inline
float mix(
float a,
float b,
float mix)
290 static 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);
299 #define FADE_TRANSITION(name, type, div) \
300 static void fade##name##_transition(AVFilterContext *ctx, \
301 const AVFrame *a, const AVFrame *b, AVFrame *out, \
303 int slice_start, int slice_end, int jobnr) \
305 XFadeContext *s = ctx->priv; \
306 const int height = slice_end - slice_start; \
307 const int width = out->width; \
309 for (int p = 0; p < s->nb_planes; p++) { \
310 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
311 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
312 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
314 for (int y = 0; y < height; y++) { \
315 for (int x = 0; x < width; x++) { \
316 dst[x] = mix(xf0[x], xf1[x], progress); \
319 dst += out->linesize[p] / div; \
320 xf0 += a->linesize[p] / div; \
321 xf1 += b->linesize[p] / div; \
329 #define WIPELEFT_TRANSITION(name, type, div) \
330 static void wipeleft##name##_transition(AVFilterContext *ctx, \
331 const AVFrame *a, const AVFrame *b, AVFrame *out, \
333 int slice_start, int slice_end, int jobnr) \
335 XFadeContext *s = ctx->priv; \
336 const int height = slice_end - slice_start; \
337 const int width = out->width; \
338 const int z = width * progress; \
340 for (int p = 0; p < s->nb_planes; p++) { \
341 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
342 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
343 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
345 for (int y = 0; y < height; y++) { \
346 for (int x = 0; x < width; x++) { \
347 dst[x] = x > z ? xf1[x] : xf0[x]; \
350 dst += out->linesize[p] / div; \
351 xf0 += a->linesize[p] / div; \
352 xf1 += b->linesize[p] / div; \
360 #define WIPERIGHT_TRANSITION(name, type, div) \
361 static void wiperight##name##_transition(AVFilterContext *ctx, \
362 const AVFrame *a, const AVFrame *b, AVFrame *out, \
364 int slice_start, int slice_end, int jobnr) \
366 XFadeContext *s = ctx->priv; \
367 const int height = slice_end - slice_start; \
368 const int width = out->width; \
369 const int z = width * (1.f - progress); \
371 for (int p = 0; p < s->nb_planes; p++) { \
372 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
373 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
374 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
376 for (int y = 0; y < height; y++) { \
377 for (int x = 0; x < width; x++) { \
378 dst[x] = x > z ? xf0[x] : xf1[x]; \
381 dst += out->linesize[p] / div; \
382 xf0 += a->linesize[p] / div; \
383 xf1 += b->linesize[p] / div; \
391 #define WIPEUP_TRANSITION(name, type, div) \
392 static void wipeup##name##_transition(AVFilterContext *ctx, \
393 const AVFrame *a, const AVFrame *b, AVFrame *out, \
395 int slice_start, int slice_end, int jobnr) \
397 XFadeContext *s = ctx->priv; \
398 const int height = slice_end - slice_start; \
399 const int width = out->width; \
400 const int z = out->height * progress; \
402 for (int p = 0; p < s->nb_planes; p++) { \
403 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
404 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
405 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
407 for (int y = 0; y < height; y++) { \
408 for (int x = 0; x < width; x++) { \
409 dst[x] = slice_start + y > z ? xf1[x] : xf0[x]; \
412 dst += out->linesize[p] / div; \
413 xf0 += a->linesize[p] / div; \
414 xf1 += b->linesize[p] / div; \
422 #define WIPEDOWN_TRANSITION(name, type, div) \
423 static void wipedown##name##_transition(AVFilterContext *ctx, \
424 const AVFrame *a, const AVFrame *b, AVFrame *out, \
426 int slice_start, int slice_end, int jobnr) \
428 XFadeContext *s = ctx->priv; \
429 const int height = slice_end - slice_start; \
430 const int width = out->width; \
431 const int z = out->height * (1.f - progress); \
433 for (int p = 0; p < s->nb_planes; p++) { \
434 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
435 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
436 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
438 for (int y = 0; y < height; y++) { \
439 for (int x = 0; x < width; x++) { \
440 dst[x] = slice_start + y > z ? xf0[x] : xf1[x]; \
443 dst += out->linesize[p] / div; \
444 xf0 += a->linesize[p] / div; \
445 xf1 += b->linesize[p] / div; \
453 #define SLIDELEFT_TRANSITION(name, type, div) \
454 static void slideleft##name##_transition(AVFilterContext *ctx, \
455 const AVFrame *a, const AVFrame *b, AVFrame *out, \
457 int slice_start, int slice_end, int jobnr) \
459 XFadeContext *s = ctx->priv; \
460 const int height = slice_end - slice_start; \
461 const int width = out->width; \
462 const int z = -progress * width; \
464 for (int p = 0; p < s->nb_planes; p++) { \
465 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
466 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
467 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
469 for (int y = 0; y < height; y++) { \
470 for (int x = 0; x < width; x++) { \
471 const int zx = z + x; \
472 const int zz = zx % width + width * (zx < 0); \
473 dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \
476 dst += out->linesize[p] / div; \
477 xf0 += a->linesize[p] / div; \
478 xf1 += b->linesize[p] / div; \
486 #define SLIDERIGHT_TRANSITION(name, type, div) \
487 static void slideright##name##_transition(AVFilterContext *ctx, \
488 const AVFrame *a, const AVFrame *b, AVFrame *out, \
490 int slice_start, int slice_end, int jobnr) \
492 XFadeContext *s = ctx->priv; \
493 const int height = slice_end - slice_start; \
494 const int width = out->width; \
495 const int z = progress * width; \
497 for (int p = 0; p < s->nb_planes; p++) { \
498 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
499 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
500 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
502 for (int y = 0; y < height; y++) { \
503 for (int x = 0; x < width; x++) { \
504 const int zx = z + x; \
505 const int zz = zx % width + width * (zx < 0); \
506 dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \
509 dst += out->linesize[p] / div; \
510 xf0 += a->linesize[p] / div; \
511 xf1 += b->linesize[p] / div; \
519 #define SLIDEUP_TRANSITION(name, type, div) \
520 static void slideup##name##_transition(AVFilterContext *ctx, \
521 const AVFrame *a, const AVFrame *b, AVFrame *out, \
523 int slice_start, int slice_end, int jobnr) \
525 XFadeContext *s = ctx->priv; \
526 const int height = out->height; \
527 const int width = out->width; \
528 const int z = -progress * height; \
530 for (int p = 0; p < s->nb_planes; p++) { \
531 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
533 for (int y = slice_start; y < slice_end; y++) { \
534 const int zy = z + y; \
535 const int zz = zy % height + height * (zy < 0); \
536 const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
537 const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
539 for (int x = 0; x < width; x++) { \
540 dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
543 dst += out->linesize[p] / div; \
551 #define SLIDEDOWN_TRANSITION(name, type, div) \
552 static void slidedown##name##_transition(AVFilterContext *ctx, \
553 const AVFrame *a, const AVFrame *b, AVFrame *out, \
555 int slice_start, int slice_end, int jobnr) \
557 XFadeContext *s = ctx->priv; \
558 const int height = out->height; \
559 const int width = out->width; \
560 const int z = progress * height; \
562 for (int p = 0; p < s->nb_planes; p++) { \
563 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
565 for (int y = slice_start; y < slice_end; y++) { \
566 const int zy = z + y; \
567 const int zz = zy % height + height * (zy < 0); \
568 const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
569 const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
571 for (int x = 0; x < width; x++) { \
572 dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
575 dst += out->linesize[p] / div; \
583 #define CIRCLECROP_TRANSITION(name, type, div) \
584 static void circlecrop##name##_transition(AVFilterContext *ctx, \
585 const AVFrame *a, const AVFrame *b, AVFrame *out, \
587 int slice_start, int slice_end, int jobnr) \
589 XFadeContext *s = ctx->priv; \
590 const int width = out->width; \
591 const int height = out->height; \
592 float z = powf(2.f * fabsf(progress - 0.5f), 3.f) * hypotf(width/2, height/2); \
594 for (int p = 0; p < s->nb_planes; p++) { \
595 const int bg = s->black[p]; \
596 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
598 for (int y = slice_start; y < slice_end; y++) { \
599 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
600 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
602 for (int x = 0; x < width; x++) { \
603 float dist = hypotf(x - width / 2, y - height / 2); \
604 int val = progress < 0.5f ? xf1[x] : xf0[x]; \
605 dst[x] = (z < dist) ? bg : val; \
608 dst += out->linesize[p] / div; \
616 #define RECTCROP_TRANSITION(name, type, div) \
617 static void rectcrop##name##_transition(AVFilterContext *ctx, \
618 const AVFrame *a, const AVFrame *b, AVFrame *out, \
620 int slice_start, int slice_end, int jobnr) \
622 XFadeContext *s = ctx->priv; \
623 const int width = out->width; \
624 const int height = out->height; \
625 int zh = fabsf(progress - 0.5f) * height; \
626 int zw = fabsf(progress - 0.5f) * width; \
628 for (int p = 0; p < s->nb_planes; p++) { \
629 const int bg = s->black[p]; \
630 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
632 for (int y = slice_start; y < slice_end; y++) { \
633 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
634 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
636 for (int x = 0; x < width; x++) { \
637 int dist = FFABS(x - width / 2) < zw && \
638 FFABS(y - height / 2) < zh; \
639 int val = progress < 0.5f ? xf1[x] : xf0[x]; \
640 dst[x] = !dist ? bg : val; \
643 dst += out->linesize[p] / div; \
651 #define DISTANCE_TRANSITION(name, type, div) \
652 static void distance##name##_transition(AVFilterContext *ctx, \
653 const AVFrame *a, const AVFrame *b, AVFrame *out, \
655 int slice_start, int slice_end, int jobnr) \
657 XFadeContext *s = ctx->priv; \
658 const int width = out->width; \
659 const float max = s->max_value; \
661 for (int y = slice_start; y < slice_end; y++) { \
662 for (int x = 0; x < width; x++) { \
664 for (int p = 0; p < s->nb_planes; p++) { \
665 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
666 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
668 dist += (xf0[x] / max - xf1[x] / max) * \
669 (xf0[x] / max - xf1[x] / max); \
672 dist = sqrtf(dist) <= progress; \
673 for (int p = 0; p < s->nb_planes; p++) { \
674 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
675 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
676 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
677 dst[x] = mix(mix(xf0[x], xf1[x], dist), xf1[x], progress); \
686 #define FADEBLACK_TRANSITION(name, type, div) \
687 static void fadeblack##name##_transition(AVFilterContext *ctx, \
688 const AVFrame *a, const AVFrame *b, AVFrame *out, \
690 int slice_start, int slice_end, int jobnr) \
692 XFadeContext *s = ctx->priv; \
693 const int height = slice_end - slice_start; \
694 const int width = out->width; \
695 const float phase = 0.2f; \
697 for (int p = 0; p < s->nb_planes; p++) { \
698 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
699 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
700 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
701 const int bg = s->black[p]; \
703 for (int y = 0; y < height; y++) { \
704 for (int x = 0; x < width; x++) { \
705 dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \
706 mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \
710 dst += out->linesize[p] / div; \
711 xf0 += a->linesize[p] / div; \
712 xf1 += b->linesize[p] / div; \
720 #define FADEWHITE_TRANSITION(name, type, div) \
721 static void fadewhite##name##_transition(AVFilterContext *ctx, \
722 const AVFrame *a, const AVFrame *b, AVFrame *out, \
724 int slice_start, int slice_end, int jobnr) \
726 XFadeContext *s = ctx->priv; \
727 const int height = slice_end - slice_start; \
728 const int width = out->width; \
729 const float phase = 0.2f; \
731 for (int p = 0; p < s->nb_planes; p++) { \
732 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
733 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
734 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
735 const int bg = s->white[p]; \
737 for (int y = 0; y < height; y++) { \
738 for (int x = 0; x < width; x++) { \
739 dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \
740 mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \
744 dst += out->linesize[p] / div; \
745 xf0 += a->linesize[p] / div; \
746 xf1 += b->linesize[p] / div; \
754 #define RADIAL_TRANSITION(name, type, div) \
755 static void radial##name##_transition(AVFilterContext *ctx, \
756 const AVFrame *a, const AVFrame *b, AVFrame *out, \
758 int slice_start, int slice_end, int jobnr) \
760 XFadeContext *s = ctx->priv; \
761 const int width = out->width; \
762 const int height = out->height; \
764 for (int y = slice_start; y < slice_end; y++) { \
765 for (int x = 0; x < width; x++) { \
766 const float smooth = atan2f(x - width / 2, y - height / 2) - \
767 (progress - 0.5f) * (M_PI * 2.5f); \
768 for (int p = 0; p < s->nb_planes; p++) { \
769 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
770 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
771 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
773 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
782 #define SMOOTHLEFT_TRANSITION(name, type, div) \
783 static void smoothleft##name##_transition(AVFilterContext *ctx, \
784 const AVFrame *a, const AVFrame *b, AVFrame *out, \
786 int slice_start, int slice_end, int jobnr) \
788 XFadeContext *s = ctx->priv; \
789 const int width = out->width; \
790 const float w = width; \
792 for (int y = slice_start; y < slice_end; y++) { \
793 for (int x = 0; x < width; x++) { \
794 const float smooth = 1.f + x / w - progress * 2.f; \
796 for (int p = 0; p < s->nb_planes; p++) { \
797 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
798 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
799 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
801 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
810 #define SMOOTHRIGHT_TRANSITION(name, type, div) \
811 static void smoothright##name##_transition(AVFilterContext *ctx, \
812 const AVFrame *a, const AVFrame *b, AVFrame *out, \
814 int slice_start, int slice_end, int jobnr) \
816 XFadeContext *s = ctx->priv; \
817 const int width = out->width; \
818 const float w = width; \
820 for (int y = slice_start; y < slice_end; y++) { \
821 for (int x = 0; x < width; x++) { \
822 const float smooth = 1.f + (w - 1 - x) / w - progress * 2.f; \
824 for (int p = 0; p < s->nb_planes; p++) { \
825 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
826 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
827 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
829 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
838 #define SMOOTHUP_TRANSITION(name, type, div) \
839 static void smoothup##name##_transition(AVFilterContext *ctx, \
840 const AVFrame *a, const AVFrame *b, AVFrame *out, \
842 int slice_start, int slice_end, int jobnr) \
844 XFadeContext *s = ctx->priv; \
845 const int width = out->width; \
846 const float h = out->height; \
848 for (int y = slice_start; y < slice_end; y++) { \
849 const float smooth = 1.f + y / h - progress * 2.f; \
850 for (int x = 0; x < width; x++) { \
851 for (int p = 0; p < s->nb_planes; p++) { \
852 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
853 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
854 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
856 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
865 #define SMOOTHDOWN_TRANSITION(name, type, div) \
866 static void smoothdown##name##_transition(AVFilterContext *ctx, \
867 const AVFrame *a, const AVFrame *b, AVFrame *out, \
869 int slice_start, int slice_end, int jobnr) \
871 XFadeContext *s = ctx->priv; \
872 const int width = out->width; \
873 const float h = out->height; \
875 for (int y = slice_start; y < slice_end; y++) { \
876 const float smooth = 1.f + (h - 1 - y) / h - progress * 2.f; \
877 for (int x = 0; x < width; x++) { \
878 for (int p = 0; p < s->nb_planes; p++) { \
879 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
880 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
881 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
883 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
892 #define CIRCLEOPEN_TRANSITION(name, type, div) \
893 static void circleopen##name##_transition(AVFilterContext *ctx, \
894 const AVFrame *a, const AVFrame *b, AVFrame *out, \
896 int slice_start, int slice_end, int jobnr) \
898 XFadeContext *s = ctx->priv; \
899 const int width = out->width; \
900 const int height = out->height; \
901 const float z = hypotf(width / 2, height / 2); \
902 const float p = (progress - 0.5f) * 3.f; \
904 for (int y = slice_start; y < slice_end; y++) { \
905 for (int x = 0; x < width; x++) { \
906 const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \
907 for (int p = 0; p < s->nb_planes; p++) { \
908 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
909 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
910 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
912 dst[x] = mix(xf0[x], xf1[x], smoothstep(0.f, 1.f, smooth)); \
921 #define CIRCLECLOSE_TRANSITION(name, type, div) \
922 static void circleclose##name##_transition(AVFilterContext *ctx, \
923 const AVFrame *a, const AVFrame *b, AVFrame *out, \
925 int slice_start, int slice_end, int jobnr) \
927 XFadeContext *s = ctx->priv; \
928 const int width = out->width; \
929 const int height = out->height; \
930 const float z = hypotf(width / 2, height / 2); \
931 const float p = (1.f - progress - 0.5f) * 3.f; \
933 for (int y = slice_start; y < slice_end; y++) { \
934 for (int x = 0; x < width; x++) { \
935 const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \
936 for (int p = 0; p < s->nb_planes; p++) { \
937 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
938 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
939 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
941 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
950 #define VERTOPEN_TRANSITION(name, type, div) \
951 static void vertopen##name##_transition(AVFilterContext *ctx, \
952 const AVFrame *a, const AVFrame *b, AVFrame *out, \
954 int slice_start, int slice_end, int jobnr) \
956 XFadeContext *s = ctx->priv; \
957 const int width = out->width; \
958 const float w2 = out->width / 2.0; \
960 for (int y = slice_start; y < slice_end; y++) { \
961 for (int x = 0; x < width; x++) { \
962 const float smooth = 2.f - fabsf((x - w2) / w2) - progress * 2.f; \
963 for (int p = 0; p < s->nb_planes; p++) { \
964 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
965 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
966 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
968 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
977 #define VERTCLOSE_TRANSITION(name, type, div) \
978 static void vertclose##name##_transition(AVFilterContext *ctx, \
979 const AVFrame *a, const AVFrame *b, AVFrame *out, \
981 int slice_start, int slice_end, int jobnr) \
983 XFadeContext *s = ctx->priv; \
984 const int nb_planes = s->nb_planes; \
985 const int width = out->width; \
986 const float w2 = out->width / 2.0; \
988 for (int y = slice_start; y < slice_end; y++) { \
989 for (int x = 0; x < width; x++) { \
990 const float smooth = 1.f + fabsf((x - w2) / w2) - progress * 2.f; \
991 for (int p = 0; p < nb_planes; p++) { \
992 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
993 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
994 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
996 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1005 #define HORZOPEN_TRANSITION(name, type, div) \
1006 static void horzopen##name##_transition(AVFilterContext *ctx, \
1007 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1009 int slice_start, int slice_end, int jobnr) \
1011 XFadeContext *s = ctx->priv; \
1012 const int nb_planes = s->nb_planes; \
1013 const int width = out->width; \
1014 const float h2 = out->height / 2.0; \
1016 for (int y = slice_start; y < slice_end; y++) { \
1017 const float smooth = 2.f - fabsf((y - h2) / h2) - progress * 2.f; \
1018 for (int x = 0; x < width; x++) { \
1019 for (int p = 0; p < nb_planes; p++) { \
1020 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1021 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1022 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1024 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1033 #define HORZCLOSE_TRANSITION(name, type, div) \
1034 static void horzclose##name##_transition(AVFilterContext *ctx, \
1035 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1037 int slice_start, int slice_end, int jobnr) \
1039 XFadeContext *s = ctx->priv; \
1040 const int nb_planes = s->nb_planes; \
1041 const int width = out->width; \
1042 const float h2 = out->height / 2.0; \
1044 for (int y = slice_start; y < slice_end; y++) { \
1045 const float smooth = 1.f + fabsf((y - h2) / h2) - progress * 2.f; \
1046 for (int x = 0; x < width; x++) { \
1047 for (int p = 0; p < nb_planes; p++) { \
1048 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1049 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1050 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1052 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1063 const float r =
sinf(x * 12.9898
f + y * 78.233
f) * 43758.545f;
1068 #define DISSOLVE_TRANSITION(name, type, div) \
1069 static void dissolve##name##_transition(AVFilterContext *ctx, \
1070 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1072 int slice_start, int slice_end, int jobnr) \
1074 XFadeContext *s = ctx->priv; \
1075 const int nb_planes = s->nb_planes; \
1076 const int width = out->width; \
1078 for (int y = slice_start; y < slice_end; y++) { \
1079 for (int x = 0; x < width; x++) { \
1080 const float smooth = frand(x, y) * 2.f + progress * 2.f - 1.5f; \
1081 for (int p = 0; p < nb_planes; p++) { \
1082 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1083 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1084 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1086 dst[x] = smooth >= 0.5f ? xf0[x] : xf1[x]; \
1095 #define PIXELIZE_TRANSITION(name, type, div) \
1096 static void pixelize##name##_transition(AVFilterContext *ctx, \
1097 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1099 int slice_start, int slice_end, int jobnr) \
1101 XFadeContext *s = ctx->priv; \
1102 const int nb_planes = s->nb_planes; \
1103 const int w = out->width; \
1104 const int h = out->height; \
1105 const float d = fminf(progress, 1.f - progress); \
1106 const float dist = ceilf(d * 50.f) / 50.f; \
1107 const float sqx = 2.f * dist * FFMIN(w, h) / 20.f; \
1108 const float sqy = 2.f * dist * FFMIN(w, h) / 20.f; \
1110 for (int y = slice_start; y < slice_end; y++) { \
1111 for (int x = 0; x < w; x++) { \
1112 int sx = dist > 0.f ? FFMIN((floorf(x / sqx) + .5f) * sqx, w - 1) : x; \
1113 int sy = dist > 0.f ? FFMIN((floorf(y / sqy) + .5f) * sqy, h - 1) : y; \
1114 for (int p = 0; p < nb_planes; p++) { \
1115 const type *xf0 = (const type *)(a->data[p] + sy * a->linesize[p]); \
1116 const type *xf1 = (const type *)(b->data[p] + sy * b->linesize[p]); \
1117 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1119 dst[x] = mix(xf0[sx], xf1[sx], progress); \
1128 #define DIAGTL_TRANSITION(name, type, div) \
1129 static void diagtl##name##_transition(AVFilterContext *ctx, \
1130 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1132 int slice_start, int slice_end, int jobnr) \
1134 XFadeContext *s = ctx->priv; \
1135 const int nb_planes = s->nb_planes; \
1136 const int width = out->width; \
1137 const float w = width; \
1138 const float h = out->height; \
1140 for (int y = slice_start; y < slice_end; y++) { \
1141 for (int x = 0; x < width; x++) { \
1142 const float smooth = 1.f + x / w * y / h - progress * 2.f; \
1144 for (int p = 0; p < nb_planes; p++) { \
1145 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1146 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1147 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1149 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1158 #define DIAGTR_TRANSITION(name, type, div) \
1159 static void diagtr##name##_transition(AVFilterContext *ctx, \
1160 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1162 int slice_start, int slice_end, int jobnr) \
1164 XFadeContext *s = ctx->priv; \
1165 const int nb_planes = s->nb_planes; \
1166 const int width = out->width; \
1167 const float w = width; \
1168 const float h = out->height; \
1170 for (int y = slice_start; y < slice_end; y++) { \
1171 for (int x = 0; x < width; x++) { \
1172 const float smooth = 1.f + (w - 1 - x) / w * y / h - progress * 2.f; \
1174 for (int p = 0; p < nb_planes; p++) { \
1175 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1176 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1177 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1179 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1188 #define DIAGBL_TRANSITION(name, type, div) \
1189 static void diagbl##name##_transition(AVFilterContext *ctx, \
1190 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1192 int slice_start, int slice_end, int jobnr) \
1194 XFadeContext *s = ctx->priv; \
1195 const int nb_planes = s->nb_planes; \
1196 const int width = out->width; \
1197 const float w = width; \
1198 const float h = out->height; \
1200 for (int y = slice_start; y < slice_end; y++) { \
1201 for (int x = 0; x < width; x++) { \
1202 const float smooth = 1.f + x / w * (h - 1 - y) / h - progress * 2.f; \
1204 for (int p = 0; p < nb_planes; p++) { \
1205 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1206 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1207 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1209 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1218 #define DIAGBR_TRANSITION(name, type, div) \
1219 static void diagbr##name##_transition(AVFilterContext *ctx, \
1220 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1222 int slice_start, int slice_end, int jobnr) \
1224 XFadeContext *s = ctx->priv; \
1225 const int nb_planes = s->nb_planes; \
1226 const int width = out->width; \
1227 const float w = width; \
1228 const float h = out->height; \
1230 for (int y = slice_start; y < slice_end; y++) { \
1231 for (int x = 0; x < width; x++) { \
1232 const float smooth = 1.f + (w - 1 - x) / w * (h - 1 - y) / h - \
1235 for (int p = 0; p < nb_planes; p++) { \
1236 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1237 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1238 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1240 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1249 #define HLSLICE_TRANSITION(name, type, div) \
1250 static void hlslice##name##_transition(AVFilterContext *ctx, \
1251 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1253 int slice_start, int slice_end, int jobnr) \
1255 XFadeContext *s = ctx->priv; \
1256 const int nb_planes = s->nb_planes; \
1257 const int width = out->width; \
1258 const float w = width; \
1260 for (int y = slice_start; y < slice_end; y++) { \
1261 for (int x = 0; x < width; x++) { \
1262 const float smooth = smoothstep(-0.5f, 0.f, x / w - progress * 1.5f); \
1263 const float ss = smooth <= fract(10.f * x / w) ? 0.f : 1.f; \
1265 for (int p = 0; p < nb_planes; p++) { \
1266 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1267 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1268 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1270 dst[x] = mix(xf1[x], xf0[x], ss); \
1279 #define HRSLICE_TRANSITION(name, type, div) \
1280 static void hrslice##name##_transition(AVFilterContext *ctx, \
1281 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1283 int slice_start, int slice_end, int jobnr) \
1285 XFadeContext *s = ctx->priv; \
1286 const int nb_planes = s->nb_planes; \
1287 const int width = out->width; \
1288 const float w = width; \
1290 for (int y = slice_start; y < slice_end; y++) { \
1291 for (int x = 0; x < width; x++) { \
1292 const float xx = (w - 1 - x) / w; \
1293 const float smooth = smoothstep(-0.5f, 0.f, xx - progress * 1.5f); \
1294 const float ss = smooth <= fract(10.f * xx) ? 0.f : 1.f; \
1296 for (int p = 0; p < nb_planes; p++) { \
1297 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1298 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1299 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1301 dst[x] = mix(xf1[x], xf0[x], ss); \
1310 #define VUSLICE_TRANSITION(name, type, div) \
1311 static void vuslice##name##_transition(AVFilterContext *ctx, \
1312 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1314 int slice_start, int slice_end, int jobnr) \
1316 XFadeContext *s = ctx->priv; \
1317 const int nb_planes = s->nb_planes; \
1318 const int width = out->width; \
1319 const float h = out->height; \
1321 for (int y = slice_start; y < slice_end; y++) { \
1322 const float smooth = smoothstep(-0.5f, 0.f, y / h - progress * 1.5f); \
1323 const float ss = smooth <= fract(10.f * y / h) ? 0.f : 1.f; \
1325 for (int x = 0; x < width; x++) { \
1326 for (int p = 0; p < nb_planes; p++) { \
1327 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1328 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1329 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1331 dst[x] = mix(xf1[x], xf0[x], ss); \
1340 #define VDSLICE_TRANSITION(name, type, div) \
1341 static void vdslice##name##_transition(AVFilterContext *ctx, \
1342 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1344 int slice_start, int slice_end, int jobnr) \
1346 XFadeContext *s = ctx->priv; \
1347 const int nb_planes = s->nb_planes; \
1348 const int width = out->width; \
1349 const float h = out->height; \
1351 for (int y = slice_start; y < slice_end; y++) { \
1352 const float yy = (h - 1 - y) / h; \
1353 const float smooth = smoothstep(-0.5f, 0.f, yy - progress * 1.5f); \
1354 const float ss = smooth <= fract(10.f * yy) ? 0.f : 1.f; \
1356 for (int x = 0; x < width; x++) { \
1357 for (int p = 0; p < nb_planes; p++) { \
1358 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1359 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1360 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1362 dst[x] = mix(xf1[x], xf0[x], ss); \
1371 #define HBLUR_TRANSITION(name, type, div) \
1372 static void hblur##name##_transition(AVFilterContext *ctx, \
1373 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1375 int slice_start, int slice_end, int jobnr) \
1377 XFadeContext *s = ctx->priv; \
1378 const int nb_planes = s->nb_planes; \
1379 const int width = out->width; \
1380 const float prog = progress <= 0.5f ? progress * 2.f : (1.f - progress) * 2.f; \
1381 const int size = 1 + (width / 2) * prog; \
1383 for (int y = slice_start; y < slice_end; y++) { \
1384 for (int p = 0; p < nb_planes; p++) { \
1385 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1386 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1387 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1392 for (int x = 0; x < size; x++) { \
1397 for (int x = 0; x < width; x++) { \
1398 dst[x] = mix(sum0 / cnt, sum1 / cnt, progress); \
1400 if (x + size < width) { \
1401 sum0 += xf0[x + size] - xf0[x]; \
1402 sum1 += xf1[x + size] - xf1[x]; \
1416 #define FADEGRAYS_TRANSITION(name, type, div) \
1417 static void fadegrays##name##_transition(AVFilterContext *ctx, \
1418 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1420 int slice_start, int slice_end, int jobnr) \
1422 XFadeContext *s = ctx->priv; \
1423 const int width = out->width; \
1424 const int is_rgb = s->is_rgb; \
1425 const int mid = (s->max_value + 1) / 2; \
1426 const float phase = 0.2f; \
1428 for (int y = slice_start; y < slice_end; y++) { \
1429 for (int x = 0; x < width; x++) { \
1432 bg[0][0] = bg[1][0] = 0; \
1433 for (int p = 0; p < s->nb_planes; p++) { \
1434 const type *xf0 = (const type *)(a->data[p] + \
1435 y * a->linesize[p]); \
1436 const type *xf1 = (const type *)(b->data[p] + \
1437 y * b->linesize[p]); \
1439 bg[0][3] = xf0[x]; \
1440 bg[1][3] = xf1[x]; \
1442 bg[0][0] += xf0[x]; \
1443 bg[1][0] += xf1[x]; \
1446 bg[0][0] = bg[0][0] / 3; \
1447 bg[1][0] = bg[1][0] / 3; \
1448 bg[0][1] = bg[0][2] = bg[0][0]; \
1449 bg[1][1] = bg[1][2] = bg[1][0]; \
1451 const type *yf0 = (const type *)(a->data[0] + \
1452 y * a->linesize[0]); \
1453 const type *yf1 = (const type *)(b->data[0] + \
1454 y * a->linesize[0]); \
1455 bg[0][0] = yf0[x]; \
1456 bg[1][0] = yf1[x]; \
1457 if (s->nb_planes == 4) { \
1458 const type *af0 = (const type *)(a->data[3] + \
1459 y * a->linesize[3]); \
1460 const type *af1 = (const type *)(b->data[3] + \
1461 y * a->linesize[3]); \
1462 bg[0][3] = af0[x]; \
1463 bg[1][3] = af1[x]; \
1465 bg[0][1] = bg[1][1] = mid; \
1466 bg[0][2] = bg[1][2] = mid; \
1469 for (int p = 0; p < s->nb_planes; p++) { \
1470 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1471 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1472 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1474 dst[x] = mix(mix(xf0[x], bg[0][p], \
1475 smoothstep(1.f-phase, 1.f, progress)), \
1476 mix(bg[1][p], xf1[x], smoothstep(phase, 1.f, progress)), \
1486 #define WIPETL_TRANSITION(name, type, div) \
1487 static void wipetl##name##_transition(AVFilterContext *ctx, \
1488 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1490 int slice_start, int slice_end, int jobnr) \
1492 XFadeContext *s = ctx->priv; \
1493 const int height = slice_end - slice_start; \
1494 const int width = out->width; \
1495 const int zw = out->width * progress; \
1496 const int zh = out->height * progress; \
1498 for (int p = 0; p < s->nb_planes; p++) { \
1499 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1500 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1501 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1503 for (int y = 0; y < height; y++) { \
1504 for (int x = 0; x < width; x++) { \
1505 dst[x] = slice_start + y <= zh && \
1506 x <= zw ? xf0[x] : xf1[x]; \
1509 dst += out->linesize[p] / div; \
1510 xf0 += a->linesize[p] / div; \
1511 xf1 += b->linesize[p] / div; \
1519 #define WIPETR_TRANSITION(name, type, div) \
1520 static void wipetr##name##_transition(AVFilterContext *ctx, \
1521 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1523 int slice_start, int slice_end, int jobnr) \
1525 XFadeContext *s = ctx->priv; \
1526 const int height = slice_end - slice_start; \
1527 const int width = out->width; \
1528 const int zw = width * (1.f - progress); \
1529 const int zh = out->height * progress; \
1531 for (int p = 0; p < s->nb_planes; p++) { \
1532 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1533 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1534 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1536 for (int y = 0; y < height; y++) { \
1537 for (int x = 0; x < width; x++) { \
1538 dst[x] = slice_start + y <= zh && \
1539 x > zw ? xf0[x] : xf1[x]; \
1542 dst += out->linesize[p] / div; \
1543 xf0 += a->linesize[p] / div; \
1544 xf1 += b->linesize[p] / div; \
1552 #define WIPEBL_TRANSITION(name, type, div) \
1553 static void wipebl##name##_transition(AVFilterContext *ctx, \
1554 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1556 int slice_start, int slice_end, int jobnr) \
1558 XFadeContext *s = ctx->priv; \
1559 const int height = slice_end - slice_start; \
1560 const int width = out->width; \
1561 const int zw = width * progress; \
1562 const int zh = out->height * (1.f - progress); \
1564 for (int p = 0; p < s->nb_planes; p++) { \
1565 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1566 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1567 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1569 for (int y = 0; y < height; y++) { \
1570 for (int x = 0; x < width; x++) { \
1571 dst[x] = slice_start + y > zh && \
1572 x <= zw ? xf0[x] : xf1[x]; \
1575 dst += out->linesize[p] / div; \
1576 xf0 += a->linesize[p] / div; \
1577 xf1 += b->linesize[p] / div; \
1585 #define WIPEBR_TRANSITION(name, type, div) \
1586 static void wipebr##name##_transition(AVFilterContext *ctx, \
1587 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1589 int slice_start, int slice_end, int jobnr) \
1591 XFadeContext *s = ctx->priv; \
1592 const int height = slice_end - slice_start; \
1593 const int zh = out->height * (1.f - progress); \
1594 const int width = out->width; \
1595 const int zw = width * (1.f - progress); \
1597 for (int p = 0; p < s->nb_planes; p++) { \
1598 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1599 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1600 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1602 for (int y = 0; y < height; y++) { \
1603 for (int x = 0; x < width; x++) { \
1604 dst[x] = slice_start + y > zh && \
1605 x > zw ? xf0[x] : xf1[x]; \
1608 dst += out->linesize[p] / div; \
1609 xf0 += a->linesize[p] / div; \
1610 xf1 += b->linesize[p] / div; \
1618 #define SQUEEZEH_TRANSITION(name, type, div) \
1619 static void squeezeh##name##_transition(AVFilterContext *ctx, \
1620 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1622 int slice_start, int slice_end, int jobnr) \
1624 XFadeContext *s = ctx->priv; \
1625 const float h = out->height; \
1626 const int height = slice_end - slice_start; \
1627 const int width = out->width; \
1629 for (int p = 0; p < s->nb_planes; p++) { \
1630 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1631 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1633 for (int y = 0; y < height; y++) { \
1634 const float z = .5f + ((slice_start + y) / h - .5f) / progress; \
1636 if (z < 0.f || z > 1.f) { \
1637 for (int x = 0; x < width; x++) \
1640 const int yy = lrintf(z * (h - 1.f)); \
1641 const type *xf0 = (const type *)(a->data[p] + yy * a->linesize[p]); \
1643 for (int x = 0; x < width; x++) \
1647 dst += out->linesize[p] / div; \
1648 xf1 += b->linesize[p] / div; \
1656 #define SQUEEZEV_TRANSITION(name, type, div) \
1657 static void squeezev##name##_transition(AVFilterContext *ctx, \
1658 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1660 int slice_start, int slice_end, int jobnr) \
1662 XFadeContext *s = ctx->priv; \
1663 const int width = out->width; \
1664 const float w = width; \
1665 const int height = slice_end - slice_start; \
1667 for (int p = 0; p < s->nb_planes; p++) { \
1668 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1669 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1670 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1672 for (int y = 0; y < height; y++) { \
1673 for (int x = 0; x < width; x++) { \
1674 const float z = .5f + (x / w - .5f) / progress; \
1676 if (z < 0.f || z > 1.f) { \
1679 const int xx = lrintf(z * (w - 1.f)); \
1685 dst += out->linesize[p] / div; \
1686 xf0 += a->linesize[p] / div; \
1687 xf1 += b->linesize[p] / div; \
1695 static
void zoom(
float *
u,
float *v,
float amount)
1697 *
u = 0.5f + ((*
u - 0.5f) * amount);
1698 *v = 0.5f + ((*v - 0.5f) * amount);
1701 #define ZOOMIN_TRANSITION(name, type, div) \
1702 static void zoomin##name##_transition(AVFilterContext *ctx, \
1703 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1705 int slice_start, int slice_end, int jobnr) \
1707 XFadeContext *s = ctx->priv; \
1708 const int width = out->width; \
1709 const float w = width; \
1710 const float h = out->height; \
1711 const float zf = smoothstep(0.5f, 1.f, progress); \
1713 for (int p = 0; p < s->nb_planes; p++) { \
1714 const type *xf0 = (const type *)(a->data[p]); \
1715 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1716 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1718 for (int y = slice_start; y < slice_end; y++) { \
1719 for (int x = 0; x < width; x++) { \
1726 iu = ceilf(u * (w - 1)); \
1727 iv = ceilf(v * (h - 1)); \
1728 zv = xf0[iu + iv * a->linesize[p] / div]; \
1729 dst[x] = mix(zv, xf1[x], smoothstep(0.f, 0.5f, progress)); \
1731 dst += out->linesize[p] / div; \
1732 xf1 += b->linesize[p] / div; \
1740 #define FADEFAST_TRANSITION(name, type, div) \
1741 static void fadefast##name##_transition(AVFilterContext *ctx, \
1742 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1744 int slice_start, int slice_end, int jobnr) \
1746 XFadeContext *s = ctx->priv; \
1747 const int height = slice_end - slice_start; \
1748 const int width = out->width; \
1749 const float imax = 1.f / s->max_value; \
1751 for (int p = 0; p < s->nb_planes; p++) { \
1752 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1753 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1754 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1756 for (int y = 0; y < height; y++) { \
1757 for (int x = 0; x < width; x++) { \
1758 dst[x] = mix(xf0[x], xf1[x], powf(progress, 1.f + \
1759 logf(1.f+FFABS(xf0[x]-xf1[x])*imax)\
1763 dst += out->linesize[p] / div; \
1764 xf0 += a->linesize[p] / div; \
1765 xf1 += b->linesize[p] / div; \
1773 #define FADESLOW_TRANSITION(name, type, div) \
1774 static void fadeslow##name##_transition(AVFilterContext *ctx, \
1775 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1777 int slice_start, int slice_end, int jobnr) \
1779 XFadeContext *s = ctx->priv; \
1780 const int height = slice_end - slice_start; \
1781 const int width = out->width; \
1782 const float imax = 1.f / s->max_value; \
1784 for (int p = 0; p < s->nb_planes; p++) { \
1785 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1786 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1787 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1789 for (int y = 0; y < height; y++) { \
1790 for (int x = 0; x < width; x++) { \
1791 dst[x] = mix(xf0[x], xf1[x], powf(progress, 1.f + \
1792 logf(2.f-FFABS(xf0[x]-xf1[x])*imax)\
1796 dst += out->linesize[p] / div; \
1797 xf0 += a->linesize[p] / div; \
1798 xf1 += b->linesize[p] / div; \
1806 #define HWIND_TRANSITION(name, z, type, div, expr) \
1807 static void h##z##wind##name##_transition(AVFilterContext *ctx, \
1808 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1810 int slice_start, int slice_end, int jobnr) \
1812 XFadeContext *s = ctx->priv; \
1813 const int width = out->width; \
1815 for (int y = slice_start; y < slice_end; y++) { \
1816 const float r = frand(0, y); \
1817 for (int x = 0; x < width; x++) { \
1818 const float fx = expr x / (float)width; \
1819 for (int p = 0; p < s->nb_planes; p++) { \
1820 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1821 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1822 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1824 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f,-0.2f, fx * (1.f - 0.2f)\
1825 + 0.2f * r - (1.f - progress)\
1837 #define VWIND_TRANSITION(name, z, type, div, expr) \
1838 static void v##z##wind##name##_transition(AVFilterContext *ctx, \
1839 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1841 int slice_start, int slice_end, int jobnr) \
1843 XFadeContext *s = ctx->priv; \
1844 const int width = out->width; \
1846 for (int y = slice_start; y < slice_end; y++) { \
1847 const float fy = expr y / (float)out->height; \
1848 for (int x = 0; x < width; x++) { \
1849 const float r = frand(x, 0); \
1850 for (int p = 0; p < s->nb_planes; p++) { \
1851 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1852 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1853 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1855 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f,-0.2f, fy * (1.f - 0.2f) \
1856 + 0.2f * r - (1.f - progress)\
1868 #define COVERH_TRANSITION(dir, name, type, div, expr) \
1869 static void cover##dir##name##_transition(AVFilterContext *ctx, \
1870 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1872 int slice_start, int slice_end, int jobnr) \
1874 XFadeContext *s = ctx->priv; \
1875 const int height = slice_end - slice_start; \
1876 const int width = out->width; \
1877 const int z = (expr progress) * width; \
1879 for (int p = 0; p < s->nb_planes; p++) { \
1880 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1881 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1882 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1884 for (int y = 0; y < height; y++) { \
1885 for (int x = 0; x < width; x++) { \
1886 const int zx = z + x; \
1887 const int zz = zx % width + width * (zx < 0); \
1888 dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[x]; \
1891 dst += out->linesize[p] / div; \
1892 xf0 += a->linesize[p] / div; \
1893 xf1 += b->linesize[p] / div; \
1903 #define COVERV_TRANSITION(dir, name, type, div, expr) \
1904 static void cover##dir##name##_transition(AVFilterContext *ctx, \
1905 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1907 int slice_start, int slice_end, int jobnr) \
1909 XFadeContext *s = ctx->priv; \
1910 const int height = out->height; \
1911 const int width = out->width; \
1912 const int z = (expr progress) * height; \
1914 for (int p = 0; p < s->nb_planes; p++) { \
1915 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1917 for (int y = slice_start; y < slice_end; y++) { \
1918 const int zy = z + y; \
1919 const int zz = zy % height + height * (zy < 0); \
1920 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1921 const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
1923 for (int x = 0; x < width; x++) \
1924 dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
1926 dst += out->linesize[p] / div; \
1936 #define REVEALH_TRANSITION(dir, name, type, div, expr) \
1937 static void reveal##dir##name##_transition(AVFilterContext *ctx, \
1938 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1940 int slice_start, int slice_end, int jobnr) \
1942 XFadeContext *s = ctx->priv; \
1943 const int height = slice_end - slice_start; \
1944 const int width = out->width; \
1945 const int z = (expr progress) * width; \
1947 for (int p = 0; p < s->nb_planes; p++) { \
1948 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1949 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1950 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1952 for (int y = 0; y < height; y++) { \
1953 for (int x = 0; x < width; x++) { \
1954 const int zx = z + x; \
1955 const int zz = zx % width + width * (zx < 0); \
1956 dst[x] = (zx >= 0) && (zx < width) ? xf1[x] : xf0[zz]; \
1959 dst += out->linesize[p] / div; \
1960 xf0 += a->linesize[p] / div; \
1961 xf1 += b->linesize[p] / div; \
1971 #define REVEALV_TRANSITION(dir, name, type, div, expr) \
1972 static void reveal##dir##name##_transition(AVFilterContext *ctx, \
1973 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1975 int slice_start, int slice_end, int jobnr) \
1977 XFadeContext *s = ctx->priv; \
1978 const int height = out->height; \
1979 const int width = out->width; \
1980 const int z = (expr progress) * height; \
1982 for (int p = 0; p < s->nb_planes; p++) { \
1983 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1985 for (int y = slice_start; y < slice_end; y++) { \
1986 const int zy = z + y; \
1987 const int zz = zy % height + height * (zy < 0); \
1988 const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
1989 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1991 for (int x = 0; x < width; x++) \
1992 dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
1994 dst += out->linesize[p] / div; \
2004 static inline
double getpix(
void *priv,
double x,
double y,
int plane,
int nb)
2008 const uint8_t *
src = in->
data[
FFMIN(plane,
s->nb_planes - 1)];
2019 const uint16_t *src16 = (
const uint16_t*)
src;
2022 return src16[
xi + yi * linesize];
2024 return src[
xi + yi * linesize];
2028 static double a0(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 0, 0); }
2029 static double a1(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 1, 0); }
2030 static double a2(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 2, 0); }
2031 static double a3(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 3, 0); }
2033 static double b0(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 0, 1); }
2034 static double b1(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 1, 1); }
2035 static double b2(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 2, 1); }
2036 static double b3(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 3, 1); }
2049 if (inlink0->
w != inlink1->
w || inlink0->
h != inlink1->
h) {
2051 "(size %dx%d) do not match the corresponding "
2052 "second input link %s parameters (size %dx%d)\n",
2053 ctx->input_pads[0].name, inlink0->
w, inlink0->
h,
2054 ctx->input_pads[1].name, inlink1->
w, inlink1->
h);
2061 "(%d/%d) do not match the corresponding "
2062 "second input link %s timebase (%d/%d)\n",
2077 "(%d/%d) do not match the corresponding "
2078 "second input link %s frame rate (%d/%d)\n",
2084 outlink->
w = inlink0->
w;
2085 outlink->
h = inlink0->
h;
2093 s->max_value = (1 <<
s->depth) - 1;
2095 s->black[1] =
s->black[2] =
s->is_rgb ? 0 :
s->max_value / 2;
2096 s->black[3] =
s->max_value;
2097 s->white[0] =
s->white[3] =
s->max_value;
2098 s->white[1] =
s->white[2] =
s->is_rgb ?
s->max_value :
s->max_value / 2;
2105 switch (
s->transition) {
2106 case CUSTOM:
s->transitionf =
s->depth <= 8 ? custom8_transition : custom16_transition;
break;
2107 case FADE:
s->transitionf =
s->depth <= 8 ? fade8_transition : fade16_transition;
break;
2108 case WIPELEFT:
s->transitionf =
s->depth <= 8 ? wipeleft8_transition : wipeleft16_transition;
break;
2109 case WIPERIGHT:
s->transitionf =
s->depth <= 8 ? wiperight8_transition : wiperight16_transition;
break;
2110 case WIPEUP:
s->transitionf =
s->depth <= 8 ? wipeup8_transition : wipeup16_transition;
break;
2111 case WIPEDOWN:
s->transitionf =
s->depth <= 8 ? wipedown8_transition : wipedown16_transition;
break;
2112 case SLIDELEFT:
s->transitionf =
s->depth <= 8 ? slideleft8_transition : slideleft16_transition;
break;
2113 case SLIDERIGHT:
s->transitionf =
s->depth <= 8 ? slideright8_transition : slideright16_transition;
break;
2114 case SLIDEUP:
s->transitionf =
s->depth <= 8 ? slideup8_transition : slideup16_transition;
break;
2115 case SLIDEDOWN:
s->transitionf =
s->depth <= 8 ? slidedown8_transition : slidedown16_transition;
break;
2116 case CIRCLECROP:
s->transitionf =
s->depth <= 8 ? circlecrop8_transition : circlecrop16_transition;
break;
2117 case RECTCROP:
s->transitionf =
s->depth <= 8 ? rectcrop8_transition : rectcrop16_transition;
break;
2118 case DISTANCE:
s->transitionf =
s->depth <= 8 ? distance8_transition : distance16_transition;
break;
2119 case FADEBLACK:
s->transitionf =
s->depth <= 8 ? fadeblack8_transition : fadeblack16_transition;
break;
2120 case FADEWHITE:
s->transitionf =
s->depth <= 8 ? fadewhite8_transition : fadewhite16_transition;
break;
2121 case RADIAL:
s->transitionf =
s->depth <= 8 ? radial8_transition : radial16_transition;
break;
2122 case SMOOTHLEFT:
s->transitionf =
s->depth <= 8 ? smoothleft8_transition : smoothleft16_transition;
break;
2123 case SMOOTHRIGHT:
s->transitionf =
s->depth <= 8 ? smoothright8_transition: smoothright16_transition;
break;
2124 case SMOOTHUP:
s->transitionf =
s->depth <= 8 ? smoothup8_transition : smoothup16_transition;
break;
2125 case SMOOTHDOWN:
s->transitionf =
s->depth <= 8 ? smoothdown8_transition : smoothdown16_transition;
break;
2126 case CIRCLEOPEN:
s->transitionf =
s->depth <= 8 ? circleopen8_transition : circleopen16_transition;
break;
2127 case CIRCLECLOSE:
s->transitionf =
s->depth <= 8 ? circleclose8_transition: circleclose16_transition;
break;
2128 case VERTOPEN:
s->transitionf =
s->depth <= 8 ? vertopen8_transition : vertopen16_transition;
break;
2129 case VERTCLOSE:
s->transitionf =
s->depth <= 8 ? vertclose8_transition : vertclose16_transition;
break;
2130 case HORZOPEN:
s->transitionf =
s->depth <= 8 ? horzopen8_transition : horzopen16_transition;
break;
2131 case HORZCLOSE:
s->transitionf =
s->depth <= 8 ? horzclose8_transition : horzclose16_transition;
break;
2132 case DISSOLVE:
s->transitionf =
s->depth <= 8 ? dissolve8_transition : dissolve16_transition;
break;
2133 case PIXELIZE:
s->transitionf =
s->depth <= 8 ? pixelize8_transition : pixelize16_transition;
break;
2134 case DIAGTL:
s->transitionf =
s->depth <= 8 ? diagtl8_transition : diagtl16_transition;
break;
2135 case DIAGTR:
s->transitionf =
s->depth <= 8 ? diagtr8_transition : diagtr16_transition;
break;
2136 case DIAGBL:
s->transitionf =
s->depth <= 8 ? diagbl8_transition : diagbl16_transition;
break;
2137 case DIAGBR:
s->transitionf =
s->depth <= 8 ? diagbr8_transition : diagbr16_transition;
break;
2138 case HLSLICE:
s->transitionf =
s->depth <= 8 ? hlslice8_transition : hlslice16_transition;
break;
2139 case HRSLICE:
s->transitionf =
s->depth <= 8 ? hrslice8_transition : hrslice16_transition;
break;
2140 case VUSLICE:
s->transitionf =
s->depth <= 8 ? vuslice8_transition : vuslice16_transition;
break;
2141 case VDSLICE:
s->transitionf =
s->depth <= 8 ? vdslice8_transition : vdslice16_transition;
break;
2142 case HBLUR:
s->transitionf =
s->depth <= 8 ? hblur8_transition : hblur16_transition;
break;
2143 case FADEGRAYS:
s->transitionf =
s->depth <= 8 ? fadegrays8_transition : fadegrays16_transition;
break;
2144 case WIPETL:
s->transitionf =
s->depth <= 8 ? wipetl8_transition : wipetl16_transition;
break;
2145 case WIPETR:
s->transitionf =
s->depth <= 8 ? wipetr8_transition : wipetr16_transition;
break;
2146 case WIPEBL:
s->transitionf =
s->depth <= 8 ? wipebl8_transition : wipebl16_transition;
break;
2147 case WIPEBR:
s->transitionf =
s->depth <= 8 ? wipebr8_transition : wipebr16_transition;
break;
2148 case SQUEEZEH:
s->transitionf =
s->depth <= 8 ? squeezeh8_transition : squeezeh16_transition;
break;
2149 case SQUEEZEV:
s->transitionf =
s->depth <= 8 ? squeezev8_transition : squeezev16_transition;
break;
2150 case ZOOMIN:
s->transitionf =
s->depth <= 8 ? zoomin8_transition : zoomin16_transition;
break;
2151 case FADEFAST:
s->transitionf =
s->depth <= 8 ? fadefast8_transition : fadefast16_transition;
break;
2152 case FADESLOW:
s->transitionf =
s->depth <= 8 ? fadeslow8_transition : fadeslow16_transition;
break;
2153 case HLWIND:
s->transitionf =
s->depth <= 8 ? hlwind8_transition : hlwind16_transition;
break;
2154 case HRWIND:
s->transitionf =
s->depth <= 8 ? hrwind8_transition : hrwind16_transition;
break;
2155 case VUWIND:
s->transitionf =
s->depth <= 8 ? vuwind8_transition : vuwind16_transition;
break;
2156 case VDWIND:
s->transitionf =
s->depth <= 8 ? vdwind8_transition : vdwind16_transition;
break;
2157 case COVERLEFT:
s->transitionf =
s->depth <= 8 ? coverleft8_transition : coverleft16_transition;
break;
2158 case COVERRIGHT:
s->transitionf =
s->depth <= 8 ? coverright8_transition : coverright16_transition;
break;
2159 case COVERUP:
s->transitionf =
s->depth <= 8 ? coverup8_transition : coverup16_transition;
break;
2160 case COVERDOWN:
s->transitionf =
s->depth <= 8 ? coverdown8_transition : coverdown16_transition;
break;
2161 case REVEALLEFT:
s->transitionf =
s->depth <= 8 ? revealleft8_transition : revealleft16_transition;
break;
2162 case REVEALRIGHT:
s->transitionf =
s->depth <= 8 ? revealright8_transition: revealright16_transition;
break;
2163 case REVEALUP:
s->transitionf =
s->depth <= 8 ? revealup8_transition : revealup16_transition;
break;
2164 case REVEALDOWN:
s->transitionf =
s->depth <= 8 ? revealdown8_transition : revealdown16_transition;
break;
2168 if (
s->transition ==
CUSTOM) {
2170 "a0",
"a1",
"a2",
"a3",
2171 "b0",
"b1",
"b2",
"b3",
2197 int slice_end = (outlink->
h * (jobnr+1)) / nb_jobs;
2208 float progress =
av_clipf(1.
f - ((
float)(
s->pts -
s->start_pts) /
s->duration_pts), 0.f, 1.f);
2241 s->inputs_offset_pts = -
frame->pts;
2244 frame->pts +=
s->inputs_offset_pts;
2251 s->inputs_offset_pts = -status_pts;
2277 if (
s->status[0] && !
s->status[1])
2284 s->pts = peeked_frame->
pts;
2292 if (
s->start_pts >
s->pts) {
2316 s->inputs_offset_pts =
s->pts -
s->xf[1]->pts;
2320 if (
s->pts -
s->start_pts >
s->duration_pts) {
2367 return s->passthrough ?
2397 .priv_class = &xfade_class,
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
static enum AVPixelFormat pix_fmts[]
#define AV_PIX_FMT_GBRAP16
AVPixelFormat
Pixel format.
#define HORZOPEN_TRANSITION(name, type, div)
#define FADEBLACK_TRANSITION(name, type, div)
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
#define SLIDERIGHT_TRANSITION(name, type, div)
#define CIRCLECROP_TRANSITION(name, type, div)
#define FILTER_PIXFMTS_ARRAY(array)
#define u(width, name, range_min, range_max)
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
#define AVERROR_EOF
End of file.
static const AVOption xfade_options[]
static __device__ float floorf(float a)
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
#define WIPEDOWN_TRANSITION(name, type, div)
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
#define VWIND_TRANSITION(name, z, type, div, expr)
static void zoom(float *u, float *v, float amount)
static int xfade_activate(AVFilterContext *avctx)
#define RECTCROP_TRANSITION(name, type, div)
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
AVFILTER_DEFINE_CLASS(xfade)
#define FILTER_INPUTS(array)
#define WIPEBL_TRANSITION(name, type, div)
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).
#define SLIDELEFT_TRANSITION(name, type, div)
static AVFrame * get_video_buffer(AVFilterLink *inlink, int w, int h)
int depth
Number of bits in the component.
#define VDSLICE_TRANSITION(name, type, div)
#define WIPERIGHT_TRANSITION(name, type, div)
@ AV_OPT_TYPE_DURATION
Underlying C type is int64_t.
const char * name
Filter name.
#define SMOOTHDOWN_TRANSITION(name, type, div)
A link between two filters.
static float mix(float a, float b, float mix)
static const char *const func2_names[]
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Link properties exposed to filter code, but not external callers.
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.
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
AVFrame * ff_default_get_video_buffer(AVFilterLink *link, int w, int h)
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
#define FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, filter)
Forward the status on an output link to all input links.
#define AV_PIX_FMT_GBRP14
static double b1(void *priv, double x, double y)
static int slice_end(AVCodecContext *avctx, AVFrame *pict, int *got_output)
Handle slice ends.
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
void * priv
private data for use by the filter
#define AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_YUVA444P16
#define VERTOPEN_TRANSITION(name, type, div)
static int xfade_frame(AVFilterContext *ctx, AVFrame *a, AVFrame *b)
#define FADEGRAYS_TRANSITION(name, type, div)
#define SLIDEDOWN_TRANSITION(name, type, div)
#define PIXELIZE_TRANSITION(name, type, div)
#define AV_PIX_FMT_GRAY16
static double a2(void *priv, double x, double y)
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
#define HLSLICE_TRANSITION(name, type, div)
A filter pad used for either input or output.
#define AV_PIX_FMT_YUV444P10
static double(*const func2[])(void *, double, double)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define DIAGTR_TRANSITION(name, type, div)
#define SMOOTHLEFT_TRANSITION(name, type, div)
#define AV_PIX_FMT_GBRAP10
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
static double b3(void *priv, double x, double y)
#define ZOOMIN_TRANSITION(name, type, div)
#define AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_YUV444P16
static float smoothstep(float edge0, float edge1, float x)
AVRational sample_aspect_ratio
agreed upon sample aspect ratio
static const char *const var_names[]
#define AV_PIX_FMT_YUVA444P12
#define xi(width, name, var, range_min, range_max, subs,...)
static double getpix(void *priv, double x, double y, int plane, int nb)
#define HWIND_TRANSITION(name, z, type, div, expr)
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
#define CIRCLECLOSE_TRANSITION(name, type, div)
int64_t inputs_offset_pts
#define FILTER_OUTPUTS(array)
#define DIAGBL_TRANSITION(name, type, div)
#define WIPETR_TRANSITION(name, type, div)
@ 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
AVFrame * ff_inlink_peek_frame(AVFilterLink *link, size_t idx)
Access a frame in the link fifo without consuming it.
#define AV_PIX_FMT_GBRP16
#define SLIDEUP_TRANSITION(name, type, div)
Describe the class of an AVClass context structure.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
static double a3(void *priv, double x, double y)
#define FADE_TRANSITION(name, type, div)
filter_frame For filters that do not use the activate() callback
AVFilterLink ** inputs
array of pointers to input links
static const AVFilterPad xfade_inputs[]
const AVFilter ff_vf_xfade
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
#define DISTANCE_TRANSITION(name, type, div)
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
static const AVFilterPad xfade_outputs[]
static FilterLink * ff_filter_link(AVFilterLink *link)
#define REVEALV_TRANSITION(dir, name, type, div, expr)
#define RADIAL_TRANSITION(name, type, div)
#define WIPELEFT_TRANSITION(name, type, div)
void ff_inlink_set_status(AVFilterLink *link, int status)
Set the status on an input link.
int ff_inlink_check_available_frame(AVFilterLink *link)
Test if a frame is available on the link.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
#define CUSTOM_TRANSITION(name, type, div)
#define FADESLOW_TRANSITION(name, type, div)
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
#define HORZCLOSE_TRANSITION(name, type, div)
int format
agreed upon media format
static av_cold void uninit(AVFilterContext *ctx)
#define AV_NOPTS_VALUE
Undefined timestamp value.
#define HBLUR_TRANSITION(name, type, div)
#define AV_PIX_FMT_YUV444P12
AVFilterContext * src
source filter
#define VUSLICE_TRANSITION(name, type, div)
static double b2(void *priv, double x, double y)
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
static double a0(void *priv, double x, double y)
#define AV_PIX_FMT_YUVA444P10
static float frand(int x, int y)
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
AVFrame * ff_null_get_video_buffer(AVFilterLink *link, int w, int h)
#define WIPEUP_TRANSITION(name, type, div)
#define REVEALH_TRANSITION(dir, name, type, div, expr)
static int config_output(AVFilterLink *outlink)
#define SMOOTHRIGHT_TRANSITION(name, type, div)
int w
agreed upon image width
#define AV_PIX_FMT_GBRP12
#define VERTCLOSE_TRANSITION(name, type, div)
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Used for passing data between threads.
#define WIPETL_TRANSITION(name, type, div)
#define DIAGTL_TRANSITION(name, type, div)
const char * name
Pad name.
#define COVERV_TRANSITION(dir, name, type, div, expr)
static float fract(float a)
static int slice_start(SliceContext *sc, VVCContext *s, VVCFrameContext *fc, const CodedBitstreamUnit *unit, const int is_first_slice)
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
#define SQUEEZEH_TRANSITION(name, type, div)
#define CIRCLEOPEN_TRANSITION(name, type, div)
#define AV_PIX_FMT_YUVA444P9
#define SQUEEZEV_TRANSITION(name, type, div)
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
static int xfade_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define COVERH_TRANSITION(dir, name, type, div, expr)
int h
agreed upon image height
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
@ AV_OPT_TYPE_INT
Underlying C type is int.
#define FADEWHITE_TRANSITION(name, type, div)
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
#define FADEFAST_TRANSITION(name, type, div)
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link.
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
#define SMOOTHUP_TRANSITION(name, type, div)
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
void(* transitionf)(AVFilterContext *ctx, const AVFrame *a, const AVFrame *b, AVFrame *out, float progress, int slice_start, int slice_end, int jobnr)
#define DIAGBR_TRANSITION(name, type, div)
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
static double b0(void *priv, double x, double y)
static double a1(void *priv, double x, double y)
the definition of that something depends on the semantic of the filter The callback must examine the status of the filter s links and proceed accordingly The status of output links is stored in the status_in and status_out fields and tested by the ff_outlink_frame_wanted() function. If this function returns true
AVRational frame_rate
Frame rate of the stream on the link, or 1/0 if unknown or variable.
#define AV_PIX_FMT_YUV444P14
@ 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 AV_PIX_FMT_GRAY12
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
#define WIPEBR_TRANSITION(name, type, div)
#define DISSOLVE_TRANSITION(name, type, div)
static int forward_frame(XFadeContext *s, AVFilterLink *inlink, AVFilterLink *outlink)
void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
Mark a filter ready and schedule it for activation.
#define HRSLICE_TRANSITION(name, type, div)
AVFilterLink ** outputs
array of pointers to output links