avfilter/vf_overlay: use slice_end in alpha_composite()
[ffmpeg.git] / libavfilter / vf_overlay.c
1 /*
2  * Copyright (c) 2010 Stefano Sabatini
3  * Copyright (c) 2010 Baptiste Coudurier
4  * Copyright (c) 2007 Bobby Bingham
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 /**
24  * @file
25  * overlay one video on top of another
26  */
27
28 #include "avfilter.h"
29 #include "formats.h"
30 #include "libavutil/common.h"
31 #include "libavutil/eval.h"
32 #include "libavutil/avstring.h"
33 #include "libavutil/pixdesc.h"
34 #include "libavutil/imgutils.h"
35 #include "libavutil/mathematics.h"
36 #include "libavutil/opt.h"
37 #include "libavutil/timestamp.h"
38 #include "internal.h"
39 #include "drawutils.h"
40 #include "framesync.h"
41 #include "video.h"
42
43 typedef struct ThreadData {
44     AVFrame *dst, *src;
45 } ThreadData;
46
47 static const char *const var_names[] = {
48     "main_w",    "W", ///< width  of the main    video
49     "main_h",    "H", ///< height of the main    video
50     "overlay_w", "w", ///< width  of the overlay video
51     "overlay_h", "h", ///< height of the overlay video
52     "hsub",
53     "vsub",
54     "x",
55     "y",
56     "n",            ///< number of frame
57     "pos",          ///< position in the file
58     "t",            ///< timestamp expressed in seconds
59     NULL
60 };
61
62 enum var_name {
63     VAR_MAIN_W,    VAR_MW,
64     VAR_MAIN_H,    VAR_MH,
65     VAR_OVERLAY_W, VAR_OW,
66     VAR_OVERLAY_H, VAR_OH,
67     VAR_HSUB,
68     VAR_VSUB,
69     VAR_X,
70     VAR_Y,
71     VAR_N,
72     VAR_POS,
73     VAR_T,
74     VAR_VARS_NB
75 };
76
77 #define MAIN    0
78 #define OVERLAY 1
79
80 #define R 0
81 #define G 1
82 #define B 2
83 #define A 3
84
85 #define Y 0
86 #define U 1
87 #define V 2
88
89 enum EvalMode {
90     EVAL_MODE_INIT,
91     EVAL_MODE_FRAME,
92     EVAL_MODE_NB
93 };
94
95 enum OverlayFormat {
96     OVERLAY_FORMAT_YUV420,
97     OVERLAY_FORMAT_YUV422,
98     OVERLAY_FORMAT_YUV444,
99     OVERLAY_FORMAT_RGB,
100     OVERLAY_FORMAT_GBRP,
101     OVERLAY_FORMAT_AUTO,
102     OVERLAY_FORMAT_NB
103 };
104
105 typedef struct OverlayContext {
106     const AVClass *class;
107     int x, y;                   ///< position of overlaid picture
108
109     uint8_t main_is_packed_rgb;
110     uint8_t main_rgba_map[4];
111     uint8_t main_has_alpha;
112     uint8_t overlay_is_packed_rgb;
113     uint8_t overlay_rgba_map[4];
114     uint8_t overlay_has_alpha;
115     int format;                 ///< OverlayFormat
116     int alpha_format;
117     int eval_mode;              ///< EvalMode
118
119     FFFrameSync fs;
120
121     int main_pix_step[4];       ///< steps per pixel for each plane of the main output
122     int overlay_pix_step[4];    ///< steps per pixel for each plane of the overlay
123     int hsub, vsub;             ///< chroma subsampling values
124     const AVPixFmtDescriptor *main_desc; ///< format descriptor for main input
125
126     double var_values[VAR_VARS_NB];
127     char *x_expr, *y_expr;
128
129     AVExpr *x_pexpr, *y_pexpr;
130
131     int (*blend_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
132 } OverlayContext;
133
134 static av_cold void uninit(AVFilterContext *ctx)
135 {
136     OverlayContext *s = ctx->priv;
137
138     ff_framesync_uninit(&s->fs);
139     av_expr_free(s->x_pexpr); s->x_pexpr = NULL;
140     av_expr_free(s->y_pexpr); s->y_pexpr = NULL;
141 }
142
143 static inline int normalize_xy(double d, int chroma_sub)
144 {
145     if (isnan(d))
146         return INT_MAX;
147     return (int)d & ~((1 << chroma_sub) - 1);
148 }
149
150 static void eval_expr(AVFilterContext *ctx)
151 {
152     OverlayContext *s = ctx->priv;
153
154     s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL);
155     s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, NULL);
156     /* It is necessary if x is expressed from y  */
157     s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL);
158     s->x = normalize_xy(s->var_values[VAR_X], s->hsub);
159     s->y = normalize_xy(s->var_values[VAR_Y], s->vsub);
160 }
161
162 static int set_expr(AVExpr **pexpr, const char *expr, const char *option, void *log_ctx)
163 {
164     int ret;
165     AVExpr *old = NULL;
166
167     if (*pexpr)
168         old = *pexpr;
169     ret = av_expr_parse(pexpr, expr, var_names,
170                         NULL, NULL, NULL, NULL, 0, log_ctx);
171     if (ret < 0) {
172         av_log(log_ctx, AV_LOG_ERROR,
173                "Error when evaluating the expression '%s' for %s\n",
174                expr, option);
175         *pexpr = old;
176         return ret;
177     }
178
179     av_expr_free(old);
180     return 0;
181 }
182
183 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
184                            char *res, int res_len, int flags)
185 {
186     OverlayContext *s = ctx->priv;
187     int ret;
188
189     if      (!strcmp(cmd, "x"))
190         ret = set_expr(&s->x_pexpr, args, cmd, ctx);
191     else if (!strcmp(cmd, "y"))
192         ret = set_expr(&s->y_pexpr, args, cmd, ctx);
193     else
194         ret = AVERROR(ENOSYS);
195
196     if (ret < 0)
197         return ret;
198
199     if (s->eval_mode == EVAL_MODE_INIT) {
200         eval_expr(ctx);
201         av_log(ctx, AV_LOG_VERBOSE, "x:%f xi:%d y:%f yi:%d\n",
202                s->var_values[VAR_X], s->x,
203                s->var_values[VAR_Y], s->y);
204     }
205     return ret;
206 }
207
208 static const enum AVPixelFormat alpha_pix_fmts[] = {
209     AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
210     AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_RGBA,
211     AV_PIX_FMT_BGRA, AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE
212 };
213
214 static int query_formats(AVFilterContext *ctx)
215 {
216     OverlayContext *s = ctx->priv;
217
218     /* overlay formats contains alpha, for avoiding conversion with alpha information loss */
219     static const enum AVPixelFormat main_pix_fmts_yuv420[] = {
220         AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVA420P,
221         AV_PIX_FMT_NV12, AV_PIX_FMT_NV21,
222         AV_PIX_FMT_NONE
223     };
224     static const enum AVPixelFormat overlay_pix_fmts_yuv420[] = {
225         AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE
226     };
227
228     static const enum AVPixelFormat main_pix_fmts_yuv422[] = {
229         AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_NONE
230     };
231     static const enum AVPixelFormat overlay_pix_fmts_yuv422[] = {
232         AV_PIX_FMT_YUVA422P, AV_PIX_FMT_NONE
233     };
234
235     static const enum AVPixelFormat main_pix_fmts_yuv444[] = {
236         AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE
237     };
238     static const enum AVPixelFormat overlay_pix_fmts_yuv444[] = {
239         AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE
240     };
241
242     static const enum AVPixelFormat main_pix_fmts_gbrp[] = {
243         AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE
244     };
245     static const enum AVPixelFormat overlay_pix_fmts_gbrp[] = {
246         AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE
247     };
248
249     static const enum AVPixelFormat main_pix_fmts_rgb[] = {
250         AV_PIX_FMT_ARGB,  AV_PIX_FMT_RGBA,
251         AV_PIX_FMT_ABGR,  AV_PIX_FMT_BGRA,
252         AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
253         AV_PIX_FMT_NONE
254     };
255     static const enum AVPixelFormat overlay_pix_fmts_rgb[] = {
256         AV_PIX_FMT_ARGB,  AV_PIX_FMT_RGBA,
257         AV_PIX_FMT_ABGR,  AV_PIX_FMT_BGRA,
258         AV_PIX_FMT_NONE
259     };
260
261     AVFilterFormats *main_formats = NULL;
262     AVFilterFormats *overlay_formats = NULL;
263     int ret;
264
265     switch (s->format) {
266     case OVERLAY_FORMAT_YUV420:
267         if (!(main_formats    = ff_make_format_list(main_pix_fmts_yuv420)) ||
268             !(overlay_formats = ff_make_format_list(overlay_pix_fmts_yuv420))) {
269                 ret = AVERROR(ENOMEM);
270                 goto fail;
271             }
272         break;
273     case OVERLAY_FORMAT_YUV422:
274         if (!(main_formats    = ff_make_format_list(main_pix_fmts_yuv422)) ||
275             !(overlay_formats = ff_make_format_list(overlay_pix_fmts_yuv422))) {
276                 ret = AVERROR(ENOMEM);
277                 goto fail;
278             }
279         break;
280     case OVERLAY_FORMAT_YUV444:
281         if (!(main_formats    = ff_make_format_list(main_pix_fmts_yuv444)) ||
282             !(overlay_formats = ff_make_format_list(overlay_pix_fmts_yuv444))) {
283                 ret = AVERROR(ENOMEM);
284                 goto fail;
285             }
286         break;
287     case OVERLAY_FORMAT_RGB:
288         if (!(main_formats    = ff_make_format_list(main_pix_fmts_rgb)) ||
289             !(overlay_formats = ff_make_format_list(overlay_pix_fmts_rgb))) {
290                 ret = AVERROR(ENOMEM);
291                 goto fail;
292             }
293         break;
294     case OVERLAY_FORMAT_GBRP:
295         if (!(main_formats    = ff_make_format_list(main_pix_fmts_gbrp)) ||
296             !(overlay_formats = ff_make_format_list(overlay_pix_fmts_gbrp))) {
297                 ret = AVERROR(ENOMEM);
298                 goto fail;
299             }
300         break;
301     case OVERLAY_FORMAT_AUTO:
302         if (!(main_formats    = ff_make_format_list(alpha_pix_fmts))) {
303                 ret = AVERROR(ENOMEM);
304                 goto fail;
305             }
306         break;
307     default:
308         av_assert0(0);
309     }
310
311     if (s->format == OVERLAY_FORMAT_AUTO) {
312         ret = ff_set_common_formats(ctx, main_formats);
313         if (ret < 0)
314             goto fail;
315     } else {
316         if ((ret = ff_formats_ref(main_formats   , &ctx->inputs[MAIN]->out_formats   )) < 0 ||
317             (ret = ff_formats_ref(overlay_formats, &ctx->inputs[OVERLAY]->out_formats)) < 0 ||
318             (ret = ff_formats_ref(main_formats   , &ctx->outputs[MAIN]->in_formats   )) < 0)
319                 goto fail;
320     }
321
322     return 0;
323 fail:
324     if (main_formats)
325         av_freep(&main_formats->formats);
326     av_freep(&main_formats);
327     if (overlay_formats)
328         av_freep(&overlay_formats->formats);
329     av_freep(&overlay_formats);
330     return ret;
331 }
332
333 static int config_input_overlay(AVFilterLink *inlink)
334 {
335     AVFilterContext *ctx  = inlink->dst;
336     OverlayContext  *s = inlink->dst->priv;
337     int ret;
338     const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
339
340     av_image_fill_max_pixsteps(s->overlay_pix_step, NULL, pix_desc);
341
342     /* Finish the configuration by evaluating the expressions
343        now when both inputs are configured. */
344     s->var_values[VAR_MAIN_W   ] = s->var_values[VAR_MW] = ctx->inputs[MAIN   ]->w;
345     s->var_values[VAR_MAIN_H   ] = s->var_values[VAR_MH] = ctx->inputs[MAIN   ]->h;
346     s->var_values[VAR_OVERLAY_W] = s->var_values[VAR_OW] = ctx->inputs[OVERLAY]->w;
347     s->var_values[VAR_OVERLAY_H] = s->var_values[VAR_OH] = ctx->inputs[OVERLAY]->h;
348     s->var_values[VAR_HSUB]  = 1<<pix_desc->log2_chroma_w;
349     s->var_values[VAR_VSUB]  = 1<<pix_desc->log2_chroma_h;
350     s->var_values[VAR_X]     = NAN;
351     s->var_values[VAR_Y]     = NAN;
352     s->var_values[VAR_N]     = 0;
353     s->var_values[VAR_T]     = NAN;
354     s->var_values[VAR_POS]   = NAN;
355
356     if ((ret = set_expr(&s->x_pexpr,      s->x_expr,      "x",      ctx)) < 0 ||
357         (ret = set_expr(&s->y_pexpr,      s->y_expr,      "y",      ctx)) < 0)
358         return ret;
359
360     s->overlay_is_packed_rgb =
361         ff_fill_rgba_map(s->overlay_rgba_map, inlink->format) >= 0;
362     s->overlay_has_alpha = ff_fmt_is_in(inlink->format, alpha_pix_fmts);
363
364     if (s->eval_mode == EVAL_MODE_INIT) {
365         eval_expr(ctx);
366         av_log(ctx, AV_LOG_VERBOSE, "x:%f xi:%d y:%f yi:%d\n",
367                s->var_values[VAR_X], s->x,
368                s->var_values[VAR_Y], s->y);
369     }
370
371     av_log(ctx, AV_LOG_VERBOSE,
372            "main w:%d h:%d fmt:%s overlay w:%d h:%d fmt:%s\n",
373            ctx->inputs[MAIN]->w, ctx->inputs[MAIN]->h,
374            av_get_pix_fmt_name(ctx->inputs[MAIN]->format),
375            ctx->inputs[OVERLAY]->w, ctx->inputs[OVERLAY]->h,
376            av_get_pix_fmt_name(ctx->inputs[OVERLAY]->format));
377     return 0;
378 }
379
380 static int config_output(AVFilterLink *outlink)
381 {
382     AVFilterContext *ctx = outlink->src;
383     OverlayContext *s = ctx->priv;
384     int ret;
385
386     if ((ret = ff_framesync_init_dualinput(&s->fs, ctx)) < 0)
387         return ret;
388
389     outlink->w = ctx->inputs[MAIN]->w;
390     outlink->h = ctx->inputs[MAIN]->h;
391     outlink->time_base = ctx->inputs[MAIN]->time_base;
392
393     return ff_framesync_configure(&s->fs);
394 }
395
396 // divide by 255 and round to nearest
397 // apply a fast variant: (X+127)/255 = ((X+127)*257+257)>>16 = ((X+128)*257)>>16
398 #define FAST_DIV255(x) ((((x) + 128) * 257) >> 16)
399
400 // calculate the unpremultiplied alpha, applying the general equation:
401 // alpha = alpha_overlay / ( (alpha_main + alpha_overlay) - (alpha_main * alpha_overlay) )
402 // (((x) << 16) - ((x) << 9) + (x)) is a faster version of: 255 * 255 * x
403 // ((((x) + (y)) << 8) - ((x) + (y)) - (y) * (x)) is a faster version of: 255 * (x + y)
404 #define UNPREMULTIPLY_ALPHA(x, y) ((((x) << 16) - ((x) << 9) + (x)) / ((((x) + (y)) << 8) - ((x) + (y)) - (y) * (x)))
405
406 /**
407  * Blend image in src to destination buffer dst at position (x, y).
408  */
409
410 static av_always_inline void blend_slice_packed_rgb(AVFilterContext *ctx,
411                                    AVFrame *dst, const AVFrame *src,
412                                    int main_has_alpha, int x, int y,
413                                    int is_straight, int jobnr, int nb_jobs)
414 {
415     OverlayContext *s = ctx->priv;
416     int i, imax, j, jmax;
417     const int src_w = src->width;
418     const int src_h = src->height;
419     const int dst_w = dst->width;
420     const int dst_h = dst->height;
421     uint8_t alpha;          ///< the amount of overlay to blend on to main
422     const int dr = s->main_rgba_map[R];
423     const int dg = s->main_rgba_map[G];
424     const int db = s->main_rgba_map[B];
425     const int da = s->main_rgba_map[A];
426     const int dstep = s->main_pix_step[0];
427     const int sr = s->overlay_rgba_map[R];
428     const int sg = s->overlay_rgba_map[G];
429     const int sb = s->overlay_rgba_map[B];
430     const int sa = s->overlay_rgba_map[A];
431     const int sstep = s->overlay_pix_step[0];
432     int slice_start, slice_end;
433     uint8_t *S, *sp, *d, *dp;
434
435     i = FFMAX(-y, 0);
436     imax = FFMIN(-y + dst_h, src_h);
437
438     slice_start = (imax * jobnr) / nb_jobs;
439     slice_end = (imax * (jobnr+1)) / nb_jobs;
440
441     sp = src->data[0] + (i + slice_start)     * src->linesize[0];
442     dp = dst->data[0] + (y + i + slice_start) * dst->linesize[0];
443
444     for (i = i + slice_start; i < slice_end; i++) {
445         j = FFMAX(-x, 0);
446         S = sp + j     * sstep;
447         d = dp + (x+j) * dstep;
448
449         for (jmax = FFMIN(-x + dst_w, src_w); j < jmax; j++) {
450             alpha = S[sa];
451
452             // if the main channel has an alpha channel, alpha has to be calculated
453             // to create an un-premultiplied (straight) alpha value
454             if (main_has_alpha && alpha != 0 && alpha != 255) {
455                 uint8_t alpha_d = d[da];
456                 alpha = UNPREMULTIPLY_ALPHA(alpha, alpha_d);
457             }
458
459             switch (alpha) {
460             case 0:
461                 break;
462             case 255:
463                 d[dr] = S[sr];
464                 d[dg] = S[sg];
465                 d[db] = S[sb];
466                 break;
467             default:
468                 // main_value = main_value * (1 - alpha) + overlay_value * alpha
469                 // since alpha is in the range 0-255, the result must divided by 255
470                 d[dr] = is_straight ? FAST_DIV255(d[dr] * (255 - alpha) + S[sr] * alpha) :
471                         FFMIN(FAST_DIV255(d[dr] * (255 - alpha)) + S[sr], 255);
472                 d[dg] = is_straight ? FAST_DIV255(d[dg] * (255 - alpha) + S[sg] * alpha) :
473                         FFMIN(FAST_DIV255(d[dg] * (255 - alpha)) + S[sg], 255);
474                 d[db] = is_straight ? FAST_DIV255(d[db] * (255 - alpha) + S[sb] * alpha) :
475                         FFMIN(FAST_DIV255(d[db] * (255 - alpha)) + S[sb], 255);
476             }
477             if (main_has_alpha) {
478                 switch (alpha) {
479                 case 0:
480                     break;
481                 case 255:
482                     d[da] = S[sa];
483                     break;
484                 default:
485                     // apply alpha compositing: main_alpha += (1-main_alpha) * overlay_alpha
486                     d[da] += FAST_DIV255((255 - d[da]) * S[sa]);
487                 }
488             }
489             d += dstep;
490             S += sstep;
491         }
492         dp += dst->linesize[0];
493         sp += src->linesize[0];
494     }
495 }
496
497 static av_always_inline void blend_plane(AVFilterContext *ctx,
498                                          AVFrame *dst, const AVFrame *src,
499                                          int src_w, int src_h,
500                                          int dst_w, int dst_h,
501                                          int i, int hsub, int vsub,
502                                          int x, int y,
503                                          int main_has_alpha,
504                                          int dst_plane,
505                                          int dst_offset,
506                                          int dst_step,
507                                          int straight,
508                                          int yuv,
509                                          int jobnr,
510                                          int nb_jobs)
511 {
512     int src_wp = AV_CEIL_RSHIFT(src_w, hsub);
513     int src_hp = AV_CEIL_RSHIFT(src_h, vsub);
514     int dst_wp = AV_CEIL_RSHIFT(dst_w, hsub);
515     int dst_hp = AV_CEIL_RSHIFT(dst_h, vsub);
516     int yp = y>>vsub;
517     int xp = x>>hsub;
518     uint8_t *s, *sp, *d, *dp, *dap, *a, *da, *ap;
519     int jmax, j, k, kmax;
520     int slice_start, slice_end;
521
522     j = FFMAX(-yp, 0);
523     jmax = FFMIN(-yp + dst_hp, src_hp);
524
525     slice_start = (jmax * jobnr) / nb_jobs;
526     slice_end = (jmax * (jobnr+1)) / nb_jobs;
527
528     sp = src->data[i] + slice_start * src->linesize[i];
529     dp = dst->data[dst_plane]
530                       + (yp + slice_start) * dst->linesize[dst_plane]
531                       + dst_offset;
532     ap = src->data[3] + (slice_start << vsub) * src->linesize[3];
533     dap = dst->data[3] + ((yp + slice_start) << vsub) * dst->linesize[3];
534
535     for (j = j + slice_start; j < slice_end; j++) {
536         k = FFMAX(-xp, 0);
537         d = dp + (xp+k) * dst_step;
538         s = sp + k;
539         a = ap + (k<<hsub);
540         da = dap + ((xp+k) << hsub);
541
542         for (kmax = FFMIN(-xp + dst_wp, src_wp); k < kmax; k++) {
543             int alpha_v, alpha_h, alpha;
544
545             // average alpha for color components, improve quality
546             if (hsub && vsub && j+1 < src_hp && k+1 < src_wp) {
547                 alpha = (a[0] + a[src->linesize[3]] +
548                          a[1] + a[src->linesize[3]+1]) >> 2;
549             } else if (hsub || vsub) {
550                 alpha_h = hsub && k+1 < src_wp ?
551                     (a[0] + a[1]) >> 1 : a[0];
552                 alpha_v = vsub && j+1 < src_hp ?
553                     (a[0] + a[src->linesize[3]]) >> 1 : a[0];
554                 alpha = (alpha_v + alpha_h) >> 1;
555             } else
556                 alpha = a[0];
557             // if the main channel has an alpha channel, alpha has to be calculated
558             // to create an un-premultiplied (straight) alpha value
559             if (main_has_alpha && alpha != 0 && alpha != 255) {
560                 // average alpha for color components, improve quality
561                 uint8_t alpha_d;
562                 if (hsub && vsub && j+1 < src_hp && k+1 < src_wp) {
563                     alpha_d = (da[0] + da[dst->linesize[3]] +
564                                da[1] + da[dst->linesize[3]+1]) >> 2;
565                 } else if (hsub || vsub) {
566                     alpha_h = hsub && k+1 < src_wp ?
567                         (da[0] + da[1]) >> 1 : da[0];
568                     alpha_v = vsub && j+1 < src_hp ?
569                         (da[0] + da[dst->linesize[3]]) >> 1 : da[0];
570                     alpha_d = (alpha_v + alpha_h) >> 1;
571                 } else
572                     alpha_d = da[0];
573                 alpha = UNPREMULTIPLY_ALPHA(alpha, alpha_d);
574             }
575             if (straight) {
576                 *d = FAST_DIV255(*d * (255 - alpha) + *s * alpha);
577             } else {
578                 if (i && yuv)
579                     *d = av_clip(FAST_DIV255((*d - 128) * (255 - alpha)) + *s - 128, -128, 128) + 128;
580                 else
581                     *d = FFMIN(FAST_DIV255(*d * (255 - alpha)) + *s, 255);
582             }
583             s++;
584             d += dst_step;
585             da += 1 << hsub;
586             a += 1 << hsub;
587         }
588         dp += dst->linesize[dst_plane];
589         sp += src->linesize[i];
590         ap += (1 << vsub) * src->linesize[3];
591         dap += (1 << vsub) * dst->linesize[3];
592     }
593 }
594
595 static inline void alpha_composite(const AVFrame *src, const AVFrame *dst,
596                                    int src_w, int src_h,
597                                    int dst_w, int dst_h,
598                                    int x, int y,
599                                    int jobnr, int nb_jobs)
600 {
601     uint8_t alpha;          ///< the amount of overlay to blend on to main
602     uint8_t *s, *sa, *d, *da;
603     int i, imax, j, jmax;
604     int slice_start, slice_end;
605
606     imax = FFMIN(-y + dst_h, src_h);
607     slice_start = (imax * jobnr) / nb_jobs;
608     slice_end = ((imax * (jobnr+1)) / nb_jobs);
609
610     i = FFMAX(-y, 0);
611     sa = src->data[3] + (i + slice_start) * src->linesize[3];
612     da = dst->data[3] + (y + i + slice_start) * dst->linesize[3];
613
614     for (i = i + slice_start; i < slice_end; i++) {
615         j = FFMAX(-x, 0);
616         s = sa + j;
617         d = da + x+j;
618
619         for (jmax = FFMIN(-x + dst_w, src_w); j < jmax; j++) {
620             alpha = *s;
621             if (alpha != 0 && alpha != 255) {
622                 uint8_t alpha_d = *d;
623                 alpha = UNPREMULTIPLY_ALPHA(alpha, alpha_d);
624             }
625             switch (alpha) {
626             case 0:
627                 break;
628             case 255:
629                 *d = *s;
630                 break;
631             default:
632                 // apply alpha compositing: main_alpha += (1-main_alpha) * overlay_alpha
633                 *d += FAST_DIV255((255 - *d) * *s);
634             }
635             d += 1;
636             s += 1;
637         }
638         da += dst->linesize[3];
639         sa += src->linesize[3];
640     }
641 }
642
643 static av_always_inline void blend_slice_yuv(AVFilterContext *ctx,
644                                              AVFrame *dst, const AVFrame *src,
645                                              int hsub, int vsub,
646                                              int main_has_alpha,
647                                              int x, int y,
648                                              int is_straight,
649                                              int jobnr, int nb_jobs)
650 {
651     OverlayContext *s = ctx->priv;
652     const int src_w = src->width;
653     const int src_h = src->height;
654     const int dst_w = dst->width;
655     const int dst_h = dst->height;
656
657     blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0,       0, x, y, main_has_alpha,
658                 s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, s->main_desc->comp[0].step, is_straight, 1,
659                 jobnr, nb_jobs);
660     blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, x, y, main_has_alpha,
661                 s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, s->main_desc->comp[1].step, is_straight, 1,
662                 jobnr, nb_jobs);
663     blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, x, y, main_has_alpha,
664                 s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, s->main_desc->comp[2].step, is_straight, 1,
665                 jobnr, nb_jobs);
666
667     if (main_has_alpha)
668         alpha_composite(src, dst, src_w, src_h, dst_w, dst_h, x, y, jobnr, nb_jobs);
669 }
670
671 static av_always_inline void blend_slice_planar_rgb(AVFilterContext *ctx,
672                                                     AVFrame *dst, const AVFrame *src,
673                                                     int hsub, int vsub,
674                                                     int main_has_alpha,
675                                                     int x, int y,
676                                                     int is_straight,
677                                                     int jobnr,
678                                                     int nb_jobs)
679 {
680     OverlayContext *s = ctx->priv;
681     const int src_w = src->width;
682     const int src_h = src->height;
683     const int dst_w = dst->width;
684     const int dst_h = dst->height;
685
686     blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0,       0, x, y, main_has_alpha,
687                 s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, s->main_desc->comp[1].step, is_straight, 0,
688                 jobnr, nb_jobs);
689     blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, x, y, main_has_alpha,
690                 s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, s->main_desc->comp[2].step, is_straight, 0,
691                 jobnr, nb_jobs);
692     blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, x, y, main_has_alpha,
693                 s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, s->main_desc->comp[0].step, is_straight, 0,
694                 jobnr, nb_jobs);
695
696     if (main_has_alpha)
697         alpha_composite(src, dst, src_w, src_h, dst_w, dst_h, x, y, jobnr, nb_jobs);
698 }
699
700 static int blend_slice_yuv420(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
701 {
702     OverlayContext *s = ctx->priv;
703     ThreadData *td = arg;
704     blend_slice_yuv(ctx, td->dst, td->src, 1, 1, 0, s->x, s->y, 1, jobnr, nb_jobs);
705     return 0;
706 }
707
708 static int blend_slice_yuva420(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
709 {
710     OverlayContext *s = ctx->priv;
711     ThreadData *td = arg;
712     blend_slice_yuv(ctx, td->dst, td->src, 1, 1, 1, s->x, s->y, 1, jobnr, nb_jobs);
713     return 0;
714 }
715
716 static int blend_slice_yuv422(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
717 {
718     OverlayContext *s = ctx->priv;
719     ThreadData *td = arg;
720     blend_slice_yuv(ctx, td->dst, td->src, 1, 0, 0, s->x, s->y, 1, jobnr, nb_jobs);
721     return 0;
722 }
723
724 static int blend_slice_yuva422(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
725 {
726     OverlayContext *s = ctx->priv;
727     ThreadData *td = arg;
728     blend_slice_yuv(ctx, td->dst, td->src, 1, 0, 1, s->x, s->y, 1, jobnr, nb_jobs);
729     return 0;
730 }
731
732 static int blend_slice_yuv444(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
733 {
734     OverlayContext *s = ctx->priv;
735     ThreadData *td = arg;
736     blend_slice_yuv(ctx, td->dst, td->src, 0, 0, 0, s->x, s->y, 1, jobnr, nb_jobs);
737     return 0;
738 }
739
740 static int blend_slice_yuva444(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
741 {
742     OverlayContext *s = ctx->priv;
743     ThreadData *td = arg;
744     blend_slice_yuv(ctx, td->dst, td->src, 0, 0, 1, s->x, s->y, 1, jobnr, nb_jobs);
745     return 0;
746 }
747
748 static int blend_slice_gbrp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
749 {
750     OverlayContext *s = ctx->priv;
751     ThreadData *td = arg;
752     blend_slice_planar_rgb(ctx, td->dst, td->src, 0, 0, 0, s->x, s->y, 1, jobnr, nb_jobs);
753     return 0;
754 }
755
756 static int blend_slice_gbrap(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
757 {
758     OverlayContext *s = ctx->priv;
759     ThreadData *td = arg;
760     blend_slice_planar_rgb(ctx, td->dst, td->src, 0, 0, 1, s->x, s->y, 1, jobnr, nb_jobs);
761     return 0;
762 }
763
764 static int blend_slice_yuv420_pm(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
765 {
766     OverlayContext *s = ctx->priv;
767     ThreadData *td = arg;
768     blend_slice_yuv(ctx, td->dst, td->src, 1, 1, 0, s->x, s->y, 0, jobnr, nb_jobs);
769     return 0;
770 }
771
772 static int blend_slice_yuva420_pm(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
773 {
774     OverlayContext *s = ctx->priv;
775     ThreadData *td = arg;
776     blend_slice_yuv(ctx, td->dst, td->src, 1, 1, 1, s->x, s->y, 0, jobnr, nb_jobs);
777     return 0;
778 }
779
780 static int blend_slice_yuv422_pm(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
781 {
782     OverlayContext *s = ctx->priv;
783     ThreadData *td = arg;
784     blend_slice_yuv(ctx, td->dst, td->src, 1, 0, 0, s->x, s->y, 0, jobnr, nb_jobs);
785     return 0;
786 }
787
788 static int blend_slice_yuva422_pm(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
789 {
790     OverlayContext *s = ctx->priv;
791     ThreadData *td = arg;
792     blend_slice_yuv(ctx, td->dst, td->src, 1, 0, 1, s->x, s->y, 0, jobnr, nb_jobs);
793     return 0;
794 }
795
796 static int blend_slice_yuv444_pm(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
797 {
798     OverlayContext *s = ctx->priv;
799     ThreadData *td = arg;
800     blend_slice_yuv(ctx, td->dst, td->src, 0, 0, 0, s->x, s->y, 0, jobnr, nb_jobs);
801     return 0;
802 }
803
804 static int blend_slice_yuva444_pm(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
805 {
806     OverlayContext *s = ctx->priv;
807     ThreadData *td = arg;
808     blend_slice_yuv(ctx, td->dst, td->src, 0, 0, 1, s->x, s->y, 0, jobnr, nb_jobs);
809     return 0;
810 }
811
812 static int blend_slice_gbrp_pm(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
813 {
814     OverlayContext *s = ctx->priv;
815     ThreadData *td = arg;
816     blend_slice_planar_rgb(ctx, td->dst, td->src, 0, 0, 0, s->x, s->y, 0, jobnr, nb_jobs);
817     return 0;
818 }
819
820 static int blend_slice_gbrap_pm(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
821 {
822     OverlayContext *s = ctx->priv;
823     ThreadData *td = arg;
824     blend_slice_planar_rgb(ctx, td->dst, td->src, 0, 0, 1, s->x, s->y, 0, jobnr, nb_jobs);
825     return 0;
826 }
827
828 static int blend_slice_rgb(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
829 {
830     OverlayContext *s = ctx->priv;
831     ThreadData *td = arg;
832     blend_slice_packed_rgb(ctx, td->dst, td->src, 0, s->x, s->y, 1, jobnr, nb_jobs);
833     return 0;
834 }
835
836 static int blend_slice_rgba(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
837 {
838     OverlayContext *s = ctx->priv;
839     ThreadData *td = arg;
840     blend_slice_packed_rgb(ctx, td->dst, td->src, 1, s->x, s->y, 1, jobnr, nb_jobs);
841     return 0;
842 }
843
844 static int blend_slice_rgb_pm(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
845 {
846     OverlayContext *s = ctx->priv;
847     ThreadData *td = arg;
848     blend_slice_packed_rgb(ctx, td->dst, td->src, 0, s->x, s->y, 0, jobnr, nb_jobs);
849     return 0;
850 }
851
852 static int blend_slice_rgba_pm(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
853 {
854     OverlayContext *s = ctx->priv;
855     ThreadData *td = arg;
856     blend_slice_packed_rgb(ctx, td->dst, td->src, 1, s->x, s->y, 0, jobnr, nb_jobs);
857     return 0;
858 }
859
860 static int config_input_main(AVFilterLink *inlink)
861 {
862     OverlayContext *s = inlink->dst->priv;
863     const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
864
865     av_image_fill_max_pixsteps(s->main_pix_step,    NULL, pix_desc);
866
867     s->hsub = pix_desc->log2_chroma_w;
868     s->vsub = pix_desc->log2_chroma_h;
869
870     s->main_desc = pix_desc;
871
872     s->main_is_packed_rgb =
873         ff_fill_rgba_map(s->main_rgba_map, inlink->format) >= 0;
874     s->main_has_alpha = ff_fmt_is_in(inlink->format, alpha_pix_fmts);
875     switch (s->format) {
876     case OVERLAY_FORMAT_YUV420:
877         s->blend_slice = s->main_has_alpha ? blend_slice_yuva420 : blend_slice_yuv420;
878         break;
879     case OVERLAY_FORMAT_YUV422:
880         s->blend_slice = s->main_has_alpha ? blend_slice_yuva422 : blend_slice_yuv422;
881         break;
882     case OVERLAY_FORMAT_YUV444:
883         s->blend_slice = s->main_has_alpha ? blend_slice_yuva444 : blend_slice_yuv444;
884         break;
885     case OVERLAY_FORMAT_RGB:
886         s->blend_slice = s->main_has_alpha ? blend_slice_rgba : blend_slice_rgb;
887         break;
888     case OVERLAY_FORMAT_GBRP:
889         s->blend_slice = s->main_has_alpha ? blend_slice_gbrap : blend_slice_gbrp;
890         break;
891     case OVERLAY_FORMAT_AUTO:
892         switch (inlink->format) {
893         case AV_PIX_FMT_YUVA420P:
894             s->blend_slice = blend_slice_yuva420;
895             break;
896         case AV_PIX_FMT_YUVA422P:
897             s->blend_slice = blend_slice_yuva422;
898             break;
899         case AV_PIX_FMT_YUVA444P:
900             s->blend_slice = blend_slice_yuva444;
901             break;
902         case AV_PIX_FMT_ARGB:
903         case AV_PIX_FMT_RGBA:
904         case AV_PIX_FMT_BGRA:
905         case AV_PIX_FMT_ABGR:
906             s->blend_slice = blend_slice_rgba;
907             break;
908         case AV_PIX_FMT_GBRAP:
909             s->blend_slice = blend_slice_gbrap;
910             break;
911         default:
912             av_assert0(0);
913             break;
914         }
915         break;
916     }
917
918     if (!s->alpha_format)
919         return 0;
920
921     switch (s->format) {
922     case OVERLAY_FORMAT_YUV420:
923         s->blend_slice = s->main_has_alpha ? blend_slice_yuva420_pm : blend_slice_yuv420_pm;
924         break;
925     case OVERLAY_FORMAT_YUV422:
926         s->blend_slice = s->main_has_alpha ? blend_slice_yuva422_pm : blend_slice_yuv422_pm;
927         break;
928     case OVERLAY_FORMAT_YUV444:
929         s->blend_slice = s->main_has_alpha ? blend_slice_yuva444_pm : blend_slice_yuv444_pm;
930         break;
931     case OVERLAY_FORMAT_RGB:
932         s->blend_slice = s->main_has_alpha ? blend_slice_rgba_pm : blend_slice_rgb_pm;
933         break;
934     case OVERLAY_FORMAT_GBRP:
935         s->blend_slice = s->main_has_alpha ? blend_slice_gbrap_pm : blend_slice_gbrp_pm;
936         break;
937     case OVERLAY_FORMAT_AUTO:
938         switch (inlink->format) {
939         case AV_PIX_FMT_YUVA420P:
940             s->blend_slice = blend_slice_yuva420_pm;
941             break;
942         case AV_PIX_FMT_YUVA422P:
943             s->blend_slice = blend_slice_yuva422_pm;
944             break;
945         case AV_PIX_FMT_YUVA444P:
946             s->blend_slice = blend_slice_yuva444_pm;
947             break;
948         case AV_PIX_FMT_ARGB:
949         case AV_PIX_FMT_RGBA:
950         case AV_PIX_FMT_BGRA:
951         case AV_PIX_FMT_ABGR:
952             s->blend_slice = blend_slice_rgba_pm;
953             break;
954         case AV_PIX_FMT_GBRAP:
955             s->blend_slice = blend_slice_gbrap_pm;
956             break;
957         default:
958             av_assert0(0);
959             break;
960         }
961         break;
962     }
963     return 0;
964 }
965
966 static int do_blend(FFFrameSync *fs)
967 {
968     AVFilterContext *ctx = fs->parent;
969     AVFrame *mainpic, *second;
970     OverlayContext *s = ctx->priv;
971     AVFilterLink *inlink = ctx->inputs[0];
972     int ret;
973
974     ret = ff_framesync_dualinput_get_writable(fs, &mainpic, &second);
975     if (ret < 0)
976         return ret;
977     if (!second)
978         return ff_filter_frame(ctx->outputs[0], mainpic);
979
980     if (s->eval_mode == EVAL_MODE_FRAME) {
981         int64_t pos = mainpic->pkt_pos;
982
983         s->var_values[VAR_N] = inlink->frame_count_out;
984         s->var_values[VAR_T] = mainpic->pts == AV_NOPTS_VALUE ?
985             NAN : mainpic->pts * av_q2d(inlink->time_base);
986         s->var_values[VAR_POS] = pos == -1 ? NAN : pos;
987
988         s->var_values[VAR_OVERLAY_W] = s->var_values[VAR_OW] = second->width;
989         s->var_values[VAR_OVERLAY_H] = s->var_values[VAR_OH] = second->height;
990         s->var_values[VAR_MAIN_W   ] = s->var_values[VAR_MW] = mainpic->width;
991         s->var_values[VAR_MAIN_H   ] = s->var_values[VAR_MH] = mainpic->height;
992
993         eval_expr(ctx);
994         av_log(ctx, AV_LOG_DEBUG, "n:%f t:%f pos:%f x:%f xi:%d y:%f yi:%d\n",
995                s->var_values[VAR_N], s->var_values[VAR_T], s->var_values[VAR_POS],
996                s->var_values[VAR_X], s->x,
997                s->var_values[VAR_Y], s->y);
998     }
999
1000     if (s->x < mainpic->width  && s->x + second->width  >= 0 ||
1001         s->y < mainpic->height && s->y + second->height >= 0) {
1002         ThreadData td;
1003
1004         td.dst = mainpic;
1005         td.src = second;
1006         ctx->internal->execute(ctx, s->blend_slice, &td, NULL, FFMIN(FFMIN(mainpic->height - s->y, second->height),
1007                                                                      ff_filter_get_nb_threads(ctx)));
1008     }
1009     return ff_filter_frame(ctx->outputs[0], mainpic);
1010 }
1011
1012 static av_cold int init(AVFilterContext *ctx)
1013 {
1014     OverlayContext *s = ctx->priv;
1015
1016     s->fs.on_event = do_blend;
1017     return 0;
1018 }
1019
1020 static int activate(AVFilterContext *ctx)
1021 {
1022     OverlayContext *s = ctx->priv;
1023     return ff_framesync_activate(&s->fs);
1024 }
1025
1026 #define OFFSET(x) offsetof(OverlayContext, x)
1027 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
1028
1029 static const AVOption overlay_options[] = {
1030     { "x", "set the x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX, FLAGS },
1031     { "y", "set the y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX, FLAGS },
1032     { "eof_action", "Action to take when encountering EOF from secondary input ",
1033         OFFSET(fs.opt_eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT },
1034         EOF_ACTION_REPEAT, EOF_ACTION_PASS, .flags = FLAGS, "eof_action" },
1035         { "repeat", "Repeat the previous frame.",   0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_REPEAT }, .flags = FLAGS, "eof_action" },
1036         { "endall", "End both streams.",            0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_ENDALL }, .flags = FLAGS, "eof_action" },
1037         { "pass",   "Pass through the main input.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_PASS },   .flags = FLAGS, "eof_action" },
1038     { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_FRAME}, 0, EVAL_MODE_NB-1, FLAGS, "eval" },
1039          { "init",  "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT},  .flags = FLAGS, .unit = "eval" },
1040          { "frame", "eval expressions per-frame",                  0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" },
1041     { "shortest", "force termination when the shortest input terminates", OFFSET(fs.opt_shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
1042     { "format", "set output format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=OVERLAY_FORMAT_YUV420}, 0, OVERLAY_FORMAT_NB-1, FLAGS, "format" },
1043         { "yuv420", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV420}, .flags = FLAGS, .unit = "format" },
1044         { "yuv422", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV422}, .flags = FLAGS, .unit = "format" },
1045         { "yuv444", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV444}, .flags = FLAGS, .unit = "format" },
1046         { "rgb",    "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_RGB},    .flags = FLAGS, .unit = "format" },
1047         { "gbrp",   "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_GBRP},   .flags = FLAGS, .unit = "format" },
1048         { "auto",   "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_AUTO},   .flags = FLAGS, .unit = "format" },
1049     { "repeatlast", "repeat overlay of the last overlay frame", OFFSET(fs.opt_repeatlast), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
1050     { "alpha", "alpha format", OFFSET(alpha_format), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "alpha_format" },
1051         { "straight",      "", 0, AV_OPT_TYPE_CONST, {.i64=0}, .flags = FLAGS, .unit = "alpha_format" },
1052         { "premultiplied", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, .flags = FLAGS, .unit = "alpha_format" },
1053     { NULL }
1054 };
1055
1056 FRAMESYNC_DEFINE_CLASS(overlay, OverlayContext, fs);
1057
1058 static const AVFilterPad avfilter_vf_overlay_inputs[] = {
1059     {
1060         .name         = "main",
1061         .type         = AVMEDIA_TYPE_VIDEO,
1062         .config_props = config_input_main,
1063     },
1064     {
1065         .name         = "overlay",
1066         .type         = AVMEDIA_TYPE_VIDEO,
1067         .config_props = config_input_overlay,
1068     },
1069     { NULL }
1070 };
1071
1072 static const AVFilterPad avfilter_vf_overlay_outputs[] = {
1073     {
1074         .name          = "default",
1075         .type          = AVMEDIA_TYPE_VIDEO,
1076         .config_props  = config_output,
1077     },
1078     { NULL }
1079 };
1080
1081 AVFilter ff_vf_overlay = {
1082     .name          = "overlay",
1083     .description   = NULL_IF_CONFIG_SMALL("Overlay a video source on top of the input."),
1084     .preinit       = overlay_framesync_preinit,
1085     .init          = init,
1086     .uninit        = uninit,
1087     .priv_size     = sizeof(OverlayContext),
1088     .priv_class    = &overlay_class,
1089     .query_formats = query_formats,
1090     .activate      = activate,
1091     .process_command = process_command,
1092     .inputs        = avfilter_vf_overlay_inputs,
1093     .outputs       = avfilter_vf_overlay_outputs,
1094     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
1095                      AVFILTER_FLAG_SLICE_THREADS,
1096 };