Go to the documentation of this file.
133 static const char *
const var_names[] = {
"X",
"Y",
"W",
"H",
"A",
"B",
"PLANE",
"P",
NULL };
168 #define OFFSET(x) offsetof(XFadeContext, x)
169 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
240 #define CUSTOM_TRANSITION(name, type, div) \
241 static void custom##name##_transition(AVFilterContext *ctx, \
242 const AVFrame *a, const AVFrame *b, AVFrame *out, \
244 int slice_start, int slice_end, int jobnr) \
246 XFadeContext *s = ctx->priv; \
247 const int height = slice_end - slice_start; \
248 const int width = out->width; \
250 double values[VAR_VARS_NB]; \
251 values[VAR_W] = width; \
252 values[VAR_H] = out->height; \
253 values[VAR_PROGRESS] = progress; \
255 for (int p = 0; p < s->nb_planes; p++) { \
256 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
257 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
258 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
260 values[VAR_PLANE] = p; \
262 for (int y = 0; y < height; y++) { \
263 values[VAR_Y] = slice_start + y; \
264 for (int x = 0; x < width; x++) { \
266 values[VAR_A] = xf0[x]; \
267 values[VAR_B] = xf1[x]; \
268 dst[x] = av_expr_eval(s->e, values, s); \
271 dst += out->linesize[p] / div; \
272 xf0 += a->linesize[p] / div; \
273 xf1 += b->linesize[p] / div; \
281 static inline
float mix(
float a,
float b,
float mix)
291 static inline float smoothstep(
float edge0,
float edge1,
float x)
295 t =
av_clipf((x - edge0) / (edge1 - edge0), 0.
f, 1.
f);
297 return t * t * (3.f - 2.f * t);
300 #define FADE_TRANSITION(name, type, div) \
301 static void fade##name##_transition(AVFilterContext *ctx, \
302 const AVFrame *a, const AVFrame *b, AVFrame *out, \
304 int slice_start, int slice_end, int jobnr) \
306 XFadeContext *s = ctx->priv; \
307 const int height = slice_end - slice_start; \
308 const int width = out->width; \
310 for (int p = 0; p < s->nb_planes; p++) { \
311 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
312 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
313 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
315 for (int y = 0; y < height; y++) { \
316 for (int x = 0; x < width; x++) { \
317 dst[x] = mix(xf0[x], xf1[x], progress); \
320 dst += out->linesize[p] / div; \
321 xf0 += a->linesize[p] / div; \
322 xf1 += b->linesize[p] / div; \
330 #define WIPELEFT_TRANSITION(name, type, div) \
331 static void wipeleft##name##_transition(AVFilterContext *ctx, \
332 const AVFrame *a, const AVFrame *b, AVFrame *out, \
334 int slice_start, int slice_end, int jobnr) \
336 XFadeContext *s = ctx->priv; \
337 const int height = slice_end - slice_start; \
338 const int width = out->width; \
339 const int z = width * progress; \
341 for (int p = 0; p < s->nb_planes; p++) { \
342 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
343 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
344 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
346 for (int y = 0; y < height; y++) { \
347 for (int x = 0; x < width; x++) { \
348 dst[x] = x > z ? xf1[x] : xf0[x]; \
351 dst += out->linesize[p] / div; \
352 xf0 += a->linesize[p] / div; \
353 xf1 += b->linesize[p] / div; \
361 #define WIPERIGHT_TRANSITION(name, type, div) \
362 static void wiperight##name##_transition(AVFilterContext *ctx, \
363 const AVFrame *a, const AVFrame *b, AVFrame *out, \
365 int slice_start, int slice_end, int jobnr) \
367 XFadeContext *s = ctx->priv; \
368 const int height = slice_end - slice_start; \
369 const int width = out->width; \
370 const int z = width * (1.f - progress); \
372 for (int p = 0; p < s->nb_planes; p++) { \
373 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
374 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
375 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
377 for (int y = 0; y < height; y++) { \
378 for (int x = 0; x < width; x++) { \
379 dst[x] = x > z ? xf0[x] : xf1[x]; \
382 dst += out->linesize[p] / div; \
383 xf0 += a->linesize[p] / div; \
384 xf1 += b->linesize[p] / div; \
392 #define WIPEUP_TRANSITION(name, type, div) \
393 static void wipeup##name##_transition(AVFilterContext *ctx, \
394 const AVFrame *a, const AVFrame *b, AVFrame *out, \
396 int slice_start, int slice_end, int jobnr) \
398 XFadeContext *s = ctx->priv; \
399 const int height = slice_end - slice_start; \
400 const int width = out->width; \
401 const int z = out->height * progress; \
403 for (int p = 0; p < s->nb_planes; p++) { \
404 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
405 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
406 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
408 for (int y = 0; y < height; y++) { \
409 for (int x = 0; x < width; x++) { \
410 dst[x] = slice_start + y > z ? xf1[x] : xf0[x]; \
413 dst += out->linesize[p] / div; \
414 xf0 += a->linesize[p] / div; \
415 xf1 += b->linesize[p] / div; \
423 #define WIPEDOWN_TRANSITION(name, type, div) \
424 static void wipedown##name##_transition(AVFilterContext *ctx, \
425 const AVFrame *a, const AVFrame *b, AVFrame *out, \
427 int slice_start, int slice_end, int jobnr) \
429 XFadeContext *s = ctx->priv; \
430 const int height = slice_end - slice_start; \
431 const int width = out->width; \
432 const int z = out->height * (1.f - progress); \
434 for (int p = 0; p < s->nb_planes; p++) { \
435 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
436 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
437 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
439 for (int y = 0; y < height; y++) { \
440 for (int x = 0; x < width; x++) { \
441 dst[x] = slice_start + y > z ? xf0[x] : xf1[x]; \
444 dst += out->linesize[p] / div; \
445 xf0 += a->linesize[p] / div; \
446 xf1 += b->linesize[p] / div; \
454 #define SLIDELEFT_TRANSITION(name, type, div) \
455 static void slideleft##name##_transition(AVFilterContext *ctx, \
456 const AVFrame *a, const AVFrame *b, AVFrame *out, \
458 int slice_start, int slice_end, int jobnr) \
460 XFadeContext *s = ctx->priv; \
461 const int height = slice_end - slice_start; \
462 const int width = out->width; \
463 const int z = -progress * width; \
465 for (int p = 0; p < s->nb_planes; p++) { \
466 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
467 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
468 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
470 for (int y = 0; y < height; y++) { \
471 for (int x = 0; x < width; x++) { \
472 const int zx = z + x; \
473 const int zz = zx % width + width * (zx < 0); \
474 dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \
477 dst += out->linesize[p] / div; \
478 xf0 += a->linesize[p] / div; \
479 xf1 += b->linesize[p] / div; \
487 #define SLIDERIGHT_TRANSITION(name, type, div) \
488 static void slideright##name##_transition(AVFilterContext *ctx, \
489 const AVFrame *a, const AVFrame *b, AVFrame *out, \
491 int slice_start, int slice_end, int jobnr) \
493 XFadeContext *s = ctx->priv; \
494 const int height = slice_end - slice_start; \
495 const int width = out->width; \
496 const int z = progress * width; \
498 for (int p = 0; p < s->nb_planes; p++) { \
499 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
500 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
501 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
503 for (int y = 0; y < height; y++) { \
504 for (int x = 0; x < width; x++) { \
505 const int zx = z + x; \
506 const int zz = zx % width + width * (zx < 0); \
507 dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \
510 dst += out->linesize[p] / div; \
511 xf0 += a->linesize[p] / div; \
512 xf1 += b->linesize[p] / div; \
520 #define SLIDEUP_TRANSITION(name, type, div) \
521 static void slideup##name##_transition(AVFilterContext *ctx, \
522 const AVFrame *a, const AVFrame *b, AVFrame *out, \
524 int slice_start, int slice_end, int jobnr) \
526 XFadeContext *s = ctx->priv; \
527 const int height = out->height; \
528 const int width = out->width; \
529 const int z = -progress * height; \
531 for (int p = 0; p < s->nb_planes; p++) { \
532 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
534 for (int y = slice_start; y < slice_end; y++) { \
535 const int zy = z + y; \
536 const int zz = zy % height + height * (zy < 0); \
537 const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
538 const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
540 for (int x = 0; x < width; x++) { \
541 dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
544 dst += out->linesize[p] / div; \
552 #define SLIDEDOWN_TRANSITION(name, type, div) \
553 static void slidedown##name##_transition(AVFilterContext *ctx, \
554 const AVFrame *a, const AVFrame *b, AVFrame *out, \
556 int slice_start, int slice_end, int jobnr) \
558 XFadeContext *s = ctx->priv; \
559 const int height = out->height; \
560 const int width = out->width; \
561 const int z = progress * height; \
563 for (int p = 0; p < s->nb_planes; p++) { \
564 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
566 for (int y = slice_start; y < slice_end; y++) { \
567 const int zy = z + y; \
568 const int zz = zy % height + height * (zy < 0); \
569 const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
570 const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
572 for (int x = 0; x < width; x++) { \
573 dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
576 dst += out->linesize[p] / div; \
584 #define CIRCLECROP_TRANSITION(name, type, div) \
585 static void circlecrop##name##_transition(AVFilterContext *ctx, \
586 const AVFrame *a, const AVFrame *b, AVFrame *out, \
588 int slice_start, int slice_end, int jobnr) \
590 XFadeContext *s = ctx->priv; \
591 const int width = out->width; \
592 const int height = out->height; \
593 float z = powf(2.f * fabsf(progress - 0.5f), 3.f) * hypotf(width/2, height/2); \
595 for (int p = 0; p < s->nb_planes; p++) { \
596 const int bg = s->black[p]; \
597 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
599 for (int y = slice_start; y < slice_end; y++) { \
600 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
601 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
603 for (int x = 0; x < width; x++) { \
604 float dist = hypotf(x - width / 2, y - height / 2); \
605 int val = progress < 0.5f ? xf1[x] : xf0[x]; \
606 dst[x] = (z < dist) ? bg : val; \
609 dst += out->linesize[p] / div; \
617 #define RECTCROP_TRANSITION(name, type, div) \
618 static void rectcrop##name##_transition(AVFilterContext *ctx, \
619 const AVFrame *a, const AVFrame *b, AVFrame *out, \
621 int slice_start, int slice_end, int jobnr) \
623 XFadeContext *s = ctx->priv; \
624 const int width = out->width; \
625 const int height = out->height; \
626 int zh = fabsf(progress - 0.5f) * height; \
627 int zw = fabsf(progress - 0.5f) * width; \
629 for (int p = 0; p < s->nb_planes; p++) { \
630 const int bg = s->black[p]; \
631 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
633 for (int y = slice_start; y < slice_end; y++) { \
634 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
635 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
637 for (int x = 0; x < width; x++) { \
638 int dist = FFABS(x - width / 2) < zw && \
639 FFABS(y - height / 2) < zh; \
640 int val = progress < 0.5f ? xf1[x] : xf0[x]; \
641 dst[x] = !dist ? bg : val; \
644 dst += out->linesize[p] / div; \
652 #define DISTANCE_TRANSITION(name, type, div) \
653 static void distance##name##_transition(AVFilterContext *ctx, \
654 const AVFrame *a, const AVFrame *b, AVFrame *out, \
656 int slice_start, int slice_end, int jobnr) \
658 XFadeContext *s = ctx->priv; \
659 const int width = out->width; \
660 const float max = s->max_value; \
662 for (int y = slice_start; y < slice_end; y++) { \
663 for (int x = 0; x < width; x++) { \
665 for (int p = 0; p < s->nb_planes; p++) { \
666 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
667 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
669 dist += (xf0[x] / max - xf1[x] / max) * \
670 (xf0[x] / max - xf1[x] / max); \
673 dist = sqrtf(dist) <= progress; \
674 for (int p = 0; p < s->nb_planes; p++) { \
675 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
676 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
677 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
678 dst[x] = mix(mix(xf0[x], xf1[x], dist), xf1[x], progress); \
687 #define FADEBLACK_TRANSITION(name, type, div) \
688 static void fadeblack##name##_transition(AVFilterContext *ctx, \
689 const AVFrame *a, const AVFrame *b, AVFrame *out, \
691 int slice_start, int slice_end, int jobnr) \
693 XFadeContext *s = ctx->priv; \
694 const int height = slice_end - slice_start; \
695 const int width = out->width; \
696 const float phase = 0.2f; \
698 for (int p = 0; p < s->nb_planes; p++) { \
699 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
700 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
701 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
702 const int bg = s->black[p]; \
704 for (int y = 0; y < height; y++) { \
705 for (int x = 0; x < width; x++) { \
706 dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \
707 mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \
711 dst += out->linesize[p] / div; \
712 xf0 += a->linesize[p] / div; \
713 xf1 += b->linesize[p] / div; \
721 #define FADEWHITE_TRANSITION(name, type, div) \
722 static void fadewhite##name##_transition(AVFilterContext *ctx, \
723 const AVFrame *a, const AVFrame *b, AVFrame *out, \
725 int slice_start, int slice_end, int jobnr) \
727 XFadeContext *s = ctx->priv; \
728 const int height = slice_end - slice_start; \
729 const int width = out->width; \
730 const float phase = 0.2f; \
732 for (int p = 0; p < s->nb_planes; p++) { \
733 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
734 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
735 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
736 const int bg = s->white[p]; \
738 for (int y = 0; y < height; y++) { \
739 for (int x = 0; x < width; x++) { \
740 dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \
741 mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \
745 dst += out->linesize[p] / div; \
746 xf0 += a->linesize[p] / div; \
747 xf1 += b->linesize[p] / div; \
755 #define RADIAL_TRANSITION(name, type, div) \
756 static void radial##name##_transition(AVFilterContext *ctx, \
757 const AVFrame *a, const AVFrame *b, AVFrame *out, \
759 int slice_start, int slice_end, int jobnr) \
761 XFadeContext *s = ctx->priv; \
762 const int width = out->width; \
763 const int height = out->height; \
765 for (int y = slice_start; y < slice_end; y++) { \
766 for (int x = 0; x < width; x++) { \
767 const float smooth = atan2f(x - width / 2, y - height / 2) - \
768 (progress - 0.5f) * (M_PI * 2.5f); \
769 for (int p = 0; p < s->nb_planes; p++) { \
770 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
771 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
772 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
774 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
783 #define SMOOTHLEFT_TRANSITION(name, type, div) \
784 static void smoothleft##name##_transition(AVFilterContext *ctx, \
785 const AVFrame *a, const AVFrame *b, AVFrame *out, \
787 int slice_start, int slice_end, int jobnr) \
789 XFadeContext *s = ctx->priv; \
790 const int width = out->width; \
791 const float w = width; \
793 for (int y = slice_start; y < slice_end; y++) { \
794 for (int x = 0; x < width; x++) { \
795 const float smooth = 1.f + x / w - progress * 2.f; \
797 for (int p = 0; p < s->nb_planes; p++) { \
798 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
799 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
800 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
802 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
811 #define SMOOTHRIGHT_TRANSITION(name, type, div) \
812 static void smoothright##name##_transition(AVFilterContext *ctx, \
813 const AVFrame *a, const AVFrame *b, AVFrame *out, \
815 int slice_start, int slice_end, int jobnr) \
817 XFadeContext *s = ctx->priv; \
818 const int width = out->width; \
819 const float w = width; \
821 for (int y = slice_start; y < slice_end; y++) { \
822 for (int x = 0; x < width; x++) { \
823 const float smooth = 1.f + (w - 1 - x) / w - progress * 2.f; \
825 for (int p = 0; p < s->nb_planes; p++) { \
826 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
827 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
828 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
830 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
839 #define SMOOTHUP_TRANSITION(name, type, div) \
840 static void smoothup##name##_transition(AVFilterContext *ctx, \
841 const AVFrame *a, const AVFrame *b, AVFrame *out, \
843 int slice_start, int slice_end, int jobnr) \
845 XFadeContext *s = ctx->priv; \
846 const int width = out->width; \
847 const float h = out->height; \
849 for (int y = slice_start; y < slice_end; y++) { \
850 const float smooth = 1.f + y / h - progress * 2.f; \
851 for (int x = 0; x < width; x++) { \
852 for (int p = 0; p < s->nb_planes; p++) { \
853 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
854 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
855 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
857 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
866 #define SMOOTHDOWN_TRANSITION(name, type, div) \
867 static void smoothdown##name##_transition(AVFilterContext *ctx, \
868 const AVFrame *a, const AVFrame *b, AVFrame *out, \
870 int slice_start, int slice_end, int jobnr) \
872 XFadeContext *s = ctx->priv; \
873 const int width = out->width; \
874 const float h = out->height; \
876 for (int y = slice_start; y < slice_end; y++) { \
877 const float smooth = 1.f + (h - 1 - y) / h - progress * 2.f; \
878 for (int x = 0; x < width; x++) { \
879 for (int p = 0; p < s->nb_planes; p++) { \
880 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
881 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
882 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
884 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
893 #define CIRCLEOPEN_TRANSITION(name, type, div) \
894 static void circleopen##name##_transition(AVFilterContext *ctx, \
895 const AVFrame *a, const AVFrame *b, AVFrame *out, \
897 int slice_start, int slice_end, int jobnr) \
899 XFadeContext *s = ctx->priv; \
900 const int width = out->width; \
901 const int height = out->height; \
902 const float z = hypotf(width / 2, height / 2); \
903 const float p = (progress - 0.5f) * 3.f; \
905 for (int y = slice_start; y < slice_end; y++) { \
906 for (int x = 0; x < width; x++) { \
907 const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \
908 for (int p = 0; p < s->nb_planes; p++) { \
909 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
910 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
911 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
913 dst[x] = mix(xf0[x], xf1[x], smoothstep(0.f, 1.f, smooth)); \
922 #define CIRCLECLOSE_TRANSITION(name, type, div) \
923 static void circleclose##name##_transition(AVFilterContext *ctx, \
924 const AVFrame *a, const AVFrame *b, AVFrame *out, \
926 int slice_start, int slice_end, int jobnr) \
928 XFadeContext *s = ctx->priv; \
929 const int width = out->width; \
930 const int height = out->height; \
931 const float z = hypotf(width / 2, height / 2); \
932 const float p = (1.f - progress - 0.5f) * 3.f; \
934 for (int y = slice_start; y < slice_end; y++) { \
935 for (int x = 0; x < width; x++) { \
936 const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \
937 for (int p = 0; p < s->nb_planes; p++) { \
938 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
939 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
940 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
942 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
951 #define VERTOPEN_TRANSITION(name, type, div) \
952 static void vertopen##name##_transition(AVFilterContext *ctx, \
953 const AVFrame *a, const AVFrame *b, AVFrame *out, \
955 int slice_start, int slice_end, int jobnr) \
957 XFadeContext *s = ctx->priv; \
958 const int width = out->width; \
959 const float w2 = out->width / 2; \
961 for (int y = slice_start; y < slice_end; y++) { \
962 for (int x = 0; x < width; x++) { \
963 const float smooth = 2.f - fabsf((x - w2) / w2) - progress * 2.f; \
964 for (int p = 0; p < s->nb_planes; p++) { \
965 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
966 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
967 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
969 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
978 #define VERTCLOSE_TRANSITION(name, type, div) \
979 static void vertclose##name##_transition(AVFilterContext *ctx, \
980 const AVFrame *a, const AVFrame *b, AVFrame *out, \
982 int slice_start, int slice_end, int jobnr) \
984 XFadeContext *s = ctx->priv; \
985 const int nb_planes = s->nb_planes; \
986 const int width = out->width; \
987 const float w2 = out->width / 2; \
989 for (int y = slice_start; y < slice_end; y++) { \
990 for (int x = 0; x < width; x++) { \
991 const float smooth = 1.f + fabsf((x - w2) / w2) - progress * 2.f; \
992 for (int p = 0; p < nb_planes; p++) { \
993 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
994 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
995 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
997 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1006 #define HORZOPEN_TRANSITION(name, type, div) \
1007 static void horzopen##name##_transition(AVFilterContext *ctx, \
1008 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1010 int slice_start, int slice_end, int jobnr) \
1012 XFadeContext *s = ctx->priv; \
1013 const int nb_planes = s->nb_planes; \
1014 const int width = out->width; \
1015 const float h2 = out->height / 2; \
1017 for (int y = slice_start; y < slice_end; y++) { \
1018 const float smooth = 2.f - fabsf((y - h2) / h2) - progress * 2.f; \
1019 for (int x = 0; x < width; x++) { \
1020 for (int p = 0; p < nb_planes; p++) { \
1021 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1022 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1023 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1025 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1034 #define HORZCLOSE_TRANSITION(name, type, div) \
1035 static void horzclose##name##_transition(AVFilterContext *ctx, \
1036 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1038 int slice_start, int slice_end, int jobnr) \
1040 XFadeContext *s = ctx->priv; \
1041 const int nb_planes = s->nb_planes; \
1042 const int width = out->width; \
1043 const float h2 = out->height / 2; \
1045 for (int y = slice_start; y < slice_end; y++) { \
1046 const float smooth = 1.f + fabsf((y - h2) / h2) - progress * 2.f; \
1047 for (int x = 0; x < width; x++) { \
1048 for (int p = 0; p < nb_planes; p++) { \
1049 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1050 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1051 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1053 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1064 const float r =
sinf(x * 12.9898
f + y * 78.233
f) * 43758.545f;
1069 #define DISSOLVE_TRANSITION(name, type, div) \
1070 static void dissolve##name##_transition(AVFilterContext *ctx, \
1071 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1073 int slice_start, int slice_end, int jobnr) \
1075 XFadeContext *s = ctx->priv; \
1076 const int nb_planes = s->nb_planes; \
1077 const int width = out->width; \
1079 for (int y = slice_start; y < slice_end; y++) { \
1080 for (int x = 0; x < width; x++) { \
1081 const float smooth = frand(x, y) * 2.f + progress * 2.f - 1.5f; \
1082 for (int p = 0; p < nb_planes; p++) { \
1083 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1084 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1085 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1087 dst[x] = smooth >= 0.5f ? xf0[x] : xf1[x]; \
1096 #define PIXELIZE_TRANSITION(name, type, div) \
1097 static void pixelize##name##_transition(AVFilterContext *ctx, \
1098 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1100 int slice_start, int slice_end, int jobnr) \
1102 XFadeContext *s = ctx->priv; \
1103 const int nb_planes = s->nb_planes; \
1104 const int w = out->width; \
1105 const int h = out->height; \
1106 const float d = fminf(progress, 1.f - progress); \
1107 const float dist = ceilf(d * 50.f) / 50.f; \
1108 const float sqx = 2.f * dist * FFMIN(w, h) / 20.f; \
1109 const float sqy = 2.f * dist * FFMIN(w, h) / 20.f; \
1111 for (int y = slice_start; y < slice_end; y++) { \
1112 for (int x = 0; x < w; x++) { \
1113 int sx = dist > 0.f ? FFMIN((floorf(x / sqx) + .5f) * sqx, w - 1) : x; \
1114 int sy = dist > 0.f ? FFMIN((floorf(y / sqy) + .5f) * sqy, h - 1) : y; \
1115 for (int p = 0; p < nb_planes; p++) { \
1116 const type *xf0 = (const type *)(a->data[p] + sy * a->linesize[p]); \
1117 const type *xf1 = (const type *)(b->data[p] + sy * b->linesize[p]); \
1118 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1120 dst[x] = mix(xf0[sx], xf1[sx], progress); \
1129 #define DIAGTL_TRANSITION(name, type, div) \
1130 static void diagtl##name##_transition(AVFilterContext *ctx, \
1131 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1133 int slice_start, int slice_end, int jobnr) \
1135 XFadeContext *s = ctx->priv; \
1136 const int nb_planes = s->nb_planes; \
1137 const int width = out->width; \
1138 const float w = width; \
1139 const float h = out->height; \
1141 for (int y = slice_start; y < slice_end; y++) { \
1142 for (int x = 0; x < width; x++) { \
1143 const float smooth = 1.f + x / w * y / h - progress * 2.f; \
1145 for (int p = 0; p < nb_planes; p++) { \
1146 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1147 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1148 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1150 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1159 #define DIAGTR_TRANSITION(name, type, div) \
1160 static void diagtr##name##_transition(AVFilterContext *ctx, \
1161 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1163 int slice_start, int slice_end, int jobnr) \
1165 XFadeContext *s = ctx->priv; \
1166 const int nb_planes = s->nb_planes; \
1167 const int width = out->width; \
1168 const float w = width; \
1169 const float h = out->height; \
1171 for (int y = slice_start; y < slice_end; y++) { \
1172 for (int x = 0; x < width; x++) { \
1173 const float smooth = 1.f + (w - 1 - x) / w * y / h - progress * 2.f; \
1175 for (int p = 0; p < nb_planes; p++) { \
1176 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1177 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1178 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1180 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1189 #define DIAGBL_TRANSITION(name, type, div) \
1190 static void diagbl##name##_transition(AVFilterContext *ctx, \
1191 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1193 int slice_start, int slice_end, int jobnr) \
1195 XFadeContext *s = ctx->priv; \
1196 const int nb_planes = s->nb_planes; \
1197 const int width = out->width; \
1198 const float w = width; \
1199 const float h = out->height; \
1201 for (int y = slice_start; y < slice_end; y++) { \
1202 for (int x = 0; x < width; x++) { \
1203 const float smooth = 1.f + x / w * (h - 1 - y) / h - progress * 2.f; \
1205 for (int p = 0; p < nb_planes; p++) { \
1206 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1207 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1208 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1210 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1219 #define DIAGBR_TRANSITION(name, type, div) \
1220 static void diagbr##name##_transition(AVFilterContext *ctx, \
1221 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1223 int slice_start, int slice_end, int jobnr) \
1225 XFadeContext *s = ctx->priv; \
1226 const int nb_planes = s->nb_planes; \
1227 const int width = out->width; \
1228 const float w = width; \
1229 const float h = out->height; \
1231 for (int y = slice_start; y < slice_end; y++) { \
1232 for (int x = 0; x < width; x++) { \
1233 const float smooth = 1.f + (w - 1 - x) / w * (h - 1 - y) / h - \
1236 for (int p = 0; p < nb_planes; p++) { \
1237 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1238 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1239 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1241 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1250 #define HLSLICE_TRANSITION(name, type, div) \
1251 static void hlslice##name##_transition(AVFilterContext *ctx, \
1252 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1254 int slice_start, int slice_end, int jobnr) \
1256 XFadeContext *s = ctx->priv; \
1257 const int nb_planes = s->nb_planes; \
1258 const int width = out->width; \
1259 const float w = width; \
1261 for (int y = slice_start; y < slice_end; y++) { \
1262 for (int x = 0; x < width; x++) { \
1263 const float smooth = smoothstep(-0.5f, 0.f, x / w - progress * 1.5f); \
1264 const float ss = smooth <= fract(10.f * x / w) ? 0.f : 1.f; \
1266 for (int p = 0; p < nb_planes; p++) { \
1267 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1268 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1269 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1271 dst[x] = mix(xf1[x], xf0[x], ss); \
1280 #define HRSLICE_TRANSITION(name, type, div) \
1281 static void hrslice##name##_transition(AVFilterContext *ctx, \
1282 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1284 int slice_start, int slice_end, int jobnr) \
1286 XFadeContext *s = ctx->priv; \
1287 const int nb_planes = s->nb_planes; \
1288 const int width = out->width; \
1289 const float w = width; \
1291 for (int y = slice_start; y < slice_end; y++) { \
1292 for (int x = 0; x < width; x++) { \
1293 const float xx = (w - 1 - x) / w; \
1294 const float smooth = smoothstep(-0.5f, 0.f, xx - progress * 1.5f); \
1295 const float ss = smooth <= fract(10.f * xx) ? 0.f : 1.f; \
1297 for (int p = 0; p < nb_planes; p++) { \
1298 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1299 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1300 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1302 dst[x] = mix(xf1[x], xf0[x], ss); \
1311 #define VUSLICE_TRANSITION(name, type, div) \
1312 static void vuslice##name##_transition(AVFilterContext *ctx, \
1313 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1315 int slice_start, int slice_end, int jobnr) \
1317 XFadeContext *s = ctx->priv; \
1318 const int nb_planes = s->nb_planes; \
1319 const int width = out->width; \
1320 const float h = out->height; \
1322 for (int y = slice_start; y < slice_end; y++) { \
1323 const float smooth = smoothstep(-0.5f, 0.f, y / h - progress * 1.5f); \
1324 const float ss = smooth <= fract(10.f * y / h) ? 0.f : 1.f; \
1326 for (int x = 0; x < width; x++) { \
1327 for (int p = 0; p < nb_planes; p++) { \
1328 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1329 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1330 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1332 dst[x] = mix(xf1[x], xf0[x], ss); \
1341 #define VDSLICE_TRANSITION(name, type, div) \
1342 static void vdslice##name##_transition(AVFilterContext *ctx, \
1343 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1345 int slice_start, int slice_end, int jobnr) \
1347 XFadeContext *s = ctx->priv; \
1348 const int nb_planes = s->nb_planes; \
1349 const int width = out->width; \
1350 const float h = out->height; \
1352 for (int y = slice_start; y < slice_end; y++) { \
1353 const float yy = (h - 1 - y) / h; \
1354 const float smooth = smoothstep(-0.5f, 0.f, yy - progress * 1.5f); \
1355 const float ss = smooth <= fract(10.f * yy) ? 0.f : 1.f; \
1357 for (int x = 0; x < width; x++) { \
1358 for (int p = 0; p < nb_planes; p++) { \
1359 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1360 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1361 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1363 dst[x] = mix(xf1[x], xf0[x], ss); \
1372 #define HBLUR_TRANSITION(name, type, div) \
1373 static void hblur##name##_transition(AVFilterContext *ctx, \
1374 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1376 int slice_start, int slice_end, int jobnr) \
1378 XFadeContext *s = ctx->priv; \
1379 const int nb_planes = s->nb_planes; \
1380 const int width = out->width; \
1381 const float prog = progress <= 0.5f ? progress * 2.f : (1.f - progress) * 2.f; \
1382 const int size = 1 + (width / 2) * prog; \
1384 for (int y = slice_start; y < slice_end; y++) { \
1385 for (int p = 0; p < nb_planes; p++) { \
1386 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1387 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1388 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1393 for (int x = 0; x < size; x++) { \
1398 for (int x = 0; x < width; x++) { \
1399 dst[x] = mix(sum0 / cnt, sum1 / cnt, progress); \
1401 if (x + size < width) { \
1402 sum0 += xf0[x + size] - xf0[x]; \
1403 sum1 += xf1[x + size] - xf1[x]; \
1417 #define FADEGRAYS_TRANSITION(name, type, div) \
1418 static void fadegrays##name##_transition(AVFilterContext *ctx, \
1419 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1421 int slice_start, int slice_end, int jobnr) \
1423 XFadeContext *s = ctx->priv; \
1424 const int width = out->width; \
1425 const int is_rgb = s->is_rgb; \
1426 const int mid = (s->max_value + 1) / 2; \
1427 const float phase = 0.2f; \
1429 for (int y = slice_start; y < slice_end; y++) { \
1430 for (int x = 0; x < width; x++) { \
1433 bg[0][0] = bg[1][0] = 0; \
1434 for (int p = 0; p < s->nb_planes; p++) { \
1435 const type *xf0 = (const type *)(a->data[p] + \
1436 y * a->linesize[p]); \
1437 const type *xf1 = (const type *)(b->data[p] + \
1438 y * b->linesize[p]); \
1440 bg[0][3] = xf0[x]; \
1441 bg[1][3] = xf1[x]; \
1443 bg[0][0] += xf0[x]; \
1444 bg[1][0] += xf1[x]; \
1447 bg[0][0] = bg[0][0] / 3; \
1448 bg[1][0] = bg[1][0] / 3; \
1449 bg[0][1] = bg[0][2] = bg[0][0]; \
1450 bg[1][1] = bg[1][2] = bg[1][0]; \
1452 const type *yf0 = (const type *)(a->data[0] + \
1453 y * a->linesize[0]); \
1454 const type *yf1 = (const type *)(b->data[0] + \
1455 y * a->linesize[0]); \
1456 bg[0][0] = yf0[x]; \
1457 bg[1][0] = yf1[x]; \
1458 if (s->nb_planes == 4) { \
1459 const type *af0 = (const type *)(a->data[3] + \
1460 y * a->linesize[3]); \
1461 const type *af1 = (const type *)(b->data[3] + \
1462 y * a->linesize[3]); \
1463 bg[0][3] = af0[x]; \
1464 bg[1][3] = af1[x]; \
1466 bg[0][1] = bg[1][1] = mid; \
1467 bg[0][2] = bg[1][2] = mid; \
1470 for (int p = 0; p < s->nb_planes; p++) { \
1471 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1472 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1473 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1475 dst[x] = mix(mix(xf0[x], bg[0][p], \
1476 smoothstep(1.f-phase, 1.f, progress)), \
1477 mix(bg[1][p], xf1[x], smoothstep(phase, 1.f, progress)), \
1487 #define WIPETL_TRANSITION(name, type, div) \
1488 static void wipetl##name##_transition(AVFilterContext *ctx, \
1489 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1491 int slice_start, int slice_end, int jobnr) \
1493 XFadeContext *s = ctx->priv; \
1494 const int height = slice_end - slice_start; \
1495 const int width = out->width; \
1496 const int zw = out->width * progress; \
1497 const int zh = out->height * progress; \
1499 for (int p = 0; p < s->nb_planes; p++) { \
1500 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1501 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1502 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1504 for (int y = 0; y < height; y++) { \
1505 for (int x = 0; x < width; x++) { \
1506 dst[x] = slice_start + y <= zh && \
1507 x <= zw ? xf0[x] : xf1[x]; \
1510 dst += out->linesize[p] / div; \
1511 xf0 += a->linesize[p] / div; \
1512 xf1 += b->linesize[p] / div; \
1520 #define WIPETR_TRANSITION(name, type, div) \
1521 static void wipetr##name##_transition(AVFilterContext *ctx, \
1522 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1524 int slice_start, int slice_end, int jobnr) \
1526 XFadeContext *s = ctx->priv; \
1527 const int height = slice_end - slice_start; \
1528 const int width = out->width; \
1529 const int zw = width * (1.f - progress); \
1530 const int zh = out->height * progress; \
1532 for (int p = 0; p < s->nb_planes; p++) { \
1533 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1534 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1535 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1537 for (int y = 0; y < height; y++) { \
1538 for (int x = 0; x < width; x++) { \
1539 dst[x] = slice_start + y <= zh && \
1540 x > zw ? xf0[x] : xf1[x]; \
1543 dst += out->linesize[p] / div; \
1544 xf0 += a->linesize[p] / div; \
1545 xf1 += b->linesize[p] / div; \
1553 #define WIPEBL_TRANSITION(name, type, div) \
1554 static void wipebl##name##_transition(AVFilterContext *ctx, \
1555 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1557 int slice_start, int slice_end, int jobnr) \
1559 XFadeContext *s = ctx->priv; \
1560 const int height = slice_end - slice_start; \
1561 const int width = out->width; \
1562 const int zw = width * progress; \
1563 const int zh = out->height * (1.f - progress); \
1565 for (int p = 0; p < s->nb_planes; p++) { \
1566 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1567 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1568 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1570 for (int y = 0; y < height; y++) { \
1571 for (int x = 0; x < width; x++) { \
1572 dst[x] = slice_start + y > zh && \
1573 x <= zw ? xf0[x] : xf1[x]; \
1576 dst += out->linesize[p] / div; \
1577 xf0 += a->linesize[p] / div; \
1578 xf1 += b->linesize[p] / div; \
1586 #define WIPEBR_TRANSITION(name, type, div) \
1587 static void wipebr##name##_transition(AVFilterContext *ctx, \
1588 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1590 int slice_start, int slice_end, int jobnr) \
1592 XFadeContext *s = ctx->priv; \
1593 const int height = slice_end - slice_start; \
1594 const int zh = out->height * (1.f - progress); \
1595 const int width = out->width; \
1596 const int zw = width * (1.f - progress); \
1598 for (int p = 0; p < s->nb_planes; p++) { \
1599 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1600 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1601 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1603 for (int y = 0; y < height; y++) { \
1604 for (int x = 0; x < width; x++) { \
1605 dst[x] = slice_start + y > zh && \
1606 x > zw ? xf0[x] : xf1[x]; \
1609 dst += out->linesize[p] / div; \
1610 xf0 += a->linesize[p] / div; \
1611 xf1 += b->linesize[p] / div; \
1619 #define SQUEEZEH_TRANSITION(name, type, div) \
1620 static void squeezeh##name##_transition(AVFilterContext *ctx, \
1621 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1623 int slice_start, int slice_end, int jobnr) \
1625 XFadeContext *s = ctx->priv; \
1626 const float h = out->height; \
1627 const int height = slice_end - slice_start; \
1628 const int width = out->width; \
1630 for (int p = 0; p < s->nb_planes; p++) { \
1631 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1632 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1634 for (int y = 0; y < height; y++) { \
1635 const float z = .5f + ((slice_start + y) / h - .5f) / progress; \
1637 if (z < 0.f || z > 1.f) { \
1638 for (int x = 0; x < width; x++) \
1641 const int yy = lrintf(z * (h - 1.f)); \
1642 const type *xf0 = (const type *)(a->data[p] + yy * a->linesize[p]); \
1644 for (int x = 0; x < width; x++) \
1648 dst += out->linesize[p] / div; \
1649 xf1 += b->linesize[p] / div; \
1657 #define SQUEEZEV_TRANSITION(name, type, div) \
1658 static void squeezev##name##_transition(AVFilterContext *ctx, \
1659 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1661 int slice_start, int slice_end, int jobnr) \
1663 XFadeContext *s = ctx->priv; \
1664 const int width = out->width; \
1665 const float w = width; \
1666 const int height = slice_end - slice_start; \
1668 for (int p = 0; p < s->nb_planes; p++) { \
1669 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1670 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1671 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1673 for (int y = 0; y < height; y++) { \
1674 for (int x = 0; x < width; x++) { \
1675 const float z = .5f + (x / w - .5f) / progress; \
1677 if (z < 0.f || z > 1.f) { \
1680 const int xx = lrintf(z * (w - 1.f)); \
1686 dst += out->linesize[p] / div; \
1687 xf0 += a->linesize[p] / div; \
1688 xf1 += b->linesize[p] / div; \
1696 static
void zoom(
float *
u,
float *v,
float amount)
1698 *
u = 0.5f + ((*
u - 0.5f) * amount);
1699 *v = 0.5f + ((*v - 0.5f) * amount);
1702 #define ZOOMIN_TRANSITION(name, type, div) \
1703 static void zoomin##name##_transition(AVFilterContext *ctx, \
1704 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1706 int slice_start, int slice_end, int jobnr) \
1708 XFadeContext *s = ctx->priv; \
1709 const int width = out->width; \
1710 const float w = width; \
1711 const float h = out->height; \
1712 const float zf = smoothstep(0.5f, 1.f, progress); \
1714 for (int p = 0; p < s->nb_planes; p++) { \
1715 const type *xf0 = (const type *)(a->data[p]); \
1716 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1717 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1719 for (int y = slice_start; y < slice_end; y++) { \
1720 for (int x = 0; x < width; x++) { \
1727 iu = ceilf(u * (w - 1)); \
1728 iv = ceilf(v * (h - 1)); \
1729 zv = xf0[iu + iv * a->linesize[p] / div]; \
1730 dst[x] = mix(zv, xf1[x], smoothstep(0.f, 0.5f, progress)); \
1732 dst += out->linesize[p] / div; \
1733 xf1 += b->linesize[p] / div; \
1741 #define FADEFAST_TRANSITION(name, type, div) \
1742 static void fadefast##name##_transition(AVFilterContext *ctx, \
1743 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1745 int slice_start, int slice_end, int jobnr) \
1747 XFadeContext *s = ctx->priv; \
1748 const int height = slice_end - slice_start; \
1749 const int width = out->width; \
1750 const float imax = 1.f / s->max_value; \
1752 for (int p = 0; p < s->nb_planes; p++) { \
1753 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1754 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1755 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1757 for (int y = 0; y < height; y++) { \
1758 for (int x = 0; x < width; x++) { \
1759 dst[x] = mix(xf0[x], xf1[x], powf(progress, 1.f + \
1760 logf(1.f+FFABS(xf0[x]-xf1[x])*imax)\
1764 dst += out->linesize[p] / div; \
1765 xf0 += a->linesize[p] / div; \
1766 xf1 += b->linesize[p] / div; \
1774 #define FADESLOW_TRANSITION(name, type, div) \
1775 static void fadeslow##name##_transition(AVFilterContext *ctx, \
1776 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1778 int slice_start, int slice_end, int jobnr) \
1780 XFadeContext *s = ctx->priv; \
1781 const int height = slice_end - slice_start; \
1782 const int width = out->width; \
1783 const float imax = 1.f / s->max_value; \
1785 for (int p = 0; p < s->nb_planes; p++) { \
1786 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1787 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1788 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1790 for (int y = 0; y < height; y++) { \
1791 for (int x = 0; x < width; x++) { \
1792 dst[x] = mix(xf0[x], xf1[x], powf(progress, 1.f + \
1793 logf(2.f-FFABS(xf0[x]-xf1[x])*imax)\
1797 dst += out->linesize[p] / div; \
1798 xf0 += a->linesize[p] / div; \
1799 xf1 += b->linesize[p] / div; \
1807 #define HWIND_TRANSITION(name, z, type, div, expr) \
1808 static void h##z##wind##name##_transition(AVFilterContext *ctx, \
1809 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1811 int slice_start, int slice_end, int jobnr) \
1813 XFadeContext *s = ctx->priv; \
1814 const int width = out->width; \
1816 for (int y = slice_start; y < slice_end; y++) { \
1817 const float r = frand(0, y); \
1818 for (int x = 0; x < width; x++) { \
1819 const float fx = expr x / (float)width; \
1820 for (int p = 0; p < s->nb_planes; p++) { \
1821 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1822 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1823 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1825 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f,-0.2f, fx * (1.f - 0.2f)\
1826 + 0.2f * r - (1.f - progress)\
1838 #define VWIND_TRANSITION(name, z, type, div, expr) \
1839 static void v##z##wind##name##_transition(AVFilterContext *ctx, \
1840 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1842 int slice_start, int slice_end, int jobnr) \
1844 XFadeContext *s = ctx->priv; \
1845 const int width = out->width; \
1847 for (int y = slice_start; y < slice_end; y++) { \
1848 const float fy = expr y / (float)out->height; \
1849 for (int x = 0; x < width; x++) { \
1850 const float r = frand(x, 0); \
1851 for (int p = 0; p < s->nb_planes; p++) { \
1852 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1853 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1854 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1856 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f,-0.2f, fy * (1.f - 0.2f) \
1857 + 0.2f * r - (1.f - progress)\
1869 #define COVERH_TRANSITION(dir, name, type, div, expr) \
1870 static void cover##dir##name##_transition(AVFilterContext *ctx, \
1871 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1873 int slice_start, int slice_end, int jobnr) \
1875 XFadeContext *s = ctx->priv; \
1876 const int height = slice_end - slice_start; \
1877 const int width = out->width; \
1878 const int z = (expr progress) * width; \
1880 for (int p = 0; p < s->nb_planes; p++) { \
1881 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1882 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1883 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1885 for (int y = 0; y < height; y++) { \
1886 for (int x = 0; x < width; x++) { \
1887 const int zx = z + x; \
1888 const int zz = zx % width + width * (zx < 0); \
1889 dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[x]; \
1892 dst += out->linesize[p] / div; \
1893 xf0 += a->linesize[p] / div; \
1894 xf1 += b->linesize[p] / div; \
1904 #define COVERV_TRANSITION(dir, name, type, div, expr) \
1905 static void cover##dir##name##_transition(AVFilterContext *ctx, \
1906 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1908 int slice_start, int slice_end, int jobnr) \
1910 XFadeContext *s = ctx->priv; \
1911 const int height = out->height; \
1912 const int width = out->width; \
1913 const int z = (expr progress) * height; \
1915 for (int p = 0; p < s->nb_planes; p++) { \
1916 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1918 for (int y = slice_start; y < slice_end; y++) { \
1919 const int zy = z + y; \
1920 const int zz = zy % height + height * (zy < 0); \
1921 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1922 const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
1924 for (int x = 0; x < width; x++) \
1925 dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
1927 dst += out->linesize[p] / div; \
1937 #define REVEALH_TRANSITION(dir, name, type, div, expr) \
1938 static void reveal##dir##name##_transition(AVFilterContext *ctx, \
1939 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1941 int slice_start, int slice_end, int jobnr) \
1943 XFadeContext *s = ctx->priv; \
1944 const int height = slice_end - slice_start; \
1945 const int width = out->width; \
1946 const int z = (expr progress) * width; \
1948 for (int p = 0; p < s->nb_planes; p++) { \
1949 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
1950 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
1951 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1953 for (int y = 0; y < height; y++) { \
1954 for (int x = 0; x < width; x++) { \
1955 const int zx = z + x; \
1956 const int zz = zx % width + width * (zx < 0); \
1957 dst[x] = (zx >= 0) && (zx < width) ? xf1[x] : xf0[zz]; \
1960 dst += out->linesize[p] / div; \
1961 xf0 += a->linesize[p] / div; \
1962 xf1 += b->linesize[p] / div; \
1972 #define REVEALV_TRANSITION(dir, name, type, div, expr) \
1973 static void reveal##dir##name##_transition(AVFilterContext *ctx, \
1974 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1976 int slice_start, int slice_end, int jobnr) \
1978 XFadeContext *s = ctx->priv; \
1979 const int height = out->height; \
1980 const int width = out->width; \
1981 const int z = (expr progress) * height; \
1983 for (int p = 0; p < s->nb_planes; p++) { \
1984 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
1986 for (int y = slice_start; y < slice_end; y++) { \
1987 const int zy = z + y; \
1988 const int zz = zy % height + height * (zy < 0); \
1989 const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
1990 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1992 for (int x = 0; x < width; x++) \
1993 dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \
1995 dst += out->linesize[p] / div; \
2005 static inline
double getpix(
void *priv,
double x,
double y,
int plane,
int nb)
2009 const uint8_t *
src = in->
data[
FFMIN(plane,
s->nb_planes - 1)];
2020 const uint16_t *src16 = (
const uint16_t*)
src;
2023 return src16[
xi + yi * linesize];
2025 return src[
xi + yi * linesize];
2029 static double a0(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 0, 0); }
2030 static double a1(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 1, 0); }
2031 static double a2(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 2, 0); }
2032 static double a3(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 3, 0); }
2034 static double b0(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 0, 1); }
2035 static double b1(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 1, 1); }
2036 static double b2(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 2, 1); }
2037 static double b3(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 3, 1); }
2047 if (inlink0->
w != inlink1->
w || inlink0->
h != inlink1->
h) {
2049 "(size %dx%d) do not match the corresponding "
2050 "second input link %s parameters (size %dx%d)\n",
2051 ctx->input_pads[0].name, inlink0->
w, inlink0->
h,
2052 ctx->input_pads[1].name, inlink1->
w, inlink1->
h);
2059 "(%d/%d) do not match the corresponding "
2060 "second input link %s timebase (%d/%d)\n",
2075 "(%d/%d) do not match the corresponding "
2076 "second input link %s frame rate (%d/%d)\n",
2082 outlink->
w = inlink0->
w;
2083 outlink->
h = inlink0->
h;
2091 s->max_value = (1 <<
s->depth) - 1;
2093 s->black[1] =
s->black[2] =
s->is_rgb ? 0 :
s->max_value / 2;
2094 s->black[3] =
s->max_value;
2095 s->white[0] =
s->white[3] =
s->max_value;
2096 s->white[1] =
s->white[2] =
s->is_rgb ?
s->max_value :
s->max_value / 2;
2103 switch (
s->transition) {
2104 case CUSTOM:
s->transitionf =
s->depth <= 8 ? custom8_transition : custom16_transition;
break;
2105 case FADE:
s->transitionf =
s->depth <= 8 ? fade8_transition : fade16_transition;
break;
2106 case WIPELEFT:
s->transitionf =
s->depth <= 8 ? wipeleft8_transition : wipeleft16_transition;
break;
2107 case WIPERIGHT:
s->transitionf =
s->depth <= 8 ? wiperight8_transition : wiperight16_transition;
break;
2108 case WIPEUP:
s->transitionf =
s->depth <= 8 ? wipeup8_transition : wipeup16_transition;
break;
2109 case WIPEDOWN:
s->transitionf =
s->depth <= 8 ? wipedown8_transition : wipedown16_transition;
break;
2110 case SLIDELEFT:
s->transitionf =
s->depth <= 8 ? slideleft8_transition : slideleft16_transition;
break;
2111 case SLIDERIGHT:
s->transitionf =
s->depth <= 8 ? slideright8_transition : slideright16_transition;
break;
2112 case SLIDEUP:
s->transitionf =
s->depth <= 8 ? slideup8_transition : slideup16_transition;
break;
2113 case SLIDEDOWN:
s->transitionf =
s->depth <= 8 ? slidedown8_transition : slidedown16_transition;
break;
2114 case CIRCLECROP:
s->transitionf =
s->depth <= 8 ? circlecrop8_transition : circlecrop16_transition;
break;
2115 case RECTCROP:
s->transitionf =
s->depth <= 8 ? rectcrop8_transition : rectcrop16_transition;
break;
2116 case DISTANCE:
s->transitionf =
s->depth <= 8 ? distance8_transition : distance16_transition;
break;
2117 case FADEBLACK:
s->transitionf =
s->depth <= 8 ? fadeblack8_transition : fadeblack16_transition;
break;
2118 case FADEWHITE:
s->transitionf =
s->depth <= 8 ? fadewhite8_transition : fadewhite16_transition;
break;
2119 case RADIAL:
s->transitionf =
s->depth <= 8 ? radial8_transition : radial16_transition;
break;
2120 case SMOOTHLEFT:
s->transitionf =
s->depth <= 8 ? smoothleft8_transition : smoothleft16_transition;
break;
2121 case SMOOTHRIGHT:
s->transitionf =
s->depth <= 8 ? smoothright8_transition: smoothright16_transition;
break;
2122 case SMOOTHUP:
s->transitionf =
s->depth <= 8 ? smoothup8_transition : smoothup16_transition;
break;
2123 case SMOOTHDOWN:
s->transitionf =
s->depth <= 8 ? smoothdown8_transition : smoothdown16_transition;
break;
2124 case CIRCLEOPEN:
s->transitionf =
s->depth <= 8 ? circleopen8_transition : circleopen16_transition;
break;
2125 case CIRCLECLOSE:
s->transitionf =
s->depth <= 8 ? circleclose8_transition: circleclose16_transition;
break;
2126 case VERTOPEN:
s->transitionf =
s->depth <= 8 ? vertopen8_transition : vertopen16_transition;
break;
2127 case VERTCLOSE:
s->transitionf =
s->depth <= 8 ? vertclose8_transition : vertclose16_transition;
break;
2128 case HORZOPEN:
s->transitionf =
s->depth <= 8 ? horzopen8_transition : horzopen16_transition;
break;
2129 case HORZCLOSE:
s->transitionf =
s->depth <= 8 ? horzclose8_transition : horzclose16_transition;
break;
2130 case DISSOLVE:
s->transitionf =
s->depth <= 8 ? dissolve8_transition : dissolve16_transition;
break;
2131 case PIXELIZE:
s->transitionf =
s->depth <= 8 ? pixelize8_transition : pixelize16_transition;
break;
2132 case DIAGTL:
s->transitionf =
s->depth <= 8 ? diagtl8_transition : diagtl16_transition;
break;
2133 case DIAGTR:
s->transitionf =
s->depth <= 8 ? diagtr8_transition : diagtr16_transition;
break;
2134 case DIAGBL:
s->transitionf =
s->depth <= 8 ? diagbl8_transition : diagbl16_transition;
break;
2135 case DIAGBR:
s->transitionf =
s->depth <= 8 ? diagbr8_transition : diagbr16_transition;
break;
2136 case HLSLICE:
s->transitionf =
s->depth <= 8 ? hlslice8_transition : hlslice16_transition;
break;
2137 case HRSLICE:
s->transitionf =
s->depth <= 8 ? hrslice8_transition : hrslice16_transition;
break;
2138 case VUSLICE:
s->transitionf =
s->depth <= 8 ? vuslice8_transition : vuslice16_transition;
break;
2139 case VDSLICE:
s->transitionf =
s->depth <= 8 ? vdslice8_transition : vdslice16_transition;
break;
2140 case HBLUR:
s->transitionf =
s->depth <= 8 ? hblur8_transition : hblur16_transition;
break;
2141 case FADEGRAYS:
s->transitionf =
s->depth <= 8 ? fadegrays8_transition : fadegrays16_transition;
break;
2142 case WIPETL:
s->transitionf =
s->depth <= 8 ? wipetl8_transition : wipetl16_transition;
break;
2143 case WIPETR:
s->transitionf =
s->depth <= 8 ? wipetr8_transition : wipetr16_transition;
break;
2144 case WIPEBL:
s->transitionf =
s->depth <= 8 ? wipebl8_transition : wipebl16_transition;
break;
2145 case WIPEBR:
s->transitionf =
s->depth <= 8 ? wipebr8_transition : wipebr16_transition;
break;
2146 case SQUEEZEH:
s->transitionf =
s->depth <= 8 ? squeezeh8_transition : squeezeh16_transition;
break;
2147 case SQUEEZEV:
s->transitionf =
s->depth <= 8 ? squeezev8_transition : squeezev16_transition;
break;
2148 case ZOOMIN:
s->transitionf =
s->depth <= 8 ? zoomin8_transition : zoomin16_transition;
break;
2149 case FADEFAST:
s->transitionf =
s->depth <= 8 ? fadefast8_transition : fadefast16_transition;
break;
2150 case FADESLOW:
s->transitionf =
s->depth <= 8 ? fadeslow8_transition : fadeslow16_transition;
break;
2151 case HLWIND:
s->transitionf =
s->depth <= 8 ? hlwind8_transition : hlwind16_transition;
break;
2152 case HRWIND:
s->transitionf =
s->depth <= 8 ? hrwind8_transition : hrwind16_transition;
break;
2153 case VUWIND:
s->transitionf =
s->depth <= 8 ? vuwind8_transition : vuwind16_transition;
break;
2154 case VDWIND:
s->transitionf =
s->depth <= 8 ? vdwind8_transition : vdwind16_transition;
break;
2155 case COVERLEFT:
s->transitionf =
s->depth <= 8 ? coverleft8_transition : coverleft16_transition;
break;
2156 case COVERRIGHT:
s->transitionf =
s->depth <= 8 ? coverright8_transition : coverright16_transition;
break;
2157 case COVERUP:
s->transitionf =
s->depth <= 8 ? coverup8_transition : coverup16_transition;
break;
2158 case COVERDOWN:
s->transitionf =
s->depth <= 8 ? coverdown8_transition : coverdown16_transition;
break;
2159 case REVEALLEFT:
s->transitionf =
s->depth <= 8 ? revealleft8_transition : revealleft16_transition;
break;
2160 case REVEALRIGHT:
s->transitionf =
s->depth <= 8 ? revealright8_transition: revealright16_transition;
break;
2161 case REVEALUP:
s->transitionf =
s->depth <= 8 ? revealup8_transition : revealup16_transition;
break;
2162 case REVEALDOWN:
s->transitionf =
s->depth <= 8 ? revealdown8_transition : revealdown16_transition;
break;
2166 if (
s->transition ==
CUSTOM) {
2168 "a0",
"a1",
"a2",
"a3",
2169 "b0",
"b1",
"b2",
"b3",
2195 int slice_end = (outlink->
h * (jobnr+1)) / nb_jobs;
2206 float progress =
av_clipf(1.
f - ((
float)(
s->pts -
s->start_pts) /
s->duration_pts), 0.f, 1.f);
2215 td.xf[0] =
a,
td.xf[1] =
b,
td.out =
out,
td.progress = progress;
2249 s->inputs_offset_pts = -status_pts;
2275 if (
s->status[0] && !
s->status[1])
2282 s->pts = peeked_frame->
pts;
2290 if (
s->start_pts >
s->pts) {
2314 s->inputs_offset_pts =
s->pts -
s->xf[1]->pts;
2318 if (
s->pts -
s->start_pts >
s->duration_pts) {
2365 return s->passthrough ?
2395 .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 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[]
#define FILTER_PIXFMTS_ARRAY(array)
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 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)
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.
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)
@ 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 int slice_start(SliceContext *sc, VVCContext *s, VVCFrameContext *fc, const CodedBitstreamUnit *unit, const int is_first_slice)
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)
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
AVRational sample_aspect_ratio
agreed upon sample aspect ratio
static const char *const var_names[]
AVRational frame_rate
Frame rate of the stream on the link, or 1/0 if unknown or variable; if left to 0/0,...
#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 DIAGBL_TRANSITION(name, type, div)
#define FILTER_INPUTS(array)
#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[]
#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)
#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
#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 FILTER_OUTPUTS(array)
#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
#define AV_PIX_FMT_YUV444P14
#define AV_PIX_FMT_GRAY12
static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
#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