LCOV - code coverage report
Current view: top level - libavfilter - vf_pad.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 144 188 76.6 %
Date: 2017-12-14 08:27:08 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2008 vmrsss
       3             :  * Copyright (c) 2009 Stefano Sabatini
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * video padding filter
      25             :  */
      26             : 
      27             : #include <float.h>  /* DBL_MAX */
      28             : 
      29             : #include "avfilter.h"
      30             : #include "formats.h"
      31             : #include "internal.h"
      32             : #include "video.h"
      33             : #include "libavutil/avstring.h"
      34             : #include "libavutil/common.h"
      35             : #include "libavutil/eval.h"
      36             : #include "libavutil/pixdesc.h"
      37             : #include "libavutil/colorspace.h"
      38             : #include "libavutil/imgutils.h"
      39             : #include "libavutil/parseutils.h"
      40             : #include "libavutil/mathematics.h"
      41             : #include "libavutil/opt.h"
      42             : 
      43             : #include "drawutils.h"
      44             : 
      45             : static const char *const var_names[] = {
      46             :     "in_w",   "iw",
      47             :     "in_h",   "ih",
      48             :     "out_w",  "ow",
      49             :     "out_h",  "oh",
      50             :     "x",
      51             :     "y",
      52             :     "a",
      53             :     "sar",
      54             :     "dar",
      55             :     "hsub",
      56             :     "vsub",
      57             :     NULL
      58             : };
      59             : 
      60             : enum var_name {
      61             :     VAR_IN_W,   VAR_IW,
      62             :     VAR_IN_H,   VAR_IH,
      63             :     VAR_OUT_W,  VAR_OW,
      64             :     VAR_OUT_H,  VAR_OH,
      65             :     VAR_X,
      66             :     VAR_Y,
      67             :     VAR_A,
      68             :     VAR_SAR,
      69             :     VAR_DAR,
      70             :     VAR_HSUB,
      71             :     VAR_VSUB,
      72             :     VARS_NB
      73             : };
      74             : 
      75          79 : static int query_formats(AVFilterContext *ctx)
      76             : {
      77          79 :     return ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0));
      78             : }
      79             : 
      80             : enum EvalMode {
      81             :     EVAL_MODE_INIT,
      82             :     EVAL_MODE_FRAME,
      83             :     EVAL_MODE_NB
      84             : };
      85             : 
      86             : typedef struct PadContext {
      87             :     const AVClass *class;
      88             :     int w, h;               ///< output dimensions, a value of 0 will result in the input size
      89             :     int x, y;               ///< offsets of the input area with respect to the padded area
      90             :     int in_w, in_h;         ///< width and height for the padded input video, which has to be aligned to the chroma values in order to avoid chroma issues
      91             :     int inlink_w, inlink_h;
      92             :     AVRational aspect;
      93             : 
      94             :     char *w_expr;           ///< width  expression string
      95             :     char *h_expr;           ///< height expression string
      96             :     char *x_expr;           ///< width  expression string
      97             :     char *y_expr;           ///< height expression string
      98             :     uint8_t rgba_color[4];  ///< color for the padding area
      99             :     FFDrawContext draw;
     100             :     FFDrawColor color;
     101             : 
     102             :     int eval_mode;          ///< expression evaluation mode
     103             : } PadContext;
     104             : 
     105          78 : static int config_input(AVFilterLink *inlink)
     106             : {
     107          78 :     AVFilterContext *ctx = inlink->dst;
     108          78 :     PadContext *s = ctx->priv;
     109          78 :     AVRational adjusted_aspect = s->aspect;
     110             :     int ret;
     111             :     double var_values[VARS_NB], res;
     112             :     char *expr;
     113             : 
     114          78 :     ff_draw_init(&s->draw, inlink->format, 0);
     115          78 :     ff_draw_color(&s->draw, &s->color, s->rgba_color);
     116             : 
     117          78 :     var_values[VAR_IN_W]  = var_values[VAR_IW] = inlink->w;
     118          78 :     var_values[VAR_IN_H]  = var_values[VAR_IH] = inlink->h;
     119          78 :     var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN;
     120          78 :     var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN;
     121          78 :     var_values[VAR_A]     = (double) inlink->w / inlink->h;
     122         156 :     var_values[VAR_SAR]   = inlink->sample_aspect_ratio.num ?
     123          78 :         (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1;
     124          78 :     var_values[VAR_DAR]   = var_values[VAR_A] * var_values[VAR_SAR];
     125          78 :     var_values[VAR_HSUB]  = 1 << s->draw.hsub_max;
     126          78 :     var_values[VAR_VSUB]  = 1 << s->draw.vsub_max;
     127             : 
     128             :     /* evaluate width and height */
     129          78 :     av_expr_parse_and_eval(&res, (expr = s->w_expr),
     130             :                            var_names, var_values,
     131             :                            NULL, NULL, NULL, NULL, NULL, 0, ctx);
     132          78 :     s->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res;
     133          78 :     if ((ret = av_expr_parse_and_eval(&res, (expr = s->h_expr),
     134             :                                       var_names, var_values,
     135             :                                       NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
     136           0 :         goto eval_fail;
     137          78 :     s->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res;
     138          78 :     if (!s->h)
     139           0 :         var_values[VAR_OUT_H] = var_values[VAR_OH] = s->h = inlink->h;
     140             : 
     141             :     /* evaluate the width again, as it may depend on the evaluated output height */
     142          78 :     if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr),
     143             :                                       var_names, var_values,
     144             :                                       NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
     145           0 :         goto eval_fail;
     146          78 :     s->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res;
     147          78 :     if (!s->w)
     148           0 :         var_values[VAR_OUT_W] = var_values[VAR_OW] = s->w = inlink->w;
     149             : 
     150          78 :     if (adjusted_aspect.num && adjusted_aspect.den) {
     151           0 :         adjusted_aspect = av_div_q(adjusted_aspect, inlink->sample_aspect_ratio);
     152           0 :         if (s->h < av_rescale(s->w, adjusted_aspect.den, adjusted_aspect.num)) {
     153           0 :             s->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = av_rescale(s->w, adjusted_aspect.den, adjusted_aspect.num);
     154             :         } else {
     155           0 :             s->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = av_rescale(s->h, adjusted_aspect.num, adjusted_aspect.den);
     156             :         }
     157             :     }
     158             : 
     159             :     /* evaluate x and y */
     160          78 :     av_expr_parse_and_eval(&res, (expr = s->x_expr),
     161             :                            var_names, var_values,
     162             :                            NULL, NULL, NULL, NULL, NULL, 0, ctx);
     163          78 :     s->x = var_values[VAR_X] = res;
     164          78 :     if ((ret = av_expr_parse_and_eval(&res, (expr = s->y_expr),
     165             :                                       var_names, var_values,
     166             :                                       NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
     167           0 :         goto eval_fail;
     168          78 :     s->y = var_values[VAR_Y] = res;
     169             :     /* evaluate x again, as it may depend on the evaluated y value */
     170          78 :     if ((ret = av_expr_parse_and_eval(&res, (expr = s->x_expr),
     171             :                                       var_names, var_values,
     172             :                                       NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
     173           0 :         goto eval_fail;
     174          78 :     s->x = var_values[VAR_X] = res;
     175             : 
     176          78 :     if (s->x < 0 || s->x + inlink->w > s->w)
     177           0 :         s->x = var_values[VAR_X] = (s->w - inlink->w) / 2;
     178          78 :     if (s->y < 0 || s->y + inlink->h > s->h)
     179           0 :         s->y = var_values[VAR_Y] = (s->h - inlink->h) / 2;
     180             : 
     181             :     /* sanity check params */
     182          78 :     if (s->w < 0 || s->h < 0) {
     183           0 :         av_log(ctx, AV_LOG_ERROR, "Negative values are not acceptable.\n");
     184           0 :         return AVERROR(EINVAL);
     185             :     }
     186             : 
     187          78 :     s->w    = ff_draw_round_to_sub(&s->draw, 0, -1, s->w);
     188          78 :     s->h    = ff_draw_round_to_sub(&s->draw, 1, -1, s->h);
     189          78 :     s->x    = ff_draw_round_to_sub(&s->draw, 0, -1, s->x);
     190          78 :     s->y    = ff_draw_round_to_sub(&s->draw, 1, -1, s->y);
     191          78 :     s->in_w = ff_draw_round_to_sub(&s->draw, 0, -1, inlink->w);
     192          78 :     s->in_h = ff_draw_round_to_sub(&s->draw, 1, -1, inlink->h);
     193          78 :     s->inlink_w = inlink->w;
     194          78 :     s->inlink_h = inlink->h;
     195             : 
     196         312 :     av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d -> w:%d h:%d x:%d y:%d color:0x%02X%02X%02X%02X\n",
     197             :            inlink->w, inlink->h, s->w, s->h, s->x, s->y,
     198         312 :            s->rgba_color[0], s->rgba_color[1], s->rgba_color[2], s->rgba_color[3]);
     199             : 
     200         156 :     if (s->x <  0 || s->y <  0                      ||
     201         234 :         s->w <= 0 || s->h <= 0                      ||
     202         156 :         (unsigned)s->x + (unsigned)inlink->w > s->w ||
     203          78 :         (unsigned)s->y + (unsigned)inlink->h > s->h) {
     204           0 :         av_log(ctx, AV_LOG_ERROR,
     205             :                "Input area %d:%d:%d:%d not within the padded area 0:0:%d:%d or zero-sized\n",
     206           0 :                s->x, s->y, s->x + inlink->w, s->y + inlink->h, s->w, s->h);
     207           0 :         return AVERROR(EINVAL);
     208             :     }
     209             : 
     210          78 :     return 0;
     211             : 
     212           0 : eval_fail:
     213           0 :     av_log(NULL, AV_LOG_ERROR,
     214             :            "Error when evaluating the expression '%s'\n", expr);
     215           0 :     return ret;
     216             : 
     217             : }
     218             : 
     219          78 : static int config_output(AVFilterLink *outlink)
     220             : {
     221          78 :     PadContext *s = outlink->src->priv;
     222             : 
     223          78 :     outlink->w = s->w;
     224          78 :     outlink->h = s->h;
     225          78 :     return 0;
     226             : }
     227             : 
     228         394 : static AVFrame *get_video_buffer(AVFilterLink *inlink, int w, int h)
     229             : {
     230         394 :     PadContext *s = inlink->dst->priv;
     231             :     AVFrame *frame;
     232             :     int plane;
     233             : 
     234         394 :     if (s->inlink_w <= 0)
     235           0 :         return NULL;
     236             : 
     237         788 :     frame = ff_get_video_buffer(inlink->dst->outputs[0],
     238         394 :                                 w + (s->w - s->in_w),
     239         394 :                                 h + (s->h - s->in_h) + (s->x > 0));
     240             : 
     241         394 :     if (!frame)
     242           0 :         return NULL;
     243             : 
     244         394 :     frame->width  = w;
     245         394 :     frame->height = h;
     246             : 
     247        1706 :     for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) {
     248        1312 :         int hsub = s->draw.hsub[plane];
     249        1312 :         int vsub = s->draw.vsub[plane];
     250        2624 :         frame->data[plane] += (s->x >> hsub) * s->draw.pixelstep[plane] +
     251        1312 :                               (s->y >> vsub) * frame->linesize[plane];
     252             :     }
     253             : 
     254         394 :     return frame;
     255             : }
     256             : 
     257             : /* check whether each plane in this buffer can be padded without copying */
     258        1325 : static int buffer_needs_copy(PadContext *s, AVFrame *frame, AVBufferRef *buf)
     259             : {
     260        1325 :     int planes[4] = { -1, -1, -1, -1}, *p = planes;
     261             :     int i, j;
     262             : 
     263             :     /* get all planes in this buffer */
     264        6226 :     for (i = 0; i < FF_ARRAY_ELEMS(planes) && frame->data[i]; i++) {
     265        4901 :         if (av_frame_get_plane_buffer(frame, i) == buf)
     266        1325 :             *p++ = i;
     267             :     }
     268             : 
     269             :     /* for each plane in this buffer, check that it can be padded without
     270             :      * going over buffer bounds or other planes */
     271        2638 :     for (i = 0; i < FF_ARRAY_ELEMS(planes) && planes[i] >= 0; i++) {
     272        1325 :         int hsub = s->draw.hsub[planes[i]];
     273        1325 :         int vsub = s->draw.vsub[planes[i]];
     274             : 
     275        1325 :         uint8_t *start = frame->data[planes[i]];
     276        2650 :         uint8_t *end   = start + (frame->height >> vsub) *
     277        1325 :                                  frame->linesize[planes[i]];
     278             : 
     279             :         /* amount of free space needed before the start and after the end
     280             :          * of the plane */
     281        2650 :         ptrdiff_t req_start = (s->x >> hsub) * s->draw.pixelstep[planes[i]] +
     282        1325 :                               (s->y >> vsub) * frame->linesize[planes[i]];
     283        3975 :         ptrdiff_t req_end   = ((s->w - s->x - frame->width) >> hsub) *
     284        2650 :                               s->draw.pixelstep[planes[i]] +
     285        1325 :                               ((s->h - s->y - frame->height) >> vsub) * frame->linesize[planes[i]];
     286             : 
     287        1325 :         if (frame->linesize[planes[i]] < (s->w >> hsub) * s->draw.pixelstep[planes[i]])
     288          12 :             return 1;
     289        2626 :         if (start - buf->data < req_start ||
     290        1313 :             (buf->data + buf->size) - end < req_end)
     291           0 :             return 1;
     292             : 
     293        2626 :         for (j = 0; j < FF_ARRAY_ELEMS(planes) && planes[j] >= 0; j++) {
     294        1313 :             int vsub1 = s->draw.vsub[planes[j]];
     295        1313 :             uint8_t *start1 = frame->data[planes[j]];
     296        2626 :             uint8_t *end1   = start1 + (frame->height >> vsub1) *
     297        1313 :                                        frame->linesize[planes[j]];
     298        1313 :             if (i == j)
     299        1313 :                 continue;
     300             : 
     301           0 :             if (FFSIGN(start - end1) != FFSIGN(start - end1 - req_start) ||
     302           0 :                 FFSIGN(end - start1) != FFSIGN(end - start1 + req_end))
     303           0 :                 return 1;
     304             :         }
     305             :     }
     306             : 
     307        1313 :     return 0;
     308             : }
     309             : 
     310         406 : static int frame_needs_copy(PadContext *s, AVFrame *frame)
     311             : {
     312             :     int i;
     313             : 
     314         406 :     if (!av_frame_is_writable(frame))
     315           0 :         return 1;
     316             : 
     317        1719 :     for (i = 0; i < 4 && frame->buf[i]; i++)
     318        1325 :         if (buffer_needs_copy(s, frame, frame->buf[i]))
     319          12 :             return 1;
     320         394 :     return 0;
     321             : }
     322             : 
     323         406 : static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     324             : {
     325         406 :     PadContext *s = inlink->dst->priv;
     326         406 :     AVFilterLink *outlink = inlink->dst->outputs[0];
     327             :     AVFrame *out;
     328             :     int needs_copy;
     329         406 :     if(s->eval_mode == EVAL_MODE_FRAME && (
     330           0 :            in->width  != s->inlink_w
     331           0 :         || in->height != s->inlink_h
     332           0 :         || in->format != outlink->format
     333           0 :         || in->sample_aspect_ratio.den != outlink->sample_aspect_ratio.den || in->sample_aspect_ratio.num != outlink->sample_aspect_ratio.num)) {
     334             :         int ret;
     335             : 
     336           0 :         inlink->dst->inputs[0]->format = in->format;
     337           0 :         inlink->dst->inputs[0]->w      = in->width;
     338           0 :         inlink->dst->inputs[0]->h      = in->height;
     339             : 
     340           0 :         inlink->dst->inputs[0]->sample_aspect_ratio.den = in->sample_aspect_ratio.den;
     341           0 :         inlink->dst->inputs[0]->sample_aspect_ratio.num = in->sample_aspect_ratio.num;
     342             : 
     343             : 
     344           0 :         if ((ret = config_input(inlink)) < 0) {
     345           0 :             s->inlink_w = -1;
     346           0 :             return ret;
     347             :         }
     348           0 :         if ((ret = config_output(outlink)) < 0) {
     349           0 :             s->inlink_w = -1;
     350           0 :             return ret;
     351             :         }
     352             :     }
     353             : 
     354         406 :     needs_copy = frame_needs_copy(s, in);
     355             : 
     356         406 :     if (needs_copy) {
     357          12 :         av_log(inlink->dst, AV_LOG_DEBUG, "Direct padding impossible allocating new frame\n");
     358          24 :         out = ff_get_video_buffer(inlink->dst->outputs[0],
     359          12 :                                   FFMAX(inlink->w, s->w),
     360          12 :                                   FFMAX(inlink->h, s->h));
     361          12 :         if (!out) {
     362           0 :             av_frame_free(&in);
     363           0 :             return AVERROR(ENOMEM);
     364             :         }
     365             : 
     366          12 :         av_frame_copy_props(out, in);
     367             :     } else {
     368             :         int i;
     369             : 
     370         394 :         out = in;
     371        1706 :         for (i = 0; i < 4 && out->data[i] && out->linesize[i]; i++) {
     372        1312 :             int hsub = s->draw.hsub[i];
     373        1312 :             int vsub = s->draw.vsub[i];
     374        2624 :             out->data[i] -= (s->x >> hsub) * s->draw.pixelstep[i] +
     375        1312 :                             (s->y >> vsub) * out->linesize[i];
     376             :         }
     377             :     }
     378             : 
     379             :     /* top bar */
     380         406 :     if (s->y) {
     381         812 :         ff_fill_rectangle(&s->draw, &s->color,
     382         406 :                           out->data, out->linesize,
     383             :                           0, 0, s->w, s->y);
     384             :     }
     385             : 
     386             :     /* bottom bar */
     387         406 :     if (s->h > s->y + s->in_h) {
     388        1140 :         ff_fill_rectangle(&s->draw, &s->color,
     389         380 :                           out->data, out->linesize,
     390         760 :                           0, s->y + s->in_h, s->w, s->h - s->y - s->in_h);
     391             :     }
     392             : 
     393             :     /* left border */
     394         406 :     ff_fill_rectangle(&s->draw, &s->color, out->data, out->linesize,
     395         406 :                       0, s->y, s->x, in->height);
     396             : 
     397         406 :     if (needs_copy) {
     398          36 :         ff_copy_rectangle2(&s->draw,
     399          12 :                           out->data, out->linesize, in->data, in->linesize,
     400          24 :                           s->x, s->y, 0, 0, in->width, in->height);
     401             :     }
     402             : 
     403             :     /* right border */
     404        1218 :     ff_fill_rectangle(&s->draw, &s->color, out->data, out->linesize,
     405         812 :                       s->x + s->in_w, s->y, s->w - s->x - s->in_w,
     406         406 :                       in->height);
     407             : 
     408         406 :     out->width  = s->w;
     409         406 :     out->height = s->h;
     410             : 
     411         406 :     if (in != out)
     412          12 :         av_frame_free(&in);
     413         406 :     return ff_filter_frame(inlink->dst->outputs[0], out);
     414             : }
     415             : 
     416             : #define OFFSET(x) offsetof(PadContext, x)
     417             : #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
     418             : 
     419             : static const AVOption pad_options[] = {
     420             :     { "width",  "set the pad area width expression",       OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, CHAR_MIN, CHAR_MAX, FLAGS },
     421             :     { "w",      "set the pad area width expression",       OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, CHAR_MIN, CHAR_MAX, FLAGS },
     422             :     { "height", "set the pad area height expression",      OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, CHAR_MIN, CHAR_MAX, FLAGS },
     423             :     { "h",      "set the pad area height expression",      OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, CHAR_MIN, CHAR_MAX, FLAGS },
     424             :     { "x",      "set the x offset expression for the input image position", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX, FLAGS },
     425             :     { "y",      "set the y offset expression for the input image position", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX, FLAGS },
     426             :     { "color",  "set the color of the padded area border", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str = "black"}, .flags = FLAGS },
     427             :     { "eval",   "specify when to evaluate expressions",    OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_INIT}, 0, EVAL_MODE_NB-1, FLAGS, "eval" },
     428             :          { "init",  "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT},  .flags = FLAGS, .unit = "eval" },
     429             :          { "frame", "eval expressions during initialization and per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" },
     430             :     { "aspect",  "pad to fit an aspect instead of a resolution", OFFSET(aspect), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, DBL_MAX, FLAGS },
     431             :     { NULL }
     432             : };
     433             : 
     434             : AVFILTER_DEFINE_CLASS(pad);
     435             : 
     436             : static const AVFilterPad avfilter_vf_pad_inputs[] = {
     437             :     {
     438             :         .name             = "default",
     439             :         .type             = AVMEDIA_TYPE_VIDEO,
     440             :         .config_props     = config_input,
     441             :         .get_video_buffer = get_video_buffer,
     442             :         .filter_frame     = filter_frame,
     443             :     },
     444             :     { NULL }
     445             : };
     446             : 
     447             : static const AVFilterPad avfilter_vf_pad_outputs[] = {
     448             :     {
     449             :         .name         = "default",
     450             :         .type         = AVMEDIA_TYPE_VIDEO,
     451             :         .config_props = config_output,
     452             :     },
     453             :     { NULL }
     454             : };
     455             : 
     456             : AVFilter ff_vf_pad = {
     457             :     .name          = "pad",
     458             :     .description   = NULL_IF_CONFIG_SMALL("Pad the input video."),
     459             :     .priv_size     = sizeof(PadContext),
     460             :     .priv_class    = &pad_class,
     461             :     .query_formats = query_formats,
     462             :     .inputs        = avfilter_vf_pad_inputs,
     463             :     .outputs       = avfilter_vf_pad_outputs,
     464             : };

Generated by: LCOV version 1.13