LCOV - code coverage report
Current view: top level - libavfilter - vf_overlay.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 381 552 69.0 %
Date: 2018-05-20 11:54:08 Functions: 28 40 70.0 %

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

Generated by: LCOV version 1.13