Go to the documentation of this file.
96 int slice_start,
int slice_end,
int jobnr);
101 static const char *
const var_names[] = {
"X",
"Y",
"W",
"H",
"A",
"B",
"PLANE",
"P",
NULL };
144 #define OFFSET(x) offsetof(XFadeContext, x)
145 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
193 #define CUSTOM_TRANSITION(name, type, div) \
194 static void custom##name##_transition(AVFilterContext *ctx, \
195 const AVFrame *a, const AVFrame *b, AVFrame *out, \
197 int slice_start, int slice_end, int jobnr) \
199 XFadeContext *s = ctx->priv; \
200 const int height = slice_end - slice_start; \
202 double values[VAR_VARS_NB]; \
203 values[VAR_W] = out->width; \
204 values[VAR_H] = out->height; \
205 values[VAR_PROGRESS] = progress; \
207 for (int p = 0; p < s->nb_planes; p++) { \
208 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
209 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
210 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
212 values[VAR_PLANE] = p; \
214 for (int y = 0; y < height; y++) { \
215 values[VAR_Y] = slice_start + y; \
216 for (int x = 0; x < out->width; x++) { \
218 values[VAR_A] = xf0[x]; \
219 values[VAR_B] = xf1[x]; \
220 dst[x] = av_expr_eval(s->e, values, s); \
223 dst += out->linesize[p] / div; \
224 xf0 += a->linesize[p] / div; \
225 xf1 += b->linesize[p] / div; \
233 static inline
float mix(
float a,
float b,
float mix)
240 return a - floorf(
a);
243 static inline float smoothstep(
float edge0,
float edge1,
float x)
247 t = av_clipf((x - edge0) / (edge1 - edge0), 0.
f, 1.
f);
249 return t * t * (3.f - 2.f * t);
252 #define FADE_TRANSITION(name, type, div) \
253 static void fade##name##_transition(AVFilterContext *ctx, \
254 const AVFrame *a, const AVFrame *b, AVFrame *out, \
256 int slice_start, int slice_end, int jobnr) \
258 XFadeContext *s = ctx->priv; \
259 const int height = slice_end - slice_start; \
261 for (int p = 0; p < s->nb_planes; p++) { \
262 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
263 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
264 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
266 for (int y = 0; y < height; y++) { \
267 for (int x = 0; x < out->width; x++) { \
268 dst[x] = mix(xf0[x], xf1[x], progress); \
271 dst += out->linesize[p] / div; \
272 xf0 += a->linesize[p] / div; \
273 xf1 += b->linesize[p] / div; \
281 #define WIPELEFT_TRANSITION(name, type, div) \
282 static void wipeleft##name##_transition(AVFilterContext *ctx, \
283 const AVFrame *a, const AVFrame *b, AVFrame *out, \
285 int slice_start, int slice_end, int jobnr) \
287 XFadeContext *s = ctx->priv; \
288 const int height = slice_end - slice_start; \
289 const int z = out->width * progress; \
291 for (int p = 0; p < s->nb_planes; p++) { \
292 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
293 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
294 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
296 for (int y = 0; y < height; y++) { \
297 for (int x = 0; x < out->width; x++) { \
298 dst[x] = x > z ? xf1[x] : xf0[x]; \
301 dst += out->linesize[p] / div; \
302 xf0 += a->linesize[p] / div; \
303 xf1 += b->linesize[p] / div; \
311 #define WIPERIGHT_TRANSITION(name, type, div) \
312 static void wiperight##name##_transition(AVFilterContext *ctx, \
313 const AVFrame *a, const AVFrame *b, AVFrame *out, \
315 int slice_start, int slice_end, int jobnr) \
317 XFadeContext *s = ctx->priv; \
318 const int height = slice_end - slice_start; \
319 const int z = out->width * (1.f - progress); \
321 for (int p = 0; p < s->nb_planes; p++) { \
322 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
323 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
324 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
326 for (int y = 0; y < height; y++) { \
327 for (int x = 0; x < out->width; x++) { \
328 dst[x] = x > z ? xf0[x] : xf1[x]; \
331 dst += out->linesize[p] / div; \
332 xf0 += a->linesize[p] / div; \
333 xf1 += b->linesize[p] / div; \
341 #define WIPEUP_TRANSITION(name, type, div) \
342 static void wipeup##name##_transition(AVFilterContext *ctx, \
343 const AVFrame *a, const AVFrame *b, AVFrame *out, \
345 int slice_start, int slice_end, int jobnr) \
347 XFadeContext *s = ctx->priv; \
348 const int height = slice_end - slice_start; \
349 const int z = out->height * progress; \
351 for (int p = 0; p < s->nb_planes; p++) { \
352 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
353 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
354 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
356 for (int y = 0; y < height; y++) { \
357 for (int x = 0; x < out->width; x++) { \
358 dst[x] = slice_start + y > z ? xf1[x] : xf0[x]; \
361 dst += out->linesize[p] / div; \
362 xf0 += a->linesize[p] / div; \
363 xf1 += b->linesize[p] / div; \
371 #define WIPEDOWN_TRANSITION(name, type, div) \
372 static void wipedown##name##_transition(AVFilterContext *ctx, \
373 const AVFrame *a, const AVFrame *b, AVFrame *out, \
375 int slice_start, int slice_end, int jobnr) \
377 XFadeContext *s = ctx->priv; \
378 const int height = slice_end - slice_start; \
379 const int z = out->height * (1.f - progress); \
381 for (int p = 0; p < s->nb_planes; p++) { \
382 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
383 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
384 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
386 for (int y = 0; y < height; y++) { \
387 for (int x = 0; x < out->width; x++) { \
388 dst[x] = slice_start + y > z ? xf0[x] : xf1[x]; \
391 dst += out->linesize[p] / div; \
392 xf0 += a->linesize[p] / div; \
393 xf1 += b->linesize[p] / div; \
401 #define SLIDELEFT_TRANSITION(name, type, div) \
402 static void slideleft##name##_transition(AVFilterContext *ctx, \
403 const AVFrame *a, const AVFrame *b, AVFrame *out, \
405 int slice_start, int slice_end, int jobnr) \
407 XFadeContext *s = ctx->priv; \
408 const int height = slice_end - slice_start; \
409 const int width = out->width; \
410 const int z = -progress * width; \
412 for (int p = 0; p < s->nb_planes; p++) { \
413 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
414 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
415 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
417 for (int y = 0; y < height; y++) { \
418 for (int x = 0; x < width; x++) { \
419 const int zx = z + x; \
420 const int zz = zx % width + width * (zx < 0); \
421 dst[x] = (zx > 0) && (zx < width) ? xf1[zz] : xf0[zz]; \
424 dst += out->linesize[p] / div; \
425 xf0 += a->linesize[p] / div; \
426 xf1 += b->linesize[p] / div; \
434 #define SLIDERIGHT_TRANSITION(name, type, div) \
435 static void slideright##name##_transition(AVFilterContext *ctx, \
436 const AVFrame *a, const AVFrame *b, AVFrame *out, \
438 int slice_start, int slice_end, int jobnr) \
440 XFadeContext *s = ctx->priv; \
441 const int height = slice_end - slice_start; \
442 const int width = out->width; \
443 const int z = progress * width; \
445 for (int p = 0; p < s->nb_planes; p++) { \
446 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
447 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
448 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
450 for (int y = 0; y < height; y++) { \
451 for (int x = 0; x < out->width; x++) { \
452 const int zx = z + x; \
453 const int zz = zx % width + width * (zx < 0); \
454 dst[x] = (zx > 0) && (zx < width) ? xf1[zz] : xf0[zz]; \
457 dst += out->linesize[p] / div; \
458 xf0 += a->linesize[p] / div; \
459 xf1 += b->linesize[p] / div; \
467 #define SLIDEUP_TRANSITION(name, type, div) \
468 static void slideup##name##_transition(AVFilterContext *ctx, \
469 const AVFrame *a, const AVFrame *b, AVFrame *out, \
471 int slice_start, int slice_end, int jobnr) \
473 XFadeContext *s = ctx->priv; \
474 const int height = out->height; \
475 const int z = -progress * height; \
477 for (int p = 0; p < s->nb_planes; p++) { \
478 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
480 for (int y = slice_start; y < slice_end; y++) { \
481 const int zy = z + y; \
482 const int zz = zy % height + height * (zy < 0); \
483 const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
484 const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
486 for (int x = 0; x < out->width; x++) { \
487 dst[x] = (zy > 0) && (zy < height) ? xf1[x] : xf0[x]; \
490 dst += out->linesize[p] / div; \
498 #define SLIDEDOWN_TRANSITION(name, type, div) \
499 static void slidedown##name##_transition(AVFilterContext *ctx, \
500 const AVFrame *a, const AVFrame *b, AVFrame *out, \
502 int slice_start, int slice_end, int jobnr) \
504 XFadeContext *s = ctx->priv; \
505 const int height = out->height; \
506 const int z = progress * height; \
508 for (int p = 0; p < s->nb_planes; p++) { \
509 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
511 for (int y = slice_start; y < slice_end; y++) { \
512 const int zy = z + y; \
513 const int zz = zy % height + height * (zy < 0); \
514 const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \
515 const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \
517 for (int x = 0; x < out->width; x++) { \
518 dst[x] = (zy > 0) && (zy < height) ? xf1[x] : xf0[x]; \
521 dst += out->linesize[p] / div; \
529 #define CIRCLECROP_TRANSITION(name, type, div) \
530 static void circlecrop##name##_transition(AVFilterContext *ctx, \
531 const AVFrame *a, const AVFrame *b, AVFrame *out, \
533 int slice_start, int slice_end, int jobnr) \
535 XFadeContext *s = ctx->priv; \
536 const int width = out->width; \
537 const int height = out->height; \
538 float z = powf(2.f * fabsf(progress - 0.5f), 3.f) * hypotf(width/2, height/2); \
540 for (int p = 0; p < s->nb_planes; p++) { \
541 const int bg = s->black[p]; \
542 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
544 for (int y = slice_start; y < slice_end; y++) { \
545 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
546 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
548 for (int x = 0; x < width; x++) { \
549 float dist = hypotf(x - width / 2, y - height / 2); \
550 int val = progress < 0.5f ? xf1[x] : xf0[x]; \
551 dst[x] = (z < dist) ? bg : val; \
554 dst += out->linesize[p] / div; \
562 #define RECTCROP_TRANSITION(name, type, div) \
563 static void rectcrop##name##_transition(AVFilterContext *ctx, \
564 const AVFrame *a, const AVFrame *b, AVFrame *out, \
566 int slice_start, int slice_end, int jobnr) \
568 XFadeContext *s = ctx->priv; \
569 const int width = out->width; \
570 const int height = out->height; \
571 int zh = fabsf(progress - 0.5f) * height; \
572 int zw = fabsf(progress - 0.5f) * width; \
574 for (int p = 0; p < s->nb_planes; p++) { \
575 const int bg = s->black[p]; \
576 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
578 for (int y = slice_start; y < slice_end; y++) { \
579 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
580 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
582 for (int x = 0; x < width; x++) { \
583 int dist = FFABS(x - width / 2) < zw && \
584 FFABS(y - height / 2) < zh; \
585 int val = progress < 0.5f ? xf1[x] : xf0[x]; \
586 dst[x] = !dist ? bg : val; \
589 dst += out->linesize[p] / div; \
597 #define DISTANCE_TRANSITION(name, type, div) \
598 static void distance##name##_transition(AVFilterContext *ctx, \
599 const AVFrame *a, const AVFrame *b, AVFrame *out, \
601 int slice_start, int slice_end, int jobnr) \
603 XFadeContext *s = ctx->priv; \
604 const int width = out->width; \
605 const float max = s->max_value; \
607 for (int y = slice_start; y < slice_end; y++) { \
608 for (int x = 0; x < width; x++) { \
610 for (int p = 0; p < s->nb_planes; p++) { \
611 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
612 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
614 dist += (xf0[x] / max - xf1[x] / max) * \
615 (xf0[x] / max - xf1[x] / max); \
618 dist = sqrtf(dist) <= progress; \
619 for (int p = 0; p < s->nb_planes; p++) { \
620 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
621 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
622 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
623 dst[x] = mix(mix(xf0[x], xf1[x], dist), xf1[x], progress); \
632 #define FADEBLACK_TRANSITION(name, type, div) \
633 static void fadeblack##name##_transition(AVFilterContext *ctx, \
634 const AVFrame *a, const AVFrame *b, AVFrame *out, \
636 int slice_start, int slice_end, int jobnr) \
638 XFadeContext *s = ctx->priv; \
639 const int height = slice_end - slice_start; \
640 const float phase = 0.2f; \
642 for (int p = 0; p < s->nb_planes; p++) { \
643 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
644 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
645 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
646 const int bg = s->black[p]; \
648 for (int y = 0; y < height; y++) { \
649 for (int x = 0; x < out->width; x++) { \
650 dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \
651 mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \
655 dst += out->linesize[p] / div; \
656 xf0 += a->linesize[p] / div; \
657 xf1 += b->linesize[p] / div; \
665 #define FADEWHITE_TRANSITION(name, type, div) \
666 static void fadewhite##name##_transition(AVFilterContext *ctx, \
667 const AVFrame *a, const AVFrame *b, AVFrame *out, \
669 int slice_start, int slice_end, int jobnr) \
671 XFadeContext *s = ctx->priv; \
672 const int height = slice_end - slice_start; \
673 const float phase = 0.2f; \
675 for (int p = 0; p < s->nb_planes; p++) { \
676 const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \
677 const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \
678 type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \
679 const int bg = s->white[p]; \
681 for (int y = 0; y < height; y++) { \
682 for (int x = 0; x < out->width; x++) { \
683 dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \
684 mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \
688 dst += out->linesize[p] / div; \
689 xf0 += a->linesize[p] / div; \
690 xf1 += b->linesize[p] / div; \
698 #define RADIAL_TRANSITION(name, type, div) \
699 static void radial##name##_transition(AVFilterContext *ctx, \
700 const AVFrame *a, const AVFrame *b, AVFrame *out, \
702 int slice_start, int slice_end, int jobnr) \
704 XFadeContext *s = ctx->priv; \
705 const int width = out->width; \
706 const int height = out->height; \
708 for (int y = slice_start; y < slice_end; y++) { \
709 for (int x = 0; x < width; x++) { \
710 const float smooth = atan2f(x - width / 2, y - height / 2) - \
711 (progress - 0.5f) * (M_PI * 2.5f); \
712 for (int p = 0; p < s->nb_planes; p++) { \
713 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
714 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
715 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
717 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
726 #define SMOOTHLEFT_TRANSITION(name, type, div) \
727 static void smoothleft##name##_transition(AVFilterContext *ctx, \
728 const AVFrame *a, const AVFrame *b, AVFrame *out, \
730 int slice_start, int slice_end, int jobnr) \
732 XFadeContext *s = ctx->priv; \
733 const int width = out->width; \
734 const float w = width; \
736 for (int y = slice_start; y < slice_end; y++) { \
737 for (int x = 0; x < width; x++) { \
738 const float smooth = 1.f + x / w - progress * 2.f; \
740 for (int p = 0; p < s->nb_planes; p++) { \
741 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
742 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
743 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
745 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
754 #define SMOOTHRIGHT_TRANSITION(name, type, div) \
755 static void smoothright##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 float w = width; \
764 for (int y = slice_start; y < slice_end; y++) { \
765 for (int x = 0; x < width; x++) { \
766 const float smooth = 1.f + (w - 1 - x) / w - progress * 2.f; \
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 SMOOTHUP_TRANSITION(name, type, div) \
783 static void smoothup##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 h = out->height; \
792 for (int y = slice_start; y < slice_end; y++) { \
793 const float smooth = 1.f + y / h - progress * 2.f; \
794 for (int x = 0; x < width; x++) { \
795 for (int p = 0; p < s->nb_planes; p++) { \
796 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
797 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
798 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
800 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
809 #define SMOOTHDOWN_TRANSITION(name, type, div) \
810 static void smoothdown##name##_transition(AVFilterContext *ctx, \
811 const AVFrame *a, const AVFrame *b, AVFrame *out, \
813 int slice_start, int slice_end, int jobnr) \
815 XFadeContext *s = ctx->priv; \
816 const int width = out->width; \
817 const float h = out->height; \
819 for (int y = slice_start; y < slice_end; y++) { \
820 const float smooth = 1.f + (h - 1 - y) / h - progress * 2.f; \
821 for (int x = 0; x < width; x++) { \
822 for (int p = 0; p < s->nb_planes; p++) { \
823 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
824 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
825 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
827 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
836 #define CIRCLEOPEN_TRANSITION(name, type, div) \
837 static void circleopen##name##_transition(AVFilterContext *ctx, \
838 const AVFrame *a, const AVFrame *b, AVFrame *out, \
840 int slice_start, int slice_end, int jobnr) \
842 XFadeContext *s = ctx->priv; \
843 const int width = out->width; \
844 const int height = out->height; \
845 const float z = hypotf(width / 2, height / 2); \
846 const float p = (progress - 0.5f) * 3.f; \
848 for (int y = slice_start; y < slice_end; y++) { \
849 for (int x = 0; x < width; x++) { \
850 const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \
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(xf0[x], xf1[x], smoothstep(0.f, 1.f, smooth)); \
865 #define CIRCLECLOSE_TRANSITION(name, type, div) \
866 static void circleclose##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 int height = out->height; \
874 const float z = hypotf(width / 2, height / 2); \
875 const float p = (1.f - progress - 0.5f) * 3.f; \
877 for (int y = slice_start; y < slice_end; y++) { \
878 for (int x = 0; x < width; x++) { \
879 const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \
880 for (int p = 0; p < s->nb_planes; p++) { \
881 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
882 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
883 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
885 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
894 #define VERTOPEN_TRANSITION(name, type, div) \
895 static void vertopen##name##_transition(AVFilterContext *ctx, \
896 const AVFrame *a, const AVFrame *b, AVFrame *out, \
898 int slice_start, int slice_end, int jobnr) \
900 XFadeContext *s = ctx->priv; \
901 const int width = out->width; \
902 const float w2 = out->width / 2; \
904 for (int y = slice_start; y < slice_end; y++) { \
905 for (int x = 0; x < width; x++) { \
906 const float smooth = 2.f - fabsf((x - w2) / w2) - progress * 2.f; \
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(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
921 #define VERTCLOSE_TRANSITION(name, type, div) \
922 static void vertclose##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 float w2 = out->width / 2; \
931 for (int y = slice_start; y < slice_end; y++) { \
932 for (int x = 0; x < width; x++) { \
933 const float smooth = 1.f + fabsf((x - w2) / w2) - progress * 2.f; \
934 for (int p = 0; p < s->nb_planes; p++) { \
935 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
936 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
937 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
939 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
948 #define HORZOPEN_TRANSITION(name, type, div) \
949 static void horzopen##name##_transition(AVFilterContext *ctx, \
950 const AVFrame *a, const AVFrame *b, AVFrame *out, \
952 int slice_start, int slice_end, int jobnr) \
954 XFadeContext *s = ctx->priv; \
955 const int width = out->width; \
956 const float h2 = out->height / 2; \
958 for (int y = slice_start; y < slice_end; y++) { \
959 const float smooth = 2.f - fabsf((y - h2) / h2) - progress * 2.f; \
960 for (int x = 0; x < width; x++) { \
961 for (int p = 0; p < s->nb_planes; p++) { \
962 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
963 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
964 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
966 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
975 #define HORZCLOSE_TRANSITION(name, type, div) \
976 static void horzclose##name##_transition(AVFilterContext *ctx, \
977 const AVFrame *a, const AVFrame *b, AVFrame *out, \
979 int slice_start, int slice_end, int jobnr) \
981 XFadeContext *s = ctx->priv; \
982 const int width = out->width; \
983 const float h2 = out->height / 2; \
985 for (int y = slice_start; y < slice_end; y++) { \
986 const float smooth = 1.f + fabsf((y - h2) / h2) - progress * 2.f; \
987 for (int x = 0; x < width; x++) { \
988 for (int p = 0; p < s->nb_planes; p++) { \
989 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
990 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
991 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
993 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1004 const float r =
sinf(x * 12.9898
f + y * 78.233
f) * 43758.545f;
1006 return r - floorf(
r);
1009 #define DISSOLVE_TRANSITION(name, type, div) \
1010 static void dissolve##name##_transition(AVFilterContext *ctx, \
1011 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1013 int slice_start, int slice_end, int jobnr) \
1015 XFadeContext *s = ctx->priv; \
1016 const int width = out->width; \
1018 for (int y = slice_start; y < slice_end; y++) { \
1019 for (int x = 0; x < width; x++) { \
1020 const float smooth = frand(x, y) * 2.f + progress * 2.f - 1.5f; \
1021 for (int p = 0; p < s->nb_planes; p++) { \
1022 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1023 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1024 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1026 dst[x] = smooth >= 0.5f ? xf0[x] : xf1[x]; \
1035 #define PIXELIZE_TRANSITION(name, type, div) \
1036 static void pixelize##name##_transition(AVFilterContext *ctx, \
1037 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1039 int slice_start, int slice_end, int jobnr) \
1041 XFadeContext *s = ctx->priv; \
1042 const int w = out->width; \
1043 const int h = out->height; \
1044 const float d = fminf(progress, 1.f - progress); \
1045 const float dist = ceilf(d * 50.f) / 50.f; \
1046 const float sqx = 2.f * dist * FFMIN(w, h) / 20.f; \
1047 const float sqy = 2.f * dist * FFMIN(w, h) / 20.f; \
1049 for (int y = slice_start; y < slice_end; y++) { \
1050 for (int x = 0; x < w; x++) { \
1051 int sx = dist > 0.f ? FFMIN((floorf(x / sqx) + .5f) * sqx, w - 1) : x; \
1052 int sy = dist > 0.f ? FFMIN((floorf(y / sqy) + .5f) * sqy, h - 1) : y; \
1053 for (int p = 0; p < s->nb_planes; p++) { \
1054 const type *xf0 = (const type *)(a->data[p] + sy * a->linesize[p]); \
1055 const type *xf1 = (const type *)(b->data[p] + sy * b->linesize[p]); \
1056 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1058 dst[x] = mix(xf0[sx], xf1[sx], progress); \
1067 #define DIAGTL_TRANSITION(name, type, div) \
1068 static void diagtl##name##_transition(AVFilterContext *ctx, \
1069 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1071 int slice_start, int slice_end, int jobnr) \
1073 XFadeContext *s = ctx->priv; \
1074 const int width = out->width; \
1075 const float w = width; \
1076 const float h = out->height; \
1078 for (int y = slice_start; y < slice_end; y++) { \
1079 for (int x = 0; x < width; x++) { \
1080 const float smooth = 1.f + x / w * y / h - progress * 2.f; \
1082 for (int p = 0; p < s->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] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1096 #define DIAGTR_TRANSITION(name, type, div) \
1097 static void diagtr##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 width = out->width; \
1104 const float w = width; \
1105 const float h = out->height; \
1107 for (int y = slice_start; y < slice_end; y++) { \
1108 for (int x = 0; x < width; x++) { \
1109 const float smooth = 1.f + (w - 1 - x) / w * y / h - progress * 2.f; \
1111 for (int p = 0; p < s->nb_planes; p++) { \
1112 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1113 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1114 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1116 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1125 #define DIAGBL_TRANSITION(name, type, div) \
1126 static void diagbl##name##_transition(AVFilterContext *ctx, \
1127 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1129 int slice_start, int slice_end, int jobnr) \
1131 XFadeContext *s = ctx->priv; \
1132 const int width = out->width; \
1133 const float w = width; \
1134 const float h = out->height; \
1136 for (int y = slice_start; y < slice_end; y++) { \
1137 for (int x = 0; x < width; x++) { \
1138 const float smooth = 1.f + x / w * (h - 1 - y) / h - progress * 2.f; \
1140 for (int p = 0; p < s->nb_planes; p++) { \
1141 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1142 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1143 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1145 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1154 #define DIAGBR_TRANSITION(name, type, div) \
1155 static void diagbr##name##_transition(AVFilterContext *ctx, \
1156 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1158 int slice_start, int slice_end, int jobnr) \
1160 XFadeContext *s = ctx->priv; \
1161 const int width = out->width; \
1162 const float w = width; \
1163 const float h = out->height; \
1165 for (int y = slice_start; y < slice_end; y++) { \
1166 for (int x = 0; x < width; x++) { \
1167 const float smooth = 1.f + (w - 1 - x) / w * (h - 1 - y) / h - \
1170 for (int p = 0; p < s->nb_planes; p++) { \
1171 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1172 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1173 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1175 dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \
1184 #define HLSLICE_TRANSITION(name, type, div) \
1185 static void hlslice##name##_transition(AVFilterContext *ctx, \
1186 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1188 int slice_start, int slice_end, int jobnr) \
1190 XFadeContext *s = ctx->priv; \
1191 const int width = out->width; \
1192 const float w = width; \
1194 for (int y = slice_start; y < slice_end; y++) { \
1195 for (int x = 0; x < width; x++) { \
1196 const float smooth = smoothstep(-0.5f, 0.f, x / w - progress * 1.5f); \
1197 const float ss = smooth <= fract(10.f * x / w) ? 0.f : 1.f; \
1199 for (int p = 0; p < s->nb_planes; p++) { \
1200 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1201 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1202 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1204 dst[x] = mix(xf1[x], xf0[x], ss); \
1213 #define HRSLICE_TRANSITION(name, type, div) \
1214 static void hrslice##name##_transition(AVFilterContext *ctx, \
1215 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1217 int slice_start, int slice_end, int jobnr) \
1219 XFadeContext *s = ctx->priv; \
1220 const int width = out->width; \
1221 const float w = width; \
1223 for (int y = slice_start; y < slice_end; y++) { \
1224 for (int x = 0; x < width; x++) { \
1225 const float xx = (w - 1 - x) / w; \
1226 const float smooth = smoothstep(-0.5f, 0.f, xx - progress * 1.5f); \
1227 const float ss = smooth <= fract(10.f * xx) ? 0.f : 1.f; \
1229 for (int p = 0; p < s->nb_planes; p++) { \
1230 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1231 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1232 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1234 dst[x] = mix(xf1[x], xf0[x], ss); \
1243 #define VUSLICE_TRANSITION(name, type, div) \
1244 static void vuslice##name##_transition(AVFilterContext *ctx, \
1245 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1247 int slice_start, int slice_end, int jobnr) \
1249 XFadeContext *s = ctx->priv; \
1250 const int width = out->width; \
1251 const float h = out->height; \
1253 for (int y = slice_start; y < slice_end; y++) { \
1254 const float smooth = smoothstep(-0.5f, 0.f, y / h - progress * 1.5f); \
1255 const float ss = smooth <= fract(10.f * y / h) ? 0.f : 1.f; \
1257 for (int x = 0; x < width; x++) { \
1258 for (int p = 0; p < s->nb_planes; p++) { \
1259 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1260 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1261 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1263 dst[x] = mix(xf1[x], xf0[x], ss); \
1272 #define VDSLICE_TRANSITION(name, type, div) \
1273 static void vdslice##name##_transition(AVFilterContext *ctx, \
1274 const AVFrame *a, const AVFrame *b, AVFrame *out, \
1276 int slice_start, int slice_end, int jobnr) \
1278 XFadeContext *s = ctx->priv; \
1279 const int width = out->width; \
1280 const float h = out->height; \
1282 for (int y = slice_start; y < slice_end; y++) { \
1283 const float yy = (h - 1 - y) / h; \
1284 const float smooth = smoothstep(-0.5f, 0.f, yy - progress * 1.5f); \
1285 const float ss = smooth <= fract(10.f * yy) ? 0.f : 1.f; \
1287 for (int x = 0; x < width; x++) { \
1288 for (int p = 0; p < s->nb_planes; p++) { \
1289 const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \
1290 const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \
1291 type *dst = (type *)(out->data[p] + y * out->linesize[p]); \
1293 dst[x] = mix(xf1[x], xf0[x], ss); \
1302 static inline
double getpix(
void *priv,
double x,
double y,
int plane,
int nb)
1307 int linesize =
in->linesize[
FFMIN(plane,
s->nb_planes - 1)];
1308 const int w =
in->width;
1309 const int h =
in->height;
1313 xi = av_clipd(x, 0,
w - 1);
1314 yi = av_clipd(y, 0,
h - 1);
1317 const uint16_t *src16 = (
const uint16_t*)
src;
1320 return src16[
xi + yi * linesize];
1322 return src[
xi + yi * linesize];
1326 static double a0(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 0, 0); }
1327 static double a1(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 1, 0); }
1328 static double a2(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 2, 0); }
1329 static double a3(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 3, 0); }
1331 static double b0(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 0, 1); }
1332 static double b1(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 1, 1); }
1333 static double b2(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 2, 1); }
1334 static double b3(
void *priv,
double x,
double y) {
return getpix(priv, x, y, 3, 1); }
1349 if (inlink0->
w != inlink1->
w || inlink0->
h != inlink1->
h) {
1351 "(size %dx%d) do not match the corresponding "
1352 "second input link %s parameters (size %dx%d)\n",
1353 ctx->input_pads[0].name, inlink0->
w, inlink0->
h,
1354 ctx->input_pads[1].name, inlink1->
w, inlink1->
h);
1361 "(%d/%d) do not match the corresponding "
1362 "second input link %s timebase (%d/%d)\n",
1368 outlink->
w = inlink0->
w;
1369 outlink->
h = inlink0->
h;
1377 s->max_value = (1 <<
s->depth) - 1;
1379 s->black[1] =
s->black[2] = is_rgb ? 0 :
s->max_value / 2;
1380 s->black[3] =
s->max_value;
1381 s->white[0] =
s->white[3] =
s->max_value;
1382 s->white[1] =
s->white[2] = is_rgb ?
s->max_value :
s->max_value / 2;
1391 switch (
s->transition) {
1392 case CUSTOM:
s->transitionf =
s->depth <= 8 ? custom8_transition : custom16_transition;
break;
1393 case FADE:
s->transitionf =
s->depth <= 8 ? fade8_transition : fade16_transition;
break;
1394 case WIPELEFT:
s->transitionf =
s->depth <= 8 ? wipeleft8_transition : wipeleft16_transition;
break;
1395 case WIPERIGHT:
s->transitionf =
s->depth <= 8 ? wiperight8_transition : wiperight16_transition;
break;
1396 case WIPEUP:
s->transitionf =
s->depth <= 8 ? wipeup8_transition : wipeup16_transition;
break;
1397 case WIPEDOWN:
s->transitionf =
s->depth <= 8 ? wipedown8_transition : wipedown16_transition;
break;
1398 case SLIDELEFT:
s->transitionf =
s->depth <= 8 ? slideleft8_transition : slideleft16_transition;
break;
1399 case SLIDERIGHT:
s->transitionf =
s->depth <= 8 ? slideright8_transition : slideright16_transition;
break;
1400 case SLIDEUP:
s->transitionf =
s->depth <= 8 ? slideup8_transition : slideup16_transition;
break;
1401 case SLIDEDOWN:
s->transitionf =
s->depth <= 8 ? slidedown8_transition : slidedown16_transition;
break;
1402 case CIRCLECROP:
s->transitionf =
s->depth <= 8 ? circlecrop8_transition : circlecrop16_transition;
break;
1403 case RECTCROP:
s->transitionf =
s->depth <= 8 ? rectcrop8_transition : rectcrop16_transition;
break;
1404 case DISTANCE:
s->transitionf =
s->depth <= 8 ? distance8_transition : distance16_transition;
break;
1405 case FADEBLACK:
s->transitionf =
s->depth <= 8 ? fadeblack8_transition : fadeblack16_transition;
break;
1406 case FADEWHITE:
s->transitionf =
s->depth <= 8 ? fadewhite8_transition : fadewhite16_transition;
break;
1407 case RADIAL:
s->transitionf =
s->depth <= 8 ? radial8_transition : radial16_transition;
break;
1408 case SMOOTHLEFT:
s->transitionf =
s->depth <= 8 ? smoothleft8_transition : smoothleft16_transition;
break;
1409 case SMOOTHRIGHT:
s->transitionf =
s->depth <= 8 ? smoothright8_transition: smoothright16_transition;
break;
1410 case SMOOTHUP:
s->transitionf =
s->depth <= 8 ? smoothup8_transition : smoothup16_transition;
break;
1411 case SMOOTHDOWN:
s->transitionf =
s->depth <= 8 ? smoothdown8_transition : smoothdown16_transition;
break;
1412 case CIRCLEOPEN:
s->transitionf =
s->depth <= 8 ? circleopen8_transition : circleopen16_transition;
break;
1413 case CIRCLECLOSE:
s->transitionf =
s->depth <= 8 ? circleclose8_transition: circleclose16_transition;
break;
1414 case VERTOPEN:
s->transitionf =
s->depth <= 8 ? vertopen8_transition : vertopen16_transition;
break;
1415 case VERTCLOSE:
s->transitionf =
s->depth <= 8 ? vertclose8_transition : vertclose16_transition;
break;
1416 case HORZOPEN:
s->transitionf =
s->depth <= 8 ? horzopen8_transition : horzopen16_transition;
break;
1417 case HORZCLOSE:
s->transitionf =
s->depth <= 8 ? horzclose8_transition : horzclose16_transition;
break;
1418 case DISSOLVE:
s->transitionf =
s->depth <= 8 ? dissolve8_transition : dissolve16_transition;
break;
1419 case PIXELIZE:
s->transitionf =
s->depth <= 8 ? pixelize8_transition : pixelize16_transition;
break;
1420 case DIAGTL:
s->transitionf =
s->depth <= 8 ? diagtl8_transition : diagtl16_transition;
break;
1421 case DIAGTR:
s->transitionf =
s->depth <= 8 ? diagtr8_transition : diagtr16_transition;
break;
1422 case DIAGBL:
s->transitionf =
s->depth <= 8 ? diagbl8_transition : diagbl16_transition;
break;
1423 case DIAGBR:
s->transitionf =
s->depth <= 8 ? diagbr8_transition : diagbr16_transition;
break;
1424 case HLSLICE:
s->transitionf =
s->depth <= 8 ? hlslice8_transition : hlslice16_transition;
break;
1425 case HRSLICE:
s->transitionf =
s->depth <= 8 ? hrslice8_transition : hrslice16_transition;
break;
1426 case VUSLICE:
s->transitionf =
s->depth <= 8 ? vuslice8_transition : vuslice16_transition;
break;
1427 case VDSLICE:
s->transitionf =
s->depth <= 8 ? vdslice8_transition : vdslice16_transition;
break;
1430 if (
s->transition ==
CUSTOM) {
1432 "a0",
"a1",
"a2",
"a3",
1433 "b0",
"b1",
"b2",
"b3",
1436 double (*
func2[])(
void *, double, double) = {
1458 int slice_start = (outlink->
h * jobnr ) / nb_jobs;
1459 int slice_end = (outlink->
h * (jobnr+1)) / nb_jobs;
1470 float progress = av_clipf(1.
f - ((
float)(
s->pts -
s->first_pts -
s->offset_pts) /
s->duration_pts), 0.f, 1.f);
1478 td.xf[0] =
a,
td.xf[1] =
b,
td.out =
out,
td.progress = progress;
1496 if (
s->xfade_is_over) {
1500 }
else if (
ret > 0) {
1501 in->pts = (
in->pts -
s->last_pts) +
s->pts;
1518 s->first_pts =
s->xf[0]->pts;
1520 s->pts =
s->xf[0]->pts;
1521 if (
s->first_pts +
s->offset_pts >
s->xf[0]->pts) {
1536 s->last_pts =
s->xf[1]->pts;
1537 s->pts =
s->xf[0]->pts;
1538 if (
s->xf[0]->pts - (
s->first_pts +
s->offset_pts) >
s->duration_pts)
1539 s->xfade_is_over = 1;
1555 s->xfade_is_over = 1;
1560 if (!
s->eof[0] && !
s->xf[0])
1562 if (!
s->eof[1] && (
s->need_second ||
s->eof[0]))
1564 if (
s->eof[0] &&
s->eof[1] && (
1599 .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.
#define AV_PIX_FMT_GBRAP16
AVPixelFormat
Pixel format.
they must not be accessed directly The fifo field contains the frames that are queued in the input for processing by the filter The status_in and status_out fields contains the queued status(EOF or error) of the link
#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)
static int xfade_activate(AVFilterContext *ctx)
#define CIRCLECROP_TRANSITION(name, type, div)
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 AV_TIME_BASE_Q
Internal time base represented as fractional value.
#define WIPEDOWN_TRANSITION(name, type, div)
#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)
This structure describes decoded (raw) audio or video data.
#define SLIDELEFT_TRANSITION(name, type, div)
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)
AVFormatInternal * internal
An opaque field for libavformat internal usage.
A link between two filters.
static float mix(float a, float b, float mix)
static const char *const func2_names[]
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.
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
#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 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
#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 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[]
static const AVFilterPad outputs[]
AVRational frame_rate
Frame rate of the stream on the link, or 1/0 if unknown or variable; if left to 0/0,...
static enum AVPixelFormat pix_fmts[]
#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)
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)
#define DIAGBL_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.
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
static const AVFilterPad xfade_inputs[]
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 inputs
@ 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[]
size_t ff_inlink_queued_frames(AVFilterLink *link)
Get the number of frames available on the link.
#define RADIAL_TRANSITION(name, type, div)
#define WIPELEFT_TRANSITION(name, type, div)
#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 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 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
#define WIPEUP_TRANSITION(name, type, div)
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
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 DIAGTL_TRANSITION(name, type, div)
const char * name
Pad name.
static float fract(float a)
#define CIRCLEOPEN_TRANSITION(name, type, div)
#define AV_PIX_FMT_YUVA444P9
static int xfade_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
int h
agreed upon image height
#define FADEWHITE_TRANSITION(name, type, div)
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
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)
int ff_outlink_get_status(AVFilterLink *link)
Get the status on an output link.
#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)
double(* func2[])(void *, double, double)
#define flags(name, subs,...)
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 int query_formats(AVFilterContext *ctx)
#define DISSOLVE_TRANSITION(name, type, div)
void ff_filter_set_ready(AVFilterContext *filter, unsigned priority)
Mark a filter ready and schedule it for activation.
#define HRSLICE_TRANSITION(name, type, div)