| Line | Branch | Exec | Source |
|---|---|---|---|
| 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 "config_components.h" | ||
| 37 | |||
| 38 | #include "libavutil/avassert.h" | ||
| 39 | #include "libavutil/common.h" | ||
| 40 | #include "libavutil/ffmath.h" | ||
| 41 | #include "libavutil/mem.h" | ||
| 42 | #include "libavutil/opt.h" | ||
| 43 | #include "libavutil/imgutils.h" | ||
| 44 | #include "libavutil/intreadwrite.h" | ||
| 45 | #include "libavutil/xga_font_data.h" | ||
| 46 | #include "avfilter.h" | ||
| 47 | #include "drawutils.h" | ||
| 48 | #include "filters.h" | ||
| 49 | #include "filters.h" | ||
| 50 | #include "formats.h" | ||
| 51 | #include "video.h" | ||
| 52 | |||
| 53 | typedef struct TestSourceContext { | ||
| 54 | const AVClass *class; | ||
| 55 | int w, h; | ||
| 56 | int pw, ph; | ||
| 57 | unsigned int nb_frame; | ||
| 58 | AVRational time_base, frame_rate; | ||
| 59 | int64_t pts; | ||
| 60 | int64_t duration; ///< duration expressed in microseconds | ||
| 61 | AVRational sar; ///< sample aspect ratio | ||
| 62 | int draw_once; ///< draw only the first frame, always put out the same picture | ||
| 63 | int draw_once_reset; ///< draw only the first frame or in case of reset | ||
| 64 | AVFrame *picref; ///< cached reference containing the painted picture | ||
| 65 | |||
| 66 | void (* fill_picture_fn)(AVFilterContext *ctx, AVFrame *frame); | ||
| 67 | |||
| 68 | /* only used by testsrc */ | ||
| 69 | int nb_decimals; | ||
| 70 | |||
| 71 | /* only used by testsrc2 */ | ||
| 72 | int alpha; | ||
| 73 | |||
| 74 | /* only used by yuvtest */ | ||
| 75 | uint8_t ayuv_map[4]; | ||
| 76 | |||
| 77 | /* only used by colorspectrum */ | ||
| 78 | int type; | ||
| 79 | |||
| 80 | /* only used by color */ | ||
| 81 | FFDrawContext draw; | ||
| 82 | FFDrawColor color; | ||
| 83 | uint8_t color_rgba[4]; | ||
| 84 | |||
| 85 | /* only used by rgbtest */ | ||
| 86 | uint8_t rgba_map[4]; | ||
| 87 | int complement; | ||
| 88 | int depth; | ||
| 89 | |||
| 90 | /* only used by haldclut */ | ||
| 91 | int level; | ||
| 92 | |||
| 93 | /* only used by zoneplate */ | ||
| 94 | int k0, kx, ky, kt; | ||
| 95 | int kxt, kyt, kxy; | ||
| 96 | int kx2, ky2, kt2; | ||
| 97 | int xo, yo, to, kU, kV; | ||
| 98 | int lut_precision; | ||
| 99 | uint8_t *lut; | ||
| 100 | int (*fill_slice_fn)(AVFilterContext *ctx, void *arg, int job, int nb_jobs); | ||
| 101 | } TestSourceContext; | ||
| 102 | |||
| 103 | #define OFFSET(x) offsetof(TestSourceContext, x) | ||
| 104 | #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM | ||
| 105 | #define FLAGSR AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM | ||
| 106 | |||
| 107 | #define SIZE_OPTIONS \ | ||
| 108 | { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "320x240"}, 0, 0, FLAGS },\ | ||
| 109 | { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "320x240"}, 0, 0, FLAGS },\ | ||
| 110 | |||
| 111 | #define COMMON_OPTIONS_NOSIZE \ | ||
| 112 | { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },\ | ||
| 113 | { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },\ | ||
| 114 | { "duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },\ | ||
| 115 | { "d", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },\ | ||
| 116 | { "sar", "set video sample aspect ratio", OFFSET(sar), AV_OPT_TYPE_RATIONAL, {.dbl= 1}, 0, INT_MAX, FLAGS }, | ||
| 117 | |||
| 118 | #define COMMON_OPTIONS SIZE_OPTIONS COMMON_OPTIONS_NOSIZE | ||
| 119 | |||
| 120 | #define NOSIZE_OPTIONS_OFFSET 2 | ||
| 121 | /* Filters using COMMON_OPTIONS_NOSIZE also use the following options | ||
| 122 | * via &options[NOSIZE_OPTIONS_OFFSET]. So don't break it. */ | ||
| 123 | static const AVOption options[] = { | ||
| 124 | COMMON_OPTIONS | ||
| 125 | { NULL } | ||
| 126 | }; | ||
| 127 | |||
| 128 | 2420 | static av_cold int init(AVFilterContext *ctx) | |
| 129 | { | ||
| 130 | 2420 | TestSourceContext *test = ctx->priv; | |
| 131 | |||
| 132 | 2420 | test->time_base = av_inv_q(test->frame_rate); | |
| 133 | 2420 | test->nb_frame = 0; | |
| 134 | 2420 | test->pts = 0; | |
| 135 | |||
| 136 | 2420 | av_log(ctx, AV_LOG_VERBOSE, "size:%dx%d rate:%d/%d duration:%f sar:%d/%d\n", | |
| 137 | test->w, test->h, test->frame_rate.num, test->frame_rate.den, | ||
| 138 |
2/2✓ Branch 0 taken 183 times.
✓ Branch 1 taken 2237 times.
|
2420 | test->duration < 0 ? -1 : (double)test->duration/1000000, |
| 139 | test->sar.num, test->sar.den); | ||
| 140 | 2420 | return 0; | |
| 141 | } | ||
| 142 | |||
| 143 | 2420 | static av_cold void uninit(AVFilterContext *ctx) | |
| 144 | { | ||
| 145 | 2420 | TestSourceContext *test = ctx->priv; | |
| 146 | |||
| 147 | 2420 | av_frame_free(&test->picref); | |
| 148 | 2420 | av_freep(&test->lut); | |
| 149 | 2420 | } | |
| 150 | |||
| 151 | 1220 | static int config_props(AVFilterLink *outlink) | |
| 152 | { | ||
| 153 | 1220 | TestSourceContext *test = outlink->src->priv; | |
| 154 | 1220 | FilterLink *l = ff_filter_link(outlink); | |
| 155 | |||
| 156 | 1220 | outlink->w = test->w; | |
| 157 | 1220 | outlink->h = test->h; | |
| 158 | 1220 | outlink->sample_aspect_ratio = test->sar; | |
| 159 | 1220 | l->frame_rate = test->frame_rate; | |
| 160 | 1220 | outlink->time_base = test->time_base; | |
| 161 | |||
| 162 | 1220 | return 0; | |
| 163 | } | ||
| 164 | |||
| 165 | static const AVFilterPad outputs[] = { | ||
| 166 | { | ||
| 167 | .name = "default", | ||
| 168 | .type = AVMEDIA_TYPE_VIDEO, | ||
| 169 | .config_props = config_props, | ||
| 170 | }, | ||
| 171 | }; | ||
| 172 | |||
| 173 | 32500 | static int activate(AVFilterContext *ctx) | |
| 174 | { | ||
| 175 | 32500 | AVFilterLink *outlink = ctx->outputs[0]; | |
| 176 | 32500 | TestSourceContext *test = ctx->priv; | |
| 177 | AVFrame *frame; | ||
| 178 | |||
| 179 |
2/2✓ Branch 1 taken 23 times.
✓ Branch 2 taken 32477 times.
|
32500 | if (!ff_outlink_frame_wanted(outlink)) |
| 180 | 23 | return FFERROR_NOT_READY; | |
| 181 |
2/2✓ Branch 0 taken 3705 times.
✓ Branch 1 taken 28772 times.
|
32477 | if (test->duration >= 0 && |
| 182 |
2/2✓ Branch 0 taken 97 times.
✓ Branch 1 taken 3608 times.
|
3705 | av_rescale_q(test->pts, test->time_base, AV_TIME_BASE_Q) >= test->duration) { |
| 183 | 97 | ff_outlink_set_status(outlink, AVERROR_EOF, test->pts); | |
| 184 | 97 | return 0; | |
| 185 | } | ||
| 186 | |||
| 187 |
2/2✓ Branch 0 taken 31025 times.
✓ Branch 1 taken 1355 times.
|
32380 | if (test->draw_once) { |
| 188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31025 times.
|
31025 | if (test->draw_once_reset) { |
| 189 | ✗ | av_frame_free(&test->picref); | |
| 190 | ✗ | test->draw_once_reset = 0; | |
| 191 | } | ||
| 192 |
2/2✓ Branch 0 taken 1152 times.
✓ Branch 1 taken 29873 times.
|
31025 | if (!test->picref) { |
| 193 | 1152 | test->picref = | |
| 194 | 1152 | ff_get_video_buffer(outlink, test->w, test->h); | |
| 195 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1152 times.
|
1152 | if (!test->picref) |
| 196 | ✗ | return AVERROR(ENOMEM); | |
| 197 | 1152 | test->fill_picture_fn(outlink->src, test->picref); | |
| 198 | } | ||
| 199 | 31025 | frame = av_frame_clone(test->picref); | |
| 200 | } else | ||
| 201 | 1355 | frame = ff_get_video_buffer(outlink, test->w, test->h); | |
| 202 | |||
| 203 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32380 times.
|
32380 | if (!frame) |
| 204 | ✗ | return AVERROR(ENOMEM); | |
| 205 | 32380 | frame->pts = test->pts; | |
| 206 | 32380 | frame->duration = 1; | |
| 207 | 32380 | frame->flags |= AV_FRAME_FLAG_KEY; | |
| 208 | 32380 | frame->flags &= ~AV_FRAME_FLAG_INTERLACED; | |
| 209 | 32380 | frame->pict_type = AV_PICTURE_TYPE_I; | |
| 210 | 32380 | frame->sample_aspect_ratio = test->sar; | |
| 211 |
2/2✓ Branch 0 taken 1355 times.
✓ Branch 1 taken 31025 times.
|
32380 | if (!test->draw_once) |
| 212 | 1355 | test->fill_picture_fn(outlink->src, frame); | |
| 213 | |||
| 214 | 32380 | test->pts++; | |
| 215 | 32380 | test->nb_frame++; | |
| 216 | |||
| 217 | 32380 | return ff_filter_frame(outlink, frame); | |
| 218 | } | ||
| 219 | |||
| 220 | #if CONFIG_COLOR_FILTER | ||
| 221 | |||
| 222 | static const AVOption color_options[] = { | ||
| 223 | { "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGSR }, | ||
| 224 | { "c", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGSR }, | ||
| 225 | COMMON_OPTIONS | ||
| 226 | { NULL } | ||
| 227 | }; | ||
| 228 | |||
| 229 | AVFILTER_DEFINE_CLASS(color); | ||
| 230 | |||
| 231 | 16 | static void color_fill_picture(AVFilterContext *ctx, AVFrame *picref) | |
| 232 | { | ||
| 233 | 16 | TestSourceContext *test = ctx->priv; | |
| 234 | 16 | ff_fill_rectangle(&test->draw, &test->color, | |
| 235 | 16 | picref->data, picref->linesize, | |
| 236 | 0, 0, test->w, test->h); | ||
| 237 | 16 | } | |
| 238 | |||
| 239 | 29 | static av_cold int color_init(AVFilterContext *ctx) | |
| 240 | { | ||
| 241 | 29 | TestSourceContext *test = ctx->priv; | |
| 242 | 29 | test->fill_picture_fn = color_fill_picture; | |
| 243 | 29 | test->draw_once = 1; | |
| 244 | 29 | return init(ctx); | |
| 245 | } | ||
| 246 | |||
| 247 | 16 | static int color_query_formats(const AVFilterContext *ctx, | |
| 248 | AVFilterFormatsConfig **cfg_in, | ||
| 249 | AVFilterFormatsConfig **cfg_out) | ||
| 250 | { | ||
| 251 | 16 | return ff_set_common_formats2(ctx, cfg_in, cfg_out, ff_draw_supported_pixel_formats(0)); | |
| 252 | } | ||
| 253 | |||
| 254 | 16 | static int color_config_props(AVFilterLink *inlink) | |
| 255 | { | ||
| 256 | 16 | AVFilterContext *ctx = inlink->src; | |
| 257 | 16 | TestSourceContext *test = ctx->priv; | |
| 258 | int ret; | ||
| 259 | |||
| 260 | 16 | ret = ff_draw_init_from_link(&test->draw, inlink, 0); | |
| 261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (ret < 0) { |
| 262 | ✗ | av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n"); | |
| 263 | ✗ | return ret; | |
| 264 | } | ||
| 265 | |||
| 266 | 16 | ff_draw_color(&test->draw, &test->color, test->color_rgba); | |
| 267 | |||
| 268 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
|
16 | if (av_image_check_size(test->w, test->h, 0, ctx) < 0) |
| 269 | ✗ | return AVERROR(EINVAL); | |
| 270 | |||
| 271 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
|
16 | if ((ret = config_props(inlink)) < 0) |
| 272 | ✗ | return ret; | |
| 273 | |||
| 274 | 16 | return 0; | |
| 275 | } | ||
| 276 | |||
| 277 | ✗ | static int color_process_command(AVFilterContext *ctx, const char *cmd, const char *args, | |
| 278 | char *res, int res_len, int flags) | ||
| 279 | { | ||
| 280 | ✗ | TestSourceContext *test = ctx->priv; | |
| 281 | int ret; | ||
| 282 | |||
| 283 | ✗ | ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); | |
| 284 | ✗ | if (ret < 0) | |
| 285 | ✗ | return ret; | |
| 286 | |||
| 287 | ✗ | ff_draw_color(&test->draw, &test->color, test->color_rgba); | |
| 288 | ✗ | test->draw_once_reset = 1; | |
| 289 | ✗ | return 0; | |
| 290 | } | ||
| 291 | |||
| 292 | static const AVFilterPad color_outputs[] = { | ||
| 293 | { | ||
| 294 | .name = "default", | ||
| 295 | .type = AVMEDIA_TYPE_VIDEO, | ||
| 296 | .config_props = color_config_props, | ||
| 297 | }, | ||
| 298 | }; | ||
| 299 | |||
| 300 | const FFFilter ff_vsrc_color = { | ||
| 301 | .p.name = "color", | ||
| 302 | .p.description = NULL_IF_CONFIG_SMALL("Provide an uniformly colored input."), | ||
| 303 | .p.priv_class = &color_class, | ||
| 304 | .priv_size = sizeof(TestSourceContext), | ||
| 305 | .init = color_init, | ||
| 306 | .uninit = uninit, | ||
| 307 | .activate = activate, | ||
| 308 | FILTER_OUTPUTS(color_outputs), | ||
| 309 | FILTER_QUERY_FUNC2(color_query_formats), | ||
| 310 | .process_command = color_process_command, | ||
| 311 | }; | ||
| 312 | |||
| 313 | #endif /* CONFIG_COLOR_FILTER */ | ||
| 314 | |||
| 315 | #if CONFIG_HALDCLUTSRC_FILTER | ||
| 316 | |||
| 317 | static const AVOption haldclutsrc_options[] = { | ||
| 318 | { "level", "set level", OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 6}, 2, 16, FLAGS }, | ||
| 319 | COMMON_OPTIONS_NOSIZE | ||
| 320 | { NULL } | ||
| 321 | }; | ||
| 322 | |||
| 323 | AVFILTER_DEFINE_CLASS(haldclutsrc); | ||
| 324 | |||
| 325 | ✗ | static void haldclutsrc_fill_picture(AVFilterContext *ctx, AVFrame *frame) | |
| 326 | { | ||
| 327 | ✗ | int i, j, k, x = 0, y = 0, is16bit = 0, step; | |
| 328 | ✗ | uint32_t alpha = 0; | |
| 329 | ✗ | const TestSourceContext *hc = ctx->priv; | |
| 330 | ✗ | int level = hc->level; | |
| 331 | float scale; | ||
| 332 | ✗ | const int w = frame->width; | |
| 333 | ✗ | const int h = frame->height; | |
| 334 | ✗ | uint8_t *data = frame->data[0]; | |
| 335 | ✗ | const ptrdiff_t linesize = frame->linesize[0]; | |
| 336 | ✗ | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); | |
| 337 | ✗ | const int depth = desc->comp[0].depth; | |
| 338 | ✗ | const int planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR; | |
| 339 | ✗ | const int planes = av_pix_fmt_count_planes(frame->format); | |
| 340 | uint8_t rgba_map[4]; | ||
| 341 | |||
| 342 | ✗ | av_assert0(w == h && w == level*level*level); | |
| 343 | |||
| 344 | ✗ | ff_fill_rgba_map(rgba_map, frame->format); | |
| 345 | |||
| 346 | ✗ | alpha = (1 << depth) - 1; | |
| 347 | ✗ | is16bit = depth > 8; | |
| 348 | |||
| 349 | ✗ | step = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit); | |
| 350 | ✗ | scale = ((float)alpha) / (level*level - 1); | |
| 351 | |||
| 352 | #define LOAD_CLUT(nbits) do { \ | ||
| 353 | uint##nbits##_t *dst = ((uint##nbits##_t *)(data + y*linesize)) + x*step; \ | ||
| 354 | dst[rgba_map[0]] = av_clip_uint##nbits(i * scale); \ | ||
| 355 | dst[rgba_map[1]] = av_clip_uint##nbits(j * scale); \ | ||
| 356 | dst[rgba_map[2]] = av_clip_uint##nbits(k * scale); \ | ||
| 357 | if (step == 4) \ | ||
| 358 | dst[rgba_map[3]] = alpha; \ | ||
| 359 | } while (0) | ||
| 360 | |||
| 361 | #define LOAD_CLUT_PLANAR(type, nbits) do { \ | ||
| 362 | type *dst = ((type *)(frame->data[2] + y*frame->linesize[2])) + x; \ | ||
| 363 | dst[0] = av_clip_uintp2(i * scale, nbits); \ | ||
| 364 | dst = ((type *)(frame->data[0] + y*frame->linesize[0])) + x; \ | ||
| 365 | dst[0] = av_clip_uintp2(j * scale, nbits); \ | ||
| 366 | dst = ((type *)(frame->data[1] + y*frame->linesize[1])) + x; \ | ||
| 367 | dst[0] = av_clip_uintp2(k * scale, nbits); \ | ||
| 368 | if (planes == 4) { \ | ||
| 369 | dst = ((type *)(frame->data[3] + y*linesize)) + x; \ | ||
| 370 | dst[0] = alpha; \ | ||
| 371 | } \ | ||
| 372 | } while (0) | ||
| 373 | |||
| 374 | ✗ | level *= level; | |
| 375 | ✗ | for (k = 0; k < level; k++) { | |
| 376 | ✗ | for (j = 0; j < level; j++) { | |
| 377 | ✗ | for (i = 0; i < level; i++) { | |
| 378 | ✗ | if (!planar) { | |
| 379 | ✗ | if (!is16bit) | |
| 380 | ✗ | LOAD_CLUT(8); | |
| 381 | else | ||
| 382 | ✗ | LOAD_CLUT(16); | |
| 383 | } else { | ||
| 384 | ✗ | switch (depth) { | |
| 385 | ✗ | case 8: LOAD_CLUT_PLANAR(uint8_t, 8); break; | |
| 386 | ✗ | case 9: LOAD_CLUT_PLANAR(uint16_t, 9); break; | |
| 387 | ✗ | case 10: LOAD_CLUT_PLANAR(uint16_t,10); break; | |
| 388 | ✗ | case 12: LOAD_CLUT_PLANAR(uint16_t,12); break; | |
| 389 | ✗ | case 14: LOAD_CLUT_PLANAR(uint16_t,14); break; | |
| 390 | ✗ | case 16: LOAD_CLUT_PLANAR(uint16_t,16); break; | |
| 391 | } | ||
| 392 | } | ||
| 393 | ✗ | if (++x == w) { | |
| 394 | ✗ | x = 0; | |
| 395 | ✗ | y++; | |
| 396 | } | ||
| 397 | } | ||
| 398 | } | ||
| 399 | } | ||
| 400 | ✗ | } | |
| 401 | |||
| 402 | ✗ | static av_cold int haldclutsrc_init(AVFilterContext *ctx) | |
| 403 | { | ||
| 404 | ✗ | TestSourceContext *hc = ctx->priv; | |
| 405 | ✗ | hc->fill_picture_fn = haldclutsrc_fill_picture; | |
| 406 | ✗ | hc->draw_once = 1; | |
| 407 | ✗ | return init(ctx); | |
| 408 | } | ||
| 409 | |||
| 410 | static const enum AVPixelFormat haldclutsrc_pix_fmts[] = { | ||
| 411 | AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, | ||
| 412 | AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, | ||
| 413 | AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, | ||
| 414 | AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR, | ||
| 415 | AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0, | ||
| 416 | AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48, | ||
| 417 | AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64, | ||
| 418 | AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, | ||
| 419 | AV_PIX_FMT_GBRP9, | ||
| 420 | AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, | ||
| 421 | AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, | ||
| 422 | AV_PIX_FMT_GBRP14, | ||
| 423 | AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, | ||
| 424 | AV_PIX_FMT_NONE, | ||
| 425 | }; | ||
| 426 | |||
| 427 | ✗ | static int haldclutsrc_config_props(AVFilterLink *outlink) | |
| 428 | { | ||
| 429 | ✗ | AVFilterContext *ctx = outlink->src; | |
| 430 | ✗ | TestSourceContext *hc = ctx->priv; | |
| 431 | |||
| 432 | ✗ | hc->w = hc->h = hc->level * hc->level * hc->level; | |
| 433 | ✗ | return config_props(outlink); | |
| 434 | } | ||
| 435 | |||
| 436 | static const AVFilterPad haldclutsrc_outputs[] = { | ||
| 437 | { | ||
| 438 | .name = "default", | ||
| 439 | .type = AVMEDIA_TYPE_VIDEO, | ||
| 440 | .config_props = haldclutsrc_config_props, | ||
| 441 | }, | ||
| 442 | }; | ||
| 443 | |||
| 444 | const FFFilter ff_vsrc_haldclutsrc = { | ||
| 445 | .p.name = "haldclutsrc", | ||
| 446 | .p.description = NULL_IF_CONFIG_SMALL("Provide an identity Hald CLUT."), | ||
| 447 | .p.priv_class = &haldclutsrc_class, | ||
| 448 | .priv_size = sizeof(TestSourceContext), | ||
| 449 | .init = haldclutsrc_init, | ||
| 450 | .uninit = uninit, | ||
| 451 | .activate = activate, | ||
| 452 | FILTER_OUTPUTS(haldclutsrc_outputs), | ||
| 453 | FILTER_PIXFMTS_ARRAY(haldclutsrc_pix_fmts), | ||
| 454 | }; | ||
| 455 | #endif /* CONFIG_HALDCLUTSRC_FILTER */ | ||
| 456 | |||
| 457 | AVFILTER_DEFINE_CLASS_EXT(nullsrc_yuvtestsrc, "nullsrc/yuvtestsrc", options); | ||
| 458 | |||
| 459 | #if CONFIG_NULLSRC_FILTER | ||
| 460 | |||
| 461 | ✗ | static void nullsrc_fill_picture(AVFilterContext *ctx, AVFrame *picref) { } | |
| 462 | |||
| 463 | ✗ | static av_cold int nullsrc_init(AVFilterContext *ctx) | |
| 464 | { | ||
| 465 | ✗ | TestSourceContext *test = ctx->priv; | |
| 466 | |||
| 467 | ✗ | test->fill_picture_fn = nullsrc_fill_picture; | |
| 468 | ✗ | return init(ctx); | |
| 469 | } | ||
| 470 | |||
| 471 | const FFFilter ff_vsrc_nullsrc = { | ||
| 472 | .p.name = "nullsrc", | ||
| 473 | .p.description= NULL_IF_CONFIG_SMALL("Null video source, return unprocessed video frames."), | ||
| 474 | .p.priv_class= &nullsrc_yuvtestsrc_class, | ||
| 475 | .init = nullsrc_init, | ||
| 476 | .uninit = uninit, | ||
| 477 | .activate = activate, | ||
| 478 | .priv_size = sizeof(TestSourceContext), | ||
| 479 | FILTER_OUTPUTS(outputs), | ||
| 480 | }; | ||
| 481 | |||
| 482 | #endif /* CONFIG_NULLSRC_FILTER */ | ||
| 483 | |||
| 484 | #if CONFIG_TESTSRC_FILTER | ||
| 485 | |||
| 486 | static const AVOption testsrc_options[] = { | ||
| 487 | COMMON_OPTIONS | ||
| 488 | { "decimals", "set number of decimals to show", OFFSET(nb_decimals), AV_OPT_TYPE_INT, {.i64=0}, 0, 17, FLAGS }, | ||
| 489 | { "n", "set number of decimals to show", OFFSET(nb_decimals), AV_OPT_TYPE_INT, {.i64=0}, 0, 17, FLAGS }, | ||
| 490 | { NULL } | ||
| 491 | }; | ||
| 492 | |||
| 493 | AVFILTER_DEFINE_CLASS(testsrc); | ||
| 494 | |||
| 495 | /** | ||
| 496 | * Fill a rectangle with value val. | ||
| 497 | * | ||
| 498 | * @param val the RGB value to set | ||
| 499 | * @param dst pointer to the destination buffer to fill | ||
| 500 | * @param dst_linesize linesize of destination | ||
| 501 | * @param segment_width width of the segment | ||
| 502 | * @param x horizontal coordinate where to draw the rectangle in the destination buffer | ||
| 503 | * @param y horizontal coordinate where to draw the rectangle in the destination buffer | ||
| 504 | * @param w width of the rectangle to draw, expressed as a number of segment_width units | ||
| 505 | * @param h height of the rectangle to draw, expressed as a number of segment_width units | ||
| 506 | */ | ||
| 507 | 4310 | static void draw_rectangle(unsigned val, uint8_t *dst, ptrdiff_t dst_linesize, int segment_width, | |
| 508 | int x, int y, int w, int h) | ||
| 509 | { | ||
| 510 | int i; | ||
| 511 | 4310 | int step = 3; | |
| 512 | |||
| 513 | 4310 | dst += segment_width * (step * x + y * dst_linesize); | |
| 514 | 4310 | w *= segment_width * step; | |
| 515 | 4310 | h *= segment_width; | |
| 516 |
2/2✓ Branch 0 taken 88165 times.
✓ Branch 1 taken 4310 times.
|
92475 | for (i = 0; i < h; i++) { |
| 517 | 88165 | memset(dst, val, w); | |
| 518 | 88165 | dst += dst_linesize; | |
| 519 | } | ||
| 520 | 4310 | } | |
| 521 | |||
| 522 | 785 | static void draw_digit(int digit, uint8_t *dst, ptrdiff_t dst_linesize, | |
| 523 | int segment_width) | ||
| 524 | { | ||
| 525 | #define TOP_HBAR 1 | ||
| 526 | #define MID_HBAR 2 | ||
| 527 | #define BOT_HBAR 4 | ||
| 528 | #define LEFT_TOP_VBAR 8 | ||
| 529 | #define LEFT_BOT_VBAR 16 | ||
| 530 | #define RIGHT_TOP_VBAR 32 | ||
| 531 | #define RIGHT_BOT_VBAR 64 | ||
| 532 | struct segments { | ||
| 533 | int x, y, w, h; | ||
| 534 | 785 | } segments[] = { | |
| 535 | { 1, 0, 5, 1 }, /* TOP_HBAR */ | ||
| 536 | { 1, 6, 5, 1 }, /* MID_HBAR */ | ||
| 537 | { 1, 12, 5, 1 }, /* BOT_HBAR */ | ||
| 538 | { 0, 1, 1, 5 }, /* LEFT_TOP_VBAR */ | ||
| 539 | { 0, 7, 1, 5 }, /* LEFT_BOT_VBAR */ | ||
| 540 | { 6, 1, 1, 5 }, /* RIGHT_TOP_VBAR */ | ||
| 541 | { 6, 7, 1, 5 } /* RIGHT_BOT_VBAR */ | ||
| 542 | }; | ||
| 543 | static const unsigned char masks[10] = { | ||
| 544 | /* 0 */ TOP_HBAR |BOT_HBAR|LEFT_TOP_VBAR|LEFT_BOT_VBAR|RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, | ||
| 545 | /* 1 */ RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, | ||
| 546 | /* 2 */ TOP_HBAR|MID_HBAR|BOT_HBAR|LEFT_BOT_VBAR |RIGHT_TOP_VBAR, | ||
| 547 | /* 3 */ TOP_HBAR|MID_HBAR|BOT_HBAR |RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, | ||
| 548 | /* 4 */ MID_HBAR |LEFT_TOP_VBAR |RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, | ||
| 549 | /* 5 */ TOP_HBAR|BOT_HBAR|MID_HBAR|LEFT_TOP_VBAR |RIGHT_BOT_VBAR, | ||
| 550 | /* 6 */ TOP_HBAR|BOT_HBAR|MID_HBAR|LEFT_TOP_VBAR|LEFT_BOT_VBAR |RIGHT_BOT_VBAR, | ||
| 551 | /* 7 */ TOP_HBAR |RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, | ||
| 552 | /* 8 */ TOP_HBAR|BOT_HBAR|MID_HBAR|LEFT_TOP_VBAR|LEFT_BOT_VBAR|RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, | ||
| 553 | /* 9 */ TOP_HBAR|BOT_HBAR|MID_HBAR|LEFT_TOP_VBAR |RIGHT_TOP_VBAR|RIGHT_BOT_VBAR, | ||
| 554 | }; | ||
| 555 | 785 | unsigned mask = masks[digit]; | |
| 556 | int i; | ||
| 557 | |||
| 558 | 785 | draw_rectangle(0, dst, dst_linesize, segment_width, 0, 0, 8, 13); | |
| 559 |
2/2✓ Branch 0 taken 5495 times.
✓ Branch 1 taken 785 times.
|
6280 | for (i = 0; i < FF_ARRAY_ELEMS(segments); i++) |
| 560 |
2/2✓ Branch 0 taken 3525 times.
✓ Branch 1 taken 1970 times.
|
5495 | if (mask & (1<<i)) |
| 561 | 3525 | draw_rectangle(255, dst, dst_linesize, segment_width, | |
| 562 | segments[i].x, segments[i].y, segments[i].w, segments[i].h); | ||
| 563 | 785 | } | |
| 564 | |||
| 565 | #define GRADIENT_SIZE (6 * 256) | ||
| 566 | |||
| 567 | 326 | static void test_fill_picture(AVFilterContext *ctx, AVFrame *frame) | |
| 568 | { | ||
| 569 | 326 | TestSourceContext *test = ctx->priv; | |
| 570 | uint8_t *p, *p0; | ||
| 571 | int x, y; | ||
| 572 | int color, color_rest; | ||
| 573 | int icolor; | ||
| 574 | int radius; | ||
| 575 | int quad0, quad; | ||
| 576 | int dquad_x, dquad_y; | ||
| 577 | int grad, dgrad, rgrad, drgrad; | ||
| 578 | int seg_size; | ||
| 579 | int second; | ||
| 580 | int i; | ||
| 581 | 326 | uint8_t *data = frame->data[0]; | |
| 582 | 326 | int width = frame->width; | |
| 583 | 326 | int height = frame->height; | |
| 584 | |||
| 585 | /* draw colored bars and circle */ | ||
| 586 | 326 | radius = (width + height) / 4; | |
| 587 | 326 | quad0 = width * width / 4 + height * height / 4 - radius * radius; | |
| 588 | 326 | dquad_y = 1 - height; | |
| 589 | 326 | p0 = data; | |
| 590 |
2/2✓ Branch 0 taken 71010 times.
✓ Branch 1 taken 326 times.
|
71336 | for (y = 0; y < height; y++) { |
| 591 | 71010 | p = p0; | |
| 592 | 71010 | color = 0; | |
| 593 | 71010 | color_rest = 0; | |
| 594 | 71010 | quad = quad0; | |
| 595 | 71010 | dquad_x = 1 - width; | |
| 596 |
2/2✓ Branch 0 taken 23007140 times.
✓ Branch 1 taken 71010 times.
|
23078150 | for (x = 0; x < width; x++) { |
| 597 | 23007140 | icolor = color; | |
| 598 |
2/2✓ Branch 0 taken 17215585 times.
✓ Branch 1 taken 5791555 times.
|
23007140 | if (quad < 0) |
| 599 | 17215585 | icolor ^= 7; | |
| 600 | 23007140 | quad += dquad_x; | |
| 601 | 23007140 | dquad_x += 2; | |
| 602 |
2/2✓ Branch 0 taken 11483623 times.
✓ Branch 1 taken 11523517 times.
|
23007140 | *(p++) = icolor & 1 ? 255 : 0; |
| 603 |
2/2✓ Branch 0 taken 11438989 times.
✓ Branch 1 taken 11568151 times.
|
23007140 | *(p++) = icolor & 2 ? 255 : 0; |
| 604 |
2/2✓ Branch 0 taken 11432589 times.
✓ Branch 1 taken 11574551 times.
|
23007140 | *(p++) = icolor & 4 ? 255 : 0; |
| 605 | 23007140 | color_rest += 8; | |
| 606 |
2/2✓ Branch 0 taken 567780 times.
✓ Branch 1 taken 22439360 times.
|
23007140 | if (color_rest >= width) { |
| 607 | 567780 | color_rest -= width; | |
| 608 | 567780 | color++; | |
| 609 | } | ||
| 610 | } | ||
| 611 | 71010 | quad0 += dquad_y; | |
| 612 | 71010 | dquad_y += 2; | |
| 613 | 71010 | p0 += frame->linesize[0]; | |
| 614 | } | ||
| 615 | |||
| 616 | /* draw sliding color line */ | ||
| 617 | 326 | p0 = p = data + frame->linesize[0] * (height * 3/4); | |
| 618 | 326 | grad = (256 * test->nb_frame * test->time_base.num / test->time_base.den) % | |
| 619 | GRADIENT_SIZE; | ||
| 620 | 326 | rgrad = 0; | |
| 621 | 326 | dgrad = GRADIENT_SIZE / width; | |
| 622 | 326 | drgrad = GRADIENT_SIZE % width; | |
| 623 |
2/2✓ Branch 0 taken 95330 times.
✓ Branch 1 taken 326 times.
|
95656 | for (x = 0; x < width; x++) { |
| 624 |
6/6✓ Branch 0 taken 80673 times.
✓ Branch 1 taken 14657 times.
✓ Branch 2 taken 50128 times.
✓ Branch 3 taken 16107 times.
✓ Branch 4 taken 16107 times.
✓ Branch 5 taken 16873 times.
|
242238 | *(p++) = |
| 625 |
2/2✓ Branch 0 taken 66235 times.
✓ Branch 1 taken 14438 times.
|
80673 | grad < 256 || grad >= 5 * 256 ? 255 : |
| 626 |
2/2✓ Branch 0 taken 16873 times.
✓ Branch 1 taken 33255 times.
|
50128 | grad >= 2 * 256 && grad < 4 * 256 ? 0 : |
| 627 | 16107 | grad < 2 * 256 ? 2 * 256 - 1 - grad : grad - 4 * 256; | |
| 628 |
6/6✓ Branch 0 taken 64019 times.
✓ Branch 1 taken 31311 times.
✓ Branch 2 taken 49362 times.
✓ Branch 3 taken 14657 times.
✓ Branch 4 taken 16721 times.
✓ Branch 5 taken 14657 times.
|
161413 | *(p++) = |
| 629 | grad >= 4 * 256 ? 0 : | ||
| 630 |
2/2✓ Branch 0 taken 16721 times.
✓ Branch 1 taken 32641 times.
|
49362 | grad >= 1 * 256 && grad < 3 * 256 ? 255 : |
| 631 | 16721 | grad < 1 * 256 ? grad : 4 * 256 - 1 - grad; | |
| 632 |
6/6✓ Branch 0 taken 64566 times.
✓ Branch 1 taken 30764 times.
✓ Branch 2 taken 48032 times.
✓ Branch 3 taken 16534 times.
✓ Branch 4 taken 16534 times.
✓ Branch 5 taken 14438 times.
|
157800 | *(p++) = |
| 633 | grad < 2 * 256 ? 0 : | ||
| 634 |
2/2✓ Branch 0 taken 14438 times.
✓ Branch 1 taken 33594 times.
|
48032 | grad >= 3 * 256 && grad < 5 * 256 ? 255 : |
| 635 | 14438 | grad < 3 * 256 ? grad - 2 * 256 : 6 * 256 - 1 - grad; | |
| 636 | 95330 | grad += dgrad; | |
| 637 | 95330 | rgrad += drgrad; | |
| 638 |
2/2✓ Branch 0 taken 15534 times.
✓ Branch 1 taken 79796 times.
|
95330 | if (rgrad >= GRADIENT_SIZE) { |
| 639 | 15534 | grad++; | |
| 640 | 15534 | rgrad -= GRADIENT_SIZE; | |
| 641 | } | ||
| 642 |
2/2✓ Branch 0 taken 225 times.
✓ Branch 1 taken 95105 times.
|
95330 | if (grad >= GRADIENT_SIZE) |
| 643 | 225 | grad -= GRADIENT_SIZE; | |
| 644 | } | ||
| 645 | 326 | p = p0; | |
| 646 |
2/2✓ Branch 0 taken 8868 times.
✓ Branch 1 taken 326 times.
|
9194 | for (y = height / 8; y > 0; y--) { |
| 647 | 8868 | memcpy(p+frame->linesize[0], p, 3 * width); | |
| 648 | 8868 | p += frame->linesize[0]; | |
| 649 | } | ||
| 650 | |||
| 651 | /* draw digits */ | ||
| 652 | 326 | seg_size = width / 80; | |
| 653 |
3/4✓ Branch 0 taken 301 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 301 times.
✗ Branch 3 not taken.
|
326 | if (seg_size >= 1 && height >= 13 * seg_size) { |
| 654 | 301 | int64_t p10decimals = 1; | |
| 655 | 301 | double time = av_q2d(test->time_base) * test->nb_frame * | |
| 656 | 301 | ff_exp10(test->nb_decimals); | |
| 657 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 301 times.
|
301 | if (time >= INT_MAX) |
| 658 | ✗ | return; | |
| 659 | |||
| 660 |
2/2✓ Branch 0 taken 473 times.
✓ Branch 1 taken 301 times.
|
774 | for (x = 0; x < test->nb_decimals; x++) |
| 661 | 473 | p10decimals *= 10; | |
| 662 | |||
| 663 | 301 | second = av_rescale_rnd(test->nb_frame * test->time_base.num, p10decimals, test->time_base.den, AV_ROUND_ZERO); | |
| 664 | 301 | x = width - (width - seg_size * 64) / 2; | |
| 665 | 301 | y = (height - seg_size * 13) / 2; | |
| 666 | 301 | p = data + (x*3 + y * frame->linesize[0]); | |
| 667 |
1/2✓ Branch 0 taken 785 times.
✗ Branch 1 not taken.
|
785 | for (i = 0; i < 8; i++) { |
| 668 | 785 | p -= 3 * 8 * seg_size; | |
| 669 | 785 | draw_digit(second % 10, p, frame->linesize[0], seg_size); | |
| 670 | 785 | second /= 10; | |
| 671 |
2/2✓ Branch 0 taken 301 times.
✓ Branch 1 taken 484 times.
|
785 | if (second == 0) |
| 672 | 301 | break; | |
| 673 | } | ||
| 674 | } | ||
| 675 | } | ||
| 676 | |||
| 677 | 26 | static av_cold int test_init(AVFilterContext *ctx) | |
| 678 | { | ||
| 679 | 26 | TestSourceContext *test = ctx->priv; | |
| 680 | |||
| 681 | 26 | test->fill_picture_fn = test_fill_picture; | |
| 682 | 26 | return init(ctx); | |
| 683 | } | ||
| 684 | |||
| 685 | const FFFilter ff_vsrc_testsrc = { | ||
| 686 | .p.name = "testsrc", | ||
| 687 | .p.description = NULL_IF_CONFIG_SMALL("Generate test pattern."), | ||
| 688 | .p.priv_class = &testsrc_class, | ||
| 689 | .priv_size = sizeof(TestSourceContext), | ||
| 690 | .init = test_init, | ||
| 691 | .uninit = uninit, | ||
| 692 | .activate = activate, | ||
| 693 | FILTER_OUTPUTS(outputs), | ||
| 694 | FILTER_SINGLE_PIXFMT(AV_PIX_FMT_RGB24), | ||
| 695 | }; | ||
| 696 | |||
| 697 | #endif /* CONFIG_TESTSRC_FILTER */ | ||
| 698 | |||
| 699 | 220732 | av_unused static void set_color(TestSourceContext *s, FFDrawColor *color, uint32_t argb) | |
| 700 | { | ||
| 701 | 220732 | uint8_t rgba[4] = { (argb >> 16) & 0xFF, | |
| 702 | 220732 | (argb >> 8) & 0xFF, | |
| 703 | (argb >> 0) & 0xFF, | ||
| 704 | 220732 | (argb >> 24) & 0xFF, }; | |
| 705 | 220732 | ff_draw_color(&s->draw, color, rgba); | |
| 706 | 220732 | } | |
| 707 | |||
| 708 | #if CONFIG_TESTSRC2_FILTER | ||
| 709 | |||
| 710 | static const AVOption testsrc2_options[] = { | ||
| 711 | COMMON_OPTIONS | ||
| 712 | { "alpha", "set global alpha (opacity)", OFFSET(alpha), AV_OPT_TYPE_INT, {.i64 = 255}, 0, 255, FLAGS }, | ||
| 713 | { NULL } | ||
| 714 | }; | ||
| 715 | |||
| 716 | AVFILTER_DEFINE_CLASS(testsrc2); | ||
| 717 | |||
| 718 | 200072 | static uint32_t color_gradient(unsigned index) | |
| 719 | { | ||
| 720 | 200072 | unsigned si = index & 0xFF, sd = 0xFF - si; | |
| 721 |
6/7✓ Branch 0 taken 33347 times.
✓ Branch 1 taken 33357 times.
✓ Branch 2 taken 33332 times.
✓ Branch 3 taken 33347 times.
✓ Branch 4 taken 33357 times.
✓ Branch 5 taken 33332 times.
✗ Branch 6 not taken.
|
200072 | switch (index >> 8) { |
| 722 | 33347 | case 0: return 0xFF0000 + (si << 8); | |
| 723 | 33357 | case 1: return 0x00FF00 + (sd << 16); | |
| 724 | 33332 | case 2: return 0x00FF00 + (si << 0); | |
| 725 | 33347 | case 3: return 0x0000FF + (sd << 8); | |
| 726 | 33357 | case 4: return 0x0000FF + (si << 16); | |
| 727 | 33332 | case 5: return 0xFF0000 + (sd << 0); | |
| 728 | ✗ | default: av_assert0(0); return 0; | |
| 729 | } | ||
| 730 | } | ||
| 731 | |||
| 732 | 1029 | static void draw_text(TestSourceContext *s, AVFrame *frame, FFDrawColor *color, | |
| 733 | int x0, int y0, const uint8_t *text) | ||
| 734 | { | ||
| 735 | 1029 | const uint8_t *vga16_font = avpriv_vga16_font_get(); | |
| 736 | 1029 | int x = x0; | |
| 737 | |||
| 738 |
2/2✓ Branch 0 taken 25725 times.
✓ Branch 1 taken 1029 times.
|
26754 | for (; *text; text++) { |
| 739 |
2/2✓ Branch 0 taken 1029 times.
✓ Branch 1 taken 24696 times.
|
25725 | if (*text == '\n') { |
| 740 | 1029 | x = x0; | |
| 741 | 1029 | y0 += 16; | |
| 742 | 1029 | continue; | |
| 743 | } | ||
| 744 | 24696 | ff_blend_mask(&s->draw, color, frame->data, frame->linesize, | |
| 745 | frame->width, frame->height, | ||
| 746 | 24696 | &vga16_font[*text * 16], 1, 8, 16, 0, 0, x, y0); | |
| 747 | 24696 | x += 8; | |
| 748 | } | ||
| 749 | 1029 | } | |
| 750 | |||
| 751 | 1029 | static void test2_fill_picture(AVFilterContext *ctx, AVFrame *frame) | |
| 752 | { | ||
| 753 | 1029 | TestSourceContext *s = ctx->priv; | |
| 754 | FFDrawColor color; | ||
| 755 | 1029 | unsigned alpha = (uint32_t)s->alpha << 24; | |
| 756 | |||
| 757 | /* colored background */ | ||
| 758 | { | ||
| 759 | 1029 | unsigned i, x = 0, x2; | |
| 760 | |||
| 761 | 1029 | x = 0; | |
| 762 |
2/2✓ Branch 0 taken 6174 times.
✓ Branch 1 taken 1029 times.
|
7203 | for (i = 1; i < 7; i++) { |
| 763 | 6174 | x2 = av_rescale(i, s->w, 6); | |
| 764 | 6174 | x2 = ff_draw_round_to_sub(&s->draw, 0, 0, x2); | |
| 765 |
2/2✓ Branch 0 taken 3087 times.
✓ Branch 1 taken 3087 times.
|
6174 | set_color(s, &color, ((i & 1) ? 0xFF0000 : 0) | |
| 766 |
2/2✓ Branch 0 taken 3087 times.
✓ Branch 1 taken 3087 times.
|
12348 | ((i & 2) ? 0x00FF00 : 0) | |
| 767 |
2/2✓ Branch 0 taken 3087 times.
✓ Branch 1 taken 3087 times.
|
6174 | ((i & 4) ? 0x0000FF : 0) | |
| 768 | alpha); | ||
| 769 | 6174 | ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize, | |
| 770 | 6174 | x, 0, x2 - x, frame->height); | |
| 771 | 6174 | x = x2; | |
| 772 | } | ||
| 773 | } | ||
| 774 | |||
| 775 | /* oblique gradient */ | ||
| 776 | /* note: too slow if using blending */ | ||
| 777 |
1/2✓ Branch 0 taken 1029 times.
✗ Branch 1 not taken.
|
1029 | if (s->h >= 64) { |
| 778 | unsigned x, dx, y0, y, g0, g; | ||
| 779 | |||
| 780 | 1029 | dx = ff_draw_round_to_sub(&s->draw, 0, +1, 1); | |
| 781 | 1029 | y0 = av_rescale_q(s->pts, s->time_base, av_make_q(2, s->h - 16)); | |
| 782 | 1029 | g0 = av_rescale_q(s->pts, s->time_base, av_make_q(1, 128)); | |
| 783 |
2/2✓ Branch 0 taken 200072 times.
✓ Branch 1 taken 1029 times.
|
201101 | for (x = 0; x < s->w; x += dx) { |
| 784 | 200072 | g = (av_rescale(x, 6 * 256, s->w) + g0) % (6 * 256); | |
| 785 | 200072 | set_color(s, &color, color_gradient(g) | alpha); | |
| 786 | 200072 | y = y0 + av_rescale(x, s->h / 2, s->w); | |
| 787 | 200072 | y %= 2 * (s->h - 16); | |
| 788 |
2/2✓ Branch 0 taken 72380 times.
✓ Branch 1 taken 127692 times.
|
200072 | if (y > s->h - 16) |
| 789 | 72380 | y = 2 * (s->h - 16) - y; | |
| 790 | 200072 | y = ff_draw_round_to_sub(&s->draw, 1, 0, y); | |
| 791 | 200072 | ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize, | |
| 792 | x, y, dx, 16); | ||
| 793 | } | ||
| 794 | } | ||
| 795 | |||
| 796 | /* top right: draw clock hands */ | ||
| 797 |
2/4✓ Branch 0 taken 1029 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1029 times.
✗ Branch 3 not taken.
|
1029 | if (s->w >= 64 && s->h >= 64) { |
| 798 | 1029 | int l = (FFMIN(s->w, s->h) - 32) >> 1; | |
| 799 | 1029 | int steps = FFMAX(4, l >> 5); | |
| 800 | 1029 | int xc = (s->w >> 2) + (s->w >> 1); | |
| 801 | 1029 | int yc = (s->h >> 2); | |
| 802 | 1029 | int cycle = l << 2; | |
| 803 | int pos, xh, yh; | ||
| 804 | int c, i; | ||
| 805 | |||
| 806 |
2/2✓ Branch 0 taken 3087 times.
✓ Branch 1 taken 1029 times.
|
4116 | for (c = 0; c < 3; c++) { |
| 807 | 3087 | set_color(s, &color, (0xBBBBBB ^ (0xFF << (c << 3))) | alpha); | |
| 808 | 3087 | pos = av_rescale_q(s->pts, s->time_base, av_make_q(64 >> (c << 1), cycle)) % cycle; | |
| 809 |
2/2✓ Branch 0 taken 911 times.
✓ Branch 1 taken 2176 times.
|
3998 | xh = pos < 1 * l ? pos : |
| 810 |
2/2✓ Branch 0 taken 427 times.
✓ Branch 1 taken 484 times.
|
1338 | pos < 2 * l ? l : |
| 811 |
2/2✓ Branch 0 taken 280 times.
✓ Branch 1 taken 147 times.
|
427 | pos < 3 * l ? 3 * l - pos : 0; |
| 812 |
2/2✓ Branch 0 taken 911 times.
✓ Branch 1 taken 2176 times.
|
3998 | yh = pos < 1 * l ? 0 : |
| 813 |
2/2✓ Branch 0 taken 484 times.
✓ Branch 1 taken 427 times.
|
1338 | pos < 2 * l ? pos - l : |
| 814 |
2/2✓ Branch 0 taken 147 times.
✓ Branch 1 taken 280 times.
|
427 | pos < 3 * l ? l : |
| 815 | cycle - pos; | ||
| 816 | 3087 | xh -= l >> 1; | |
| 817 | 3087 | yh -= l >> 1; | |
| 818 |
2/2✓ Branch 0 taken 12384 times.
✓ Branch 1 taken 3087 times.
|
15471 | for (i = 1; i <= steps; i++) { |
| 819 | 12384 | int x = av_rescale(xh, i, steps) + xc; | |
| 820 | 12384 | int y = av_rescale(yh, i, steps) + yc; | |
| 821 | 12384 | x = ff_draw_round_to_sub(&s->draw, 0, -1, x); | |
| 822 | 12384 | y = ff_draw_round_to_sub(&s->draw, 1, -1, y); | |
| 823 | 12384 | ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize, | |
| 824 | x, y, 8, 8); | ||
| 825 | } | ||
| 826 | } | ||
| 827 | } | ||
| 828 | |||
| 829 | /* bottom left: beating rectangles */ | ||
| 830 |
2/4✓ Branch 0 taken 1029 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1029 times.
✗ Branch 3 not taken.
|
1029 | if (s->w >= 64 && s->h >= 64) { |
| 831 | 1029 | int l = (FFMIN(s->w, s->h) - 16) >> 2; | |
| 832 | 1029 | int cycle = l << 3; | |
| 833 | 1029 | int xc = (s->w >> 2); | |
| 834 | 1029 | int yc = (s->h >> 2) + (s->h >> 1); | |
| 835 | 1029 | int xm1 = ff_draw_round_to_sub(&s->draw, 0, -1, xc - 8); | |
| 836 | 1029 | int xm2 = ff_draw_round_to_sub(&s->draw, 0, +1, xc + 8); | |
| 837 | 1029 | int ym1 = ff_draw_round_to_sub(&s->draw, 1, -1, yc - 8); | |
| 838 | 1029 | int ym2 = ff_draw_round_to_sub(&s->draw, 1, +1, yc + 8); | |
| 839 | int size, step, x1, x2, y1, y2; | ||
| 840 | |||
| 841 | 1029 | size = av_rescale_q(s->pts, s->time_base, av_make_q(4, cycle)); | |
| 842 | 1029 | step = size / l; | |
| 843 | 1029 | size %= l; | |
| 844 |
2/2✓ Branch 0 taken 432 times.
✓ Branch 1 taken 597 times.
|
1029 | if (step & 1) |
| 845 | 432 | size = l - size; | |
| 846 | 1029 | step = (step >> 1) & 3; | |
| 847 | 1029 | set_color(s, &color, 0xFF808080); | |
| 848 | 1029 | x1 = ff_draw_round_to_sub(&s->draw, 0, -1, xc - 4 - size); | |
| 849 | 1029 | x2 = ff_draw_round_to_sub(&s->draw, 0, +1, xc + 4 + size); | |
| 850 | 1029 | y1 = ff_draw_round_to_sub(&s->draw, 1, -1, yc - 4 - size); | |
| 851 | 1029 | y2 = ff_draw_round_to_sub(&s->draw, 1, +1, yc + 4 + size); | |
| 852 |
4/4✓ Branch 0 taken 560 times.
✓ Branch 1 taken 469 times.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 392 times.
|
1029 | if (step == 0 || step == 2) |
| 853 | 637 | ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize, | |
| 854 | x1, ym1, x2 - x1, ym2 - ym1); | ||
| 855 |
4/4✓ Branch 0 taken 784 times.
✓ Branch 1 taken 245 times.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 616 times.
|
1029 | if (step == 1 || step == 2) |
| 856 | 413 | ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize, | |
| 857 | xm1, y1, xm2 - xm1, y2 - y1); | ||
| 858 |
2/2✓ Branch 0 taken 147 times.
✓ Branch 1 taken 882 times.
|
1029 | if (step == 3) |
| 859 | 147 | ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize, | |
| 860 | x1, y1, x2 - x1, y2 - y1); | ||
| 861 | } | ||
| 862 | |||
| 863 | /* bottom right: checker with random noise */ | ||
| 864 | { | ||
| 865 | 1029 | unsigned xmin = av_rescale(5, s->w, 8); | |
| 866 | 1029 | unsigned xmax = av_rescale(7, s->w, 8); | |
| 867 | 1029 | unsigned ymin = av_rescale(5, s->h, 8); | |
| 868 | 1029 | unsigned ymax = av_rescale(7, s->h, 8); | |
| 869 | unsigned x, y, i, r; | ||
| 870 | uint8_t alpha[256]; | ||
| 871 | |||
| 872 | 1029 | r = s->pts; | |
| 873 |
2/2✓ Branch 0 taken 3064 times.
✓ Branch 1 taken 1029 times.
|
4093 | for (y = ymin; y + 15 < ymax; y += 16) { |
| 874 |
2/2✓ Branch 0 taken 15531 times.
✓ Branch 1 taken 3064 times.
|
18595 | for (x = xmin; x + 15 < xmax; x += 16) { |
| 875 |
2/2✓ Branch 0 taken 8248 times.
✓ Branch 1 taken 7283 times.
|
15531 | if ((x ^ y) & 16) |
| 876 | 8248 | continue; | |
| 877 |
2/2✓ Branch 0 taken 1864448 times.
✓ Branch 1 taken 7283 times.
|
1871731 | for (i = 0; i < 256; i++) { |
| 878 | 1864448 | r = r * 1664525 + 1013904223; | |
| 879 | 1864448 | alpha[i] = r >> 24; | |
| 880 | } | ||
| 881 | 7283 | set_color(s, &color, 0xFF00FF80); | |
| 882 | 7283 | ff_blend_mask(&s->draw, &color, frame->data, frame->linesize, | |
| 883 | frame->width, frame->height, | ||
| 884 | alpha, 16, 16, 16, 3, 0, x, y); | ||
| 885 | } | ||
| 886 | } | ||
| 887 | } | ||
| 888 | |||
| 889 | /* bouncing square */ | ||
| 890 |
2/4✓ Branch 0 taken 1029 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1029 times.
✗ Branch 3 not taken.
|
1029 | if (s->w >= 16 && s->h >= 16) { |
| 891 | 1029 | unsigned w = s->w - 8; | |
| 892 | 1029 | unsigned h = s->h - 8; | |
| 893 | 1029 | unsigned x = av_rescale_q(s->pts, s->time_base, av_make_q(233, 55 * w)) % (w << 1); | |
| 894 | 1029 | unsigned y = av_rescale_q(s->pts, s->time_base, av_make_q(233, 89 * h)) % (h << 1); | |
| 895 |
2/2✓ Branch 0 taken 240 times.
✓ Branch 1 taken 789 times.
|
1029 | if (x > w) |
| 896 | 240 | x = (w << 1) - x; | |
| 897 |
2/2✓ Branch 0 taken 320 times.
✓ Branch 1 taken 709 times.
|
1029 | if (y > h) |
| 898 | 320 | y = (h << 1) - y; | |
| 899 | 1029 | x = ff_draw_round_to_sub(&s->draw, 0, -1, x); | |
| 900 | 1029 | y = ff_draw_round_to_sub(&s->draw, 1, -1, y); | |
| 901 | 1029 | set_color(s, &color, 0xFF8000FF); | |
| 902 | 1029 | ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize, | |
| 903 | x, y, 8, 8); | ||
| 904 | } | ||
| 905 | |||
| 906 | /* top right: draw frame time and frame number */ | ||
| 907 | { | ||
| 908 | char buf[256]; | ||
| 909 | unsigned time; | ||
| 910 | |||
| 911 | 1029 | time = av_rescale_q(s->pts, s->time_base, av_make_q(1, 1000)) % 86400000; | |
| 912 | 1029 | set_color(s, &color, 0xC0000000); | |
| 913 | 1029 | ff_blend_rectangle(&s->draw, &color, frame->data, frame->linesize, | |
| 914 | frame->width, frame->height, | ||
| 915 | 2, 2, 100, 36); | ||
| 916 | 1029 | set_color(s, &color, 0xFFFF8000); | |
| 917 | 1029 | snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%03d\n%12"PRIi64, | |
| 918 | 1029 | time / 3600000, (time / 60000) % 60, (time / 1000) % 60, | |
| 919 | time % 1000, s->pts); | ||
| 920 | 1029 | draw_text(s, frame, &color, 4, 4, buf); | |
| 921 | } | ||
| 922 | 1029 | } | |
| 923 | 97 | static av_cold int test2_init(AVFilterContext *ctx) | |
| 924 | { | ||
| 925 | 97 | TestSourceContext *s = ctx->priv; | |
| 926 | |||
| 927 | 97 | s->fill_picture_fn = test2_fill_picture; | |
| 928 | 97 | return init(ctx); | |
| 929 | } | ||
| 930 | |||
| 931 | 52 | static int test2_query_formats(const AVFilterContext *ctx, | |
| 932 | AVFilterFormatsConfig **cfg_in, | ||
| 933 | AVFilterFormatsConfig **cfg_out) | ||
| 934 | { | ||
| 935 | 52 | return ff_set_common_formats2(ctx, cfg_in, cfg_out, ff_draw_supported_pixel_formats(0)); | |
| 936 | } | ||
| 937 | |||
| 938 | 52 | static int test2_config_props(AVFilterLink *inlink) | |
| 939 | { | ||
| 940 | 52 | AVFilterContext *ctx = inlink->src; | |
| 941 | 52 | TestSourceContext *s = ctx->priv; | |
| 942 | |||
| 943 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
|
52 | av_assert0(ff_draw_init_from_link(&s->draw, inlink, 0) >= 0); |
| 944 | 52 | s->w = ff_draw_round_to_sub(&s->draw, 0, -1, s->w); | |
| 945 | 52 | s->h = ff_draw_round_to_sub(&s->draw, 1, -1, s->h); | |
| 946 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
|
52 | if (av_image_check_size(s->w, s->h, 0, ctx) < 0) |
| 947 | ✗ | return AVERROR(EINVAL); | |
| 948 | 52 | return config_props(inlink); | |
| 949 | } | ||
| 950 | |||
| 951 | static const AVFilterPad avfilter_vsrc_testsrc2_outputs[] = { | ||
| 952 | { | ||
| 953 | .name = "default", | ||
| 954 | .type = AVMEDIA_TYPE_VIDEO, | ||
| 955 | .config_props = test2_config_props, | ||
| 956 | }, | ||
| 957 | }; | ||
| 958 | |||
| 959 | const FFFilter ff_vsrc_testsrc2 = { | ||
| 960 | .p.name = "testsrc2", | ||
| 961 | .p.description = NULL_IF_CONFIG_SMALL("Generate another test pattern."), | ||
| 962 | .p.priv_class = &testsrc2_class, | ||
| 963 | .priv_size = sizeof(TestSourceContext), | ||
| 964 | .init = test2_init, | ||
| 965 | .uninit = uninit, | ||
| 966 | .activate = activate, | ||
| 967 | FILTER_OUTPUTS(avfilter_vsrc_testsrc2_outputs), | ||
| 968 | FILTER_QUERY_FUNC2(test2_query_formats), | ||
| 969 | }; | ||
| 970 | |||
| 971 | #endif /* CONFIG_TESTSRC2_FILTER */ | ||
| 972 | |||
| 973 | #if CONFIG_RGBTESTSRC_FILTER | ||
| 974 | |||
| 975 | static const AVOption rgbtestsrc_options[] = { | ||
| 976 | COMMON_OPTIONS | ||
| 977 | { "complement", "set complement colors", OFFSET(complement), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, | ||
| 978 | { "co", "set complement colors", OFFSET(complement), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, | ||
| 979 | { NULL } | ||
| 980 | }; | ||
| 981 | |||
| 982 | AVFILTER_DEFINE_CLASS(rgbtestsrc); | ||
| 983 | |||
| 984 | #define R 0 | ||
| 985 | #define G 1 | ||
| 986 | #define B 2 | ||
| 987 | #define A 3 | ||
| 988 | |||
| 989 | 50718720 | static void rgbtest_put_pixel(uint8_t *dstp[4], int dst_linesizep[4], | |
| 990 | int x, int y, unsigned r, unsigned g, unsigned b, unsigned a, enum AVPixelFormat fmt, | ||
| 991 | uint8_t rgba_map[4]) | ||
| 992 | { | ||
| 993 | 50718720 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); | |
| 994 | 50718720 | uint8_t *dst = dstp[0]; | |
| 995 | 50718720 | ptrdiff_t dst_linesize = dst_linesizep[0]; | |
| 996 | uint32_t v; | ||
| 997 | uint64_t v16; | ||
| 998 | uint8_t *p; | ||
| 999 | uint16_t *p16; | ||
| 1000 | |||
| 1001 |
8/16✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 9707520 times.
✓ Branch 7 taken 9630720 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 76800 times.
✓ Branch 10 taken 76800 times.
✓ Branch 11 taken 76800 times.
✓ Branch 12 taken 9707520 times.
✓ Branch 13 taken 76800 times.
✓ Branch 14 taken 21365760 times.
✗ Branch 15 not taken.
|
50718720 | switch (fmt) { |
| 1002 | ✗ | case AV_PIX_FMT_BGR444: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4); break; | |
| 1003 | ✗ | case AV_PIX_FMT_RGB444: ((uint16_t*)(dst + y*dst_linesize))[x] = ((b >> 4) << 8) | ((g >> 4) << 4) | (r >> 4); break; | |
| 1004 | ✗ | case AV_PIX_FMT_BGR555: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r>>3)<<10) | ((g>>3)<<5) | (b>>3); break; | |
| 1005 | ✗ | case AV_PIX_FMT_RGB555: ((uint16_t*)(dst + y*dst_linesize))[x] = ((b>>3)<<10) | ((g>>3)<<5) | (r>>3); break; | |
| 1006 | ✗ | case AV_PIX_FMT_BGR565: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r>>3)<<11) | ((g>>2)<<5) | (b>>3); break; | |
| 1007 | ✗ | case AV_PIX_FMT_RGB565: ((uint16_t*)(dst + y*dst_linesize))[x] = ((b>>3)<<11) | ((g>>2)<<5) | (r>>3); break; | |
| 1008 | 9707520 | case AV_PIX_FMT_RGB24: | |
| 1009 | case AV_PIX_FMT_BGR24: | ||
| 1010 | 9707520 | v = (r << (rgba_map[R]*8)) + (g << (rgba_map[G]*8)) + (b << (rgba_map[B]*8)); | |
| 1011 | 9707520 | p = dst + 3*x + y*dst_linesize; | |
| 1012 | 9707520 | AV_WL24(p, v); | |
| 1013 | 9707520 | break; | |
| 1014 | 9630720 | case AV_PIX_FMT_RGB48: | |
| 1015 | case AV_PIX_FMT_BGR48: | ||
| 1016 | 9630720 | v16 = ((uint64_t)r << (rgba_map[R]*16)) + ((uint64_t)g << (rgba_map[G]*16)) + ((uint64_t)b << (rgba_map[B]*16)); | |
| 1017 | 9630720 | p16 = (uint16_t *)(dst + 6*x + y*dst_linesize); | |
| 1018 | 9630720 | *p16++ = v16 >> 32; | |
| 1019 | 9630720 | *p16++ = v16 >> 16; | |
| 1020 | 9630720 | *p16++ = v16; | |
| 1021 | 9630720 | break; | |
| 1022 | ✗ | case AV_PIX_FMT_RGBA64: | |
| 1023 | case AV_PIX_FMT_BGRA64: | ||
| 1024 | ✗ | v16 = ((uint64_t)r << (rgba_map[R]*16)) + ((uint64_t)g << (rgba_map[G]*16)) + ((uint64_t)b << (rgba_map[B]*16)); | |
| 1025 | ✗ | p16 = (uint16_t *)(dst + 8*x + y*dst_linesize); | |
| 1026 | ✗ | *p16++ = v16 >> 32; | |
| 1027 | ✗ | *p16++ = v16 >> 16; | |
| 1028 | ✗ | *p16++ = v16; | |
| 1029 | ✗ | *p16++ = a; | |
| 1030 | ✗ | break; | |
| 1031 | 76800 | case AV_PIX_FMT_RGBA: | |
| 1032 | case AV_PIX_FMT_BGRA: | ||
| 1033 | case AV_PIX_FMT_ARGB: | ||
| 1034 | case AV_PIX_FMT_ABGR: | ||
| 1035 | 76800 | v = (r << (rgba_map[R]*8)) + (g << (rgba_map[G]*8)) + (b << (rgba_map[B]*8)) + (a << (rgba_map[A]*8)); | |
| 1036 | 76800 | p = dst + 4*x + y*dst_linesize; | |
| 1037 | 76800 | AV_WL32A(p, v); | |
| 1038 | 76800 | break; | |
| 1039 | 76800 | case AV_PIX_FMT_X2RGB10LE: | |
| 1040 | case AV_PIX_FMT_X2BGR10LE: | ||
| 1041 | 76800 | v = (r << ((desc->comp[0].offset*8) + desc->comp[0].shift)) + | |
| 1042 | 76800 | (g << ((desc->comp[1].offset*8) + desc->comp[1].shift)) + | |
| 1043 | 76800 | (b << ((desc->comp[2].offset*8) + desc->comp[2].shift)) + | |
| 1044 | 76800 | (3U << ((desc->comp[3].offset*8) + desc->comp[3].shift)); | |
| 1045 | 76800 | p = dst + 4*x + y*dst_linesize; | |
| 1046 | 76800 | AV_WL32A(p, v); | |
| 1047 | 76800 | break; | |
| 1048 | 76800 | case AV_PIX_FMT_GBRAP: | |
| 1049 | 76800 | p = dstp[3] + x + y * dst_linesizep[3]; | |
| 1050 | 76800 | p[0] = a; | |
| 1051 | // fall-through | ||
| 1052 | 9784320 | case AV_PIX_FMT_GBRP: | |
| 1053 | 9784320 | p = dstp[0] + x + y * dst_linesize; | |
| 1054 | 9784320 | p[0] = g; | |
| 1055 | 9784320 | p = dstp[1] + x + y * dst_linesizep[1]; | |
| 1056 | 9784320 | p[0] = b; | |
| 1057 | 9784320 | p = dstp[2] + x + y * dst_linesizep[2]; | |
| 1058 | 9784320 | p[0] = r; | |
| 1059 | 9784320 | break; | |
| 1060 | 76800 | case AV_PIX_FMT_GBRAP10: | |
| 1061 | case AV_PIX_FMT_GBRAP12: | ||
| 1062 | case AV_PIX_FMT_GBRAP14: | ||
| 1063 | case AV_PIX_FMT_GBRAP16: | ||
| 1064 | 76800 | p16 = (uint16_t *)(dstp[3] + x*2 + y * dst_linesizep[3]); | |
| 1065 | 76800 | p16[0] = a; | |
| 1066 | // fall-through | ||
| 1067 | 21442560 | case AV_PIX_FMT_GBRP9: | |
| 1068 | case AV_PIX_FMT_GBRP10: | ||
| 1069 | case AV_PIX_FMT_GBRP12: | ||
| 1070 | case AV_PIX_FMT_GBRP14: | ||
| 1071 | case AV_PIX_FMT_GBRP16: | ||
| 1072 | 21442560 | p16 = (uint16_t *)(dstp[0] + x*2 + y * dst_linesizep[0]); | |
| 1073 | 21442560 | p16[0] = g; | |
| 1074 | 21442560 | p16 = (uint16_t *)(dstp[1] + x*2 + y * dst_linesizep[1]); | |
| 1075 | 21442560 | p16[0] = b; | |
| 1076 | 21442560 | p16 = (uint16_t *)(dstp[2] + x*2 + y * dst_linesizep[2]); | |
| 1077 | 21442560 | p16[0] = r; | |
| 1078 | 21442560 | break; | |
| 1079 | } | ||
| 1080 | 50718720 | } | |
| 1081 | |||
| 1082 | ✗ | static void rgbtest_fill_picture_complement(AVFilterContext *ctx, AVFrame *frame) | |
| 1083 | { | ||
| 1084 | ✗ | TestSourceContext *test = ctx->priv; | |
| 1085 | ✗ | int x, y, w = frame->width, h = frame->height; | |
| 1086 | |||
| 1087 | ✗ | for (y = 0; y < h; y++) { | |
| 1088 | ✗ | for (x = 0; x < w; x++) { | |
| 1089 | ✗ | int c = (1 << FFMAX(test->depth, 8))*x/w; | |
| 1090 | ✗ | int r = 0, g = 0, b = 0; | |
| 1091 | |||
| 1092 | ✗ | if (6*y < h ) r = c; | |
| 1093 | ✗ | else if (6*y < 2*h) g = c, b = c; | |
| 1094 | ✗ | else if (6*y < 3*h) g = c; | |
| 1095 | ✗ | else if (6*y < 4*h) r = c, b = c; | |
| 1096 | ✗ | else if (6*y < 5*h) b = c; | |
| 1097 | ✗ | else r = c, g = c; | |
| 1098 | |||
| 1099 | ✗ | rgbtest_put_pixel(frame->data, frame->linesize, x, y, r, g, b, c, | |
| 1100 | ✗ | ctx->outputs[0]->format, test->rgba_map); | |
| 1101 | } | ||
| 1102 | } | ||
| 1103 | ✗ | } | |
| 1104 | |||
| 1105 | 502 | static void rgbtest_fill_picture(AVFilterContext *ctx, AVFrame *frame) | |
| 1106 | { | ||
| 1107 | 502 | TestSourceContext *test = ctx->priv; | |
| 1108 | 502 | int x, y, w = frame->width, h = frame->height; | |
| 1109 | |||
| 1110 |
2/2✓ Branch 0 taken 144240 times.
✓ Branch 1 taken 502 times.
|
144742 | for (y = 0; y < h; y++) { |
| 1111 |
2/2✓ Branch 0 taken 50718720 times.
✓ Branch 1 taken 144240 times.
|
50862960 | for (x = 0; x < w; x++) { |
| 1112 | 50718720 | int c = (1 << FFMAX(test->depth, 8))*x/w; | |
| 1113 | 50718720 | int r = 0, g = 0, b = 0; | |
| 1114 | |||
| 1115 |
2/2✓ Branch 0 taken 16906240 times.
✓ Branch 1 taken 33812480 times.
|
50718720 | if (3*y < h ) r = c; |
| 1116 |
2/2✓ Branch 0 taken 16906240 times.
✓ Branch 1 taken 16906240 times.
|
33812480 | else if (3*y < 2*h) g = c; |
| 1117 | 16906240 | else b = c; | |
| 1118 | |||
| 1119 | 50718720 | rgbtest_put_pixel(frame->data, frame->linesize, x, y, r, g, b, c, | |
| 1120 | 50718720 | ctx->outputs[0]->format, test->rgba_map); | |
| 1121 | } | ||
| 1122 | } | ||
| 1123 | 502 | } | |
| 1124 | |||
| 1125 | 1004 | static av_cold int rgbtest_init(AVFilterContext *ctx) | |
| 1126 | { | ||
| 1127 | 1004 | TestSourceContext *test = ctx->priv; | |
| 1128 | |||
| 1129 | 1004 | test->draw_once = 1; | |
| 1130 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1004 times.
|
1004 | test->fill_picture_fn = test->complement ? rgbtest_fill_picture_complement : rgbtest_fill_picture; |
| 1131 | 1004 | return init(ctx); | |
| 1132 | } | ||
| 1133 | |||
| 1134 | static const enum AVPixelFormat rgbtest_pix_fmts[] = { | ||
| 1135 | AV_PIX_FMT_RGBA, AV_PIX_FMT_ARGB, AV_PIX_FMT_BGRA, AV_PIX_FMT_ABGR, | ||
| 1136 | AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB24, | ||
| 1137 | AV_PIX_FMT_RGB444, AV_PIX_FMT_BGR444, | ||
| 1138 | AV_PIX_FMT_RGB565, AV_PIX_FMT_BGR565, | ||
| 1139 | AV_PIX_FMT_RGB555, AV_PIX_FMT_BGR555, | ||
| 1140 | AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48, | ||
| 1141 | AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64, | ||
| 1142 | AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, | ||
| 1143 | AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, | ||
| 1144 | AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, | ||
| 1145 | AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP14, AV_PIX_FMT_GBRAP16, | ||
| 1146 | AV_PIX_FMT_X2RGB10LE, AV_PIX_FMT_X2BGR10LE, | ||
| 1147 | AV_PIX_FMT_NONE | ||
| 1148 | }; | ||
| 1149 | |||
| 1150 | 502 | static int rgbtest_config_props(AVFilterLink *outlink) | |
| 1151 | { | ||
| 1152 | 502 | TestSourceContext *test = outlink->src->priv; | |
| 1153 | 502 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); | |
| 1154 | |||
| 1155 | 502 | test->depth = desc->comp[0].depth; | |
| 1156 | 502 | ff_fill_rgba_map(test->rgba_map, outlink->format); | |
| 1157 | 502 | return config_props(outlink); | |
| 1158 | } | ||
| 1159 | |||
| 1160 | static const AVFilterPad avfilter_vsrc_rgbtestsrc_outputs[] = { | ||
| 1161 | { | ||
| 1162 | .name = "default", | ||
| 1163 | .type = AVMEDIA_TYPE_VIDEO, | ||
| 1164 | .config_props = rgbtest_config_props, | ||
| 1165 | }, | ||
| 1166 | }; | ||
| 1167 | |||
| 1168 | const FFFilter ff_vsrc_rgbtestsrc = { | ||
| 1169 | .p.name = "rgbtestsrc", | ||
| 1170 | .p.description = NULL_IF_CONFIG_SMALL("Generate RGB test pattern."), | ||
| 1171 | .p.priv_class = &rgbtestsrc_class, | ||
| 1172 | .priv_size = sizeof(TestSourceContext), | ||
| 1173 | .init = rgbtest_init, | ||
| 1174 | .uninit = uninit, | ||
| 1175 | .activate = activate, | ||
| 1176 | FILTER_OUTPUTS(avfilter_vsrc_rgbtestsrc_outputs), | ||
| 1177 | FILTER_PIXFMTS_ARRAY(rgbtest_pix_fmts), | ||
| 1178 | }; | ||
| 1179 | |||
| 1180 | #undef R | ||
| 1181 | #undef G | ||
| 1182 | #undef B | ||
| 1183 | #undef A | ||
| 1184 | |||
| 1185 | #endif /* CONFIG_RGBTESTSRC_FILTER */ | ||
| 1186 | |||
| 1187 | #if CONFIG_YUVTESTSRC_FILTER | ||
| 1188 | |||
| 1189 | #define Y 0 | ||
| 1190 | #define U 1 | ||
| 1191 | #define V 2 | ||
| 1192 | #define A 3 | ||
| 1193 | |||
| 1194 | 62914560 | static void yuvtest_put_pixel(uint8_t *dstp[4], int dst_linesizep[4], | |
| 1195 | int i, int j, unsigned y, unsigned u, unsigned v, unsigned a, enum AVPixelFormat fmt, | ||
| 1196 | uint8_t ayuv_map[4]) | ||
| 1197 | { | ||
| 1198 | 62914560 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); | |
| 1199 | uint32_t n; | ||
| 1200 | |||
| 1201 |
11/15✓ Branch 0 taken 76800 times.
✓ Branch 1 taken 153600 times.
✓ Branch 2 taken 153600 times.
✓ Branch 3 taken 76800 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 153600 times.
✓ Branch 6 taken 76800 times.
✓ Branch 7 taken 9707520 times.
✓ Branch 8 taken 76800 times.
✓ Branch 9 taken 21365760 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 9707520 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 21365760 times.
✗ Branch 14 not taken.
|
62914560 | switch (fmt) { |
| 1202 | 76800 | case AV_PIX_FMT_VYU444: | |
| 1203 | 76800 | n = (y << (ayuv_map[Y]*8)) + (u << (ayuv_map[U]*8)) + (v << (ayuv_map[V]*8)); | |
| 1204 | 76800 | AV_WL24(&dstp[0][i*3 + j*dst_linesizep[0]], n); | |
| 1205 | 76800 | break; | |
| 1206 | 153600 | case AV_PIX_FMT_V30XLE: | |
| 1207 | case AV_PIX_FMT_XV30LE: | ||
| 1208 | 153600 | n = (y << ((desc->comp[0].offset*8) + desc->comp[0].shift)) + | |
| 1209 | 153600 | (u << ((desc->comp[1].offset*8) + desc->comp[1].shift)) + | |
| 1210 | 153600 | (v << ((desc->comp[2].offset*8) + desc->comp[2].shift)) + | |
| 1211 | 153600 | (3U << ((desc->comp[3].offset*8) + desc->comp[3].shift)); | |
| 1212 | 153600 | AV_WL32A(&dstp[0][i*4 + j*dst_linesizep[0]], n); | |
| 1213 | 153600 | break; | |
| 1214 | 153600 | case AV_PIX_FMT_XV36: | |
| 1215 | case AV_PIX_FMT_XV48: | ||
| 1216 | 153600 | a = UINT16_MAX; | |
| 1217 | // fall-through | ||
| 1218 | 230400 | case AV_PIX_FMT_AYUV64: | |
| 1219 | 230400 | AV_WN16A(&dstp[0][i*8 + ayuv_map[Y]*2 + j*dst_linesizep[0]], y << desc->comp[0].shift); | |
| 1220 | 230400 | AV_WN16A(&dstp[0][i*8 + ayuv_map[U]*2 + j*dst_linesizep[0]], u << desc->comp[1].shift); | |
| 1221 | 230400 | AV_WN16A(&dstp[0][i*8 + ayuv_map[V]*2 + j*dst_linesizep[0]], v << desc->comp[2].shift); | |
| 1222 | 230400 | AV_WN16A(&dstp[0][i*8 + ayuv_map[A]*2 + j*dst_linesizep[0]], a << desc->comp[3].shift); | |
| 1223 | 230400 | break; | |
| 1224 | ✗ | case AV_PIX_FMT_VUYX: | |
| 1225 | ✗ | a = UINT8_MAX; | |
| 1226 | // fall-through | ||
| 1227 | 153600 | case AV_PIX_FMT_UYVA: | |
| 1228 | case AV_PIX_FMT_VUYA: | ||
| 1229 | case AV_PIX_FMT_AYUV: | ||
| 1230 | 153600 | n = (y << (ayuv_map[Y]*8)) + (u << (ayuv_map[U]*8)) + (v << (ayuv_map[V]*8)) + (a << (ayuv_map[A]*8)); | |
| 1231 | 153600 | AV_WL32A(&dstp[0][i*4 + j*dst_linesizep[0]], n); | |
| 1232 | 153600 | break; | |
| 1233 | 76800 | case AV_PIX_FMT_YUVA444P: | |
| 1234 | 76800 | dstp[3][i + j*dst_linesizep[3]] = a; | |
| 1235 | // fall-through | ||
| 1236 | 9784320 | case AV_PIX_FMT_YUV444P: | |
| 1237 | case AV_PIX_FMT_YUVJ444P: | ||
| 1238 | 9784320 | dstp[0][i + j*dst_linesizep[0]] = y; | |
| 1239 | 9784320 | dstp[1][i + j*dst_linesizep[1]] = u; | |
| 1240 | 9784320 | dstp[2][i + j*dst_linesizep[2]] = v; | |
| 1241 | 9784320 | break; | |
| 1242 | 76800 | case AV_PIX_FMT_YUVA444P9: | |
| 1243 | case AV_PIX_FMT_YUVA444P10: | ||
| 1244 | case AV_PIX_FMT_YUVA444P12: | ||
| 1245 | case AV_PIX_FMT_YUVA444P16: | ||
| 1246 | 76800 | AV_WN16A(&dstp[3][i*2 + j*dst_linesizep[3]], a); | |
| 1247 | // fall-through | ||
| 1248 | 21442560 | case AV_PIX_FMT_YUV444P9: | |
| 1249 | case AV_PIX_FMT_YUV444P10: | ||
| 1250 | case AV_PIX_FMT_YUV444P12: | ||
| 1251 | case AV_PIX_FMT_YUV444P14: | ||
| 1252 | case AV_PIX_FMT_YUV444P16: | ||
| 1253 | 21442560 | AV_WN16A(&dstp[0][i*2 + j*dst_linesizep[0]], y); | |
| 1254 | 21442560 | AV_WN16A(&dstp[1][i*2 + j*dst_linesizep[1]], u); | |
| 1255 | 21442560 | AV_WN16A(&dstp[2][i*2 + j*dst_linesizep[2]], v); | |
| 1256 | 21442560 | break; | |
| 1257 | ✗ | case AV_PIX_FMT_YUV444P10MSB: | |
| 1258 | case AV_PIX_FMT_YUV444P12MSB: | ||
| 1259 | ✗ | AV_WN16A(&dstp[0][i*2 + j*dst_linesizep[0]], y << desc->comp[0].shift); | |
| 1260 | ✗ | AV_WN16A(&dstp[1][i*2 + j*dst_linesizep[1]], u << desc->comp[1].shift); | |
| 1261 | ✗ | AV_WN16A(&dstp[2][i*2 + j*dst_linesizep[2]], v << desc->comp[2].shift); | |
| 1262 | ✗ | break; | |
| 1263 | 9707520 | case AV_PIX_FMT_NV24: | |
| 1264 | 9707520 | dstp[0][i + j*dst_linesizep[0] + 0] = y; | |
| 1265 | 9707520 | dstp[1][i*2 + j*dst_linesizep[1] + 0] = u; | |
| 1266 | 9707520 | dstp[1][i*2 + j*dst_linesizep[1] + 1] = v; | |
| 1267 | 9707520 | break; | |
| 1268 | ✗ | case AV_PIX_FMT_NV42: | |
| 1269 | ✗ | dstp[0][i + j*dst_linesizep[0] + 0] = y; | |
| 1270 | ✗ | dstp[1][i*2 + j*dst_linesizep[1] + 1] = u; | |
| 1271 | ✗ | dstp[1][i*2 + j*dst_linesizep[1] + 0] = v; | |
| 1272 | ✗ | break; | |
| 1273 | 21365760 | case AV_PIX_FMT_P410: | |
| 1274 | case AV_PIX_FMT_P412: | ||
| 1275 | case AV_PIX_FMT_P416: | ||
| 1276 | 21365760 | AV_WN16A(&dstp[0][i*2 + j*dst_linesizep[0] + 0], y << (16 - desc->comp[0].depth)); | |
| 1277 | 21365760 | AV_WN16A(&dstp[1][i*4 + j*dst_linesizep[1] + 0], u << (16 - desc->comp[1].depth)); | |
| 1278 | 21365760 | AV_WN16A(&dstp[1][i*4 + j*dst_linesizep[1] + 2], v << (16 - desc->comp[1].depth)); | |
| 1279 | 21365760 | break; | |
| 1280 | } | ||
| 1281 | 62914560 | } | |
| 1282 | |||
| 1283 | 624 | static void yuvtest_fill_picture(AVFilterContext *ctx, AVFrame *frame) | |
| 1284 | { | ||
| 1285 | 624 | TestSourceContext *test = ctx->priv; | |
| 1286 | 624 | int i, j, w = frame->width, h = frame->height; | |
| 1287 | 624 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(ctx->outputs[0]->format); | |
| 1288 | 624 | const int factor = 1 << desc->comp[0].depth; | |
| 1289 | 624 | const int mid = 1 << (desc->comp[0].depth - 1); | |
| 1290 | |||
| 1291 |
2/2✓ Branch 0 taken 179040 times.
✓ Branch 1 taken 624 times.
|
179664 | for (j = 0; j < h; j++) { |
| 1292 |
2/2✓ Branch 0 taken 62914560 times.
✓ Branch 1 taken 179040 times.
|
63093600 | for (i = 0; i < w; i++) { |
| 1293 | 62914560 | int c = factor * i / w; | |
| 1294 | 62914560 | int y = mid, u = mid, v = mid; | |
| 1295 | |||
| 1296 |
2/2✓ Branch 0 taken 20971520 times.
✓ Branch 1 taken 41943040 times.
|
62914560 | if (3*j < h ) y = c; |
| 1297 |
2/2✓ Branch 0 taken 20971520 times.
✓ Branch 1 taken 20971520 times.
|
41943040 | else if (3*j < 2*h) u = c; |
| 1298 | 20971520 | else v = c; | |
| 1299 | |||
| 1300 | 62914560 | yuvtest_put_pixel(frame->data, frame->linesize, i, j, y, u, v, c, | |
| 1301 | 62914560 | ctx->outputs[0]->format, test->ayuv_map); | |
| 1302 | } | ||
| 1303 | } | ||
| 1304 | 624 | } | |
| 1305 | |||
| 1306 | 1248 | static av_cold int yuvtest_init(AVFilterContext *ctx) | |
| 1307 | { | ||
| 1308 | 1248 | TestSourceContext *test = ctx->priv; | |
| 1309 | |||
| 1310 | 1248 | test->draw_once = 1; | |
| 1311 | 1248 | test->fill_picture_fn = yuvtest_fill_picture; | |
| 1312 | 1248 | return init(ctx); | |
| 1313 | } | ||
| 1314 | |||
| 1315 | static const enum AVPixelFormat yuvtest_pix_fmts[] = { | ||
| 1316 | AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, | ||
| 1317 | AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, | ||
| 1318 | AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14, | ||
| 1319 | AV_PIX_FMT_YUV444P16, AV_PIX_FMT_VYU444, | ||
| 1320 | AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA444P9, | ||
| 1321 | AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, | ||
| 1322 | AV_PIX_FMT_YUV444P10MSB, AV_PIX_FMT_YUV444P12MSB, | ||
| 1323 | AV_PIX_FMT_AYUV, AV_PIX_FMT_UYVA, AV_PIX_FMT_AYUV64, | ||
| 1324 | AV_PIX_FMT_VUYA, AV_PIX_FMT_VUYX, AV_PIX_FMT_XV48, | ||
| 1325 | AV_PIX_FMT_XV30LE, AV_PIX_FMT_V30XLE, AV_PIX_FMT_XV36, | ||
| 1326 | AV_PIX_FMT_NV24, AV_PIX_FMT_NV42, | ||
| 1327 | AV_PIX_FMT_P410, AV_PIX_FMT_P412, AV_PIX_FMT_P416, | ||
| 1328 | AV_PIX_FMT_NONE | ||
| 1329 | }; | ||
| 1330 | |||
| 1331 | 624 | static int yuvtest_config_props(AVFilterLink *outlink) | |
| 1332 | { | ||
| 1333 | 624 | TestSourceContext *test = outlink->src->priv; | |
| 1334 | |||
| 1335 | 624 | ff_fill_ayuv_map(test->ayuv_map, outlink->format); | |
| 1336 | 624 | return config_props(outlink); | |
| 1337 | } | ||
| 1338 | |||
| 1339 | static const AVFilterPad avfilter_vsrc_yuvtestsrc_outputs[] = { | ||
| 1340 | { | ||
| 1341 | .name = "default", | ||
| 1342 | .type = AVMEDIA_TYPE_VIDEO, | ||
| 1343 | .config_props = yuvtest_config_props, | ||
| 1344 | }, | ||
| 1345 | }; | ||
| 1346 | |||
| 1347 | const FFFilter ff_vsrc_yuvtestsrc = { | ||
| 1348 | .p.name = "yuvtestsrc", | ||
| 1349 | .p.description = NULL_IF_CONFIG_SMALL("Generate YUV test pattern."), | ||
| 1350 | .p.priv_class = &nullsrc_yuvtestsrc_class, | ||
| 1351 | .priv_size = sizeof(TestSourceContext), | ||
| 1352 | .init = yuvtest_init, | ||
| 1353 | .uninit = uninit, | ||
| 1354 | .activate = activate, | ||
| 1355 | FILTER_OUTPUTS(avfilter_vsrc_yuvtestsrc_outputs), | ||
| 1356 | FILTER_PIXFMTS_ARRAY(yuvtest_pix_fmts), | ||
| 1357 | }; | ||
| 1358 | |||
| 1359 | #undef Y | ||
| 1360 | #undef U | ||
| 1361 | #undef V | ||
| 1362 | #undef A | ||
| 1363 | |||
| 1364 | #endif /* CONFIG_YUVTESTSRC_FILTER */ | ||
| 1365 | |||
| 1366 | #if CONFIG_PAL75BARS_FILTER || CONFIG_PAL100BARS_FILTER || CONFIG_SMPTEBARS_FILTER || CONFIG_SMPTEHDBARS_FILTER | ||
| 1367 | |||
| 1368 | static const uint8_t rainbow[7][4] = { | ||
| 1369 | { 180, 128, 128, 255 }, /* 75% white */ | ||
| 1370 | { 162, 44, 142, 255 }, /* 75% yellow */ | ||
| 1371 | { 131, 156, 44, 255 }, /* 75% cyan */ | ||
| 1372 | { 112, 72, 58, 255 }, /* 75% green */ | ||
| 1373 | { 84, 184, 198, 255 }, /* 75% magenta */ | ||
| 1374 | { 65, 100, 212, 255 }, /* 75% red */ | ||
| 1375 | { 35, 212, 114, 255 }, /* 75% blue */ | ||
| 1376 | }; | ||
| 1377 | |||
| 1378 | static const uint8_t rainbow100[7][4] = { | ||
| 1379 | { 235, 128, 128, 255 }, /* 100% white */ | ||
| 1380 | { 210, 16, 146, 255 }, /* 100% yellow */ | ||
| 1381 | { 170, 166, 16, 255 }, /* 100% cyan */ | ||
| 1382 | { 145, 54, 34, 255 }, /* 100% green */ | ||
| 1383 | { 106, 202, 222, 255 }, /* 100% magenta */ | ||
| 1384 | { 81, 90, 240, 255 }, /* 100% red */ | ||
| 1385 | { 41, 240, 110, 255 }, /* 100% blue */ | ||
| 1386 | }; | ||
| 1387 | |||
| 1388 | static const uint8_t rainbowhd[7][4] = { | ||
| 1389 | { 180, 128, 128, 255 }, /* 75% white */ | ||
| 1390 | { 168, 44, 136, 255 }, /* 75% yellow */ | ||
| 1391 | { 145, 147, 44, 255 }, /* 75% cyan */ | ||
| 1392 | { 133, 63, 52, 255 }, /* 75% green */ | ||
| 1393 | { 63, 193, 204, 255 }, /* 75% magenta */ | ||
| 1394 | { 51, 109, 212, 255 }, /* 75% red */ | ||
| 1395 | { 28, 212, 120, 255 }, /* 75% blue */ | ||
| 1396 | }; | ||
| 1397 | |||
| 1398 | static const uint8_t wobnair[7][4] = { | ||
| 1399 | { 35, 212, 114, 255 }, /* 75% blue */ | ||
| 1400 | { 19, 128, 128, 255 }, /* 7.5% intensity black */ | ||
| 1401 | { 84, 184, 198, 255 }, /* 75% magenta */ | ||
| 1402 | { 19, 128, 128, 255 }, /* 7.5% intensity black */ | ||
| 1403 | { 131, 156, 44, 255 }, /* 75% cyan */ | ||
| 1404 | { 19, 128, 128, 255 }, /* 7.5% intensity black */ | ||
| 1405 | { 180, 128, 128, 255 }, /* 75% white */ | ||
| 1406 | }; | ||
| 1407 | |||
| 1408 | static const uint8_t white[4] = { 235, 128, 128, 255 }; | ||
| 1409 | |||
| 1410 | /* pluge pulses */ | ||
| 1411 | static const uint8_t neg4ire[4] = { 7, 128, 128, 255 }; | ||
| 1412 | static const uint8_t pos4ire[4] = { 24, 128, 128, 255 }; | ||
| 1413 | |||
| 1414 | /* fudged Q/-I */ | ||
| 1415 | static const uint8_t i_pixel[4] = { 57, 156, 97, 255 }; | ||
| 1416 | static const uint8_t q_pixel[4] = { 44, 171, 147, 255 }; | ||
| 1417 | |||
| 1418 | static const uint8_t gray40[4] = { 104, 128, 128, 255 }; | ||
| 1419 | static const uint8_t gray15[4] = { 49, 128, 128, 255 }; | ||
| 1420 | static const uint8_t cyan[4] = { 188, 154, 16, 255 }; | ||
| 1421 | static const uint8_t yellow[4] = { 219, 16, 138, 255 }; | ||
| 1422 | static const uint8_t blue[4] = { 32, 240, 118, 255 }; | ||
| 1423 | static const uint8_t red[4] = { 63, 102, 240, 255 }; | ||
| 1424 | static const uint8_t black0[4] = { 16, 128, 128, 255 }; | ||
| 1425 | static const uint8_t black2[4] = { 20, 128, 128, 255 }; | ||
| 1426 | static const uint8_t black4[4] = { 25, 128, 128, 255 }; | ||
| 1427 | static const uint8_t neg2[4] = { 12, 128, 128, 255 }; | ||
| 1428 | |||
| 1429 | 571 | static void draw_bar(TestSourceContext *test, const uint8_t color[4], | |
| 1430 | int x, int y, int w, int h, | ||
| 1431 | AVFrame *frame) | ||
| 1432 | { | ||
| 1433 | 571 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); | |
| 1434 | uint8_t *p, *p0; | ||
| 1435 | int plane; | ||
| 1436 | |||
| 1437 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 571 times.
|
571 | x = FFMIN(x, test->w - 1); |
| 1438 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 571 times.
|
571 | y = FFMIN(y, test->h - 1); |
| 1439 | 571 | w = FFMAX(FFMIN(w, test->w - x), 0); | |
| 1440 | 571 | h = FFMAX(FFMIN(h, test->h - y), 0); | |
| 1441 | |||
| 1442 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 571 times.
|
571 | av_assert0(x + w <= test->w); |
| 1443 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 571 times.
|
571 | av_assert0(y + h <= test->h); |
| 1444 | |||
| 1445 |
2/2✓ Branch 0 taken 1713 times.
✓ Branch 1 taken 571 times.
|
2284 | for (plane = 0; frame->data[plane]; plane++) { |
| 1446 | 1713 | const int c = color[plane]; | |
| 1447 | 1713 | const ptrdiff_t linesize = frame->linesize[plane]; | |
| 1448 | int i, px, py, pw, ph; | ||
| 1449 | |||
| 1450 |
4/4✓ Branch 0 taken 1142 times.
✓ Branch 1 taken 571 times.
✓ Branch 2 taken 571 times.
✓ Branch 3 taken 571 times.
|
1713 | if (plane == 1 || plane == 2) { |
| 1451 | 1142 | px = x >> desc->log2_chroma_w; | |
| 1452 | 1142 | pw = AV_CEIL_RSHIFT(w, desc->log2_chroma_w); | |
| 1453 | 1142 | py = y >> desc->log2_chroma_h; | |
| 1454 | 1142 | ph = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); | |
| 1455 | } else { | ||
| 1456 | 571 | px = x; | |
| 1457 | 571 | pw = w; | |
| 1458 | 571 | py = y; | |
| 1459 | 571 | ph = h; | |
| 1460 | } | ||
| 1461 | |||
| 1462 | 1713 | p0 = p = frame->data[plane] + py * linesize + px; | |
| 1463 | 1713 | memset(p, c, pw); | |
| 1464 | 1713 | p += linesize; | |
| 1465 |
2/2✓ Branch 0 taken 47467 times.
✓ Branch 1 taken 1713 times.
|
49180 | for (i = 1; i < ph; i++, p += linesize) |
| 1466 | 47467 | memcpy(p, p0, pw); | |
| 1467 | } | ||
| 1468 | 571 | } | |
| 1469 | |||
| 1470 | static const enum AVPixelFormat smptebars_pix_fmts[] = { | ||
| 1471 | AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, | ||
| 1472 | AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, | ||
| 1473 | AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, | ||
| 1474 | AV_PIX_FMT_NONE, | ||
| 1475 | }; | ||
| 1476 | |||
| 1477 | 8 | static int smptebars_query_formats(const AVFilterContext *ctx, | |
| 1478 | AVFilterFormatsConfig **cfg_in, | ||
| 1479 | AVFilterFormatsConfig **cfg_out) | ||
| 1480 | { | ||
| 1481 | enum AVColorSpace csp; | ||
| 1482 | int ret; | ||
| 1483 | |||
| 1484 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (!strcmp(ctx->name, "smptehdbars")) { |
| 1485 | ✗ | csp = AVCOL_SPC_BT709; | |
| 1486 | } else { | ||
| 1487 | 8 | csp = AVCOL_SPC_BT470BG; | |
| 1488 | } | ||
| 1489 | |||
| 1490 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if ((ret = ff_set_common_color_spaces2(ctx, cfg_in, cfg_out, |
| 1491 | ff_make_formats_list_singleton(csp)))) | ||
| 1492 | ✗ | return ret; | |
| 1493 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if ((ret = ff_set_common_color_ranges2(ctx, cfg_in, cfg_out, |
| 1494 | ff_make_formats_list_singleton(AVCOL_RANGE_MPEG)))) | ||
| 1495 | ✗ | return ret; | |
| 1496 | 8 | return ff_set_pixel_formats_from_list2(ctx, cfg_in, cfg_out, smptebars_pix_fmts); | |
| 1497 | } | ||
| 1498 | |||
| 1499 | AVFILTER_DEFINE_CLASS_EXT(palbars, "pal(75|100)bars", options); | ||
| 1500 | |||
| 1501 | #if CONFIG_PAL75BARS_FILTER | ||
| 1502 | |||
| 1503 | 1 | static void pal75bars_fill_picture(AVFilterContext *ctx, AVFrame *picref) | |
| 1504 | { | ||
| 1505 | 1 | TestSourceContext *test = ctx->priv; | |
| 1506 | 1 | int r_w, i, x = 0; | |
| 1507 | 1 | const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(picref->format); | |
| 1508 | |||
| 1509 | 1 | r_w = FFALIGN((test->w + 7) / 8, 1 << pixdesc->log2_chroma_w); | |
| 1510 | |||
| 1511 | 1 | draw_bar(test, white, x, 0, r_w, test->h, picref); | |
| 1512 | 1 | x += r_w; | |
| 1513 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
|
7 | for (i = 1; i < 7; i++) { |
| 1514 | 6 | draw_bar(test, rainbow[i], x, 0, r_w, test->h, picref); | |
| 1515 | 6 | x += r_w; | |
| 1516 | } | ||
| 1517 | 1 | draw_bar(test, black0, x, 0, r_w, test->h, picref); | |
| 1518 | 1 | } | |
| 1519 | |||
| 1520 | 2 | static av_cold int pal75bars_init(AVFilterContext *ctx) | |
| 1521 | { | ||
| 1522 | 2 | TestSourceContext *test = ctx->priv; | |
| 1523 | |||
| 1524 | 2 | test->fill_picture_fn = pal75bars_fill_picture; | |
| 1525 | 2 | test->draw_once = 1; | |
| 1526 | 2 | return init(ctx); | |
| 1527 | } | ||
| 1528 | |||
| 1529 | const FFFilter ff_vsrc_pal75bars = { | ||
| 1530 | .p.name = "pal75bars", | ||
| 1531 | .p.description = NULL_IF_CONFIG_SMALL("Generate PAL 75% color bars."), | ||
| 1532 | .p.priv_class = &palbars_class, | ||
| 1533 | .priv_size = sizeof(TestSourceContext), | ||
| 1534 | .init = pal75bars_init, | ||
| 1535 | .uninit = uninit, | ||
| 1536 | .activate = activate, | ||
| 1537 | FILTER_OUTPUTS(outputs), | ||
| 1538 | FILTER_QUERY_FUNC2(smptebars_query_formats), | ||
| 1539 | }; | ||
| 1540 | |||
| 1541 | #endif /* CONFIG_PAL75BARS_FILTER */ | ||
| 1542 | |||
| 1543 | #if CONFIG_PAL100BARS_FILTER | ||
| 1544 | |||
| 1545 | 1 | static void pal100bars_fill_picture(AVFilterContext *ctx, AVFrame *picref) | |
| 1546 | { | ||
| 1547 | 1 | TestSourceContext *test = ctx->priv; | |
| 1548 | 1 | int r_w, i, x = 0; | |
| 1549 | 1 | const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(picref->format); | |
| 1550 | |||
| 1551 | 1 | r_w = FFALIGN((test->w + 7) / 8, 1 << pixdesc->log2_chroma_w); | |
| 1552 | |||
| 1553 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
|
8 | for (i = 0; i < 7; i++) { |
| 1554 | 7 | draw_bar(test, rainbow100[i], x, 0, r_w, test->h, picref); | |
| 1555 | 7 | x += r_w; | |
| 1556 | } | ||
| 1557 | 1 | draw_bar(test, black0, x, 0, r_w, test->h, picref); | |
| 1558 | 1 | } | |
| 1559 | |||
| 1560 | 2 | static av_cold int pal100bars_init(AVFilterContext *ctx) | |
| 1561 | { | ||
| 1562 | 2 | TestSourceContext *test = ctx->priv; | |
| 1563 | |||
| 1564 | 2 | test->fill_picture_fn = pal100bars_fill_picture; | |
| 1565 | 2 | test->draw_once = 1; | |
| 1566 | 2 | return init(ctx); | |
| 1567 | } | ||
| 1568 | |||
| 1569 | const FFFilter ff_vsrc_pal100bars = { | ||
| 1570 | .p.name = "pal100bars", | ||
| 1571 | .p.description = NULL_IF_CONFIG_SMALL("Generate PAL 100% color bars."), | ||
| 1572 | .p.priv_class = &palbars_class, | ||
| 1573 | .priv_size = sizeof(TestSourceContext), | ||
| 1574 | .init = pal100bars_init, | ||
| 1575 | .uninit = uninit, | ||
| 1576 | .activate = activate, | ||
| 1577 | FILTER_OUTPUTS(outputs), | ||
| 1578 | FILTER_QUERY_FUNC2(smptebars_query_formats), | ||
| 1579 | }; | ||
| 1580 | |||
| 1581 | #endif /* CONFIG_PAL100BARS_FILTER */ | ||
| 1582 | |||
| 1583 | AVFILTER_DEFINE_CLASS_EXT(smptebars, "smpte(hd)bars", options); | ||
| 1584 | |||
| 1585 | #if CONFIG_SMPTEBARS_FILTER | ||
| 1586 | |||
| 1587 | 3 | static void smptebars_fill_picture(AVFilterContext *ctx, AVFrame *picref) | |
| 1588 | { | ||
| 1589 | 3 | TestSourceContext *test = ctx->priv; | |
| 1590 | 3 | int r_w, r_h, w_h, p_w, p_h, i, tmp, x = 0; | |
| 1591 | 3 | const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(picref->format); | |
| 1592 | |||
| 1593 | 3 | r_w = FFALIGN((test->w + 6) / 7, 1 << pixdesc->log2_chroma_w); | |
| 1594 | 3 | r_h = FFALIGN(test->h * 2 / 3, 1 << pixdesc->log2_chroma_h); | |
| 1595 | 3 | w_h = FFALIGN(test->h * 3 / 4 - r_h, 1 << pixdesc->log2_chroma_h); | |
| 1596 | 3 | p_w = FFALIGN(r_w * 5 / 4, 1 << pixdesc->log2_chroma_w); | |
| 1597 | 3 | p_h = test->h - w_h - r_h; | |
| 1598 | |||
| 1599 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 3 times.
|
24 | for (i = 0; i < 7; i++) { |
| 1600 | 21 | draw_bar(test, rainbow[i], x, 0, r_w, r_h, picref); | |
| 1601 | 21 | draw_bar(test, wobnair[i], x, r_h, r_w, w_h, picref); | |
| 1602 | 21 | x += r_w; | |
| 1603 | } | ||
| 1604 | 3 | x = 0; | |
| 1605 | 3 | draw_bar(test, i_pixel, x, r_h + w_h, p_w, p_h, picref); | |
| 1606 | 3 | x += p_w; | |
| 1607 | 3 | draw_bar(test, white, x, r_h + w_h, p_w, p_h, picref); | |
| 1608 | 3 | x += p_w; | |
| 1609 | 3 | draw_bar(test, q_pixel, x, r_h + w_h, p_w, p_h, picref); | |
| 1610 | 3 | x += p_w; | |
| 1611 | 3 | tmp = FFALIGN(5 * r_w - x, 1 << pixdesc->log2_chroma_w); | |
| 1612 | 3 | draw_bar(test, black0, x, r_h + w_h, tmp, p_h, picref); | |
| 1613 | 3 | x += tmp; | |
| 1614 | 3 | tmp = FFALIGN(r_w / 3, 1 << pixdesc->log2_chroma_w); | |
| 1615 | 3 | draw_bar(test, neg4ire, x, r_h + w_h, tmp, p_h, picref); | |
| 1616 | 3 | x += tmp; | |
| 1617 | 3 | draw_bar(test, black0, x, r_h + w_h, tmp, p_h, picref); | |
| 1618 | 3 | x += tmp; | |
| 1619 | 3 | draw_bar(test, pos4ire, x, r_h + w_h, tmp, p_h, picref); | |
| 1620 | 3 | x += tmp; | |
| 1621 | 3 | draw_bar(test, black0, x, r_h + w_h, test->w - x, p_h, picref); | |
| 1622 | 3 | } | |
| 1623 | |||
| 1624 | 4 | static av_cold int smptebars_init(AVFilterContext *ctx) | |
| 1625 | { | ||
| 1626 | 4 | TestSourceContext *test = ctx->priv; | |
| 1627 | |||
| 1628 | 4 | test->fill_picture_fn = smptebars_fill_picture; | |
| 1629 | 4 | test->draw_once = 1; | |
| 1630 | 4 | return init(ctx); | |
| 1631 | } | ||
| 1632 | |||
| 1633 | const FFFilter ff_vsrc_smptebars = { | ||
| 1634 | .p.name = "smptebars", | ||
| 1635 | .p.description = NULL_IF_CONFIG_SMALL("Generate SMPTE color bars."), | ||
| 1636 | .p.priv_class = &smptebars_class, | ||
| 1637 | .priv_size = sizeof(TestSourceContext), | ||
| 1638 | .init = smptebars_init, | ||
| 1639 | .uninit = uninit, | ||
| 1640 | .activate = activate, | ||
| 1641 | FILTER_OUTPUTS(outputs), | ||
| 1642 | FILTER_QUERY_FUNC2(smptebars_query_formats), | ||
| 1643 | }; | ||
| 1644 | |||
| 1645 | #endif /* CONFIG_SMPTEBARS_FILTER */ | ||
| 1646 | |||
| 1647 | #if CONFIG_SMPTEHDBARS_FILTER | ||
| 1648 | |||
| 1649 | 3 | static void smptehdbars_fill_picture(AVFilterContext *ctx, AVFrame *picref) | |
| 1650 | { | ||
| 1651 | 3 | TestSourceContext *test = ctx->priv; | |
| 1652 | 3 | int d_w, r_w, r_h, l_w, i, tmp, x = 0, y = 0; | |
| 1653 | 3 | const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(picref->format); | |
| 1654 | |||
| 1655 | 3 | d_w = FFALIGN(test->w / 8, 1 << pixdesc->log2_chroma_w); | |
| 1656 | 3 | r_h = FFALIGN(test->h * 7 / 12, 1 << pixdesc->log2_chroma_h); | |
| 1657 | 3 | draw_bar(test, gray40, x, 0, d_w, r_h, picref); | |
| 1658 | 3 | x += d_w; | |
| 1659 | |||
| 1660 | 3 | r_w = FFALIGN((((test->w + 3) / 4) * 3) / 7, 1 << pixdesc->log2_chroma_w); | |
| 1661 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 3 times.
|
24 | for (i = 0; i < 7; i++) { |
| 1662 | 21 | draw_bar(test, rainbowhd[i], x, 0, r_w, r_h, picref); | |
| 1663 | 21 | x += r_w; | |
| 1664 | } | ||
| 1665 | 3 | draw_bar(test, gray40, x, 0, test->w - x, r_h, picref); | |
| 1666 | 3 | y = r_h; | |
| 1667 | 3 | r_h = FFALIGN(test->h / 12, 1 << pixdesc->log2_chroma_h); | |
| 1668 | 3 | draw_bar(test, cyan, 0, y, d_w, r_h, picref); | |
| 1669 | 3 | x = d_w; | |
| 1670 | 3 | draw_bar(test, i_pixel, x, y, r_w, r_h, picref); | |
| 1671 | 3 | x += r_w; | |
| 1672 | 3 | tmp = r_w * 6; | |
| 1673 | 3 | draw_bar(test, rainbowhd[0], x, y, tmp, r_h, picref); | |
| 1674 | 3 | x += tmp; | |
| 1675 | 3 | l_w = x; | |
| 1676 | 3 | draw_bar(test, blue, x, y, test->w - x, r_h, picref); | |
| 1677 | 3 | y += r_h; | |
| 1678 | 3 | draw_bar(test, yellow, 0, y, d_w, r_h, picref); | |
| 1679 | 3 | x = d_w; | |
| 1680 | 3 | draw_bar(test, q_pixel, x, y, r_w, r_h, picref); | |
| 1681 | 3 | x += r_w; | |
| 1682 | |||
| 1683 |
2/2✓ Branch 0 taken 408 times.
✓ Branch 1 taken 3 times.
|
411 | for (i = 0; i < tmp; i += 1 << pixdesc->log2_chroma_w) { |
| 1684 | 408 | uint8_t yramp[4] = {0}; | |
| 1685 | |||
| 1686 | 408 | yramp[0] = i * 255 / tmp; | |
| 1687 | 408 | yramp[1] = 128; | |
| 1688 | 408 | yramp[2] = 128; | |
| 1689 | 408 | yramp[3] = 255; | |
| 1690 | |||
| 1691 | 408 | draw_bar(test, yramp, x, y, 1 << pixdesc->log2_chroma_w, r_h, picref); | |
| 1692 | 408 | x += 1 << pixdesc->log2_chroma_w; | |
| 1693 | } | ||
| 1694 | 3 | draw_bar(test, red, x, y, test->w - x, r_h, picref); | |
| 1695 | 3 | y += r_h; | |
| 1696 | 3 | draw_bar(test, gray15, 0, y, d_w, test->h - y, picref); | |
| 1697 | 3 | x = d_w; | |
| 1698 | 3 | tmp = FFALIGN(r_w * 3 / 2, 1 << pixdesc->log2_chroma_w); | |
| 1699 | 3 | draw_bar(test, black0, x, y, tmp, test->h - y, picref); | |
| 1700 | 3 | x += tmp; | |
| 1701 | 3 | tmp = FFALIGN(r_w * 2, 1 << pixdesc->log2_chroma_w); | |
| 1702 | 3 | draw_bar(test, white, x, y, tmp, test->h - y, picref); | |
| 1703 | 3 | x += tmp; | |
| 1704 | 3 | tmp = FFALIGN(r_w * 5 / 6, 1 << pixdesc->log2_chroma_w); | |
| 1705 | 3 | draw_bar(test, black0, x, y, tmp, test->h - y, picref); | |
| 1706 | 3 | x += tmp; | |
| 1707 | 3 | tmp = FFALIGN(r_w / 3, 1 << pixdesc->log2_chroma_w); | |
| 1708 | 3 | draw_bar(test, neg2, x, y, tmp, test->h - y, picref); | |
| 1709 | 3 | x += tmp; | |
| 1710 | 3 | draw_bar(test, black0, x, y, tmp, test->h - y, picref); | |
| 1711 | 3 | x += tmp; | |
| 1712 | 3 | draw_bar(test, black2, x, y, tmp, test->h - y, picref); | |
| 1713 | 3 | x += tmp; | |
| 1714 | 3 | draw_bar(test, black0, x, y, tmp, test->h - y, picref); | |
| 1715 | 3 | x += tmp; | |
| 1716 | 3 | draw_bar(test, black4, x, y, tmp, test->h - y, picref); | |
| 1717 | 3 | x += tmp; | |
| 1718 | 3 | r_w = l_w - x; | |
| 1719 | 3 | draw_bar(test, black0, x, y, r_w, test->h - y, picref); | |
| 1720 | 3 | x += r_w; | |
| 1721 | 3 | draw_bar(test, gray15, x, y, test->w - x, test->h - y, picref); | |
| 1722 | 3 | } | |
| 1723 | |||
| 1724 | 4 | static av_cold int smptehdbars_init(AVFilterContext *ctx) | |
| 1725 | { | ||
| 1726 | 4 | TestSourceContext *test = ctx->priv; | |
| 1727 | |||
| 1728 | 4 | test->fill_picture_fn = smptehdbars_fill_picture; | |
| 1729 | 4 | test->draw_once = 1; | |
| 1730 | 4 | return init(ctx); | |
| 1731 | } | ||
| 1732 | |||
| 1733 | const FFFilter ff_vsrc_smptehdbars = { | ||
| 1734 | .p.name = "smptehdbars", | ||
| 1735 | .p.description = NULL_IF_CONFIG_SMALL("Generate SMPTE HD color bars."), | ||
| 1736 | .p.priv_class = &smptebars_class, | ||
| 1737 | .priv_size = sizeof(TestSourceContext), | ||
| 1738 | .init = smptehdbars_init, | ||
| 1739 | .uninit = uninit, | ||
| 1740 | .activate = activate, | ||
| 1741 | FILTER_OUTPUTS(outputs), | ||
| 1742 | FILTER_QUERY_FUNC2(smptebars_query_formats), | ||
| 1743 | }; | ||
| 1744 | |||
| 1745 | #endif /* CONFIG_SMPTEHDBARS_FILTER */ | ||
| 1746 | #endif /* CONFIG_SMPTEBARS_FILTER || CONFIG_SMPTEHDBARS_FILTER */ | ||
| 1747 | |||
| 1748 | AVFILTER_DEFINE_CLASS_EXT(allyuv_allrgb, "allyuv/allrgb", | ||
| 1749 | &options[NOSIZE_OPTIONS_OFFSET]); | ||
| 1750 | |||
| 1751 | #if CONFIG_ALLYUV_FILTER | ||
| 1752 | |||
| 1753 | 1 | static void allyuv_fill_picture(AVFilterContext *ctx, AVFrame *frame) | |
| 1754 | { | ||
| 1755 | 1 | const ptrdiff_t ys = frame->linesize[0]; | |
| 1756 | 1 | const ptrdiff_t us = frame->linesize[1]; | |
| 1757 | 1 | const ptrdiff_t vs = frame->linesize[2]; | |
| 1758 | int x, y, j; | ||
| 1759 | |||
| 1760 |
2/2✓ Branch 0 taken 4096 times.
✓ Branch 1 taken 1 times.
|
4097 | for (y = 0; y < 4096; y++) { |
| 1761 |
2/2✓ Branch 0 taken 8388608 times.
✓ Branch 1 taken 4096 times.
|
8392704 | for (x = 0; x < 2048; x++) { |
| 1762 | 8388608 | frame->data[0][y * ys + x] = ((x / 8) % 256); | |
| 1763 | 8388608 | frame->data[0][y * ys + 4095 - x] = ((x / 8) % 256); | |
| 1764 | } | ||
| 1765 | |||
| 1766 |
2/2✓ Branch 0 taken 1048576 times.
✓ Branch 1 taken 4096 times.
|
1052672 | for (x = 0; x < 2048; x+=8) { |
| 1767 |
2/2✓ Branch 0 taken 8388608 times.
✓ Branch 1 taken 1048576 times.
|
9437184 | for (j = 0; j < 8; j++) { |
| 1768 | 8388608 | frame->data[1][vs * y + x + j] = (y%16 + (j % 8) * 16); | |
| 1769 | 8388608 | frame->data[1][vs * y + 4095 - x - j] = (128 + y%16 + (j % 8) * 16); | |
| 1770 | } | ||
| 1771 | } | ||
| 1772 | |||
| 1773 |
2/2✓ Branch 0 taken 16777216 times.
✓ Branch 1 taken 4096 times.
|
16781312 | for (x = 0; x < 4096; x++) |
| 1774 | 16777216 | frame->data[2][y * us + x] = 256 * y / 4096; | |
| 1775 | } | ||
| 1776 | 1 | } | |
| 1777 | |||
| 1778 | 2 | static av_cold int allyuv_init(AVFilterContext *ctx) | |
| 1779 | { | ||
| 1780 | 2 | TestSourceContext *test = ctx->priv; | |
| 1781 | |||
| 1782 | 2 | test->w = test->h = 4096; | |
| 1783 | 2 | test->draw_once = 1; | |
| 1784 | 2 | test->fill_picture_fn = allyuv_fill_picture; | |
| 1785 | 2 | return init(ctx); | |
| 1786 | } | ||
| 1787 | |||
| 1788 | const FFFilter ff_vsrc_allyuv = { | ||
| 1789 | .p.name = "allyuv", | ||
| 1790 | .p.description = NULL_IF_CONFIG_SMALL("Generate all yuv colors."), | ||
| 1791 | .p.priv_class = &allyuv_allrgb_class, | ||
| 1792 | .priv_size = sizeof(TestSourceContext), | ||
| 1793 | .init = allyuv_init, | ||
| 1794 | .uninit = uninit, | ||
| 1795 | .activate = activate, | ||
| 1796 | FILTER_OUTPUTS(outputs), | ||
| 1797 | FILTER_PIXFMTS(AV_PIX_FMT_YUV444P, AV_PIX_FMT_GBRP), | ||
| 1798 | }; | ||
| 1799 | |||
| 1800 | #endif /* CONFIG_ALLYUV_FILTER */ | ||
| 1801 | |||
| 1802 | #if CONFIG_ALLRGB_FILTER | ||
| 1803 | |||
| 1804 | 1 | static void allrgb_fill_picture(AVFilterContext *ctx, AVFrame *frame) | |
| 1805 | { | ||
| 1806 | unsigned x, y; | ||
| 1807 | 1 | const ptrdiff_t linesize = frame->linesize[0]; | |
| 1808 | 1 | uint8_t *line = frame->data[0]; | |
| 1809 | |||
| 1810 |
2/2✓ Branch 0 taken 4096 times.
✓ Branch 1 taken 1 times.
|
4097 | for (y = 0; y < 4096; y++) { |
| 1811 | 4096 | uint8_t *dst = line; | |
| 1812 | |||
| 1813 |
2/2✓ Branch 0 taken 16777216 times.
✓ Branch 1 taken 4096 times.
|
16781312 | for (x = 0; x < 4096; x++) { |
| 1814 | 16777216 | *dst++ = x; | |
| 1815 | 16777216 | *dst++ = y; | |
| 1816 | 16777216 | *dst++ = (x >> 8) | ((y >> 8) << 4); | |
| 1817 | } | ||
| 1818 | 4096 | line += linesize; | |
| 1819 | } | ||
| 1820 | 1 | } | |
| 1821 | |||
| 1822 | 2 | static av_cold int allrgb_init(AVFilterContext *ctx) | |
| 1823 | { | ||
| 1824 | 2 | TestSourceContext *test = ctx->priv; | |
| 1825 | |||
| 1826 | 2 | test->w = test->h = 4096; | |
| 1827 | 2 | test->draw_once = 1; | |
| 1828 | 2 | test->fill_picture_fn = allrgb_fill_picture; | |
| 1829 | 2 | return init(ctx); | |
| 1830 | } | ||
| 1831 | |||
| 1832 | 1 | static int allrgb_config_props(AVFilterLink *outlink) | |
| 1833 | { | ||
| 1834 | 1 | TestSourceContext *test = outlink->src->priv; | |
| 1835 | |||
| 1836 | 1 | ff_fill_rgba_map(test->rgba_map, outlink->format); | |
| 1837 | 1 | return config_props(outlink); | |
| 1838 | } | ||
| 1839 | |||
| 1840 | static const AVFilterPad avfilter_vsrc_allrgb_outputs[] = { | ||
| 1841 | { | ||
| 1842 | .name = "default", | ||
| 1843 | .type = AVMEDIA_TYPE_VIDEO, | ||
| 1844 | .config_props = allrgb_config_props, | ||
| 1845 | }, | ||
| 1846 | }; | ||
| 1847 | |||
| 1848 | const FFFilter ff_vsrc_allrgb = { | ||
| 1849 | .p.name = "allrgb", | ||
| 1850 | .p.description = NULL_IF_CONFIG_SMALL("Generate all RGB colors."), | ||
| 1851 | .p.priv_class = &allyuv_allrgb_class, | ||
| 1852 | .priv_size = sizeof(TestSourceContext), | ||
| 1853 | .init = allrgb_init, | ||
| 1854 | .uninit = uninit, | ||
| 1855 | .activate = activate, | ||
| 1856 | FILTER_OUTPUTS(avfilter_vsrc_allrgb_outputs), | ||
| 1857 | FILTER_SINGLE_PIXFMT(AV_PIX_FMT_RGB24), | ||
| 1858 | }; | ||
| 1859 | |||
| 1860 | #endif /* CONFIG_ALLRGB_FILTER */ | ||
| 1861 | |||
| 1862 | #if CONFIG_COLORSPECTRUM_FILTER | ||
| 1863 | |||
| 1864 | static const AVOption colorspectrum_options[] = { | ||
| 1865 | COMMON_OPTIONS | ||
| 1866 | { "type", "set the color spectrum type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, .unit = "type" }, | ||
| 1867 | { "black","fade to black", 0, AV_OPT_TYPE_CONST,{.i64=0},0, 0, FLAGS, .unit = "type" }, | ||
| 1868 | { "white","fade to white", 0, AV_OPT_TYPE_CONST,{.i64=1},0, 0, FLAGS, .unit = "type" }, | ||
| 1869 | { "all", "white to black", 0, AV_OPT_TYPE_CONST,{.i64=2},0, 0, FLAGS, .unit = "type" }, | ||
| 1870 | { NULL } | ||
| 1871 | }; | ||
| 1872 | |||
| 1873 | AVFILTER_DEFINE_CLASS(colorspectrum); | ||
| 1874 | |||
| 1875 | ✗ | static inline float mix(float a, float b, float mix) | |
| 1876 | { | ||
| 1877 | ✗ | return a * mix + b * (1.f - mix); | |
| 1878 | } | ||
| 1879 | |||
| 1880 | ✗ | static void hsb2rgb(const float *c, float *rgb) | |
| 1881 | { | ||
| 1882 | ✗ | rgb[0] = av_clipf(fabsf(fmodf(c[0] * 6.f + 0.f, 6.f) - 3.f) - 1.f, 0.f, 1.f); | |
| 1883 | ✗ | rgb[1] = av_clipf(fabsf(fmodf(c[0] * 6.f + 4.f, 6.f) - 3.f) - 1.f, 0.f, 1.f); | |
| 1884 | ✗ | rgb[2] = av_clipf(fabsf(fmodf(c[0] * 6.f + 2.f, 6.f) - 3.f) - 1.f, 0.f, 1.f); | |
| 1885 | ✗ | rgb[0] = mix(c[3], (rgb[0] * rgb[0] * (3.f - 2.f * rgb[0])), c[1]) * c[2]; | |
| 1886 | ✗ | rgb[1] = mix(c[3], (rgb[1] * rgb[1] * (3.f - 2.f * rgb[1])), c[1]) * c[2]; | |
| 1887 | ✗ | rgb[2] = mix(c[3], (rgb[2] * rgb[2] * (3.f - 2.f * rgb[2])), c[1]) * c[2]; | |
| 1888 | ✗ | } | |
| 1889 | |||
| 1890 | ✗ | static void colorspectrum_fill_picture(AVFilterContext *ctx, AVFrame *frame) | |
| 1891 | { | ||
| 1892 | ✗ | TestSourceContext *test = ctx->priv; | |
| 1893 | ✗ | const float w = frame->width - 1.f; | |
| 1894 | ✗ | const float h = frame->height - 1.f; | |
| 1895 | float c[4]; | ||
| 1896 | |||
| 1897 | ✗ | for (int y = 0; y < frame->height; y++) { | |
| 1898 | ✗ | float *r = (float *)(frame->data[2] + y * frame->linesize[2]); | |
| 1899 | ✗ | float *g = (float *)(frame->data[0] + y * frame->linesize[0]); | |
| 1900 | ✗ | float *b = (float *)(frame->data[1] + y * frame->linesize[1]); | |
| 1901 | ✗ | const float yh = y / h; | |
| 1902 | |||
| 1903 | ✗ | c[1] = test->type == 2 ? yh > 0.5f ? 2.f * (yh - 0.5f) : 1.f - 2.f * yh : test->type == 1 ? 1.f - yh : yh; | |
| 1904 | ✗ | c[2] = 1.f; | |
| 1905 | ✗ | c[3] = test->type == 1 ? 1.f : test->type == 2 ? (yh > 0.5f ? 0.f : 1.f): 0.f; | |
| 1906 | ✗ | for (int x = 0; x < frame->width; x++) { | |
| 1907 | float rgb[3]; | ||
| 1908 | |||
| 1909 | ✗ | c[0] = x / w; | |
| 1910 | ✗ | hsb2rgb(c, rgb); | |
| 1911 | |||
| 1912 | ✗ | r[x] = rgb[0]; | |
| 1913 | ✗ | g[x] = rgb[1]; | |
| 1914 | ✗ | b[x] = rgb[2]; | |
| 1915 | } | ||
| 1916 | } | ||
| 1917 | ✗ | } | |
| 1918 | |||
| 1919 | ✗ | static av_cold int colorspectrum_init(AVFilterContext *ctx) | |
| 1920 | { | ||
| 1921 | ✗ | TestSourceContext *test = ctx->priv; | |
| 1922 | |||
| 1923 | ✗ | test->draw_once = 1; | |
| 1924 | ✗ | test->fill_picture_fn = colorspectrum_fill_picture; | |
| 1925 | ✗ | return init(ctx); | |
| 1926 | } | ||
| 1927 | |||
| 1928 | const FFFilter ff_vsrc_colorspectrum = { | ||
| 1929 | .p.name = "colorspectrum", | ||
| 1930 | .p.description = NULL_IF_CONFIG_SMALL("Generate colors spectrum."), | ||
| 1931 | .p.priv_class = &colorspectrum_class, | ||
| 1932 | .priv_size = sizeof(TestSourceContext), | ||
| 1933 | .init = colorspectrum_init, | ||
| 1934 | .uninit = uninit, | ||
| 1935 | .activate = activate, | ||
| 1936 | FILTER_OUTPUTS(outputs), | ||
| 1937 | FILTER_SINGLE_PIXFMT(AV_PIX_FMT_GBRPF32), | ||
| 1938 | }; | ||
| 1939 | |||
| 1940 | #endif /* CONFIG_COLORSPECTRUM_FILTER */ | ||
| 1941 | |||
| 1942 | #if CONFIG_COLORCHART_FILTER | ||
| 1943 | |||
| 1944 | static const AVOption colorchart_options[] = { | ||
| 1945 | COMMON_OPTIONS_NOSIZE | ||
| 1946 | { "patch_size", "set the single patch size", OFFSET(pw), AV_OPT_TYPE_IMAGE_SIZE, {.str="64x64"}, 0, 0, FLAGS }, | ||
| 1947 | { "preset", "set the color checker chart preset", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, .unit = "preset" }, | ||
| 1948 | { "reference", "reference", 0, AV_OPT_TYPE_CONST,{.i64=0}, 0, 0, FLAGS, .unit = "preset" }, | ||
| 1949 | { "skintones", "skintones", 0, AV_OPT_TYPE_CONST,{.i64=1}, 0, 0, FLAGS, .unit = "preset" }, | ||
| 1950 | { NULL } | ||
| 1951 | }; | ||
| 1952 | |||
| 1953 | AVFILTER_DEFINE_CLASS(colorchart); | ||
| 1954 | |||
| 1955 | static const uint8_t reference_colors[][3] = { | ||
| 1956 | { 115, 82, 68 }, // dark skin | ||
| 1957 | { 194, 150, 130 }, // light skin | ||
| 1958 | { 98, 122, 157 }, // blue sky | ||
| 1959 | { 87, 108, 67 }, // foliage | ||
| 1960 | { 133, 128, 177 }, // blue flower | ||
| 1961 | { 103, 189, 170 }, // bluish green | ||
| 1962 | |||
| 1963 | { 214, 126, 44 }, // orange | ||
| 1964 | { 80, 91, 166 }, // purple red | ||
| 1965 | { 193, 90, 99 }, // moderate red | ||
| 1966 | { 94, 60, 108 }, // purple | ||
| 1967 | { 157, 188, 64 }, // yellow green | ||
| 1968 | { 224, 163, 46 }, // orange yellow | ||
| 1969 | |||
| 1970 | { 56, 61, 150 }, // blue | ||
| 1971 | { 70, 148, 73 }, // green | ||
| 1972 | { 175, 54, 60 }, // red | ||
| 1973 | { 231, 199, 31 }, // yellow | ||
| 1974 | { 187, 86, 149 }, // magenta | ||
| 1975 | { 8, 133, 161 }, // cyan | ||
| 1976 | |||
| 1977 | { 243, 243, 242 }, // white | ||
| 1978 | { 200, 200, 200 }, // neutral 8 | ||
| 1979 | { 160, 160, 160 }, // neutral 65 | ||
| 1980 | { 122, 122, 121 }, // neutral 5 | ||
| 1981 | { 85, 85, 85 }, // neutral 35 | ||
| 1982 | { 52, 52, 52 }, // black | ||
| 1983 | }; | ||
| 1984 | |||
| 1985 | static const uint8_t skintones_colors[][3] = { | ||
| 1986 | { 54, 38, 43 }, | ||
| 1987 | { 105, 43, 42 }, | ||
| 1988 | { 147, 43, 43 }, | ||
| 1989 | { 77, 41, 42 }, | ||
| 1990 | { 134, 43, 41 }, | ||
| 1991 | { 201, 134, 118 }, | ||
| 1992 | |||
| 1993 | { 59, 41, 41 }, | ||
| 1994 | { 192, 103, 76 }, | ||
| 1995 | { 208, 156, 141 }, | ||
| 1996 | { 152, 82, 61 }, | ||
| 1997 | { 162, 132, 118 }, | ||
| 1998 | { 212, 171, 150 }, | ||
| 1999 | |||
| 2000 | { 205, 91, 31 }, | ||
| 2001 | { 164, 100, 55 }, | ||
| 2002 | { 204, 136, 95 }, | ||
| 2003 | { 178, 142, 116 }, | ||
| 2004 | { 210, 152, 108 }, | ||
| 2005 | { 217, 167, 131 }, | ||
| 2006 | |||
| 2007 | { 206, 166, 126 }, | ||
| 2008 | { 208, 163, 97 }, | ||
| 2009 | { 245, 180, 0 }, | ||
| 2010 | { 212, 184, 125 }, | ||
| 2011 | { 179, 165, 150 }, | ||
| 2012 | { 196, 184, 105 }, | ||
| 2013 | }; | ||
| 2014 | |||
| 2015 | typedef struct ColorChartPreset { | ||
| 2016 | int w, h; | ||
| 2017 | const uint8_t (*colors)[3]; | ||
| 2018 | } ColorChartPreset; | ||
| 2019 | |||
| 2020 | static const ColorChartPreset colorchart_presets[] = { | ||
| 2021 | { 6, 4, reference_colors, }, | ||
| 2022 | { 6, 4, skintones_colors, }, | ||
| 2023 | }; | ||
| 2024 | |||
| 2025 | ✗ | static int colorchart_config_props(AVFilterLink *inlink) | |
| 2026 | { | ||
| 2027 | ✗ | AVFilterContext *ctx = inlink->src; | |
| 2028 | ✗ | TestSourceContext *s = ctx->priv; | |
| 2029 | |||
| 2030 | ✗ | av_assert0(ff_draw_init_from_link(&s->draw, inlink, 0) >= 0); | |
| 2031 | ✗ | if (av_image_check_size(s->w, s->h, 0, ctx) < 0) | |
| 2032 | ✗ | return AVERROR(EINVAL); | |
| 2033 | ✗ | return config_props(inlink); | |
| 2034 | } | ||
| 2035 | |||
| 2036 | ✗ | static void colorchart_fill_picture(AVFilterContext *ctx, AVFrame *frame) | |
| 2037 | { | ||
| 2038 | ✗ | TestSourceContext *test = ctx->priv; | |
| 2039 | ✗ | const int preset = test->type; | |
| 2040 | ✗ | const int w = colorchart_presets[preset].w; | |
| 2041 | ✗ | const int h = colorchart_presets[preset].h; | |
| 2042 | ✗ | const int pw = test->pw; | |
| 2043 | ✗ | const int ph = test->ph; | |
| 2044 | |||
| 2045 | ✗ | for (int y = 0; y < h; y++) { | |
| 2046 | ✗ | for (int x = 0; x < w; x++) { | |
| 2047 | ✗ | uint32_t pc = AV_RB24(colorchart_presets[preset].colors[y * w + x]); | |
| 2048 | FFDrawColor color; | ||
| 2049 | |||
| 2050 | ✗ | set_color(test, &color, pc); | |
| 2051 | ✗ | ff_fill_rectangle(&test->draw, &color, frame->data, frame->linesize, | |
| 2052 | x * pw, y * ph, pw, ph); | ||
| 2053 | } | ||
| 2054 | } | ||
| 2055 | ✗ | } | |
| 2056 | |||
| 2057 | ✗ | static av_cold int colorchart_init(AVFilterContext *ctx) | |
| 2058 | { | ||
| 2059 | ✗ | TestSourceContext *test = ctx->priv; | |
| 2060 | ✗ | const int preset = test->type; | |
| 2061 | ✗ | const int w = colorchart_presets[preset].w; | |
| 2062 | ✗ | const int h = colorchart_presets[preset].h; | |
| 2063 | |||
| 2064 | ✗ | test->w = w * test->pw; | |
| 2065 | ✗ | test->h = h * test->ph; | |
| 2066 | ✗ | test->draw_once = 1; | |
| 2067 | ✗ | test->fill_picture_fn = colorchart_fill_picture; | |
| 2068 | ✗ | return init(ctx); | |
| 2069 | } | ||
| 2070 | |||
| 2071 | static const AVFilterPad avfilter_vsrc_colorchart_outputs[] = { | ||
| 2072 | { | ||
| 2073 | .name = "default", | ||
| 2074 | .type = AVMEDIA_TYPE_VIDEO, | ||
| 2075 | .config_props = colorchart_config_props, | ||
| 2076 | }, | ||
| 2077 | }; | ||
| 2078 | |||
| 2079 | const FFFilter ff_vsrc_colorchart = { | ||
| 2080 | .p.name = "colorchart", | ||
| 2081 | .p.description = NULL_IF_CONFIG_SMALL("Generate color checker chart."), | ||
| 2082 | .p.priv_class = &colorchart_class, | ||
| 2083 | .priv_size = sizeof(TestSourceContext), | ||
| 2084 | .init = colorchart_init, | ||
| 2085 | .uninit = uninit, | ||
| 2086 | .activate = activate, | ||
| 2087 | FILTER_OUTPUTS(avfilter_vsrc_colorchart_outputs), | ||
| 2088 | FILTER_SINGLE_PIXFMT(AV_PIX_FMT_GBRP), | ||
| 2089 | }; | ||
| 2090 | |||
| 2091 | #endif /* CONFIG_COLORCHART_FILTER */ | ||
| 2092 | |||
| 2093 | #if CONFIG_ZONEPLATE_FILTER | ||
| 2094 | |||
| 2095 | static const AVOption zoneplate_options[] = { | ||
| 2096 | COMMON_OPTIONS | ||
| 2097 | { "precision", "set LUT precision", OFFSET(lut_precision), AV_OPT_TYPE_INT, {.i64=10}, 4, 16, FLAGS }, | ||
| 2098 | { "xo", "set X-axis offset", OFFSET(xo), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2099 | { "yo", "set Y-axis offset", OFFSET(yo), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2100 | { "to", "set T-axis offset", OFFSET(to), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2101 | { "k0", "set 0-order phase", OFFSET(k0), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2102 | { "kx", "set 1-order X-axis phase", OFFSET(kx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2103 | { "ky", "set 1-order Y-axis phase", OFFSET(ky), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2104 | { "kt", "set 1-order T-axis phase", OFFSET(kt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2105 | { "kxt", "set X-axis*T-axis product phase", OFFSET(kxt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2106 | { "kyt", "set Y-axis*T-axis product phase", OFFSET(kyt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2107 | { "kxy", "set X-axis*Y-axis product phase", OFFSET(kxy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2108 | { "kx2", "set 2-order X-axis phase", OFFSET(kx2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2109 | { "ky2", "set 2-order Y-axis phase", OFFSET(ky2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2110 | { "kt2", "set 2-order T-axis phase", OFFSET(kt2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2111 | { "ku", "set 0-order U-color phase", OFFSET(kU), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2112 | { "kv", "set 0-order V-color phase", OFFSET(kV), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR }, | ||
| 2113 | { NULL } | ||
| 2114 | }; | ||
| 2115 | |||
| 2116 | AVFILTER_DEFINE_CLASS(zoneplate); | ||
| 2117 | |||
| 2118 | #define ZONEPLATE_SLICE(name, type) \ | ||
| 2119 | static int zoneplate_fill_slice_##name(AVFilterContext *ctx, \ | ||
| 2120 | void *arg, int job, \ | ||
| 2121 | int nb_jobs) \ | ||
| 2122 | { \ | ||
| 2123 | TestSourceContext *test = ctx->priv; \ | ||
| 2124 | AVFrame *frame = arg; \ | ||
| 2125 | const int w = frame->width; \ | ||
| 2126 | const int h = frame->height; \ | ||
| 2127 | const int kxt = test->kxt, kyt = test->kyt, kx2 = test->kx2; \ | ||
| 2128 | const int t = test->pts + test->to, k0 = test->k0; \ | ||
| 2129 | const int kt = test->kt, kt2 = test->kt2, ky2 = test->ky2; \ | ||
| 2130 | const int ky = test->ky, kx = test->kx, kxy = test->kxy; \ | ||
| 2131 | const int lut_mask = (1 << test->lut_precision) - 1; \ | ||
| 2132 | const int nkt2t = kt2 * t * t, nktt = kt * t; \ | ||
| 2133 | const int start = (h * job ) / nb_jobs; \ | ||
| 2134 | const int end = (h * (job+1)) / nb_jobs; \ | ||
| 2135 | const ptrdiff_t ylinesize = frame->linesize[0] / sizeof(type); \ | ||
| 2136 | const ptrdiff_t ulinesize = frame->linesize[1] / sizeof(type); \ | ||
| 2137 | const ptrdiff_t vlinesize = frame->linesize[2] / sizeof(type); \ | ||
| 2138 | const int xreset = -(w / 2) - test->xo; \ | ||
| 2139 | const int yreset = -(h / 2) - test->yo + start; \ | ||
| 2140 | const int kU = test->kU, kV = test->kV; \ | ||
| 2141 | const int skxy = 0xffff / (w / 2); \ | ||
| 2142 | const int skx2 = 0xffff / w; \ | ||
| 2143 | const int dkxt = kxt * t; \ | ||
| 2144 | type *ydst = ((type *)frame->data[0]) + start * ylinesize; \ | ||
| 2145 | type *udst = ((type *)frame->data[1]) + start * ulinesize; \ | ||
| 2146 | type *vdst = ((type *)frame->data[2]) + start * vlinesize; \ | ||
| 2147 | const type *lut = (const type *)test->lut; \ | ||
| 2148 | int akx, akxt, aky, akyt; \ | ||
| 2149 | \ | ||
| 2150 | aky = start * ky; \ | ||
| 2151 | akyt = start * kyt * t; \ | ||
| 2152 | \ | ||
| 2153 | for (int j = start, y = yreset; j < end; j++, y++) { \ | ||
| 2154 | const int dkxy = kxy * y * skxy; \ | ||
| 2155 | const int nky2kt2 = (ky2 * y * y) / h + (nkt2t >> 1); \ | ||
| 2156 | int akxy = dkxy * xreset; \ | ||
| 2157 | \ | ||
| 2158 | akx = 0; \ | ||
| 2159 | akxt = 0; \ | ||
| 2160 | aky += ky; \ | ||
| 2161 | akyt += kyt * t; \ | ||
| 2162 | \ | ||
| 2163 | for (int i = 0, x = xreset; i < w; i++, x++) { \ | ||
| 2164 | int phase = k0, uphase = kU, vphase = kV; \ | ||
| 2165 | \ | ||
| 2166 | akx += kx; \ | ||
| 2167 | phase += akx + aky + nktt; \ | ||
| 2168 | \ | ||
| 2169 | akxt += dkxt; \ | ||
| 2170 | akxy += dkxy; \ | ||
| 2171 | phase += akxt + akyt; \ | ||
| 2172 | phase += akxy >> 16; \ | ||
| 2173 | phase += ((kx2 * x * x * skx2) >> 16) + nky2kt2; \ | ||
| 2174 | uphase += phase; \ | ||
| 2175 | vphase += phase; \ | ||
| 2176 | \ | ||
| 2177 | ydst[i] = lut[phase & lut_mask]; \ | ||
| 2178 | udst[i] = lut[uphase & lut_mask]; \ | ||
| 2179 | vdst[i] = lut[vphase & lut_mask]; \ | ||
| 2180 | } \ | ||
| 2181 | \ | ||
| 2182 | ydst += ylinesize; \ | ||
| 2183 | udst += ulinesize; \ | ||
| 2184 | vdst += vlinesize; \ | ||
| 2185 | } \ | ||
| 2186 | \ | ||
| 2187 | return 0; \ | ||
| 2188 | } | ||
| 2189 | |||
| 2190 | ✗ | ZONEPLATE_SLICE( 8, uint8_t) | |
| 2191 | ✗ | ZONEPLATE_SLICE( 9, uint16_t) | |
| 2192 | ✗ | ZONEPLATE_SLICE(10, uint16_t) | |
| 2193 | ✗ | ZONEPLATE_SLICE(12, uint16_t) | |
| 2194 | ✗ | ZONEPLATE_SLICE(14, uint16_t) | |
| 2195 | ✗ | ZONEPLATE_SLICE(16, uint16_t) | |
| 2196 | |||
| 2197 | ✗ | static void zoneplate_fill_picture(AVFilterContext *ctx, AVFrame *frame) | |
| 2198 | { | ||
| 2199 | ✗ | TestSourceContext *test = ctx->priv; | |
| 2200 | ✗ | ff_filter_execute(ctx, test->fill_slice_fn, frame, NULL, | |
| 2201 | ✗ | FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); | |
| 2202 | ✗ | } | |
| 2203 | |||
| 2204 | ✗ | static int zoneplate_config_props(AVFilterLink *outlink) | |
| 2205 | { | ||
| 2206 | ✗ | AVFilterContext *ctx = outlink->src; | |
| 2207 | ✗ | TestSourceContext *test = ctx->priv; | |
| 2208 | ✗ | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); | |
| 2209 | ✗ | const int lut_size = 1 << test->lut_precision; | |
| 2210 | ✗ | const int depth = desc->comp[0].depth; | |
| 2211 | uint16_t *lut16; | ||
| 2212 | uint8_t *lut8; | ||
| 2213 | |||
| 2214 | ✗ | if (av_image_check_size(test->w, test->h, 0, ctx) < 0) | |
| 2215 | ✗ | return AVERROR(EINVAL); | |
| 2216 | |||
| 2217 | ✗ | test->lut = av_calloc(lut_size, sizeof(*test->lut) * ((depth + 7) / 8)); | |
| 2218 | ✗ | if (!test->lut) | |
| 2219 | ✗ | return AVERROR(ENOMEM); | |
| 2220 | |||
| 2221 | ✗ | lut8 = test->lut; | |
| 2222 | ✗ | lut16 = (uint16_t *)test->lut; | |
| 2223 | ✗ | switch (depth) { | |
| 2224 | ✗ | case 8: | |
| 2225 | ✗ | for (int i = 0; i < lut_size; i++) | |
| 2226 | ✗ | lut8[i] = lrintf(255.f * (0.5f + 0.5f * sinf((2.f * M_PI * i) / lut_size))); | |
| 2227 | ✗ | break; | |
| 2228 | ✗ | default: | |
| 2229 | ✗ | for (int i = 0; i < lut_size; i++) | |
| 2230 | ✗ | lut16[i] = lrintf(((1 << depth) - 1) * (0.5f + 0.5f * sinf((2.f * M_PI * i) / lut_size))); | |
| 2231 | ✗ | break; | |
| 2232 | } | ||
| 2233 | |||
| 2234 | ✗ | test->draw_once = 0; | |
| 2235 | ✗ | test->fill_picture_fn = zoneplate_fill_picture; | |
| 2236 | |||
| 2237 | ✗ | switch (depth) { | |
| 2238 | ✗ | case 8: test->fill_slice_fn = zoneplate_fill_slice_8; break; | |
| 2239 | ✗ | case 9: test->fill_slice_fn = zoneplate_fill_slice_9; break; | |
| 2240 | ✗ | case 10: test->fill_slice_fn = zoneplate_fill_slice_10; break; | |
| 2241 | ✗ | case 12: test->fill_slice_fn = zoneplate_fill_slice_12; break; | |
| 2242 | ✗ | case 14: test->fill_slice_fn = zoneplate_fill_slice_14; break; | |
| 2243 | ✗ | case 16: test->fill_slice_fn = zoneplate_fill_slice_16; break; | |
| 2244 | } | ||
| 2245 | ✗ | return config_props(outlink); | |
| 2246 | } | ||
| 2247 | |||
| 2248 | static const enum AVPixelFormat zoneplate_pix_fmts[] = { | ||
| 2249 | AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P9, | ||
| 2250 | AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, | ||
| 2251 | AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16, | ||
| 2252 | AV_PIX_FMT_NONE, | ||
| 2253 | }; | ||
| 2254 | |||
| 2255 | ✗ | static int zoneplate_query_formats(const AVFilterContext *ctx, | |
| 2256 | AVFilterFormatsConfig **cfg_in, | ||
| 2257 | AVFilterFormatsConfig **cfg_out) | ||
| 2258 | { | ||
| 2259 | int ret; | ||
| 2260 | ✗ | if ((ret = ff_set_common_color_ranges2(ctx, cfg_in, cfg_out, | |
| 2261 | ff_make_formats_list_singleton(AVCOL_RANGE_JPEG)))) | ||
| 2262 | ✗ | return ret; | |
| 2263 | ✗ | return ff_set_pixel_formats_from_list2(ctx, cfg_in, cfg_out, zoneplate_pix_fmts); | |
| 2264 | } | ||
| 2265 | |||
| 2266 | static const AVFilterPad avfilter_vsrc_zoneplate_outputs[] = { | ||
| 2267 | { | ||
| 2268 | .name = "default", | ||
| 2269 | .type = AVMEDIA_TYPE_VIDEO, | ||
| 2270 | .config_props = zoneplate_config_props, | ||
| 2271 | }, | ||
| 2272 | }; | ||
| 2273 | |||
| 2274 | const FFFilter ff_vsrc_zoneplate = { | ||
| 2275 | .p.name = "zoneplate", | ||
| 2276 | .p.description = NULL_IF_CONFIG_SMALL("Generate zone-plate."), | ||
| 2277 | .p.priv_class = &zoneplate_class, | ||
| 2278 | .p.flags = AVFILTER_FLAG_SLICE_THREADS, | ||
| 2279 | .priv_size = sizeof(TestSourceContext), | ||
| 2280 | .init = init, | ||
| 2281 | .uninit = uninit, | ||
| 2282 | .activate = activate, | ||
| 2283 | FILTER_OUTPUTS(avfilter_vsrc_zoneplate_outputs), | ||
| 2284 | FILTER_QUERY_FUNC2(zoneplate_query_formats), | ||
| 2285 | .process_command = ff_filter_process_command, | ||
| 2286 | }; | ||
| 2287 | |||
| 2288 | #endif /* CONFIG_ZONEPLATE_FILTER */ | ||
| 2289 |