-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathvf_xfade.patch
More file actions
91 lines (81 loc) · 4.77 KB
/
vf_xfade.patch
File metadata and controls
91 lines (81 loc) · 4.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
--- libavfilter/vf_xfade.c 2026-02-19 20:54:22
+++ vf_xfade.c 2026-02-19 20:54:22
@@ -126,6 +126,11 @@
void (*transitionf)(AVFilterContext *ctx, const AVFrame *a, const AVFrame *b, AVFrame *out, float progress,
int slice_start, int slice_end, int jobnr);
+ char *easing_str; // easing name with optional args
+ char *transition_str; // transition name with optional args
+ int reverse; // reverse option bit flags (enum ReverseFlags)
+ struct XFadeEasingContext *k; // xfade-easing data
+
AVExpr *e;
} XFadeContext;
@@ -157,18 +162,22 @@
AV_PIX_FMT_NONE
};
+static void xe_data_free(struct XFadeEasingContext *k);
static av_cold void uninit(AVFilterContext *ctx)
{
XFadeContext *s = ctx->priv;
av_expr_free(s->e);
+ xe_data_free(s->k);
}
#define OFFSET(x) offsetof(XFadeContext, x)
#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
static const AVOption xfade_options[] = {
- { "transition", "set cross fade transition", OFFSET(transition), AV_OPT_TYPE_INT, {.i64=FADE}, -1, NB_TRANSITIONS-1, FLAGS, .unit = "transition" },
+ { "easing", "set cross fade easing", OFFSET(easing_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+ { "reverse", "reverse easing/transition", OFFSET(reverse), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 3, FLAGS },
+ { "transition", "set cross fade transition", OFFSET(transition_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS, .unit = "transition" },
{ "custom", "custom transition", 0, AV_OPT_TYPE_CONST, {.i64=CUSTOM}, 0, 0, FLAGS, .unit = "transition" },
{ "fade", "fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADE}, 0, 0, FLAGS, .unit = "transition" },
{ "wipeleft", "wipe left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPELEFT}, 0, 0, FLAGS, .unit = "transition" },
@@ -1633,7 +1642,7 @@
for (int y = 0; y < height; y++) { \
const float z = .5f + ((slice_start + y) / h - .5f) / progress; \
\
- if (z < 0.f || z > 1.f) { \
+ if (z < 0.f || z > 1.f || isnan(z)) { \
for (int x = 0; x < width; x++) \
dst[x] = xf1[x]; \
} else { \
@@ -1673,7 +1682,7 @@
for (int x = 0; x < width; x++) { \
const float z = .5f + (x / w - .5f) / progress; \
\
- if (z < 0.f || z > 1.f) { \
+ if (z < 0.f || z > 1.f || isnan(z)) { \
dst[x] = xf1[x]; \
} else { \
const int xx = lrintf(z * (w - 1.f)); \
@@ -2001,6 +2010,8 @@
REVEALV_TRANSITION(down, 8, uint8_t, 1, )
REVEALV_TRANSITION(down, 16, uint16_t, 2, )
+#include "xfade-easing.h" // easing & extended transitions
+
static inline double getpix(void *priv, double x, double y, int plane, int nb)
{
XFadeContext *s = priv;
@@ -2102,6 +2113,9 @@
if (s->duration)
s->duration_pts = av_rescale_q(s->duration, AV_TIME_BASE_Q, outlink->time_base);
+ int ret = config_xfade_easing(ctx);
+ if (ret <= 0) return ret; // error or extended transition
+
switch (s->transition) {
case CUSTOM: s->transitionf = s->depth <= 8 ? custom8_transition : custom16_transition; break;
case FADE: s->transitionf = s->depth <= 8 ? fade8_transition : fade16_transition; break;
@@ -2214,7 +2228,14 @@
return AVERROR(ENOMEM);
av_frame_copy_props(out, a);
- td.xf[0] = a, td.xf[1] = b, td.out = out, td.progress = progress;
+ progress = (s->reverse & REVERSE_EASING) ? 1 - ease(s, 1 - progress) : ease(s, progress); // eased progress
+ int i = s->reverse & REVERSE_TRANSITION;
+ if (i) progress = 1 - progress;
+ if (s->reverse & REVERSE_OVERSHOOT) { // internal flag
+ if (progress < 0) progress += 1, i ^= 1; // undershoot
+ else if (progress > 1) progress -= 1, i ^= 1; // overshoot
+ }
+ td.xf[i] = a, td.xf[i ^ 1] = b, td.out = out, td.progress = av_clipf(progress, 0, 1);
ff_filter_execute(ctx, xfade_slice, &td, NULL,
FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));