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