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