FFmpeg
Loading...
Searching...
No Matches
vf_lut2.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 Paul B Mahol
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config_components.h"
22
24#include "libavutil/common.h"
25#include "libavutil/eval.h"
26#include "libavutil/mem.h"
27#include "libavutil/opt.h"
28#include "libavutil/pixdesc.h"
29#include "avfilter.h"
30#include "filters.h"
31#include "formats.h"
32#include "video.h"
33#include "framesync.h"
34
35static const char *const var_names[] = {
36 "w", ///< width of the input video
37 "h", ///< height of the input video
38 "x", ///< input value for the pixel from input #1
39 "y", ///< input value for the pixel from input #2
40 "bdx", ///< input #1 video bitdepth
41 "bdy", ///< input #2 video bitdepth
42 NULL
43};
44
54
55typedef struct LUT2Context {
56 const AVClass *class;
58
59 int odepth;
60 char *comp_expr_str[4];
61
64 uint16_t *lut[4]; ///< lookup table for each component
65 int width[4], height[4];
66 int widthx[4], heightx[4];
67 int widthy[4], heighty[4];
72 int tlut2;
73 AVFrame *prev_frame; /* only used with tlut2 */
74
75 int (*lut2)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
77
78typedef struct ThreadData {
81
82#define OFFSET(x) offsetof(LUT2Context, x)
83#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
84#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
85
86static const AVOption options[] = {
87 { "c0", "set component #0 expression", OFFSET(comp_expr_str[0]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS },
88 { "c1", "set component #1 expression", OFFSET(comp_expr_str[1]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS },
89 { "c2", "set component #2 expression", OFFSET(comp_expr_str[2]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS },
90 { "c3", "set component #3 expression", OFFSET(comp_expr_str[3]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS },
91 { "d", "set output depth", OFFSET(odepth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 16, .flags = FLAGS },
92 { NULL }
93};
94
96{
97 LUT2Context *s = ctx->priv;
98 int i;
99
101 av_frame_free(&s->prev_frame);
102
103 for (i = 0; i < 4; i++) {
104 av_expr_free(s->comp_expr[i]);
105 s->comp_expr[i] = NULL;
106 av_freep(&s->comp_expr_str[i]);
107 av_freep(&s->lut[i]);
108 }
109}
110
111#define BIT8_FMTS \
112 AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, \
113 AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, \
114 AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV420P, \
115 AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, \
116 AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, \
117 AV_PIX_FMT_GRAY8, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
118
119#define BIT9_FMTS \
120 AV_PIX_FMT_GBRP9, AV_PIX_FMT_GRAY9, \
121 AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, \
122 AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9,
123
124#define BIT10_FMTS \
125 AV_PIX_FMT_GRAY10, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, \
126 AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, \
127 AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10,
128
129#define BIT12_FMTS \
130 AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, \
131 AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, \
132 AV_PIX_FMT_GRAY12, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRP12,
133
134#define BIT14_FMTS \
135 AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, \
136 AV_PIX_FMT_GRAY14, AV_PIX_FMT_GBRP14,
137
138#define BIT16_FMTS \
139 AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, \
140 AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, \
141 AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_GRAY16,
142
144 AVFilterFormatsConfig **cfg_in,
145 AVFilterFormatsConfig **cfg_out)
146{
147 const LUT2Context *s = ctx->priv;
148 static const enum AVPixelFormat all_pix_fmts[] = {
154 };
155 static const enum AVPixelFormat bit8_pix_fmts[] = {
158 };
159 static const enum AVPixelFormat bit9_pix_fmts[] = {
162 };
163 static const enum AVPixelFormat bit10_pix_fmts[] = {
166 };
167 static const enum AVPixelFormat bit12_pix_fmts[] = {
170 };
171 static const enum AVPixelFormat bit14_pix_fmts[] = {
174 };
175 static const enum AVPixelFormat bit16_pix_fmts[] = {
178 };
179 const enum AVPixelFormat *pix_fmts;
180 int ret;
181
182 if (s->tlut2 || !s->odepth)
183 return ff_set_pixel_formats_from_list2(ctx, cfg_in, cfg_out, all_pix_fmts);
184
186 if (ret < 0)
187 return ret;
188
189 switch (s->odepth) {
190 case 8: pix_fmts = bit8_pix_fmts; break;
191 case 9: pix_fmts = bit9_pix_fmts; break;
192 case 10: pix_fmts = bit10_pix_fmts; break;
193 case 12: pix_fmts = bit12_pix_fmts; break;
194 case 14: pix_fmts = bit14_pix_fmts; break;
195 case 16: pix_fmts = bit16_pix_fmts; break;
196 default: av_assert0(0);
197 }
198
200}
201
202static int config_inputx(AVFilterLink *inlink)
203{
204 AVFilterContext *ctx = inlink->dst;
205 LUT2Context *s = ctx->priv;
207 int hsub = desc->log2_chroma_w;
208 int vsub = desc->log2_chroma_h;
209
210 s->nb_planesx = av_pix_fmt_count_planes(inlink->format);
211 s->heightx[1] = s->heightx[2] = AV_CEIL_RSHIFT(inlink->h, vsub);
212 s->heightx[0] = s->heightx[3] = inlink->h;
213 s->widthx[1] = s->widthx[2] = AV_CEIL_RSHIFT(inlink->w, hsub);
214 s->widthx[0] = s->widthx[3] = inlink->w;
215
216 s->var_values[VAR_W] = inlink->w;
217 s->var_values[VAR_H] = inlink->h;
218 s->depthx = desc->comp[0].depth;
219 s->var_values[VAR_BITDEPTHX] = s->depthx;
220
221 if (s->tlut2) {
222 s->depthy = desc->comp[0].depth;
223 s->var_values[VAR_BITDEPTHY] = s->depthy;
224 }
225
226 return 0;
227}
228
229static int config_inputy(AVFilterLink *inlink)
230{
231 AVFilterContext *ctx = inlink->dst;
232 LUT2Context *s = ctx->priv;
234 int hsub = desc->log2_chroma_w;
235 int vsub = desc->log2_chroma_h;
236
237 s->nb_planesy = av_pix_fmt_count_planes(inlink->format);
238 s->depthy = desc->comp[0].depth;
239 s->var_values[VAR_BITDEPTHY] = s->depthy;
240 s->heighty[1] = s->heighty[2] = AV_CEIL_RSHIFT(inlink->h, vsub);
241 s->heighty[0] = s->heighty[3] = inlink->h;
242 s->widthy[1] = s->widthy[2] = AV_CEIL_RSHIFT(inlink->w, hsub);
243 s->widthy[0] = s->widthy[3] = inlink->w;
244
245 return 0;
246}
247
248#define DEFINE_LUT2(zname, xname, yname, ztype, xtype, ytype, zdiv, xdiv, ydiv) \
249static int lut2_##zname##_##xname##_##yname(AVFilterContext *ctx, \
250 void *arg, \
251 int jobnr, int nb_jobs) \
252{ \
253 LUT2Context *s = ctx->priv; \
254 ThreadData *td = arg; \
255 AVFrame *out = td->out; \
256 AVFrame *srcx = td->srcx; \
257 AVFrame *srcy = td->srcy; \
258 const int odepth = s->odepth; \
259 int p, y, x; \
260 \
261 for (p = 0; p < s->nb_planes; p++) { \
262 const int slice_start = ff_slice_pos(s->heightx[p], jobnr, nb_jobs); \
263 const int slice_end = ff_slice_pos(s->heightx[p], jobnr + 1, nb_jobs); \
264 const uint16_t *lut = s->lut[p]; \
265 const xtype *srcxx; \
266 const ytype *srcyy; \
267 ztype *dst; \
268 \
269 dst = (ztype *)(out->data[p] + slice_start * out->linesize[p]); \
270 srcxx = (const xtype *)(srcx->data[p] + slice_start * srcx->linesize[p]);\
271 srcyy = (const ytype *)(srcy->data[p] + slice_start * srcy->linesize[p]);\
272 \
273 for (y = slice_start; y < slice_end; y++) { \
274 for (x = 0; x < s->widthx[p]; x++) { \
275 dst[x] = av_clip_uintp2_c(lut[(srcyy[x] << s->depthx) | srcxx[x]], odepth); \
276 } \
277 \
278 dst += out->linesize[p] / zdiv; \
279 srcxx += srcx->linesize[p] / xdiv; \
280 srcyy += srcy->linesize[p] / ydiv; \
281 } \
282 } \
283 return 0; \
284}
285
286DEFINE_LUT2(8, 8, 8, uint8_t, uint8_t, uint8_t, 1, 1, 1)
287DEFINE_LUT2(8, 8, 16, uint8_t, uint8_t, uint16_t, 1, 1, 2)
288DEFINE_LUT2(8, 16, 8, uint8_t, uint16_t, uint8_t, 1, 2, 1)
289DEFINE_LUT2(8, 16, 16, uint8_t, uint16_t, uint16_t, 1, 2, 2)
290DEFINE_LUT2(16, 8, 8, uint16_t, uint8_t, uint8_t, 2, 1, 1)
291DEFINE_LUT2(16, 8, 16, uint16_t, uint8_t, uint16_t, 2, 1, 2)
292DEFINE_LUT2(16, 16, 8, uint16_t, uint16_t, uint8_t, 2, 2, 1)
293DEFINE_LUT2(16, 16, 16, uint16_t, uint16_t, uint16_t, 2, 2, 2)
294
296{
297 AVFilterContext *ctx = fs->parent;
298 LUT2Context *s = fs->opaque;
299 AVFilterLink *outlink = ctx->outputs[0];
300 AVFrame *out, *srcx = NULL, *srcy = NULL;
301 int ret;
302
303 if ((ret = ff_framesync_get_frame(&s->fs, 0, &srcx, 0)) < 0 ||
304 (ret = ff_framesync_get_frame(&s->fs, 1, &srcy, 0)) < 0)
305 return ret;
306
307 if (ctx->is_disabled || !srcy) {
308 out = av_frame_clone(srcx);
309 if (!out)
310 return AVERROR(ENOMEM);
311 } else {
312 ThreadData td;
313
314 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
315 if (!out)
316 return AVERROR(ENOMEM);
317 av_frame_copy_props(out, srcx);
318
319 td.out = out;
320 td.srcx = srcx;
321 td.srcy = srcy;
322 ff_filter_execute(ctx, s->lut2, &td, NULL,
323 FFMIN(s->heightx[1], ff_filter_get_nb_threads(ctx)));
324 }
325
326 out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base);
327
328 return ff_filter_frame(outlink, out);
329}
330
331static int config_output(AVFilterLink *outlink)
332{
333 AVFilterContext *ctx = outlink->src;
334 LUT2Context *s = ctx->priv;
335 int p, ret;
336
337 s->depth = s->depthx + s->depthy;
338 s->nb_planes = s->nb_planesx;
339
340 s->lut2 = s->depth > 16 ? lut2_16_16_16 : lut2_8_8_8;
341 if (s->odepth) {
342 if (s->depthx == 8 && s->depthy == 8 && s->odepth > 8)
343 s->lut2 = lut2_16_8_8;
344 if (s->depthx > 8 && s->depthy == 8 && s->odepth > 8)
345 s->lut2 = lut2_16_16_8;
346 if (s->depthx == 8 && s->depthy > 8 && s->odepth > 8)
347 s->lut2 = lut2_16_8_16;
348 if (s->depthx == 8 && s->depthy == 8 && s->odepth == 8)
349 s->lut2 = lut2_8_8_8;
350 if (s->depthx > 8 && s->depthy == 8 && s->odepth == 8)
351 s->lut2 = lut2_8_16_8;
352 if (s->depthx == 8 && s->depthy > 8 && s->odepth == 8)
353 s->lut2 = lut2_8_8_16;
354 if (s->depthx > 8 && s->depthy > 8 && s->odepth == 8)
355 s->lut2 = lut2_8_16_16;
356 } else {
357 s->odepth = s->depthx;
358 }
359
360 for (p = 0; p < s->nb_planes; p++) {
361 if (!s->lut[p])
362 s->lut[p] = av_malloc_array(1 << s->depth, sizeof(uint16_t));
363 if (!s->lut[p])
364 return AVERROR(ENOMEM);
365 }
366
367 for (p = 0; p < s->nb_planes; p++) {
368 double res;
369 int x, y;
370
371 /* create the parsed expression */
372 av_expr_free(s->comp_expr[p]);
373 s->comp_expr[p] = NULL;
374 ret = av_expr_parse(&s->comp_expr[p], s->comp_expr_str[p],
375 var_names, NULL, NULL, NULL, NULL, 0, ctx);
376 if (ret < 0) {
378 "Error when parsing the expression '%s' for the component %d.\n",
379 s->comp_expr_str[p], p);
380 return AVERROR(EINVAL);
381 }
382
383 /* compute the lut */
384 for (y = 0; y < (1 << s->depthy); y++) {
385 s->var_values[VAR_Y] = y;
386 for (x = 0; x < (1 << s->depthx); x++) {
387 s->var_values[VAR_X] = x;
388 res = av_expr_eval(s->comp_expr[p], s->var_values, s);
389 if (isnan(res)) {
391 "Error when evaluating the expression '%s' for the values %d and %d for the component %d.\n",
392 s->comp_expr_str[p], x, y, p);
393 return AVERROR(EINVAL);
394 }
395
396 s->lut[p][(y << s->depthx) + x] = res;
397 }
398 }
399 }
400
401 return 0;
402}
403
405{
406 AVFilterContext *ctx = outlink->src;
407 LUT2Context *s = ctx->priv;
408 AVFilterLink *srcx = ctx->inputs[0];
409 AVFilterLink *srcy = ctx->inputs[1];
410 FilterLink *il = ff_filter_link(srcx);
411 FilterLink *ol = ff_filter_link(outlink);
412 FFFrameSyncIn *in;
414 int hsub = desc->log2_chroma_w;
415 int vsub = desc->log2_chroma_h;
416 int ret;
417
418 outlink->w = srcx->w;
419 outlink->h = srcx->h;
420 outlink->time_base = srcx->time_base;
422 ol->frame_rate = il->frame_rate;
423
424 s->nb_planes = av_pix_fmt_count_planes(outlink->format);
425 s->height[1] = s->height[2] = AV_CEIL_RSHIFT(outlink->h, vsub);
426 s->height[0] = s->height[3] = outlink->h;
427 s->width[1] = s->width[2] = AV_CEIL_RSHIFT(outlink->w, hsub);
428 s->width[0] = s->width[3] = outlink->w;
429
430 if (!s->odepth && srcx->format != srcy->format) {
431 av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n");
432 return AVERROR(EINVAL);
433 }
434
435 if (srcx->w != srcy->w || srcx->h != srcy->h) {
436 av_log(ctx, AV_LOG_ERROR, "First input link %s parameters "
437 "(size %dx%d) do not match the corresponding "
438 "second input link %s parameters (size %dx%d)\n",
439 ctx->input_pads[0].name, srcx->w, srcx->h,
440 ctx->input_pads[1].name,
441 srcy->w, srcy->h);
442 return AVERROR(EINVAL);
443 }
444
445 if (s->nb_planesx != s->nb_planesy) {
446 av_log(ctx, AV_LOG_ERROR, "First input link %s number of planes "
447 "(%d) do not match the corresponding "
448 "second input link %s number of planes (%d)\n",
449 ctx->input_pads[0].name, s->nb_planesx,
450 ctx->input_pads[1].name, s->nb_planesy);
451 return AVERROR(EINVAL);
452 }
453
454 if (s->nb_planesx != s->nb_planes) {
455 av_log(ctx, AV_LOG_ERROR, "First input link %s number of planes "
456 "(%d) do not match the corresponding "
457 "output link %s number of planes (%d)\n",
458 ctx->input_pads[0].name, s->nb_planesx,
459 ctx->output_pads[0].name, s->nb_planes);
460 return AVERROR(EINVAL);
461 }
462
463 if (s->widthx[1] != s->widthy[1] || s->heightx[1] != s->heighty[1]) {
464 av_log(ctx, AV_LOG_ERROR, "First input link %s 2nd plane "
465 "(size %dx%d) do not match the corresponding "
466 "second input link %s 2nd plane (size %dx%d)\n",
467 ctx->input_pads[0].name, s->widthx[1], s->heightx[1],
468 ctx->input_pads[1].name,
469 s->widthy[1], s->heighty[1]);
470 return AVERROR(EINVAL);
471 }
472
473 if (s->widthx[2] != s->widthy[2] || s->heightx[2] != s->heighty[2]) {
474 av_log(ctx, AV_LOG_ERROR, "First input link %s 3rd plane "
475 "(size %dx%d) do not match the corresponding "
476 "second input link %s 3rd plane (size %dx%d)\n",
477 ctx->input_pads[0].name, s->widthx[2], s->heightx[2],
478 ctx->input_pads[1].name,
479 s->widthy[2], s->heighty[2]);
480 return AVERROR(EINVAL);
481 }
482
483 if (s->widthx[1] != s->width[1] || s->heightx[1] != s->height[1]) {
484 av_log(ctx, AV_LOG_ERROR, "First input link %s 2nd plane "
485 "(size %dx%d) do not match the corresponding "
486 "output link %s 2nd plane (size %dx%d)\n",
487 ctx->input_pads[0].name, s->widthx[1], s->heightx[1],
488 ctx->output_pads[0].name, s->width[1], s->height[1]);
489 return AVERROR(EINVAL);
490 }
491
492 if (s->widthx[2] != s->width[2] || s->heightx[2] != s->height[2]) {
493 av_log(ctx, AV_LOG_ERROR, "First input link %s 3rd plane "
494 "(size %dx%d) do not match the corresponding "
495 "output link %s 3rd plane (size %dx%d)\n",
496 ctx->input_pads[0].name, s->widthx[2], s->heightx[2],
497 ctx->output_pads[0].name, s->width[2], s->height[2]);
498 return AVERROR(EINVAL);
499 }
500
501 if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
502 return ret;
503
504 in = s->fs.in;
505 in[0].time_base = srcx->time_base;
506 in[1].time_base = srcy->time_base;
507 in[0].sync = 2;
508 in[0].before = EXT_STOP;
509 in[0].after = EXT_INFINITY;
510 in[1].sync = 1;
511 in[1].before = EXT_STOP;
512 in[1].after = EXT_INFINITY;
513 s->fs.opaque = s;
514 s->fs.on_event = process_frame;
515
516 if ((ret = config_output(outlink)) < 0)
517 return ret;
518
519 ret = ff_framesync_configure(&s->fs);
520 outlink->time_base = s->fs.time_base;
521
522 return ret;
523}
524
526{
527 LUT2Context *s = ctx->priv;
528 return ff_framesync_activate(&s->fs);
529}
530
531static const AVFilterPad inputs[] = {
532 {
533 .name = "srcx",
534 .type = AVMEDIA_TYPE_VIDEO,
535 .config_props = config_inputx,
536 },
537 {
538 .name = "srcy",
539 .type = AVMEDIA_TYPE_VIDEO,
540 .config_props = config_inputy,
541 },
542};
543
544static const AVFilterPad outputs[] = {
545 {
546 .name = "default",
547 .type = AVMEDIA_TYPE_VIDEO,
548 .config_props = lut2_config_output,
549 },
550};
551
552static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
553 char *res, int res_len, int flags)
554{
555 int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
556
557 if (ret < 0)
558 return ret;
559
560 return config_output(ctx->outputs[0]);
561}
562
563#define lut2_options options
564
566
568 .p.name = "lut2",
569 .p.description = NULL_IF_CONFIG_SMALL("Compute and apply a lookup table from two video inputs."),
570 .p.priv_class = &lut2_class,
573 .preinit = lut2_framesync_preinit,
574 .priv_size = sizeof(LUT2Context),
575 .uninit = uninit,
580 .process_command = process_command,
581};
582
583#if CONFIG_TLUT2_FILTER
584
585static av_cold int init(AVFilterContext *ctx)
586{
587 LUT2Context *s = ctx->priv;
588
589 s->tlut2 = !strcmp(ctx->filter->name, "tlut2");
590
591 if (!(s->odepth == 0 || s->odepth == 8 || s->odepth == 9 || s->odepth == 10 ||
592 s->odepth == 12 || s->odepth == 14 || s->odepth == 16)) {
593 av_log(ctx, AV_LOG_ERROR, "Unsupported output bit depth %d.\n", s->odepth);
594 return AVERROR(EINVAL);
595 }
596
597 return 0;
598}
599
600static int tlut2_filter_frame(AVFilterLink *inlink, AVFrame *frame)
601{
602 AVFilterContext *ctx = inlink->dst;
603 LUT2Context *s = ctx->priv;
604 AVFilterLink *outlink = ctx->outputs[0];
605
606 if (s->prev_frame) {
607 AVFrame *out;
608
609 if (ctx->is_disabled) {
611 } else {
612 ThreadData td;
613
614 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
615 if (!out) {
616 av_frame_free(&s->prev_frame);
617 s->prev_frame = frame;
618 return AVERROR(ENOMEM);
619 }
620
622 av_frame_side_data_remove_by_props(&out->side_data, &out->nb_side_data,
624
625 td.out = out;
626 td.srcx = frame;
627 td.srcy = s->prev_frame;
628 ff_filter_execute(ctx, s->lut2, &td, NULL,
629 FFMIN(s->heightx[1], ff_filter_get_nb_threads(ctx)));
630 }
631 av_frame_free(&s->prev_frame);
632 s->prev_frame = frame;
633 return ff_filter_frame(outlink, out);
634 }
635 s->prev_frame = frame;
636 return 0;
637}
638
639static const AVOption tlut2_options[] = {
640 { "c0", "set component #0 expression", OFFSET(comp_expr_str[0]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS },
641 { "c1", "set component #1 expression", OFFSET(comp_expr_str[1]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS },
642 { "c2", "set component #2 expression", OFFSET(comp_expr_str[2]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS },
643 { "c3", "set component #3 expression", OFFSET(comp_expr_str[3]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS },
644 { NULL }
645};
646
648
649static const AVFilterPad tlut2_inputs[] = {
650 {
651 .name = "default",
652 .type = AVMEDIA_TYPE_VIDEO,
653 .filter_frame = tlut2_filter_frame,
654 .config_props = config_inputx,
655 },
656};
657
658static const AVFilterPad tlut2_outputs[] = {
659 {
660 .name = "default",
661 .type = AVMEDIA_TYPE_VIDEO,
662 .config_props = config_output,
663 },
664};
665
666const FFFilter ff_vf_tlut2 = {
667 .p.name = "tlut2",
668 .p.description = NULL_IF_CONFIG_SMALL("Compute and apply a lookup table from two successive frames."),
669 .p.priv_class = &tlut2_class,
672 .priv_size = sizeof(LUT2Context),
673 .init = init,
674 .uninit = uninit,
675 FILTER_INPUTS(tlut2_inputs),
676 FILTER_OUTPUTS(tlut2_outputs),
678 .process_command = process_command,
679};
680
681#endif
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition aeval.c:246
static const AVFilterPad inputs[]
Definition af_aap.c:299
static const AVFilterPad outputs[]
Definition af_aap.c:310
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
#define TFLAGS
Definition af_afade.c:66
const FFFilter ff_vf_tlut2
const FFFilter ff_vf_lut2
Definition vf_lut2.c:567
static FILE * out
static AVFormatContext * ctx
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
@ VAR_H
Definition avfilter.c:565
@ VAR_W
Definition avfilter.c:564
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
Definition avfilter.c:906
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition avfilter.c:1696
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition avfilter.c:846
Main libavfilter public API header.
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define fs(width, name, subs,...)
Definition cbs_vp9.c:200
#define FLAGS
Definition cmdutils.c:598
common internal and external API header
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
#define NULL
Definition coverity.c:32
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition eval.c:368
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition eval.c:824
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
Definition eval.c:735
simple arithmetic expression evaluator
static av_always_inline int process_frame(AVTextFormatContext *tfc, InputFile *ifile, AVFrame *frame, const AVPacket *pkt, int *packet_new)
Definition ffprobe.c:1596
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add ref as a new reference to formats.
Definition formats.c:756
int ff_set_pixel_formats_from_list2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, const enum AVPixelFormat *fmts)
Definition formats.c:1162
av_warn_unused_result AVFilterFormats * ff_make_pixel_format_list(const enum AVPixelFormat *fmts)
Create a list of supported pixel formats.
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition framesync.c:137
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
Definition framesync.c:352
int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, unsigned get)
Get the current frame in an input.
Definition framesync.c:269
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition framesync.c:301
int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in)
Initialize a frame sync structure.
Definition framesync.c:86
#define FRAMESYNC_DEFINE_CLASS(name, context, field)
Definition framesync.h:352
@ EXT_INFINITY
Extend the frame to infinity.
Definition framesync.h:75
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition avfilter.h:166
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will have its filter_frame() c...
Definition avfilter.h:204
#define AVERROR(e)
Definition error.h:45
void av_frame_side_data_remove_by_props(AVFrameSideData ***sd, int *nb_sd, int props)
Remove and free all side data instances that match any of the given side data properties.
Definition side_data.c:123
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition frame.c:599
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition frame.c:483
@ AV_SIDE_DATA_PROP_COLOR_DEPENDENT
Side data depends on the video color space.
Definition frame.h:361
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
if(svq3)
static enum AVPixelFormat all_pix_fmts[]
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
static int config_output(AVBitStreamFilterLink *outlink)
const char * arg
Definition jacosubdec.c:65
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define FILTER_QUERY_FUNC2(func)
Definition filters.h:241
@ VAR_X
Definition vf_blend.c:55
@ VAR_Y
Definition vf_blend.c:55
Macro definitions for various function/variable attributes.
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
static enum AVPixelFormat pix_fmts[]
Definition libkvazaar.c:296
#define isnan(x)
Definition libm.h:342
const char * desc
Definition libsvtav1.c:83
#define FFMIN(a, b)
Definition macros.h:49
Memory handling functions.
var_name
Definition noise.c:46
@ VAR_VARS_NB
Definition noise.c:59
static const char *const var_names[]
Definition noise.c:30
AVOptions.
@ EXT_STOP
Completely stop all streams with this one.
Definition packetsync.h:62
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3500
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
formats
Definition signature.h:47
Describe the class of an AVClass context structure.
Definition log.h:76
Definition eval.c:171
An instance of a filter.
Definition avfilter.h:273
Lists of formats / etc.
Definition avfilter.h:120
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
AVOption.
Definition opt.h:428
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
Input stream structure.
Definition framesync.h:102
enum FFFrameSyncExtMode after
Extrapolation mode for timestamps after the last frame.
Definition framesync.h:112
enum FFFrameSyncExtMode before
Extrapolation mode for timestamps before the first frame.
Definition framesync.h:107
AVRational time_base
Time base for the incoming frames.
Definition framesync.h:117
unsigned sync
Synchronization level: frames on input at the highest sync level will generate output frame events.
Definition framesync.h:160
Frame sync structure.
Definition framesync.h:168
double var_values[VAR_VARS_NB]
Definition vf_lut2.c:63
int widthx[4]
Definition vf_lut2.c:66
char * comp_expr_str[4]
Definition vf_lut2.c:60
int tlut2
Definition vf_lut2.c:72
int widthy[4]
Definition vf_lut2.c:67
int heighty[4]
Definition vf_lut2.c:67
uint16_t * lut[4]
lookup table for each component
Definition vf_lut2.c:64
int height[4]
Definition vf_lut2.c:65
int(* lut2)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition vf_lut2.c:75
int nb_planesy
Definition vf_lut2.c:69
int width[4]
Definition vf_lut2.c:65
int depthx
Definition vf_lut2.c:71
int nb_planes
Definition vf_lut2.c:70
int nb_planesx
Definition vf_lut2.c:68
FFFrameSync fs
Definition vf_lut2.c:57
AVFrame * prev_frame
Definition vf_lut2.c:73
int depth
Definition vf_lut2.c:71
int odepth
Definition vf_lut2.c:59
int heightx[4]
Definition vf_lut2.c:66
AVExpr * comp_expr[4]
Definition vf_lut2.c:62
int depthy
Definition vf_lut2.c:71
Used for passing data between threads.
Definition dsddec.c:71
AVFrame * srcy
Definition vf_lut2.c:79
AVFrame * srcx
Definition vf_lut2.c:79
AVFrame * out
#define av_malloc_array(a, b)
#define av_freep(p)
#define av_log(a,...)
@ VAR_BITDEPTHY
Definition vf_lut2.c:51
@ VAR_VARS_NB
Definition vf_lut2.c:52
@ VAR_BITDEPTHX
Definition vf_lut2.c:50
static int lut2_config_output(AVFilterLink *outlink)
Definition vf_lut2.c:404
#define BIT8_FMTS
Definition vf_lut2.c:111
static int config_inputx(AVFilterLink *inlink)
Definition vf_lut2.c:202
#define DEFINE_LUT2(zname, xname, yname, ztype, xtype, ytype, zdiv, xdiv, ydiv)
Definition vf_lut2.c:248
static int config_inputy(AVFilterLink *inlink)
Definition vf_lut2.c:229
#define BIT14_FMTS
Definition vf_lut2.c:134
#define BIT16_FMTS
Definition vf_lut2.c:138
#define BIT10_FMTS
Definition vf_lut2.c:124
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition vf_lut2.c:143
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition vf_lut2.c:552
static int activate(AVFilterContext *ctx)
Definition vf_lut2.c:525
static av_cold void uninit(AVFilterContext *ctx)
Definition vf_lut2.c:95
#define BIT12_FMTS
Definition vf_lut2.c:129
#define BIT9_FMTS
Definition vf_lut2.c:119
#define OFFSET(x)
Definition vf_lut2.c:82
static int config_output(AVFilterLink *outlink)
Definition vf_lut2.c:331
static void hsub(htype *dst, const htype *src, int bins)
Definition vf_median.c:74
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition video.c:89