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