LCOV - code coverage report
Current view: top level - libavfilter - vsrc_testsrc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 636 726 87.6 %
Date: 2017-12-18 13:19:42 Functions: 43 50 86.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2007 Nicolas George <nicolas.george@normalesup.org>
       3             :  * Copyright (c) 2011 Stefano Sabatini
       4             :  * Copyright (c) 2012 Paul B Mahol
       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             :  * Misc test sources.
      26             :  *
      27             :  * testsrc is based on the test pattern generator demuxer by Nicolas George:
      28             :  * http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2007-October/037845.html
      29             :  *
      30             :  * rgbtestsrc is ported from MPlayer libmpcodecs/vf_rgbtest.c by
      31             :  * Michael Niedermayer.
      32             :  *
      33             :  * allyuv, smptebars and smptehdbars are by Paul B Mahol.
      34             :  */
      35             : 
      36             : #include <float.h>
      37             : 
      38             : #include "libavutil/avassert.h"
      39             : #include "libavutil/common.h"
      40             : #include "libavutil/ffmath.h"
      41             : #include "libavutil/opt.h"
      42             : #include "libavutil/imgutils.h"
      43             : #include "libavutil/intreadwrite.h"
      44             : #include "libavutil/parseutils.h"
      45             : #include "libavutil/xga_font_data.h"
      46             : #include "avfilter.h"
      47             : #include "drawutils.h"
      48             : #include "formats.h"
      49             : #include "internal.h"
      50             : #include "video.h"
      51             : 
      52             : typedef struct TestSourceContext {
      53             :     const AVClass *class;
      54             :     int w, h;
      55             :     unsigned int nb_frame;
      56             :     AVRational time_base, frame_rate;
      57             :     int64_t pts;
      58             :     int64_t duration;           ///< duration expressed in microseconds
      59             :     AVRational sar;             ///< sample aspect ratio
      60             :     int draw_once;              ///< draw only the first frame, always put out the same picture
      61             :     int draw_once_reset;        ///< draw only the first frame or in case of reset
      62             :     AVFrame *picref;            ///< cached reference containing the painted picture
      63             : 
      64             :     void (* fill_picture_fn)(AVFilterContext *ctx, AVFrame *frame);
      65             : 
      66             :     /* only used by testsrc */
      67             :     int nb_decimals;
      68             : 
      69             :     /* only used by testsrc2 */
      70             :     int alpha;
      71             : 
      72             :     /* only used by color */
      73             :     FFDrawContext draw;
      74             :     FFDrawColor color;
      75             :     uint8_t color_rgba[4];
      76             : 
      77             :     /* only used by rgbtest */
      78             :     uint8_t rgba_map[4];
      79             : 
      80             :     /* only used by haldclut */
      81             :     int level;
      82             : } TestSourceContext;
      83             : 
      84             : #define OFFSET(x) offsetof(TestSourceContext, x)
      85             : #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
      86             : 
      87             : #define SIZE_OPTIONS \
      88             :     { "size",     "set video size",     OFFSET(w),        AV_OPT_TYPE_IMAGE_SIZE, {.str = "320x240"}, 0, 0, FLAGS },\
      89             :     { "s",        "set video size",     OFFSET(w),        AV_OPT_TYPE_IMAGE_SIZE, {.str = "320x240"}, 0, 0, FLAGS },\
      90             : 
      91             : #define COMMON_OPTIONS_NOSIZE \
      92             :     { "rate",     "set video rate",     OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },\
      93             :     { "r",        "set video rate",     OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },\
      94             :     { "duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },\
      95             :     { "d",        "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },\
      96             :     { "sar",      "set video sample aspect ratio", OFFSET(sar), AV_OPT_TYPE_RATIONAL, {.dbl= 1},  0, INT_MAX, FLAGS },
      97             : 
      98             : #define COMMON_OPTIONS SIZE_OPTIONS COMMON_OPTIONS_NOSIZE
      99             : 
     100             : static const AVOption options[] = {
     101             :     COMMON_OPTIONS
     102             :     { NULL }
     103             : };
     104             : 
     105          66 : static av_cold int init(AVFilterContext *ctx)
     106             : {
     107          66 :     TestSourceContext *test = ctx->priv;
     108             : 
     109          66 :     test->time_base = av_inv_q(test->frame_rate);
     110          66 :     test->nb_frame = 0;
     111          66 :     test->pts = 0;
     112             : 
     113         184 :     av_log(ctx, AV_LOG_VERBOSE, "size:%dx%d rate:%d/%d duration:%f sar:%d/%d\n",
     114             :            test->w, test->h, test->frame_rate.num, test->frame_rate.den,
     115         118 :            test->duration < 0 ? -1 : (double)test->duration/1000000,
     116             :            test->sar.num, test->sar.den);
     117          66 :     return 0;
     118             : }
     119             : 
     120          66 : static av_cold void uninit(AVFilterContext *ctx)
     121             : {
     122          66 :     TestSourceContext *test = ctx->priv;
     123             : 
     124          66 :     av_frame_free(&test->picref);
     125          66 : }
     126             : 
     127          41 : static int config_props(AVFilterLink *outlink)
     128             : {
     129          41 :     TestSourceContext *test = outlink->src->priv;
     130             : 
     131          41 :     outlink->w = test->w;
     132          41 :     outlink->h = test->h;
     133          41 :     outlink->sample_aspect_ratio = test->sar;
     134          41 :     outlink->frame_rate = test->frame_rate;
     135          41 :     outlink->time_base  = test->time_base;
     136             : 
     137          41 :     return 0;
     138             : }
     139             : 
     140         678 : static int request_frame(AVFilterLink *outlink)
     141             : {
     142         678 :     TestSourceContext *test = outlink->src->priv;
     143             :     AVFrame *frame;
     144             : 
     145        1326 :     if (test->duration >= 0 &&
     146         648 :         av_rescale_q(test->pts, test->time_base, AV_TIME_BASE_Q) >= test->duration)
     147          27 :         return AVERROR_EOF;
     148             : 
     149         651 :     if (test->draw_once) {
     150          65 :         if (test->draw_once_reset) {
     151           0 :             av_frame_free(&test->picref);
     152           0 :             test->draw_once_reset = 0;
     153             :         }
     154          65 :         if (!test->picref) {
     155          19 :             test->picref =
     156          19 :                 ff_get_video_buffer(outlink, test->w, test->h);
     157          19 :             if (!test->picref)
     158           0 :                 return AVERROR(ENOMEM);
     159          19 :             test->fill_picture_fn(outlink->src, test->picref);
     160             :         }
     161          65 :         frame = av_frame_clone(test->picref);
     162             :     } else
     163         586 :         frame = ff_get_video_buffer(outlink, test->w, test->h);
     164             : 
     165         651 :     if (!frame)
     166           0 :         return AVERROR(ENOMEM);
     167         651 :     frame->pts                 = test->pts;
     168         651 :     frame->key_frame           = 1;
     169         651 :     frame->interlaced_frame    = 0;
     170         651 :     frame->pict_type           = AV_PICTURE_TYPE_I;
     171         651 :     frame->sample_aspect_ratio = test->sar;
     172         651 :     if (!test->draw_once)
     173         586 :         test->fill_picture_fn(outlink->src, frame);
     174             : 
     175         651 :     test->pts++;
     176         651 :     test->nb_frame++;
     177             : 
     178         651 :     return ff_filter_frame(outlink, frame);
     179             : }
     180             : 
     181             : #if CONFIG_COLOR_FILTER
     182             : 
     183             : static const AVOption color_options[] = {
     184             :     { "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, FLAGS },
     185             :     { "c",     "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, FLAGS },
     186             :     COMMON_OPTIONS
     187             :     { NULL }
     188             : };
     189             : 
     190             : AVFILTER_DEFINE_CLASS(color);
     191             : 
     192          12 : static void color_fill_picture(AVFilterContext *ctx, AVFrame *picref)
     193             : {
     194          12 :     TestSourceContext *test = ctx->priv;
     195          24 :     ff_fill_rectangle(&test->draw, &test->color,
     196          12 :                       picref->data, picref->linesize,
     197             :                       0, 0, test->w, test->h);
     198          12 : }
     199             : 
     200          14 : static av_cold int color_init(AVFilterContext *ctx)
     201             : {
     202          14 :     TestSourceContext *test = ctx->priv;
     203          14 :     test->fill_picture_fn = color_fill_picture;
     204          14 :     test->draw_once = 1;
     205          14 :     return init(ctx);
     206             : }
     207             : 
     208          12 : static int color_query_formats(AVFilterContext *ctx)
     209             : {
     210          12 :     return ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0));
     211             : }
     212             : 
     213          12 : static int color_config_props(AVFilterLink *inlink)
     214             : {
     215          12 :     AVFilterContext *ctx = inlink->src;
     216          12 :     TestSourceContext *test = ctx->priv;
     217             :     int ret;
     218             : 
     219          12 :     ff_draw_init(&test->draw, inlink->format, 0);
     220          12 :     ff_draw_color(&test->draw, &test->color, test->color_rgba);
     221             : 
     222          12 :     test->w = ff_draw_round_to_sub(&test->draw, 0, -1, test->w);
     223          12 :     test->h = ff_draw_round_to_sub(&test->draw, 1, -1, test->h);
     224          12 :     if (av_image_check_size(test->w, test->h, 0, ctx) < 0)
     225           0 :         return AVERROR(EINVAL);
     226             : 
     227          12 :     if ((ret = config_props(inlink)) < 0)
     228           0 :         return ret;
     229             : 
     230          12 :     return 0;
     231             : }
     232             : 
     233           0 : static int color_process_command(AVFilterContext *ctx, const char *cmd, const char *args,
     234             :                                  char *res, int res_len, int flags)
     235             : {
     236           0 :     TestSourceContext *test = ctx->priv;
     237             :     int ret;
     238             : 
     239           0 :     if (!strcmp(cmd, "color") || !strcmp(cmd, "c")) {
     240             :         uint8_t color_rgba[4];
     241             : 
     242           0 :         ret = av_parse_color(color_rgba, args, -1, ctx);
     243           0 :         if (ret < 0)
     244           0 :             return ret;
     245             : 
     246           0 :         memcpy(test->color_rgba, color_rgba, sizeof(color_rgba));
     247           0 :         ff_draw_color(&test->draw, &test->color, test->color_rgba);
     248           0 :         test->draw_once_reset = 1;
     249           0 :         return 0;
     250             :     }
     251             : 
     252           0 :     return AVERROR(ENOSYS);
     253             : }
     254             : 
     255             : static const AVFilterPad color_outputs[] = {
     256             :     {
     257             :         .name          = "default",
     258             :         .type          = AVMEDIA_TYPE_VIDEO,
     259             :         .request_frame = request_frame,
     260             :         .config_props  = color_config_props,
     261             :     },
     262             :     {  NULL }
     263             : };
     264             : 
     265             : AVFilter ff_vsrc_color = {
     266             :     .name            = "color",
     267             :     .description     = NULL_IF_CONFIG_SMALL("Provide an uniformly colored input."),
     268             :     .priv_class      = &color_class,
     269             :     .priv_size       = sizeof(TestSourceContext),
     270             :     .init            = color_init,
     271             :     .uninit          = uninit,
     272             :     .query_formats   = color_query_formats,
     273             :     .inputs          = NULL,
     274             :     .outputs         = color_outputs,
     275             :     .process_command = color_process_command,
     276             : };
     277             : 
     278             : #endif /* CONFIG_COLOR_FILTER */
     279             : 
     280             : #if CONFIG_HALDCLUTSRC_FILTER
     281             : 
     282             : static const AVOption haldclutsrc_options[] = {
     283             :     { "level", "set level", OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 6}, 2, 8, FLAGS },
     284             :     COMMON_OPTIONS_NOSIZE
     285             :     { NULL }
     286             : };
     287             : 
     288             : AVFILTER_DEFINE_CLASS(haldclutsrc);
     289             : 
     290           0 : static void haldclutsrc_fill_picture(AVFilterContext *ctx, AVFrame *frame)
     291             : {
     292           0 :     int i, j, k, x = 0, y = 0, is16bit = 0, step;
     293           0 :     uint32_t alpha = 0;
     294           0 :     const TestSourceContext *hc = ctx->priv;
     295           0 :     int level = hc->level;
     296             :     float scale;
     297           0 :     const int w = frame->width;
     298           0 :     const int h = frame->height;
     299           0 :     const uint8_t *data = frame->data[0];
     300           0 :     const int linesize  = frame->linesize[0];
     301           0 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
     302             :     uint8_t rgba_map[4];
     303             : 
     304           0 :     av_assert0(w == h && w == level*level*level);
     305             : 
     306           0 :     ff_fill_rgba_map(rgba_map, frame->format);
     307             : 
     308           0 :     switch (frame->format) {
     309           0 :     case AV_PIX_FMT_RGB48:
     310             :     case AV_PIX_FMT_BGR48:
     311             :     case AV_PIX_FMT_RGBA64:
     312             :     case AV_PIX_FMT_BGRA64:
     313           0 :         is16bit = 1;
     314           0 :         alpha = 0xffff;
     315           0 :         break;
     316           0 :     case AV_PIX_FMT_RGBA:
     317             :     case AV_PIX_FMT_BGRA:
     318             :     case AV_PIX_FMT_ARGB:
     319             :     case AV_PIX_FMT_ABGR:
     320           0 :         alpha = 0xff;
     321           0 :         break;
     322             :     }
     323             : 
     324           0 :     step  = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit);
     325           0 :     scale = ((float)(1 << (8*(is16bit+1))) - 1) / (level*level - 1);
     326             : 
     327             : #define LOAD_CLUT(nbits) do {                                                   \
     328             :     uint##nbits##_t *dst = ((uint##nbits##_t *)(data + y*linesize)) + x*step;   \
     329             :     dst[rgba_map[0]] = av_clip_uint##nbits(i * scale);                          \
     330             :     dst[rgba_map[1]] = av_clip_uint##nbits(j * scale);                          \
     331             :     dst[rgba_map[2]] = av_clip_uint##nbits(k * scale);                          \
     332             :     if (step == 4)                                                              \
     333             :         dst[rgba_map[3]] = alpha;                                               \
     334             : } while (0)
     335             : 
     336           0 :     level *= level;
     337           0 :     for (k = 0; k < level; k++) {
     338           0 :         for (j = 0; j < level; j++) {
     339           0 :             for (i = 0; i < level; i++) {
     340           0 :                 if (!is16bit)
     341           0 :                     LOAD_CLUT(8);
     342             :                 else
     343           0 :                     LOAD_CLUT(16);
     344           0 :                 if (++x == w) {
     345           0 :                     x = 0;
     346           0 :                     y++;
     347             :                 }
     348             :             }
     349             :         }
     350             :     }
     351           0 : }
     352             : 
     353           0 : static av_cold int haldclutsrc_init(AVFilterContext *ctx)
     354             : {
     355           0 :     TestSourceContext *hc = ctx->priv;
     356           0 :     hc->fill_picture_fn = haldclutsrc_fill_picture;
     357           0 :     hc->draw_once = 1;
     358           0 :     return init(ctx);
     359             : }
     360             : 
     361           0 : static int haldclutsrc_query_formats(AVFilterContext *ctx)
     362             : {
     363             :     static const enum AVPixelFormat pix_fmts[] = {
     364             :         AV_PIX_FMT_RGB24,  AV_PIX_FMT_BGR24,
     365             :         AV_PIX_FMT_RGBA,   AV_PIX_FMT_BGRA,
     366             :         AV_PIX_FMT_ARGB,   AV_PIX_FMT_ABGR,
     367             :         AV_PIX_FMT_0RGB,   AV_PIX_FMT_0BGR,
     368             :         AV_PIX_FMT_RGB0,   AV_PIX_FMT_BGR0,
     369             :         AV_PIX_FMT_RGB48,  AV_PIX_FMT_BGR48,
     370             :         AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64,
     371             :         AV_PIX_FMT_NONE,
     372             :     };
     373             : 
     374           0 :     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
     375           0 :     if (!fmts_list)
     376           0 :         return AVERROR(ENOMEM);
     377           0 :     return ff_set_common_formats(ctx, fmts_list);
     378             : }
     379             : 
     380           0 : static int haldclutsrc_config_props(AVFilterLink *outlink)
     381             : {
     382           0 :     AVFilterContext *ctx = outlink->src;
     383           0 :     TestSourceContext *hc = ctx->priv;
     384             : 
     385           0 :     hc->w = hc->h = hc->level * hc->level * hc->level;
     386           0 :     return config_props(outlink);
     387             : }
     388             : 
     389             : static const AVFilterPad haldclutsrc_outputs[] = {
     390             :     {
     391             :         .name          = "default",
     392             :         .type          = AVMEDIA_TYPE_VIDEO,
     393             :         .request_frame = request_frame,
     394             :         .config_props  = haldclutsrc_config_props,
     395             :     },
     396             :     {  NULL }
     397             : };
     398             : 
     399             : AVFilter ff_vsrc_haldclutsrc = {
     400             :     .name          = "haldclutsrc",
     401             :     .description   = NULL_IF_CONFIG_SMALL("Provide an identity Hald CLUT."),
     402             :     .priv_class    = &haldclutsrc_class,
     403             :     .priv_size     = sizeof(TestSourceContext),
     404             :     .init          = haldclutsrc_init,
     405             :     .uninit        = uninit,
     406             :     .query_formats = haldclutsrc_query_formats,
     407             :     .inputs        = NULL,
     408             :     .outputs       = haldclutsrc_outputs,
     409             : };
     410             : #endif /* CONFIG_HALDCLUTSRC_FILTER */
     411             : 
     412             : #if CONFIG_NULLSRC_FILTER
     413             : 
     414             : #define nullsrc_options options
     415             : AVFILTER_DEFINE_CLASS(nullsrc);
     416             : 
     417           0 : static void nullsrc_fill_picture(AVFilterContext *ctx, AVFrame *picref) { }
     418             : 
     419           0 : static av_cold int nullsrc_init(AVFilterContext *ctx)
     420             : {
     421           0 :     TestSourceContext *test = ctx->priv;
     422             : 
     423           0 :     test->fill_picture_fn = nullsrc_fill_picture;
     424           0 :     return init(ctx);
     425             : }
     426             : 
     427             : static const AVFilterPad nullsrc_outputs[] = {
     428             :     {
     429             :         .name          = "default",
     430             :         .type          = AVMEDIA_TYPE_VIDEO,
     431             :         .request_frame = request_frame,
     432             :         .config_props  = config_props,
     433             :     },
     434             :     { NULL },
     435             : };
     436             : 
     437             : AVFilter ff_vsrc_nullsrc = {
     438             :     .name        = "nullsrc",
     439             :     .description = NULL_IF_CONFIG_SMALL("Null video source, return unprocessed video frames."),
     440             :     .init        = nullsrc_init,
     441             :     .uninit      = uninit,
     442             :     .priv_size   = sizeof(TestSourceContext),
     443             :     .priv_class  = &nullsrc_class,
     444             :     .inputs      = NULL,
     445             :     .outputs     = nullsrc_outputs,
     446             : };
     447             : 
     448             : #endif /* CONFIG_NULLSRC_FILTER */
     449             : 
     450             : #if CONFIG_TESTSRC_FILTER
     451             : 
     452             : static const AVOption testsrc_options[] = {
     453             :     COMMON_OPTIONS
     454             :     { "decimals", "set number of decimals to show", OFFSET(nb_decimals), AV_OPT_TYPE_INT, {.i64=0},  0, 17, FLAGS },
     455             :     { "n",        "set number of decimals to show", OFFSET(nb_decimals), AV_OPT_TYPE_INT, {.i64=0},  0, 17, FLAGS },
     456             :     { NULL }
     457             : };
     458             : 
     459             : AVFILTER_DEFINE_CLASS(testsrc);
     460             : 
     461             : /**
     462             :  * Fill a rectangle with value val.
     463             :  *
     464             :  * @param val the RGB value to set
     465             :  * @param dst pointer to the destination buffer to fill
     466             :  * @param dst_linesize linesize of destination
     467             :  * @param segment_width width of the segment
     468             :  * @param x horizontal coordinate where to draw the rectangle in the destination buffer
     469             :  * @param y horizontal coordinate where to draw the rectangle in the destination buffer
     470             :  * @param w width  of the rectangle to draw, expressed as a number of segment_width units
     471             :  * @param h height of the rectangle to draw, expressed as a number of segment_width units
     472             :  */
     473        4020 : static void draw_rectangle(unsigned val, uint8_t *dst, int dst_linesize, int segment_width,
     474             :                            int x, int y, int w, int h)
     475             : {
     476             :     int i;
     477        4020 :     int step = 3;
     478             : 
     479        4020 :     dst += segment_width * (step * x + y * dst_linesize);
     480        4020 :     w *= segment_width * step;
     481        4020 :     h *= segment_width;
     482       86385 :     for (i = 0; i < h; i++) {
     483       82365 :         memset(dst, val, w);
     484       82365 :         dst += dst_linesize;
     485             :     }
     486        4020 : }
     487             : 
     488         737 : static void draw_digit(int digit, uint8_t *dst, int dst_linesize,
     489             :                        int segment_width)
     490             : {
     491             : #define TOP_HBAR        1
     492             : #define MID_HBAR        2
     493             : #define BOT_HBAR        4
     494             : #define LEFT_TOP_VBAR   8
     495             : #define LEFT_BOT_VBAR  16
     496             : #define RIGHT_TOP_VBAR 32
     497             : #define RIGHT_BOT_VBAR 64
     498             :     struct segments {
     499             :         int x, y, w, h;
     500         737 :     } segments[] = {
     501             :         { 1,  0, 5, 1 }, /* TOP_HBAR */
     502             :         { 1,  6, 5, 1 }, /* MID_HBAR */
     503             :         { 1, 12, 5, 1 }, /* BOT_HBAR */
     504             :         { 0,  1, 1, 5 }, /* LEFT_TOP_VBAR */
     505             :         { 0,  7, 1, 5 }, /* LEFT_BOT_VBAR */
     506             :         { 6,  1, 1, 5 }, /* RIGHT_TOP_VBAR */
     507             :         { 6,  7, 1, 5 }  /* RIGHT_BOT_VBAR */
     508             :     };
     509             :     static const unsigned char masks[10] = {
     510             :         /* 0 */ TOP_HBAR         |BOT_HBAR|LEFT_TOP_VBAR|LEFT_BOT_VBAR|RIGHT_TOP_VBAR|RIGHT_BOT_VBAR,
     511             :         /* 1 */                                                        RIGHT_TOP_VBAR|RIGHT_BOT_VBAR,
     512             :         /* 2 */ TOP_HBAR|MID_HBAR|BOT_HBAR|LEFT_BOT_VBAR                             |RIGHT_TOP_VBAR,
     513             :         /* 3 */ TOP_HBAR|MID_HBAR|BOT_HBAR                            |RIGHT_TOP_VBAR|RIGHT_BOT_VBAR,
     514             :         /* 4 */          MID_HBAR         |LEFT_TOP_VBAR              |RIGHT_TOP_VBAR|RIGHT_BOT_VBAR,
     515             :         /* 5 */ TOP_HBAR|BOT_HBAR|MID_HBAR|LEFT_TOP_VBAR                             |RIGHT_BOT_VBAR,
     516             :         /* 6 */ TOP_HBAR|BOT_HBAR|MID_HBAR|LEFT_TOP_VBAR|LEFT_BOT_VBAR               |RIGHT_BOT_VBAR,
     517             :         /* 7 */ TOP_HBAR                                              |RIGHT_TOP_VBAR|RIGHT_BOT_VBAR,
     518             :         /* 8 */ TOP_HBAR|BOT_HBAR|MID_HBAR|LEFT_TOP_VBAR|LEFT_BOT_VBAR|RIGHT_TOP_VBAR|RIGHT_BOT_VBAR,
     519             :         /* 9 */ TOP_HBAR|BOT_HBAR|MID_HBAR|LEFT_TOP_VBAR              |RIGHT_TOP_VBAR|RIGHT_BOT_VBAR,
     520             :     };
     521         737 :     unsigned mask = masks[digit];
     522             :     int i;
     523             : 
     524         737 :     draw_rectangle(0, dst, dst_linesize, segment_width, 0, 0, 8, 13);
     525        5896 :     for (i = 0; i < FF_ARRAY_ELEMS(segments); i++)
     526        5159 :         if (mask & (1<<i))
     527        3283 :             draw_rectangle(255, dst, dst_linesize, segment_width,
     528             :                            segments[i].x, segments[i].y, segments[i].w, segments[i].h);
     529         737 : }
     530             : 
     531             : #define GRADIENT_SIZE (6 * 256)
     532             : 
     533         258 : static void test_fill_picture(AVFilterContext *ctx, AVFrame *frame)
     534             : {
     535         258 :     TestSourceContext *test = ctx->priv;
     536             :     uint8_t *p, *p0;
     537             :     int x, y;
     538             :     int color, color_rest;
     539             :     int icolor;
     540             :     int radius;
     541             :     int quad0, quad;
     542             :     int dquad_x, dquad_y;
     543             :     int grad, dgrad, rgrad, drgrad;
     544             :     int seg_size;
     545             :     int second;
     546             :     int i;
     547         258 :     uint8_t *data = frame->data[0];
     548         258 :     int width  = frame->width;
     549         258 :     int height = frame->height;
     550             : 
     551             :     /* draw colored bars and circle */
     552         258 :     radius = (width + height) / 4;
     553         258 :     quad0 = width * width / 4 + height * height / 4 - radius * radius;
     554         258 :     dquad_y = 1 - height;
     555         258 :     p0 = data;
     556       60898 :     for (y = 0; y < height; y++) {
     557       60640 :         p = p0;
     558       60640 :         color = 0;
     559       60640 :         color_rest = 0;
     560       60640 :         quad = quad0;
     561       60640 :         dquad_x = 1 - width;
     562    19765280 :         for (x = 0; x < width; x++) {
     563    19704640 :             icolor = color;
     564    19704640 :             if (quad < 0)
     565    14737470 :                 icolor ^= 7;
     566    19704640 :             quad += dquad_x;
     567    19704640 :             dquad_x += 2;
     568    19704640 :             *(p++) = icolor & 1 ? 255 : 0;
     569    19704640 :             *(p++) = icolor & 2 ? 255 : 0;
     570    19704640 :             *(p++) = icolor & 4 ? 255 : 0;
     571    19704640 :             color_rest += 8;
     572    19704640 :             if (color_rest >= width) {
     573      485120 :                 color_rest -= width;
     574      485120 :                 color++;
     575             :             }
     576             :         }
     577       60640 :         quad0 += dquad_y;
     578       60640 :         dquad_y += 2;
     579       60640 :         p0 += frame->linesize[0];
     580             :     }
     581             : 
     582             :     /* draw sliding color line */
     583         258 :     p0 = p = data + frame->linesize[0] * (height * 3/4);
     584         258 :     grad = (256 * test->nb_frame * test->time_base.num / test->time_base.den) %
     585             :         GRADIENT_SIZE;
     586         258 :     rgrad = 0;
     587         258 :     dgrad = GRADIENT_SIZE / width;
     588         258 :     drgrad = GRADIENT_SIZE % width;
     589       81778 :     for (x = 0; x < width; x++) {
     590      178688 :         *(p++) =
     591       68568 :             grad < 256 || grad >= 5 * 256 ? 255 :
     592       42174 :             grad >= 2 * 256 && grad < 4 * 256 ? 0 :
     593       13588 :             grad < 2 * 256 ? 2 * 256 - 1 - grad : grad - 4 * 256;
     594      122580 :         *(p++) =
     595             :             grad >= 4 * 256 ? 0 :
     596       41532 :             grad >= 1 * 256 && grad < 3 * 256 ? 255 :
     597       14054 :             grad < 1 * 256 ? grad : 4 * 256 - 1 - grad;
     598      121022 :         *(p++) =
     599             :             grad < 2 * 256 ? 0 :
     600       41090 :             grad >= 3 * 256 && grad < 5 * 256 ? 255 :
     601       12806 :             grad < 3 * 256 ? grad - 2 * 256 : 6 * 256 - 1 - grad;
     602       81520 :         grad += dgrad;
     603       81520 :         rgrad += drgrad;
     604       81520 :         if (rgrad >= GRADIENT_SIZE) {
     605       13255 :             grad++;
     606       13255 :             rgrad -= GRADIENT_SIZE;
     607             :         }
     608       81520 :         if (grad >= GRADIENT_SIZE)
     609         190 :             grad -= GRADIENT_SIZE;
     610             :     }
     611         258 :     p = p0;
     612        7836 :     for (y = height / 8; y > 0; y--) {
     613        7578 :         memcpy(p+frame->linesize[0], p, 3 * width);
     614        7578 :         p += frame->linesize[0];
     615             :     }
     616             : 
     617             :     /* draw digits */
     618         258 :     seg_size = width / 80;
     619         258 :     if (seg_size >= 1 && height >= 13 * seg_size) {
     620         258 :         int64_t p10decimals = 1;
     621         516 :         double time = av_q2d(test->time_base) * test->nb_frame *
     622         258 :                       ff_exp10(test->nb_decimals);
     623         258 :         if (time >= INT_MAX)
     624           0 :             return;
     625             : 
     626         698 :         for (x = 0; x < test->nb_decimals; x++)
     627         440 :             p10decimals *= 10;
     628             : 
     629         258 :         second = av_rescale_rnd(test->nb_frame * test->time_base.num, p10decimals, test->time_base.den, AV_ROUND_ZERO);
     630         258 :         x = width - (width - seg_size * 64) / 2;
     631         258 :         y = (height - seg_size * 13) / 2;
     632         258 :         p = data + (x*3 + y * frame->linesize[0]);
     633         737 :         for (i = 0; i < 8; i++) {
     634         737 :             p -= 3 * 8 * seg_size;
     635         737 :             draw_digit(second % 10, p, frame->linesize[0], seg_size);
     636         737 :             second /= 10;
     637         737 :             if (second == 0)
     638         258 :                 break;
     639             :         }
     640             :     }
     641             : }
     642             : 
     643          16 : static av_cold int test_init(AVFilterContext *ctx)
     644             : {
     645          16 :     TestSourceContext *test = ctx->priv;
     646             : 
     647          16 :     test->fill_picture_fn = test_fill_picture;
     648          16 :     return init(ctx);
     649             : }
     650             : 
     651          11 : static int test_query_formats(AVFilterContext *ctx)
     652             : {
     653             :     static const enum AVPixelFormat pix_fmts[] = {
     654             :         AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE
     655             :     };
     656             : 
     657          11 :     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
     658          11 :     if (!fmts_list)
     659           0 :         return AVERROR(ENOMEM);
     660          11 :     return ff_set_common_formats(ctx, fmts_list);
     661             : }
     662             : 
     663             : static const AVFilterPad avfilter_vsrc_testsrc_outputs[] = {
     664             :     {
     665             :         .name          = "default",
     666             :         .type          = AVMEDIA_TYPE_VIDEO,
     667             :         .request_frame = request_frame,
     668             :         .config_props  = config_props,
     669             :     },
     670             :     { NULL }
     671             : };
     672             : 
     673             : AVFilter ff_vsrc_testsrc = {
     674             :     .name          = "testsrc",
     675             :     .description   = NULL_IF_CONFIG_SMALL("Generate test pattern."),
     676             :     .priv_size     = sizeof(TestSourceContext),
     677             :     .priv_class    = &testsrc_class,
     678             :     .init          = test_init,
     679             :     .uninit        = uninit,
     680             :     .query_formats = test_query_formats,
     681             :     .inputs        = NULL,
     682             :     .outputs       = avfilter_vsrc_testsrc_outputs,
     683             : };
     684             : 
     685             : #endif /* CONFIG_TESTSRC_FILTER */
     686             : 
     687             : #if CONFIG_TESTSRC2_FILTER
     688             : 
     689             : static const AVOption testsrc2_options[] = {
     690             :     COMMON_OPTIONS
     691             :     { "alpha", "set global alpha (opacity)", OFFSET(alpha), AV_OPT_TYPE_INT, {.i64 = 255}, 0, 255, FLAGS },
     692             :     { NULL }
     693             : };
     694             : 
     695             : AVFILTER_DEFINE_CLASS(testsrc2);
     696             : 
     697       93920 : static void set_color(TestSourceContext *s, FFDrawColor *color, uint32_t argb)
     698             : {
     699      281760 :     uint8_t rgba[4] = { (argb >> 16) & 0xFF,
     700       93920 :                         (argb >>  8) & 0xFF,
     701             :                         (argb >>  0) & 0xFF,
     702       93920 :                         (argb >> 24) & 0xFF, };
     703       93920 :     ff_draw_color(&s->draw, color, rgba);
     704       93920 : }
     705             : 
     706       87380 : static uint32_t color_gradient(unsigned index)
     707             : {
     708       87380 :     unsigned si = index & 0xFF, sd = 0xFF - si;
     709       87380 :     switch (index >> 8) {
     710       14568 :     case 0: return 0xFF0000 + (si <<  8);
     711       14560 :     case 1: return 0x00FF00 + (sd << 16);
     712       14562 :     case 2: return 0x00FF00 + (si <<  0);
     713       14568 :     case 3: return 0x0000FF + (sd <<  8);
     714       14560 :     case 4: return 0x0000FF + (si << 16);
     715       14562 :     case 5: return 0xFF0000 + (sd <<  0);
     716             :     }
     717           0 :     av_assert0(0);
     718             : }
     719             : 
     720         328 : static void draw_text(TestSourceContext *s, AVFrame *frame, FFDrawColor *color,
     721             :                       int x0, int y0, const uint8_t *text)
     722             : {
     723         328 :     int x = x0;
     724             : 
     725        8528 :     for (; *text; text++) {
     726        8200 :         if (*text == '\n') {
     727         328 :             x = x0;
     728         328 :             y0 += 16;
     729         328 :             continue;
     730             :         }
     731        7872 :         ff_blend_mask(&s->draw, color, frame->data, frame->linesize,
     732             :                       frame->width, frame->height,
     733        7872 :                       avpriv_vga16_font + *text * 16, 1, 8, 16, 0, 0, x, y0);
     734        7872 :         x += 8;
     735             :     }
     736         328 : }
     737             : 
     738         328 : static void test2_fill_picture(AVFilterContext *ctx, AVFrame *frame)
     739             : {
     740         328 :     TestSourceContext *s = ctx->priv;
     741             :     FFDrawColor color;
     742         328 :     unsigned alpha = (uint32_t)s->alpha << 24;
     743             : 
     744             :     /* colored background */
     745             :     {
     746         328 :         unsigned i, x = 0, x2;
     747             : 
     748         328 :         x = 0;
     749        2296 :         for (i = 1; i < 7; i++) {
     750        1968 :             x2 = av_rescale(i, s->w, 6);
     751        1968 :             x2 = ff_draw_round_to_sub(&s->draw, 0, 0, x2);
     752        5904 :             set_color(s, &color, ((i & 1) ? 0xFF0000 : 0) |
     753        3936 :                                  ((i & 2) ? 0x00FF00 : 0) |
     754        1968 :                                  ((i & 4) ? 0x0000FF : 0) |
     755             :                                  alpha);
     756        3936 :             ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
     757        1968 :                               x, 0, x2 - x, frame->height);
     758        1968 :             x = x2;
     759             :         }
     760             :     }
     761             : 
     762             :     /* oblique gradient */
     763             :     /* note: too slow if using blending */
     764         328 :     if (s->h >= 64) {
     765             :         unsigned x, dx, y0, y, g0, g;
     766             : 
     767         328 :         dx = ff_draw_round_to_sub(&s->draw, 0, +1, 1);
     768         328 :         y0 = av_rescale_q(s->pts, s->time_base, av_make_q(2, s->h - 16));
     769         328 :         g0 = av_rescale_q(s->pts, s->time_base, av_make_q(1, 128));
     770       87708 :         for (x = 0; x < s->w; x += dx) {
     771       87380 :             g = (av_rescale(x, 6 * 256, s->w) + g0) % (6 * 256);
     772       87380 :             set_color(s, &color, color_gradient(g) | alpha);
     773       87380 :             y = y0 + av_rescale(x, s->h / 2, s->w);
     774       87380 :             y %= 2 * (s->h - 16);
     775       87380 :             if (y > s->h - 16)
     776       38178 :                 y = 2 * (s->h - 16) - y;
     777       87380 :             y = ff_draw_round_to_sub(&s->draw, 1, 0, y);
     778       87380 :             ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
     779             :                               x, y, dx, 16);
     780             :         }
     781             :     }
     782             : 
     783             :     /* top right: draw clock hands */
     784         328 :     if (s->w >= 64 && s->h >= 64) {
     785         328 :         int l = (FFMIN(s->w, s->h) - 32) >> 1;
     786         328 :         int steps = FFMAX(4, l >> 5);
     787         328 :         int xc = (s->w >> 2) + (s->w >> 1);
     788         328 :         int yc = (s->h >> 2);
     789         328 :         int cycle = l << 2;
     790             :         int pos, xh, yh;
     791             :         int c, i;
     792             : 
     793        1312 :         for (c = 0; c < 3; c++) {
     794         984 :             set_color(s, &color, (0xBBBBBB ^ (0xFF << (c << 3))) | alpha);
     795         984 :             pos = av_rescale_q(s->pts, s->time_base, av_make_q(64 >> (c << 1), cycle)) % cycle;
     796        1394 :             xh = pos < 1 * l ? pos :
     797         598 :                  pos < 2 * l ? l :
     798         188 :                  pos < 3 * l ? 3 * l - pos : 0;
     799        1394 :             yh = pos < 1 * l ? 0 :
     800         598 :                  pos < 2 * l ? pos - l :
     801         188 :                  pos < 3 * l ? l :
     802             :                                cycle - pos;
     803         984 :             xh -= l >> 1;
     804         984 :             yh -= l >> 1;
     805        4920 :             for (i = 1; i <= steps; i++) {
     806        3936 :                 int x = av_rescale(xh, i, steps) + xc;
     807        3936 :                 int y = av_rescale(yh, i, steps) + yc;
     808        3936 :                 x = ff_draw_round_to_sub(&s->draw, 0, -1, x);
     809        3936 :                 y = ff_draw_round_to_sub(&s->draw, 1, -1, y);
     810        3936 :                 ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
     811             :                                   x, y, 8, 8);
     812             :             }
     813             :         }
     814             :     }
     815             : 
     816             :     /* bottom left: beating rectangles */
     817         328 :     if (s->w >= 64 && s->h >= 64) {
     818         328 :         int l = (FFMIN(s->w, s->h) - 16) >> 2;
     819         328 :         int cycle = l << 3;
     820         328 :         int xc = (s->w >> 2);
     821         328 :         int yc = (s->h >> 2) + (s->h >> 1);
     822         328 :         int xm1 = ff_draw_round_to_sub(&s->draw, 0, -1, xc - 8);
     823         328 :         int xm2 = ff_draw_round_to_sub(&s->draw, 0, +1, xc + 8);
     824         328 :         int ym1 = ff_draw_round_to_sub(&s->draw, 1, -1, yc - 8);
     825         328 :         int ym2 = ff_draw_round_to_sub(&s->draw, 1, +1, yc + 8);
     826             :         int size, step, x1, x2, y1, y2;
     827             : 
     828         328 :         size = av_rescale_q(s->pts, s->time_base, av_make_q(4, cycle));
     829         328 :         step = size / l;
     830         328 :         size %= l;
     831         328 :         if (step & 1)
     832         134 :             size = l - size;
     833         328 :         step = (step >> 1) & 3;
     834         328 :         set_color(s, &color, 0xFF808080);
     835         328 :         x1 = ff_draw_round_to_sub(&s->draw, 0, -1, xc - 4 - size);
     836         328 :         x2 = ff_draw_round_to_sub(&s->draw, 0, +1, xc + 4 + size);
     837         328 :         y1 = ff_draw_round_to_sub(&s->draw, 1, -1, yc - 4 - size);
     838         328 :         y2 = ff_draw_round_to_sub(&s->draw, 1, +1, yc + 4 + size);
     839         328 :         if (step == 0 || step == 2)
     840         166 :             ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
     841             :                               x1, ym1, x2 - x1, ym2 - ym1);
     842         328 :         if (step == 1 || step == 2)
     843         162 :             ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
     844             :                               xm1, y1, xm2 - xm1, y2 - y1);
     845         328 :         if (step == 3)
     846          64 :             ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
     847             :                               x1, y1, x2 - x1, y2 - y1);
     848             :     }
     849             : 
     850             :     /* bottom right: checker with random noise */
     851             :     {
     852         328 :         unsigned xmin = av_rescale(5, s->w, 8);
     853         328 :         unsigned xmax = av_rescale(7, s->w, 8);
     854         328 :         unsigned ymin = av_rescale(5, s->h, 8);
     855         328 :         unsigned ymax = av_rescale(7, s->h, 8);
     856             :         unsigned x, y, i, r;
     857             :         uint8_t alpha[256];
     858             : 
     859         328 :         r = s->pts;
     860        1312 :         for (y = ymin; y + 15 < ymax; y += 16) {
     861        5844 :             for (x = xmin; x + 15 < xmax; x += 16) {
     862        4860 :                 if ((x ^ y) & 16)
     863        2584 :                     continue;
     864      584932 :                 for (i = 0; i < 256; i++) {
     865      582656 :                     r = r * 1664525 + 1013904223;
     866      582656 :                     alpha[i] = r >> 24;
     867             :                 }
     868        2276 :                 set_color(s, &color, 0xFF00FF80);
     869        2276 :                 ff_blend_mask(&s->draw, &color, frame->data, frame->linesize,
     870             :                                    frame->width, frame->height,
     871             :                                    alpha, 16, 16, 16, 3, 0, x, y);
     872             :             }
     873             :         }
     874             :     }
     875             : 
     876             :     /* bouncing square */
     877         328 :     if (s->w >= 16 && s->h >= 16) {
     878         328 :         unsigned w = s->w - 8;
     879         328 :         unsigned h = s->h - 8;
     880         328 :         unsigned x = av_rescale_q(s->pts, s->time_base, av_make_q(233, 55 * w)) % (w << 1);
     881         328 :         unsigned y = av_rescale_q(s->pts, s->time_base, av_make_q(233, 89 * h)) % (h << 1);
     882         328 :         if (x > w)
     883         128 :             x = (w << 1) - x;
     884         328 :         if (y > h)
     885         145 :             y = (h << 1) - y;
     886         328 :         x = ff_draw_round_to_sub(&s->draw, 0, -1, x);
     887         328 :         y = ff_draw_round_to_sub(&s->draw, 1, -1, y);
     888         328 :         set_color(s, &color, 0xFF8000FF);
     889         328 :         ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
     890             :                           x, y, 8, 8);
     891             :     }
     892             : 
     893             :     /* top right: draw frame time and frame number */
     894             :     {
     895             :         char buf[256];
     896             :         unsigned time;
     897             : 
     898         328 :         time = av_rescale_q(s->pts, s->time_base, av_make_q(1, 1000)) % 86400000;
     899         328 :         set_color(s, &color, 0xC0000000);
     900         328 :         ff_blend_rectangle(&s->draw, &color, frame->data, frame->linesize,
     901             :                            frame->width, frame->height,
     902             :                            2, 2, 100, 36);
     903         328 :         set_color(s, &color, 0xFFFF8000);
     904         984 :         snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%03d\n%12"PRIi64,
     905         656 :                  time / 3600000, (time / 60000) % 60, (time / 1000) % 60,
     906             :                  time % 1000, s->pts);
     907         328 :         draw_text(s, frame, &color, 4, 4, buf);
     908             :     }
     909         328 : }
     910          22 : static av_cold int test2_init(AVFilterContext *ctx)
     911             : {
     912          22 :     TestSourceContext *s = ctx->priv;
     913             : 
     914          22 :     s->fill_picture_fn = test2_fill_picture;
     915          22 :     return init(ctx);
     916             : }
     917             : 
     918          11 : static int test2_query_formats(AVFilterContext *ctx)
     919             : {
     920          11 :     return ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0));
     921             : }
     922             : 
     923          11 : static int test2_config_props(AVFilterLink *inlink)
     924             : {
     925          11 :     AVFilterContext *ctx = inlink->src;
     926          11 :     TestSourceContext *s = ctx->priv;
     927             : 
     928          11 :     av_assert0(ff_draw_init(&s->draw, inlink->format, 0) >= 0);
     929          11 :     s->w = ff_draw_round_to_sub(&s->draw, 0, -1, s->w);
     930          11 :     s->h = ff_draw_round_to_sub(&s->draw, 1, -1, s->h);
     931          11 :     if (av_image_check_size(s->w, s->h, 0, ctx) < 0)
     932           0 :         return AVERROR(EINVAL);
     933          11 :     return config_props(inlink);
     934             : }
     935             : 
     936             : static const AVFilterPad avfilter_vsrc_testsrc2_outputs[] = {
     937             :     {
     938             :         .name          = "default",
     939             :         .type          = AVMEDIA_TYPE_VIDEO,
     940             :         .request_frame = request_frame,
     941             :         .config_props  = test2_config_props,
     942             :     },
     943             :     { NULL }
     944             : };
     945             : 
     946             : AVFilter ff_vsrc_testsrc2 = {
     947             :     .name          = "testsrc2",
     948             :     .description   = NULL_IF_CONFIG_SMALL("Generate another test pattern."),
     949             :     .priv_size     = sizeof(TestSourceContext),
     950             :     .priv_class    = &testsrc2_class,
     951             :     .init          = test2_init,
     952             :     .uninit        = uninit,
     953             :     .query_formats = test2_query_formats,
     954             :     .inputs        = NULL,
     955             :     .outputs       = avfilter_vsrc_testsrc2_outputs,
     956             : };
     957             : 
     958             : #endif /* CONFIG_TESTSRC2_FILTER */
     959             : 
     960             : #if CONFIG_RGBTESTSRC_FILTER
     961             : 
     962             : #define rgbtestsrc_options options
     963             : AVFILTER_DEFINE_CLASS(rgbtestsrc);
     964             : 
     965             : #define R 0
     966             : #define G 1
     967             : #define B 2
     968             : #define A 3
     969             : 
     970       76800 : static void rgbtest_put_pixel(uint8_t *dst, int dst_linesize,
     971             :                               int x, int y, int r, int g, int b, enum AVPixelFormat fmt,
     972             :                               uint8_t rgba_map[4])
     973             : {
     974             :     int32_t v;
     975             :     uint8_t *p;
     976             : 
     977       76800 :     switch (fmt) {
     978           0 :     case AV_PIX_FMT_BGR444: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4); break;
     979           0 :     case AV_PIX_FMT_RGB444: ((uint16_t*)(dst + y*dst_linesize))[x] = ((b >> 4) << 8) | ((g >> 4) << 4) | (r >> 4); break;
     980           0 :     case AV_PIX_FMT_BGR555: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r>>3)<<10) | ((g>>3)<<5) | (b>>3); break;
     981           0 :     case AV_PIX_FMT_RGB555: ((uint16_t*)(dst + y*dst_linesize))[x] = ((b>>3)<<10) | ((g>>3)<<5) | (r>>3); break;
     982           0 :     case AV_PIX_FMT_BGR565: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r>>3)<<11) | ((g>>2)<<5) | (b>>3); break;
     983           0 :     case AV_PIX_FMT_RGB565: ((uint16_t*)(dst + y*dst_linesize))[x] = ((b>>3)<<11) | ((g>>2)<<5) | (r>>3); break;
     984       76800 :     case AV_PIX_FMT_RGB24:
     985             :     case AV_PIX_FMT_BGR24:
     986       76800 :         v = (r << (rgba_map[R]*8)) + (g << (rgba_map[G]*8)) + (b << (rgba_map[B]*8));
     987       76800 :         p = dst + 3*x + y*dst_linesize;
     988       76800 :         AV_WL24(p, v);
     989       76800 :         break;
     990           0 :     case AV_PIX_FMT_RGBA:
     991             :     case AV_PIX_FMT_BGRA:
     992             :     case AV_PIX_FMT_ARGB:
     993             :     case AV_PIX_FMT_ABGR:
     994           0 :         v = (r << (rgba_map[R]*8)) + (g << (rgba_map[G]*8)) + (b << (rgba_map[B]*8)) + (255 << (rgba_map[A]*8));
     995           0 :         p = dst + 4*x + y*dst_linesize;
     996           0 :         AV_WL32(p, v);
     997           0 :         break;
     998             :     }
     999       76800 : }
    1000             : 
    1001           1 : static void rgbtest_fill_picture(AVFilterContext *ctx, AVFrame *frame)
    1002             : {
    1003           1 :     TestSourceContext *test = ctx->priv;
    1004           1 :     int x, y, w = frame->width, h = frame->height;
    1005             : 
    1006         241 :     for (y = 0; y < h; y++) {
    1007       77040 :          for (x = 0; x < w; x++) {
    1008       76800 :              int c = 256*x/w;
    1009       76800 :              int r = 0, g = 0, b = 0;
    1010             : 
    1011       76800 :              if      (3*y < h  ) r = c;
    1012       51200 :              else if (3*y < 2*h) g = c;
    1013       25600 :              else                b = c;
    1014             : 
    1015       76800 :              rgbtest_put_pixel(frame->data[0], frame->linesize[0], x, y, r, g, b,
    1016       76800 :                                ctx->outputs[0]->format, test->rgba_map);
    1017             :          }
    1018             :      }
    1019           1 : }
    1020             : 
    1021           2 : static av_cold int rgbtest_init(AVFilterContext *ctx)
    1022             : {
    1023           2 :     TestSourceContext *test = ctx->priv;
    1024             : 
    1025           2 :     test->draw_once = 1;
    1026           2 :     test->fill_picture_fn = rgbtest_fill_picture;
    1027           2 :     return init(ctx);
    1028             : }
    1029             : 
    1030           1 : static int rgbtest_query_formats(AVFilterContext *ctx)
    1031             : {
    1032             :     static const enum AVPixelFormat pix_fmts[] = {
    1033             :         AV_PIX_FMT_RGBA, AV_PIX_FMT_ARGB, AV_PIX_FMT_BGRA, AV_PIX_FMT_ABGR,
    1034             :         AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB24,
    1035             :         AV_PIX_FMT_RGB444, AV_PIX_FMT_BGR444,
    1036             :         AV_PIX_FMT_RGB565, AV_PIX_FMT_BGR565,
    1037             :         AV_PIX_FMT_RGB555, AV_PIX_FMT_BGR555,
    1038             :         AV_PIX_FMT_NONE
    1039             :     };
    1040             : 
    1041           1 :     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
    1042           1 :     if (!fmts_list)
    1043           0 :         return AVERROR(ENOMEM);
    1044           1 :     return ff_set_common_formats(ctx, fmts_list);
    1045             : }
    1046             : 
    1047           1 : static int rgbtest_config_props(AVFilterLink *outlink)
    1048             : {
    1049           1 :     TestSourceContext *test = outlink->src->priv;
    1050             : 
    1051           1 :     ff_fill_rgba_map(test->rgba_map, outlink->format);
    1052           1 :     return config_props(outlink);
    1053             : }
    1054             : 
    1055             : static const AVFilterPad avfilter_vsrc_rgbtestsrc_outputs[] = {
    1056             :     {
    1057             :         .name          = "default",
    1058             :         .type          = AVMEDIA_TYPE_VIDEO,
    1059             :         .request_frame = request_frame,
    1060             :         .config_props  = rgbtest_config_props,
    1061             :     },
    1062             :     { NULL }
    1063             : };
    1064             : 
    1065             : AVFilter ff_vsrc_rgbtestsrc = {
    1066             :     .name          = "rgbtestsrc",
    1067             :     .description   = NULL_IF_CONFIG_SMALL("Generate RGB test pattern."),
    1068             :     .priv_size     = sizeof(TestSourceContext),
    1069             :     .priv_class    = &rgbtestsrc_class,
    1070             :     .init          = rgbtest_init,
    1071             :     .uninit        = uninit,
    1072             :     .query_formats = rgbtest_query_formats,
    1073             :     .inputs        = NULL,
    1074             :     .outputs       = avfilter_vsrc_rgbtestsrc_outputs,
    1075             : };
    1076             : 
    1077             : #endif /* CONFIG_RGBTESTSRC_FILTER */
    1078             : 
    1079             : #if CONFIG_YUVTESTSRC_FILTER
    1080             : 
    1081             : #define yuvtestsrc_options options
    1082             : AVFILTER_DEFINE_CLASS(yuvtestsrc);
    1083             : 
    1084           1 : static void yuvtest_fill_picture8(AVFilterContext *ctx, AVFrame *frame)
    1085             : {
    1086           1 :     int x, y, w = frame->width, h = frame->height / 3;
    1087           1 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
    1088           1 :     const int factor = 1 << desc->comp[0].depth;
    1089           1 :     const int mid = 1 << (desc->comp[0].depth - 1);
    1090           1 :     uint8_t *ydst = frame->data[0];
    1091           1 :     uint8_t *udst = frame->data[1];
    1092           1 :     uint8_t *vdst = frame->data[2];
    1093           1 :     int ylinesize = frame->linesize[0];
    1094           1 :     int ulinesize = frame->linesize[1];
    1095           1 :     int vlinesize = frame->linesize[2];
    1096             : 
    1097          81 :     for (y = 0; y < h; y++) {
    1098       25680 :         for (x = 0; x < w; x++) {
    1099       25600 :             int c = factor * x / w;
    1100             : 
    1101       25600 :             ydst[x] = c;
    1102       25600 :             udst[x] = mid;
    1103       25600 :             vdst[x] = mid;
    1104             :         }
    1105             : 
    1106          80 :         ydst += ylinesize;
    1107          80 :         udst += ulinesize;
    1108          80 :         vdst += vlinesize;
    1109             :     }
    1110             : 
    1111           1 :     h += h;
    1112          81 :     for (; y < h; y++) {
    1113       25680 :         for (x = 0; x < w; x++) {
    1114       25600 :             int c = factor * x / w;
    1115             : 
    1116       25600 :             ydst[x] = mid;
    1117       25600 :             udst[x] = c;
    1118       25600 :             vdst[x] = mid;
    1119             :         }
    1120             : 
    1121          80 :         ydst += ylinesize;
    1122          80 :         udst += ulinesize;
    1123          80 :         vdst += vlinesize;
    1124             :     }
    1125             : 
    1126          81 :     for (; y < frame->height; y++) {
    1127       25680 :         for (x = 0; x < w; x++) {
    1128       25600 :             int c = factor * x / w;
    1129             : 
    1130       25600 :             ydst[x] = mid;
    1131       25600 :             udst[x] = mid;
    1132       25600 :             vdst[x] = c;
    1133             :         }
    1134             : 
    1135          80 :         ydst += ylinesize;
    1136          80 :         udst += ulinesize;
    1137          80 :         vdst += vlinesize;
    1138             :     }
    1139           1 : }
    1140             : 
    1141           1 : static void yuvtest_fill_picture16(AVFilterContext *ctx, AVFrame *frame)
    1142             : {
    1143           1 :     int x, y, w = frame->width, h = frame->height / 3;
    1144           1 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
    1145           1 :     const int factor = 1 << desc->comp[0].depth;
    1146           1 :     const int mid = 1 << (desc->comp[0].depth - 1);
    1147           1 :     uint16_t *ydst = (uint16_t *)frame->data[0];
    1148           1 :     uint16_t *udst = (uint16_t *)frame->data[1];
    1149           1 :     uint16_t *vdst = (uint16_t *)frame->data[2];
    1150           1 :     int ylinesize = frame->linesize[0] / 2;
    1151           1 :     int ulinesize = frame->linesize[1] / 2;
    1152           1 :     int vlinesize = frame->linesize[2] / 2;
    1153             : 
    1154          81 :     for (y = 0; y < h; y++) {
    1155       25680 :         for (x = 0; x < w; x++) {
    1156       25600 :             int c = factor * x / w;
    1157             : 
    1158       25600 :             ydst[x] = c;
    1159       25600 :             udst[x] = mid;
    1160       25600 :             vdst[x] = mid;
    1161             :         }
    1162             : 
    1163          80 :         ydst += ylinesize;
    1164          80 :         udst += ulinesize;
    1165          80 :         vdst += vlinesize;
    1166             :     }
    1167             : 
    1168           1 :     h += h;
    1169          81 :     for (; y < h; y++) {
    1170       25680 :         for (x = 0; x < w; x++) {
    1171       25600 :             int c = factor * x / w;
    1172             : 
    1173       25600 :             ydst[x] = mid;
    1174       25600 :             udst[x] = c;
    1175       25600 :             vdst[x] = mid;
    1176             :         }
    1177             : 
    1178          80 :         ydst += ylinesize;
    1179          80 :         udst += ulinesize;
    1180          80 :         vdst += vlinesize;
    1181             :     }
    1182             : 
    1183          81 :     for (; y < frame->height; y++) {
    1184       25680 :         for (x = 0; x < w; x++) {
    1185       25600 :             int c = factor * x / w;
    1186             : 
    1187       25600 :             ydst[x] = mid;
    1188       25600 :             udst[x] = mid;
    1189       25600 :             vdst[x] = c;
    1190             :         }
    1191             : 
    1192          80 :         ydst += ylinesize;
    1193          80 :         udst += ulinesize;
    1194          80 :         vdst += vlinesize;
    1195             :     }
    1196           1 : }
    1197             : 
    1198           4 : static av_cold int yuvtest_init(AVFilterContext *ctx)
    1199             : {
    1200           4 :     TestSourceContext *test = ctx->priv;
    1201             : 
    1202           4 :     test->draw_once = 1;
    1203           4 :     return init(ctx);
    1204             : }
    1205             : 
    1206           2 : static int yuvtest_query_formats(AVFilterContext *ctx)
    1207             : {
    1208             :     static const enum AVPixelFormat pix_fmts[] = {
    1209             :         AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P,
    1210             :         AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10,
    1211             :         AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14,
    1212             :         AV_PIX_FMT_YUV444P16,
    1213             :         AV_PIX_FMT_NONE
    1214             :     };
    1215             : 
    1216           2 :     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
    1217           2 :     if (!fmts_list)
    1218           0 :         return AVERROR(ENOMEM);
    1219           2 :     return ff_set_common_formats(ctx, fmts_list);
    1220             : }
    1221             : 
    1222           2 : static int yuvtest_config_props(AVFilterLink *outlink)
    1223             : {
    1224           2 :     TestSourceContext *test = outlink->src->priv;
    1225           2 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
    1226             : 
    1227           2 :     test->fill_picture_fn = desc->comp[0].depth > 8 ? yuvtest_fill_picture16 : yuvtest_fill_picture8;
    1228           2 :     return config_props(outlink);
    1229             : }
    1230             : 
    1231             : static const AVFilterPad avfilter_vsrc_yuvtestsrc_outputs[] = {
    1232             :     {
    1233             :         .name          = "default",
    1234             :         .type          = AVMEDIA_TYPE_VIDEO,
    1235             :         .request_frame = request_frame,
    1236             :         .config_props  = yuvtest_config_props,
    1237             :     },
    1238             :     { NULL }
    1239             : };
    1240             : 
    1241             : AVFilter ff_vsrc_yuvtestsrc = {
    1242             :     .name          = "yuvtestsrc",
    1243             :     .description   = NULL_IF_CONFIG_SMALL("Generate YUV test pattern."),
    1244             :     .priv_size     = sizeof(TestSourceContext),
    1245             :     .priv_class    = &yuvtestsrc_class,
    1246             :     .init          = yuvtest_init,
    1247             :     .uninit        = uninit,
    1248             :     .query_formats = yuvtest_query_formats,
    1249             :     .inputs        = NULL,
    1250             :     .outputs       = avfilter_vsrc_yuvtestsrc_outputs,
    1251             : };
    1252             : 
    1253             : #endif /* CONFIG_YUVTESTSRC_FILTER */
    1254             : 
    1255             : #if CONFIG_SMPTEBARS_FILTER || CONFIG_SMPTEHDBARS_FILTER
    1256             : 
    1257             : static const uint8_t rainbow[7][4] = {
    1258             :     { 180, 128, 128, 255 },     /* 75% white */
    1259             :     { 162,  44, 142, 255 },     /* 75% yellow */
    1260             :     { 131, 156,  44, 255 },     /* 75% cyan */
    1261             :     { 112,  72,  58, 255 },     /* 75% green */
    1262             :     {  84, 184, 198, 255 },     /* 75% magenta */
    1263             :     {  65, 100, 212, 255 },     /* 75% red */
    1264             :     {  35, 212, 114, 255 },     /* 75% blue */
    1265             : };
    1266             : 
    1267             : static const uint8_t rainbowhd[7][4] = {
    1268             :     { 180, 128, 128, 255 },     /* 75% white */
    1269             :     { 168,  44, 136, 255 },     /* 75% yellow */
    1270             :     { 145, 147,  44, 255 },     /* 75% cyan */
    1271             :     { 133,  63,  52, 255 },     /* 75% green */
    1272             :     {  63, 193, 204, 255 },     /* 75% magenta */
    1273             :     {  51, 109, 212, 255 },     /* 75% red */
    1274             :     {  28, 212, 120, 255 },     /* 75% blue */
    1275             : };
    1276             : 
    1277             : static const uint8_t wobnair[7][4] = {
    1278             :     {  35, 212, 114, 255 },     /* 75% blue */
    1279             :     {  19, 128, 128, 255 },     /* 7.5% intensity black */
    1280             :     {  84, 184, 198, 255 },     /* 75% magenta */
    1281             :     {  19, 128, 128, 255 },     /* 7.5% intensity black */
    1282             :     { 131, 156,  44, 255 },     /* 75% cyan */
    1283             :     {  19, 128, 128, 255 },     /* 7.5% intensity black */
    1284             :     { 180, 128, 128, 255 },     /* 75% white */
    1285             : };
    1286             : 
    1287             : static const uint8_t white[4] = { 235, 128, 128, 255 };
    1288             : 
    1289             : /* pluge pulses */
    1290             : static const uint8_t neg4ire[4] = {  7, 128, 128, 255 };
    1291             : static const uint8_t pos4ire[4] = { 24, 128, 128, 255 };
    1292             : 
    1293             : /* fudged Q/-I */
    1294             : static const uint8_t i_pixel[4] = { 57, 156,  97, 255 };
    1295             : static const uint8_t q_pixel[4] = { 44, 171, 147, 255 };
    1296             : 
    1297             : static const uint8_t gray40[4] = { 104, 128, 128, 255 };
    1298             : static const uint8_t gray15[4] = {  49, 128, 128, 255 };
    1299             : static const uint8_t   cyan[4] = { 188, 154,  16, 255 };
    1300             : static const uint8_t yellow[4] = { 219,  16, 138, 255 };
    1301             : static const uint8_t   blue[4] = {  32, 240, 118, 255 };
    1302             : static const uint8_t    red[4] = {  63, 102, 240, 255 };
    1303             : static const uint8_t black0[4] = {  16, 128, 128, 255 };
    1304             : static const uint8_t black2[4] = {  20, 128, 128, 255 };
    1305             : static const uint8_t black4[4] = {  25, 128, 128, 255 };
    1306             : static const uint8_t   neg2[4] = {  12, 128, 128, 255 };
    1307             : 
    1308         253 : static void draw_bar(TestSourceContext *test, const uint8_t color[4],
    1309             :                      int x, int y, int w, int h,
    1310             :                      AVFrame *frame)
    1311             : {
    1312         253 :     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
    1313             :     uint8_t *p, *p0;
    1314             :     int plane;
    1315             : 
    1316         253 :     x = FFMIN(x, test->w - 1);
    1317         253 :     y = FFMIN(y, test->h - 1);
    1318         253 :     w = FFMAX(FFMIN(w, test->w - x), 0);
    1319         253 :     h = FFMAX(FFMIN(h, test->h - y), 0);
    1320             : 
    1321         253 :     av_assert0(x + w <= test->w);
    1322         253 :     av_assert0(y + h <= test->h);
    1323             : 
    1324        1012 :     for (plane = 0; frame->data[plane]; plane++) {
    1325         759 :         const int c = color[plane];
    1326         759 :         const int linesize = frame->linesize[plane];
    1327             :         int i, px, py, pw, ph;
    1328             : 
    1329         759 :         if (plane == 1 || plane == 2) {
    1330         506 :             px = x >> desc->log2_chroma_w;
    1331         506 :             pw = AV_CEIL_RSHIFT(w, desc->log2_chroma_w);
    1332         506 :             py = y >> desc->log2_chroma_h;
    1333         506 :             ph = AV_CEIL_RSHIFT(h, desc->log2_chroma_h);
    1334             :         } else {
    1335         253 :             px = x;
    1336         253 :             pw = w;
    1337         253 :             py = y;
    1338         253 :             ph = h;
    1339             :         }
    1340             : 
    1341         759 :         p0 = p = frame->data[plane] + py * linesize + px;
    1342         759 :         memset(p, c, pw);
    1343         759 :         p += linesize;
    1344       21900 :         for (i = 1; i < ph; i++, p += linesize)
    1345       21141 :             memcpy(p, p0, pw);
    1346             :     }
    1347         253 : }
    1348             : 
    1349           2 : static int smptebars_query_formats(AVFilterContext *ctx)
    1350             : {
    1351             :     static const enum AVPixelFormat pix_fmts[] = {
    1352             :         AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P,
    1353             :         AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P,
    1354             :         AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P,
    1355             :         AV_PIX_FMT_NONE,
    1356             :     };
    1357             : 
    1358           2 :     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
    1359           2 :     if (!fmts_list)
    1360           0 :         return AVERROR(ENOMEM);
    1361           2 :     return ff_set_common_formats(ctx, fmts_list);
    1362             : }
    1363             : 
    1364             : static const AVFilterPad smptebars_outputs[] = {
    1365             :     {
    1366             :         .name          = "default",
    1367             :         .type          = AVMEDIA_TYPE_VIDEO,
    1368             :         .request_frame = request_frame,
    1369             :         .config_props  = config_props,
    1370             :     },
    1371             :     { NULL }
    1372             : };
    1373             : 
    1374             : #if CONFIG_SMPTEBARS_FILTER
    1375             : 
    1376             : #define smptebars_options options
    1377             : AVFILTER_DEFINE_CLASS(smptebars);
    1378             : 
    1379           1 : static void smptebars_fill_picture(AVFilterContext *ctx, AVFrame *picref)
    1380             : {
    1381           1 :     TestSourceContext *test = ctx->priv;
    1382           1 :     int r_w, r_h, w_h, p_w, p_h, i, tmp, x = 0;
    1383           1 :     const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(picref->format);
    1384             : 
    1385           1 :     picref->colorspace = AVCOL_SPC_BT470BG;
    1386             : 
    1387           1 :     r_w = FFALIGN((test->w + 6) / 7, 1 << pixdesc->log2_chroma_w);
    1388           1 :     r_h = FFALIGN(test->h * 2 / 3, 1 << pixdesc->log2_chroma_h);
    1389           1 :     w_h = FFALIGN(test->h * 3 / 4 - r_h,  1 << pixdesc->log2_chroma_h);
    1390           1 :     p_w = FFALIGN(r_w * 5 / 4, 1 << pixdesc->log2_chroma_w);
    1391           1 :     p_h = test->h - w_h - r_h;
    1392             : 
    1393           8 :     for (i = 0; i < 7; i++) {
    1394           7 :         draw_bar(test, rainbow[i], x, 0,   r_w, r_h, picref);
    1395           7 :         draw_bar(test, wobnair[i], x, r_h, r_w, w_h, picref);
    1396           7 :         x += r_w;
    1397             :     }
    1398           1 :     x = 0;
    1399           1 :     draw_bar(test, i_pixel, x, r_h + w_h, p_w, p_h, picref);
    1400           1 :     x += p_w;
    1401           1 :     draw_bar(test, white, x, r_h + w_h, p_w, p_h, picref);
    1402           1 :     x += p_w;
    1403           1 :     draw_bar(test, q_pixel, x, r_h + w_h, p_w, p_h, picref);
    1404           1 :     x += p_w;
    1405           1 :     tmp = FFALIGN(5 * r_w - x,  1 << pixdesc->log2_chroma_w);
    1406           1 :     draw_bar(test, black0, x, r_h + w_h, tmp, p_h, picref);
    1407           1 :     x += tmp;
    1408           1 :     tmp = FFALIGN(r_w / 3,  1 << pixdesc->log2_chroma_w);
    1409           1 :     draw_bar(test, neg4ire, x, r_h + w_h, tmp, p_h, picref);
    1410           1 :     x += tmp;
    1411           1 :     draw_bar(test, black0, x, r_h + w_h, tmp, p_h, picref);
    1412           1 :     x += tmp;
    1413           1 :     draw_bar(test, pos4ire, x, r_h + w_h, tmp, p_h, picref);
    1414           1 :     x += tmp;
    1415           1 :     draw_bar(test, black0, x, r_h + w_h, test->w - x, p_h, picref);
    1416           1 : }
    1417             : 
    1418           2 : static av_cold int smptebars_init(AVFilterContext *ctx)
    1419             : {
    1420           2 :     TestSourceContext *test = ctx->priv;
    1421             : 
    1422           2 :     test->fill_picture_fn = smptebars_fill_picture;
    1423           2 :     test->draw_once = 1;
    1424           2 :     return init(ctx);
    1425             : }
    1426             : 
    1427             : AVFilter ff_vsrc_smptebars = {
    1428             :     .name          = "smptebars",
    1429             :     .description   = NULL_IF_CONFIG_SMALL("Generate SMPTE color bars."),
    1430             :     .priv_size     = sizeof(TestSourceContext),
    1431             :     .priv_class    = &smptebars_class,
    1432             :     .init          = smptebars_init,
    1433             :     .uninit        = uninit,
    1434             :     .query_formats = smptebars_query_formats,
    1435             :     .inputs        = NULL,
    1436             :     .outputs       = smptebars_outputs,
    1437             : };
    1438             : 
    1439             : #endif  /* CONFIG_SMPTEBARS_FILTER */
    1440             : 
    1441             : #if CONFIG_SMPTEHDBARS_FILTER
    1442             : 
    1443             : #define smptehdbars_options options
    1444             : AVFILTER_DEFINE_CLASS(smptehdbars);
    1445             : 
    1446           1 : static void smptehdbars_fill_picture(AVFilterContext *ctx, AVFrame *picref)
    1447             : {
    1448           1 :     TestSourceContext *test = ctx->priv;
    1449           1 :     int d_w, r_w, r_h, l_w, i, tmp, x = 0, y = 0;
    1450           1 :     const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(picref->format);
    1451             : 
    1452           1 :     picref->colorspace = AVCOL_SPC_BT709;
    1453             : 
    1454           1 :     d_w = FFALIGN(test->w / 8, 1 << pixdesc->log2_chroma_w);
    1455           1 :     r_h = FFALIGN(test->h * 7 / 12, 1 << pixdesc->log2_chroma_h);
    1456           1 :     draw_bar(test, gray40, x, 0, d_w, r_h, picref);
    1457           1 :     x += d_w;
    1458             : 
    1459           1 :     r_w = FFALIGN((((test->w + 3) / 4) * 3) / 7, 1 << pixdesc->log2_chroma_w);
    1460           8 :     for (i = 0; i < 7; i++) {
    1461           7 :         draw_bar(test, rainbowhd[i], x, 0, r_w, r_h, picref);
    1462           7 :         x += r_w;
    1463             :     }
    1464           1 :     draw_bar(test, gray40, x, 0, test->w - x, r_h, picref);
    1465           1 :     y = r_h;
    1466           1 :     r_h = FFALIGN(test->h / 12, 1 << pixdesc->log2_chroma_h);
    1467           1 :     draw_bar(test, cyan, 0, y, d_w, r_h, picref);
    1468           1 :     x = d_w;
    1469           1 :     draw_bar(test, i_pixel, x, y, r_w, r_h, picref);
    1470           1 :     x += r_w;
    1471           1 :     tmp = r_w * 6;
    1472           1 :     draw_bar(test, rainbowhd[0], x, y, tmp, r_h, picref);
    1473           1 :     x += tmp;
    1474           1 :     l_w = x;
    1475           1 :     draw_bar(test, blue, x, y, test->w - x, r_h, picref);
    1476           1 :     y += r_h;
    1477           1 :     draw_bar(test, yellow, 0, y, d_w, r_h, picref);
    1478           1 :     x = d_w;
    1479           1 :     draw_bar(test, q_pixel, x, y, r_w, r_h, picref);
    1480           1 :     x += r_w;
    1481             : 
    1482         205 :     for (i = 0; i < tmp; i += 1 << pixdesc->log2_chroma_w) {
    1483         204 :         uint8_t yramp[4] = {0};
    1484             : 
    1485         204 :         yramp[0] = i * 255 / tmp;
    1486         204 :         yramp[1] = 128;
    1487         204 :         yramp[2] = 128;
    1488         204 :         yramp[3] = 255;
    1489             : 
    1490         204 :         draw_bar(test, yramp, x, y, 1 << pixdesc->log2_chroma_w, r_h, picref);
    1491         204 :         x += 1 << pixdesc->log2_chroma_w;
    1492             :     }
    1493           1 :     draw_bar(test, red, x, y, test->w - x, r_h, picref);
    1494           1 :     y += r_h;
    1495           1 :     draw_bar(test, gray15, 0, y, d_w, test->h - y, picref);
    1496           1 :     x = d_w;
    1497           1 :     tmp = FFALIGN(r_w * 3 / 2, 1 << pixdesc->log2_chroma_w);
    1498           1 :     draw_bar(test, black0, x, y, tmp, test->h - y, picref);
    1499           1 :     x += tmp;
    1500           1 :     tmp = FFALIGN(r_w * 2, 1 << pixdesc->log2_chroma_w);
    1501           1 :     draw_bar(test, white, x, y, tmp, test->h - y, picref);
    1502           1 :     x += tmp;
    1503           1 :     tmp = FFALIGN(r_w * 5 / 6, 1 << pixdesc->log2_chroma_w);
    1504           1 :     draw_bar(test, black0, x, y, tmp, test->h - y, picref);
    1505           1 :     x += tmp;
    1506           1 :     tmp = FFALIGN(r_w / 3, 1 << pixdesc->log2_chroma_w);
    1507           1 :     draw_bar(test,   neg2, x, y, tmp, test->h - y, picref);
    1508           1 :     x += tmp;
    1509           1 :     draw_bar(test, black0, x, y, tmp, test->h - y, picref);
    1510           1 :     x += tmp;
    1511           1 :     draw_bar(test, black2, x, y, tmp, test->h - y, picref);
    1512           1 :     x += tmp;
    1513           1 :     draw_bar(test, black0, x, y, tmp, test->h - y, picref);
    1514           1 :     x += tmp;
    1515           1 :     draw_bar(test, black4, x, y, tmp, test->h - y, picref);
    1516           1 :     x += tmp;
    1517           1 :     r_w = l_w - x;
    1518           1 :     draw_bar(test, black0, x, y, r_w, test->h - y, picref);
    1519           1 :     x += r_w;
    1520           1 :     draw_bar(test, gray15, x, y, test->w - x, test->h - y, picref);
    1521           1 : }
    1522             : 
    1523           2 : static av_cold int smptehdbars_init(AVFilterContext *ctx)
    1524             : {
    1525           2 :     TestSourceContext *test = ctx->priv;
    1526             : 
    1527           2 :     test->fill_picture_fn = smptehdbars_fill_picture;
    1528           2 :     test->draw_once = 1;
    1529           2 :     return init(ctx);
    1530             : }
    1531             : 
    1532             : AVFilter ff_vsrc_smptehdbars = {
    1533             :     .name          = "smptehdbars",
    1534             :     .description   = NULL_IF_CONFIG_SMALL("Generate SMPTE HD color bars."),
    1535             :     .priv_size     = sizeof(TestSourceContext),
    1536             :     .priv_class    = &smptehdbars_class,
    1537             :     .init          = smptehdbars_init,
    1538             :     .uninit        = uninit,
    1539             :     .query_formats = smptebars_query_formats,
    1540             :     .inputs        = NULL,
    1541             :     .outputs       = smptebars_outputs,
    1542             : };
    1543             : 
    1544             : #endif  /* CONFIG_SMPTEHDBARS_FILTER */
    1545             : #endif  /* CONFIG_SMPTEBARS_FILTER || CONFIG_SMPTEHDBARS_FILTER */
    1546             : 
    1547             : #if CONFIG_ALLYUV_FILTER
    1548             : 
    1549             : static const AVOption allyuv_options[] = {
    1550             :     COMMON_OPTIONS_NOSIZE
    1551             :     { NULL }
    1552             : };
    1553             : 
    1554             : AVFILTER_DEFINE_CLASS(allyuv);
    1555             : 
    1556           1 : static void allyuv_fill_picture(AVFilterContext *ctx, AVFrame *frame)
    1557             : {
    1558           1 :     const int ys = frame->linesize[0];
    1559           1 :     const int us = frame->linesize[1];
    1560           1 :     const int vs = frame->linesize[2];
    1561             :     int x, y, j;
    1562             : 
    1563        4097 :     for (y = 0; y < 4096; y++) {
    1564     8392704 :         for (x = 0; x < 2048; x++) {
    1565     8388608 :             frame->data[0][y * ys + x] = ((x / 8) % 256);
    1566     8388608 :             frame->data[0][y * ys + 4095 - x] = ((x / 8) % 256);
    1567             :         }
    1568             : 
    1569     1052672 :         for (x = 0; x < 2048; x+=8) {
    1570     9437184 :             for (j = 0; j < 8; j++) {
    1571     8388608 :                 frame->data[1][vs * y + x + j]        = (y%16 + (j % 8) * 16);
    1572     8388608 :                 frame->data[1][vs * y + 4095 - x - j] = (128 + y%16 + (j % 8) * 16);
    1573             :             }
    1574             :         }
    1575             : 
    1576    16781312 :         for (x = 0; x < 4096; x++)
    1577    16777216 :             frame->data[2][y * us + x] = 256 * y / 4096;
    1578             :     }
    1579           1 : }
    1580             : 
    1581           2 : static av_cold int allyuv_init(AVFilterContext *ctx)
    1582             : {
    1583           2 :     TestSourceContext *test = ctx->priv;
    1584             : 
    1585           2 :     test->w = test->h = 4096;
    1586           2 :     test->draw_once = 1;
    1587           2 :     test->fill_picture_fn = allyuv_fill_picture;
    1588           2 :     return init(ctx);
    1589             : }
    1590             : 
    1591           1 : static int allyuv_query_formats(AVFilterContext *ctx)
    1592             : {
    1593             :     static const enum AVPixelFormat pix_fmts[] = {
    1594             :         AV_PIX_FMT_YUV444P, AV_PIX_FMT_GBRP,
    1595             :         AV_PIX_FMT_NONE
    1596             :     };
    1597             : 
    1598           1 :     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
    1599           1 :     if (!fmts_list)
    1600           0 :         return AVERROR(ENOMEM);
    1601           1 :     return ff_set_common_formats(ctx, fmts_list);
    1602             : }
    1603             : 
    1604             : static const AVFilterPad avfilter_vsrc_allyuv_outputs[] = {
    1605             :     {
    1606             :         .name          = "default",
    1607             :         .type          = AVMEDIA_TYPE_VIDEO,
    1608             :         .request_frame = request_frame,
    1609             :         .config_props  = config_props,
    1610             :     },
    1611             :     { NULL }
    1612             : };
    1613             : 
    1614             : AVFilter ff_vsrc_allyuv = {
    1615             :     .name          = "allyuv",
    1616             :     .description   = NULL_IF_CONFIG_SMALL("Generate all yuv colors."),
    1617             :     .priv_size     = sizeof(TestSourceContext),
    1618             :     .priv_class    = &allyuv_class,
    1619             :     .init          = allyuv_init,
    1620             :     .uninit        = uninit,
    1621             :     .query_formats = allyuv_query_formats,
    1622             :     .inputs        = NULL,
    1623             :     .outputs       = avfilter_vsrc_allyuv_outputs,
    1624             : };
    1625             : 
    1626             : #endif /* CONFIG_ALLYUV_FILTER */
    1627             : 
    1628             : #if CONFIG_ALLRGB_FILTER
    1629             : 
    1630             : static const AVOption allrgb_options[] = {
    1631             :     COMMON_OPTIONS_NOSIZE
    1632             :     { NULL }
    1633             : };
    1634             : 
    1635             : AVFILTER_DEFINE_CLASS(allrgb);
    1636             : 
    1637           1 : static void allrgb_fill_picture(AVFilterContext *ctx, AVFrame *frame)
    1638             : {
    1639             :     unsigned x, y;
    1640           1 :     const int linesize = frame->linesize[0];
    1641           1 :     uint8_t *line = frame->data[0];
    1642             : 
    1643        4097 :     for (y = 0; y < 4096; y++) {
    1644        4096 :         uint8_t *dst = line;
    1645             : 
    1646    16781312 :         for (x = 0; x < 4096; x++) {
    1647    16777216 :             *dst++ = x;
    1648    16777216 :             *dst++ = y;
    1649    16777216 :             *dst++ = (x >> 8) | ((y >> 8) << 4);
    1650             :         }
    1651        4096 :         line += linesize;
    1652             :     }
    1653           1 : }
    1654             : 
    1655           2 : static av_cold int allrgb_init(AVFilterContext *ctx)
    1656             : {
    1657           2 :     TestSourceContext *test = ctx->priv;
    1658             : 
    1659           2 :     test->w = test->h = 4096;
    1660           2 :     test->draw_once = 1;
    1661           2 :     test->fill_picture_fn = allrgb_fill_picture;
    1662           2 :     return init(ctx);
    1663             : }
    1664             : 
    1665           1 : static int allrgb_config_props(AVFilterLink *outlink)
    1666             : {
    1667           1 :     TestSourceContext *test = outlink->src->priv;
    1668             : 
    1669           1 :     ff_fill_rgba_map(test->rgba_map, outlink->format);
    1670           1 :     return config_props(outlink);
    1671             : }
    1672             : 
    1673           1 : static int allrgb_query_formats(AVFilterContext *ctx)
    1674             : {
    1675             :     static const enum AVPixelFormat pix_fmts[] = {
    1676             :         AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE
    1677             :     };
    1678             : 
    1679           1 :     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
    1680           1 :     if (!fmts_list)
    1681           0 :         return AVERROR(ENOMEM);
    1682           1 :     return ff_set_common_formats(ctx, fmts_list);
    1683             : }
    1684             : 
    1685             : static const AVFilterPad avfilter_vsrc_allrgb_outputs[] = {
    1686             :     {
    1687             :         .name          = "default",
    1688             :         .type          = AVMEDIA_TYPE_VIDEO,
    1689             :         .request_frame = request_frame,
    1690             :         .config_props  = allrgb_config_props,
    1691             :     },
    1692             :     { NULL }
    1693             : };
    1694             : 
    1695             : AVFilter ff_vsrc_allrgb = {
    1696             :     .name          = "allrgb",
    1697             :     .description   = NULL_IF_CONFIG_SMALL("Generate all RGB colors."),
    1698             :     .priv_size     = sizeof(TestSourceContext),
    1699             :     .priv_class    = &allrgb_class,
    1700             :     .init          = allrgb_init,
    1701             :     .uninit        = uninit,
    1702             :     .query_formats = allrgb_query_formats,
    1703             :     .inputs        = NULL,
    1704             :     .outputs       = avfilter_vsrc_allrgb_outputs,
    1705             : };
    1706             : 
    1707             : #endif /* CONFIG_ALLRGB_FILTER */

Generated by: LCOV version 1.13