FFmpeg  4.4.4
vf_curves.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Clément Bœsch
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 "libavutil/opt.h"
22 #include "libavutil/bprint.h"
23 #include "libavutil/eval.h"
24 #include "libavutil/file.h"
25 #include "libavutil/intreadwrite.h"
26 #include "libavutil/avassert.h"
27 #include "libavutil/pixdesc.h"
28 #include "avfilter.h"
29 #include "drawutils.h"
30 #include "formats.h"
31 #include "internal.h"
32 #include "video.h"
33 
34 #define R 0
35 #define G 1
36 #define B 2
37 #define A 3
38 
39 struct keypoint {
40  double x, y;
41  struct keypoint *next;
42 };
43 
44 #define NB_COMP 3
45 
46 enum preset {
59 };
60 
61 typedef struct CurvesContext {
62  const AVClass *class;
63  int preset;
66  uint16_t *graph[NB_COMP + 1];
67  int lut_size;
68  char *psfile;
70  int step;
73  int is_16bit;
74  int depth;
76 
77  int (*filter_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
79 
80 typedef struct ThreadData {
81  AVFrame *in, *out;
82 } ThreadData;
83 
84 #define OFFSET(x) offsetof(CurvesContext, x)
85 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
86 static const AVOption curves_options[] = {
87  { "preset", "select a color curves preset", OFFSET(preset), AV_OPT_TYPE_INT, {.i64=PRESET_NONE}, PRESET_NONE, NB_PRESETS-1, FLAGS, "preset_name" },
88  { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_NONE}, 0, 0, FLAGS, "preset_name" },
89  { "color_negative", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_COLOR_NEGATIVE}, 0, 0, FLAGS, "preset_name" },
90  { "cross_process", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_CROSS_PROCESS}, 0, 0, FLAGS, "preset_name" },
91  { "darker", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_DARKER}, 0, 0, FLAGS, "preset_name" },
92  { "increase_contrast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_INCREASE_CONTRAST}, 0, 0, FLAGS, "preset_name" },
93  { "lighter", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_LIGHTER}, 0, 0, FLAGS, "preset_name" },
94  { "linear_contrast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_LINEAR_CONTRAST}, 0, 0, FLAGS, "preset_name" },
95  { "medium_contrast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_MEDIUM_CONTRAST}, 0, 0, FLAGS, "preset_name" },
96  { "negative", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_NEGATIVE}, 0, 0, FLAGS, "preset_name" },
97  { "strong_contrast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_STRONG_CONTRAST}, 0, 0, FLAGS, "preset_name" },
98  { "vintage", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_VINTAGE}, 0, 0, FLAGS, "preset_name" },
99  { "master","set master points coordinates",OFFSET(comp_points_str[NB_COMP]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
100  { "m", "set master points coordinates",OFFSET(comp_points_str[NB_COMP]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
101  { "red", "set red points coordinates", OFFSET(comp_points_str[0]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
102  { "r", "set red points coordinates", OFFSET(comp_points_str[0]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
103  { "green", "set green points coordinates", OFFSET(comp_points_str[1]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
104  { "g", "set green points coordinates", OFFSET(comp_points_str[1]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
105  { "blue", "set blue points coordinates", OFFSET(comp_points_str[2]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
106  { "b", "set blue points coordinates", OFFSET(comp_points_str[2]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
107  { "all", "set points coordinates for all components", OFFSET(comp_points_str_all), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
108  { "psfile", "set Photoshop curves file name", OFFSET(psfile), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
109  { "plot", "save Gnuplot script of the curves in specified file", OFFSET(plot_filename), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
110  { NULL }
111 };
112 
114 
115 static const struct {
116  const char *r;
117  const char *g;
118  const char *b;
119  const char *master;
120 } curves_presets[] = {
122  "0.129/1 0.466/0.498 0.725/0",
123  "0.109/1 0.301/0.498 0.517/0",
124  "0.098/1 0.235/0.498 0.423/0",
125  },
127  "0/0 0.25/0.156 0.501/0.501 0.686/0.745 1/1",
128  "0/0 0.25/0.188 0.38/0.501 0.745/0.815 1/0.815",
129  "0/0 0.231/0.094 0.709/0.874 1/1",
130  },
131  [PRESET_DARKER] = { .master = "0/0 0.5/0.4 1/1" },
132  [PRESET_INCREASE_CONTRAST] = { .master = "0/0 0.149/0.066 0.831/0.905 0.905/0.98 1/1" },
133  [PRESET_LIGHTER] = { .master = "0/0 0.4/0.5 1/1" },
134  [PRESET_LINEAR_CONTRAST] = { .master = "0/0 0.305/0.286 0.694/0.713 1/1" },
135  [PRESET_MEDIUM_CONTRAST] = { .master = "0/0 0.286/0.219 0.639/0.643 1/1" },
136  [PRESET_NEGATIVE] = { .master = "0/1 1/0" },
137  [PRESET_STRONG_CONTRAST] = { .master = "0/0 0.301/0.196 0.592/0.6 0.686/0.737 1/1" },
138  [PRESET_VINTAGE] = {
139  "0/0.11 0.42/0.51 1/0.95",
140  "0/0 0.50/0.48 1/1",
141  "0/0.22 0.49/0.44 1/0.8",
142  }
143 };
144 
145 static struct keypoint *make_point(double x, double y, struct keypoint *next)
146 {
147  struct keypoint *point = av_mallocz(sizeof(*point));
148 
149  if (!point)
150  return NULL;
151  point->x = x;
152  point->y = y;
153  point->next = next;
154  return point;
155 }
156 
157 static int parse_points_str(AVFilterContext *ctx, struct keypoint **points, const char *s,
158  int lut_size)
159 {
160  char *p = (char *)s; // strtod won't alter the string
161  struct keypoint *last = NULL;
162  const int scale = lut_size - 1;
163 
164  /* construct a linked list based on the key points string */
165  while (p && *p) {
166  struct keypoint *point = make_point(0, 0, NULL);
167  if (!point)
168  return AVERROR(ENOMEM);
169  point->x = av_strtod(p, &p); if (p && *p) p++;
170  point->y = av_strtod(p, &p); if (p && *p) p++;
171  if (point->x < 0 || point->x > 1 || point->y < 0 || point->y > 1) {
172  av_log(ctx, AV_LOG_ERROR, "Invalid key point coordinates (%f;%f), "
173  "x and y must be in the [0;1] range.\n", point->x, point->y);
174  return AVERROR(EINVAL);
175  }
176  if (!*points)
177  *points = point;
178  if (last) {
179  if ((int)(last->x * scale) >= (int)(point->x * scale)) {
180  av_log(ctx, AV_LOG_ERROR, "Key point coordinates (%f;%f) "
181  "and (%f;%f) are too close from each other or not "
182  "strictly increasing on the x-axis\n",
183  last->x, last->y, point->x, point->y);
184  return AVERROR(EINVAL);
185  }
186  last->next = point;
187  }
188  last = point;
189  }
190 
191  if (*points && !(*points)->next) {
192  av_log(ctx, AV_LOG_WARNING, "Only one point (at (%f;%f)) is defined, "
193  "this is unlikely to behave as you expect. You probably want"
194  "at least 2 points.",
195  (*points)->x, (*points)->y);
196  }
197 
198  return 0;
199 }
200 
201 static int get_nb_points(const struct keypoint *d)
202 {
203  int n = 0;
204  while (d) {
205  n++;
206  d = d->next;
207  }
208  return n;
209 }
210 
211 /**
212  * Natural cubic spline interpolation
213  * Finding curves using Cubic Splines notes by Steven Rauch and John Stockie.
214  * @see http://people.math.sfu.ca/~stockie/teaching/macm316/notes/splines.pdf
215  */
216 
217 #define CLIP(v) (nbits == 8 ? av_clip_uint8(v) : av_clip_uintp2_c(v, nbits))
218 
219 static inline int interpolate(void *log_ctx, uint16_t *y,
220  const struct keypoint *points, int nbits)
221 {
222  int i, ret = 0;
223  const struct keypoint *point = points;
224  double xprev = 0;
225  const int lut_size = 1<<nbits;
226  const int scale = lut_size - 1;
227 
228  double (*matrix)[3];
229  double *h, *r;
230  const int n = get_nb_points(points); // number of splines
231 
232  if (n == 0) {
233  for (i = 0; i < lut_size; i++)
234  y[i] = i;
235  return 0;
236  }
237 
238  if (n == 1) {
239  for (i = 0; i < lut_size; i++)
240  y[i] = CLIP(point->y * scale);
241  return 0;
242  }
243 
244  matrix = av_calloc(n, sizeof(*matrix));
245  h = av_malloc((n - 1) * sizeof(*h));
246  r = av_calloc(n, sizeof(*r));
247 
248  if (!matrix || !h || !r) {
249  ret = AVERROR(ENOMEM);
250  goto end;
251  }
252 
253  /* h(i) = x(i+1) - x(i) */
254  i = -1;
255  for (point = points; point; point = point->next) {
256  if (i != -1)
257  h[i] = point->x - xprev;
258  xprev = point->x;
259  i++;
260  }
261 
262  /* right-side of the polynomials, will be modified to contains the solution */
263  point = points;
264  for (i = 1; i < n - 1; i++) {
265  const double yp = point->y;
266  const double yc = point->next->y;
267  const double yn = point->next->next->y;
268  r[i] = 6 * ((yn-yc)/h[i] - (yc-yp)/h[i-1]);
269  point = point->next;
270  }
271 
272 #define BD 0 /* sub diagonal (below main) */
273 #define MD 1 /* main diagonal (center) */
274 #define AD 2 /* sup diagonal (above main) */
275 
276  /* left side of the polynomials into a tridiagonal matrix. */
277  matrix[0][MD] = matrix[n - 1][MD] = 1;
278  for (i = 1; i < n - 1; i++) {
279  matrix[i][BD] = h[i-1];
280  matrix[i][MD] = 2 * (h[i-1] + h[i]);
281  matrix[i][AD] = h[i];
282  }
283 
284  /* tridiagonal solving of the linear system */
285  for (i = 1; i < n; i++) {
286  const double den = matrix[i][MD] - matrix[i][BD] * matrix[i-1][AD];
287  const double k = den ? 1./den : 1.;
288  matrix[i][AD] *= k;
289  r[i] = (r[i] - matrix[i][BD] * r[i - 1]) * k;
290  }
291  for (i = n - 2; i >= 0; i--)
292  r[i] = r[i] - matrix[i][AD] * r[i + 1];
293 
294  point = points;
295 
296  /* left padding */
297  for (i = 0; i < (int)(point->x * scale); i++)
298  y[i] = CLIP(point->y * scale);
299 
300  /* compute the graph with x=[x0..xN] */
301  i = 0;
302  av_assert0(point->next); // always at least 2 key points
303  while (point->next) {
304  const double yc = point->y;
305  const double yn = point->next->y;
306 
307  const double a = yc;
308  const double b = (yn-yc)/h[i] - h[i]*r[i]/2. - h[i]*(r[i+1]-r[i])/6.;
309  const double c = r[i] / 2.;
310  const double d = (r[i+1] - r[i]) / (6.*h[i]);
311 
312  int x;
313  const int x_start = point->x * scale;
314  const int x_end = point->next->x * scale;
315 
316  av_assert0(x_start >= 0 && x_start < lut_size &&
317  x_end >= 0 && x_end < lut_size);
318 
319  for (x = x_start; x <= x_end; x++) {
320  const double xx = (x - x_start) * 1./scale;
321  const double yy = a + b*xx + c*xx*xx + d*xx*xx*xx;
322  y[x] = CLIP(yy * scale);
323  av_log(log_ctx, AV_LOG_DEBUG, "f(%f)=%f -> y[%d]=%d\n", xx, yy, x, y[x]);
324  }
325 
326  point = point->next;
327  i++;
328  }
329 
330  /* right padding */
331  for (i = (int)(point->x * scale); i < lut_size; i++)
332  y[i] = CLIP(point->y * scale);
333 
334 end:
335  av_free(matrix);
336  av_free(h);
337  av_free(r);
338  return ret;
339 }
340 
341 #define DECLARE_INTERPOLATE_FUNC(nbits) \
342 static int interpolate##nbits(void *log_ctx, uint16_t *y, \
343  const struct keypoint *points) \
344 { \
345  return interpolate(log_ctx, y, points, nbits); \
346 }
347 
354 
355 static int parse_psfile(AVFilterContext *ctx, const char *fname)
356 {
357  CurvesContext *curves = ctx->priv;
358  uint8_t *buf;
359  size_t size;
360  int i, ret, av_unused(version), nb_curves;
361  AVBPrint ptstr;
362  static const int comp_ids[] = {3, 0, 1, 2};
363 
365 
366  ret = av_file_map(fname, &buf, &size, 0, NULL);
367  if (ret < 0)
368  return ret;
369 
370 #define READ16(dst) do { \
371  if (size < 2) { \
372  ret = AVERROR_INVALIDDATA; \
373  goto end; \
374  } \
375  dst = AV_RB16(buf); \
376  buf += 2; \
377  size -= 2; \
378 } while (0)
379 
380  READ16(version);
381  READ16(nb_curves);
382  for (i = 0; i < FFMIN(nb_curves, FF_ARRAY_ELEMS(comp_ids)); i++) {
383  int nb_points, n;
384  av_bprint_clear(&ptstr);
385  READ16(nb_points);
386  for (n = 0; n < nb_points; n++) {
387  int y, x;
388  READ16(y);
389  READ16(x);
390  av_bprintf(&ptstr, "%f/%f ", x / 255., y / 255.);
391  }
392  if (*ptstr.str) {
393  char **pts = &curves->comp_points_str[comp_ids[i]];
394  if (!*pts) {
395  *pts = av_strdup(ptstr.str);
396  av_log(ctx, AV_LOG_DEBUG, "curves %d (intid=%d) [%d points]: [%s]\n",
397  i, comp_ids[i], nb_points, *pts);
398  if (!*pts) {
399  ret = AVERROR(ENOMEM);
400  goto end;
401  }
402  }
403  }
404  }
405 end:
406  av_bprint_finalize(&ptstr, NULL);
407  av_file_unmap(buf, size);
408  return ret;
409 }
410 
411 static int dump_curves(const char *fname, uint16_t *graph[NB_COMP + 1],
412  struct keypoint *comp_points[NB_COMP + 1],
413  int lut_size)
414 {
415  int i;
416  AVBPrint buf;
417  const double scale = 1. / (lut_size - 1);
418  static const char * const colors[] = { "red", "green", "blue", "#404040", };
419  FILE *f = av_fopen_utf8(fname, "w");
420 
421  av_assert0(FF_ARRAY_ELEMS(colors) == NB_COMP + 1);
422 
423  if (!f) {
424  int ret = AVERROR(errno);
425  av_log(NULL, AV_LOG_ERROR, "Cannot open file '%s' for writing: %s\n",
426  fname, av_err2str(ret));
427  return ret;
428  }
429 
431 
432  av_bprintf(&buf, "set xtics 0.1\n");
433  av_bprintf(&buf, "set ytics 0.1\n");
434  av_bprintf(&buf, "set size square\n");
435  av_bprintf(&buf, "set grid\n");
436 
437  for (i = 0; i < FF_ARRAY_ELEMS(colors); i++) {
438  av_bprintf(&buf, "%s'-' using 1:2 with lines lc '%s' title ''",
439  i ? ", " : "plot ", colors[i]);
440  if (comp_points[i])
441  av_bprintf(&buf, ", '-' using 1:2 with points pointtype 3 lc '%s' title ''",
442  colors[i]);
443  }
444  av_bprintf(&buf, "\n");
445 
446  for (i = 0; i < FF_ARRAY_ELEMS(colors); i++) {
447  int x;
448 
449  /* plot generated values */
450  for (x = 0; x < lut_size; x++)
451  av_bprintf(&buf, "%f %f\n", x * scale, graph[i][x] * scale);
452  av_bprintf(&buf, "e\n");
453 
454  /* plot user knots */
455  if (comp_points[i]) {
456  const struct keypoint *point = comp_points[i];
457 
458  while (point) {
459  av_bprintf(&buf, "%f %f\n", point->x, point->y);
460  point = point->next;
461  }
462  av_bprintf(&buf, "e\n");
463  }
464  }
465 
466  fwrite(buf.str, 1, buf.len, f);
467  fclose(f);
468  av_bprint_finalize(&buf, NULL);
469  return 0;
470 }
471 
473 {
474  int i, ret;
475  CurvesContext *curves = ctx->priv;
476  char **pts = curves->comp_points_str;
477  const char *allp = curves->comp_points_str_all;
478 
479  //if (!allp && curves->preset != PRESET_NONE && curves_presets[curves->preset].all)
480  // allp = curves_presets[curves->preset].all;
481 
482  if (allp) {
483  for (i = 0; i < NB_COMP; i++) {
484  if (!pts[i])
485  pts[i] = av_strdup(allp);
486  if (!pts[i])
487  return AVERROR(ENOMEM);
488  }
489  }
490 
491  if (curves->psfile && !curves->parsed_psfile) {
492  ret = parse_psfile(ctx, curves->psfile);
493  if (ret < 0)
494  return ret;
495  curves->parsed_psfile = 1;
496  }
497 
498  if (curves->preset != PRESET_NONE) {
499 #define SET_COMP_IF_NOT_SET(n, name) do { \
500  if (!pts[n] && curves_presets[curves->preset].name) { \
501  pts[n] = av_strdup(curves_presets[curves->preset].name); \
502  if (!pts[n]) \
503  return AVERROR(ENOMEM); \
504  } \
505 } while (0)
510  curves->preset = PRESET_NONE;
511  }
512 
513  return 0;
514 }
515 
517 {
518  static const enum AVPixelFormat pix_fmts[] = {
533  };
535  if (!fmts_list)
536  return AVERROR(ENOMEM);
537  return ff_set_common_formats(ctx, fmts_list);
538 }
539 
540 static int filter_slice_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
541 {
542  int x, y;
543  const CurvesContext *curves = ctx->priv;
544  const ThreadData *td = arg;
545  const AVFrame *in = td->in;
546  const AVFrame *out = td->out;
547  const int direct = out == in;
548  const int step = curves->step;
549  const uint8_t r = curves->rgba_map[R];
550  const uint8_t g = curves->rgba_map[G];
551  const uint8_t b = curves->rgba_map[B];
552  const uint8_t a = curves->rgba_map[A];
553  const int slice_start = (in->height * jobnr ) / nb_jobs;
554  const int slice_end = (in->height * (jobnr+1)) / nb_jobs;
555 
556  if (curves->is_16bit) {
557  for (y = slice_start; y < slice_end; y++) {
558  uint16_t *dstp = ( uint16_t *)(out->data[0] + y * out->linesize[0]);
559  const uint16_t *srcp = (const uint16_t *)(in ->data[0] + y * in->linesize[0]);
560 
561  for (x = 0; x < in->width * step; x += step) {
562  dstp[x + r] = curves->graph[R][srcp[x + r]];
563  dstp[x + g] = curves->graph[G][srcp[x + g]];
564  dstp[x + b] = curves->graph[B][srcp[x + b]];
565  if (!direct && step == 4)
566  dstp[x + a] = srcp[x + a];
567  }
568  }
569  } else {
570  uint8_t *dst = out->data[0] + slice_start * out->linesize[0];
571  const uint8_t *src = in->data[0] + slice_start * in->linesize[0];
572 
573  for (y = slice_start; y < slice_end; y++) {
574  for (x = 0; x < in->width * step; x += step) {
575  dst[x + r] = curves->graph[R][src[x + r]];
576  dst[x + g] = curves->graph[G][src[x + g]];
577  dst[x + b] = curves->graph[B][src[x + b]];
578  if (!direct && step == 4)
579  dst[x + a] = src[x + a];
580  }
581  dst += out->linesize[0];
582  src += in ->linesize[0];
583  }
584  }
585  return 0;
586 }
587 
588 static int filter_slice_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
589 {
590  int x, y;
591  const CurvesContext *curves = ctx->priv;
592  const ThreadData *td = arg;
593  const AVFrame *in = td->in;
594  const AVFrame *out = td->out;
595  const int direct = out == in;
596  const int step = curves->step;
597  const uint8_t r = curves->rgba_map[R];
598  const uint8_t g = curves->rgba_map[G];
599  const uint8_t b = curves->rgba_map[B];
600  const uint8_t a = curves->rgba_map[A];
601  const int slice_start = (in->height * jobnr ) / nb_jobs;
602  const int slice_end = (in->height * (jobnr+1)) / nb_jobs;
603 
604  if (curves->is_16bit) {
605  for (y = slice_start; y < slice_end; y++) {
606  uint16_t *dstrp = ( uint16_t *)(out->data[r] + y * out->linesize[r]);
607  uint16_t *dstgp = ( uint16_t *)(out->data[g] + y * out->linesize[g]);
608  uint16_t *dstbp = ( uint16_t *)(out->data[b] + y * out->linesize[b]);
609  uint16_t *dstap = ( uint16_t *)(out->data[a] + y * out->linesize[a]);
610  const uint16_t *srcrp = (const uint16_t *)(in ->data[r] + y * in->linesize[r]);
611  const uint16_t *srcgp = (const uint16_t *)(in ->data[g] + y * in->linesize[g]);
612  const uint16_t *srcbp = (const uint16_t *)(in ->data[b] + y * in->linesize[b]);
613  const uint16_t *srcap = (const uint16_t *)(in ->data[a] + y * in->linesize[a]);
614 
615  for (x = 0; x < in->width; x++) {
616  dstrp[x] = curves->graph[R][srcrp[x]];
617  dstgp[x] = curves->graph[G][srcgp[x]];
618  dstbp[x] = curves->graph[B][srcbp[x]];
619  if (!direct && step == 4)
620  dstap[x] = srcap[x];
621  }
622  }
623  } else {
624  uint8_t *dstr = out->data[r] + slice_start * out->linesize[r];
625  uint8_t *dstg = out->data[g] + slice_start * out->linesize[g];
626  uint8_t *dstb = out->data[b] + slice_start * out->linesize[b];
627  uint8_t *dsta = out->data[a] + slice_start * out->linesize[a];
628  const uint8_t *srcr = in->data[r] + slice_start * in->linesize[r];
629  const uint8_t *srcg = in->data[g] + slice_start * in->linesize[g];
630  const uint8_t *srcb = in->data[b] + slice_start * in->linesize[b];
631  const uint8_t *srca = in->data[a] + slice_start * in->linesize[a];
632 
633  for (y = slice_start; y < slice_end; y++) {
634  for (x = 0; x < in->width; x++) {
635  dstr[x] = curves->graph[R][srcr[x]];
636  dstg[x] = curves->graph[G][srcg[x]];
637  dstb[x] = curves->graph[B][srcb[x]];
638  if (!direct && step == 4)
639  dsta[x] = srca[x];
640  }
641  dstr += out->linesize[r];
642  dstg += out->linesize[g];
643  dstb += out->linesize[b];
644  dsta += out->linesize[a];
645  srcr += in ->linesize[r];
646  srcg += in ->linesize[g];
647  srcb += in ->linesize[b];
648  srca += in ->linesize[a];
649  }
650  }
651  return 0;
652 }
653 
654 static int config_input(AVFilterLink *inlink)
655 {
656  int i, j, ret;
657  AVFilterContext *ctx = inlink->dst;
658  CurvesContext *curves = ctx->priv;
660  char **pts = curves->comp_points_str;
661  struct keypoint *comp_points[NB_COMP + 1] = {0};
662 
663  ff_fill_rgba_map(curves->rgba_map, inlink->format);
664  curves->is_16bit = desc->comp[0].depth > 8;
665  curves->depth = desc->comp[0].depth;
666  curves->lut_size = 1 << curves->depth;
667  curves->step = av_get_padded_bits_per_pixel(desc) >> (3 + curves->is_16bit);
669 
670  for (i = 0; i < NB_COMP + 1; i++) {
671  if (!curves->graph[i])
672  curves->graph[i] = av_mallocz_array(curves->lut_size, sizeof(*curves->graph[0]));
673  if (!curves->graph[i])
674  return AVERROR(ENOMEM);
675  ret = parse_points_str(ctx, comp_points + i, curves->comp_points_str[i], curves->lut_size);
676  if (ret < 0)
677  return ret;
678  switch (curves->depth) {
679  case 8: ret = interpolate8 (ctx, curves->graph[i], comp_points[i]); break;
680  case 9: ret = interpolate9 (ctx, curves->graph[i], comp_points[i]); break;
681  case 10: ret = interpolate10(ctx, curves->graph[i], comp_points[i]); break;
682  case 12: ret = interpolate12(ctx, curves->graph[i], comp_points[i]); break;
683  case 14: ret = interpolate14(ctx, curves->graph[i], comp_points[i]); break;
684  case 16: ret = interpolate16(ctx, curves->graph[i], comp_points[i]); break;
685  }
686  if (ret < 0)
687  return ret;
688  }
689 
690  if (pts[NB_COMP]) {
691  for (i = 0; i < NB_COMP; i++)
692  for (j = 0; j < curves->lut_size; j++)
693  curves->graph[i][j] = curves->graph[NB_COMP][curves->graph[i][j]];
694  }
695 
696  if (av_log_get_level() >= AV_LOG_VERBOSE) {
697  for (i = 0; i < NB_COMP; i++) {
698  const struct keypoint *point = comp_points[i];
699  av_log(ctx, AV_LOG_VERBOSE, "#%d points:", i);
700  while (point) {
701  av_log(ctx, AV_LOG_VERBOSE, " (%f;%f)", point->x, point->y);
702  point = point->next;
703  }
704  }
705  }
706 
707  if (curves->plot_filename && !curves->saved_plot) {
708  dump_curves(curves->plot_filename, curves->graph, comp_points, curves->lut_size);
709  curves->saved_plot = 1;
710  }
711 
712  for (i = 0; i < NB_COMP + 1; i++) {
713  struct keypoint *point = comp_points[i];
714  while (point) {
715  struct keypoint *next = point->next;
716  av_free(point);
717  point = next;
718  }
719  }
720 
721  return 0;
722 }
723 
724 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
725 {
726  AVFilterContext *ctx = inlink->dst;
727  CurvesContext *curves = ctx->priv;
728  AVFilterLink *outlink = ctx->outputs[0];
729  AVFrame *out;
730  ThreadData td;
731 
732  if (av_frame_is_writable(in)) {
733  out = in;
734  } else {
735  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
736  if (!out) {
737  av_frame_free(&in);
738  return AVERROR(ENOMEM);
739  }
741  }
742 
743  td.in = in;
744  td.out = out;
745  ctx->internal->execute(ctx, curves->filter_slice, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
746 
747  if (out != in)
748  av_frame_free(&in);
749 
750  return ff_filter_frame(outlink, out);
751 }
752 
753 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
754  char *res, int res_len, int flags)
755 {
756  CurvesContext *curves = ctx->priv;
757  int ret;
758 
759  if (!strcmp(cmd, "plot")) {
760  curves->saved_plot = 0;
761  } else if (!strcmp(cmd, "all") || !strcmp(cmd, "preset") || !strcmp(cmd, "psfile")) {
762  if (!strcmp(cmd, "psfile"))
763  curves->parsed_psfile = 0;
764  av_freep(&curves->comp_points_str_all);
765  av_freep(&curves->comp_points_str[0]);
766  av_freep(&curves->comp_points_str[1]);
767  av_freep(&curves->comp_points_str[2]);
768  av_freep(&curves->comp_points_str[NB_COMP]);
769  } else if (!strcmp(cmd, "red") || !strcmp(cmd, "r")) {
770  av_freep(&curves->comp_points_str[0]);
771  } else if (!strcmp(cmd, "green") || !strcmp(cmd, "g")) {
772  av_freep(&curves->comp_points_str[1]);
773  } else if (!strcmp(cmd, "blue") || !strcmp(cmd, "b")) {
774  av_freep(&curves->comp_points_str[2]);
775  } else if (!strcmp(cmd, "master") || !strcmp(cmd, "m")) {
776  av_freep(&curves->comp_points_str[NB_COMP]);
777  }
778 
779  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
780  if (ret < 0)
781  return ret;
782 
783  ret = curves_init(ctx);
784  if (ret < 0)
785  return ret;
786  return config_input(ctx->inputs[0]);
787 }
788 
790 {
791  int i;
792  CurvesContext *curves = ctx->priv;
793 
794  for (i = 0; i < NB_COMP + 1; i++)
795  av_freep(&curves->graph[i]);
796 }
797 
798 static const AVFilterPad curves_inputs[] = {
799  {
800  .name = "default",
801  .type = AVMEDIA_TYPE_VIDEO,
802  .filter_frame = filter_frame,
803  .config_props = config_input,
804  },
805  { NULL }
806 };
807 
808 static const AVFilterPad curves_outputs[] = {
809  {
810  .name = "default",
811  .type = AVMEDIA_TYPE_VIDEO,
812  },
813  { NULL }
814 };
815 
817  .name = "curves",
818  .description = NULL_IF_CONFIG_SMALL("Adjust components curves."),
819  .priv_size = sizeof(CurvesContext),
820  .init = curves_init,
825  .priv_class = &curves_class,
828 };
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
#define av_unused
Definition: attributes.h:131
#define av_cold
Definition: attributes.h:88
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
uint8_t
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1096
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:882
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:802
Main libavfilter public API header.
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:31
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:227
#define AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_AUTOMATIC
#define flags(name, subs,...)
Definition: cbs_av1.c:561
#define s(width, name)
Definition: cbs_vp9.c:257
#define f(width, name)
Definition: cbs_vp9.c:255
#define FFMIN(a, b)
Definition: common.h:105
#define NULL
Definition: coverity.c:32
static av_cold int uninit(AVCodecContext *avctx)
Definition: crystalhd.c:279
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:35
misc drawing utilities
double av_strtod(const char *numstr, char **tail)
Parse the string in numstr and return its value as a double.
Definition: eval.c:106
simple arithmetic expression evaluator
int
Misc file utilities.
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:587
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:286
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
@ AV_OPT_TYPE_INT
Definition: opt.h:225
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition: avfilter.h:126
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:117
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:119
#define AVERROR(e)
Definition: error.h:43
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:594
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:658
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
int av_log_get_level(void)
Get the current log level.
Definition: log.c:435
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:253
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:245
void * av_mallocz_array(size_t nmemb, size_t size)
Allocate a memory block for an array with av_mallocz().
Definition: mem.c:190
FILE * av_fopen_utf8(const char *path, const char *mode)
Open a file using a UTF-8 filename.
Definition: file_open.c:158
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
int i
Definition: input.c:407
const char * arg
Definition: jacosubdec.c:66
static void direct(const float *in, const FFTComplex *ir, int len, float *out)
Definition: af_afir.c:60
void av_file_unmap(uint8_t *bufptr, size_t size)
Unmap or free the buffer bufptr created by av_file_map().
Definition: file.c:144
int av_file_map(const char *filename, uint8_t **bufptr, size_t *size, int log_offset, void *log_ctx)
Read the file with name filename, and put its content in a newly allocated buffer or map it with mmap...
Definition: file.c:53
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
version
Definition: libkvazaar.c:326
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:309
const char * desc
Definition: libsvtav1.c:79
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2033
const char data[16]
Definition: mxf.c:142
AVOptions.
int av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc)
Return the number of bits per pixel for the pixel format described by pixdesc, including any padding ...
Definition: pixdesc.c:2538
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2573
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
Definition: pixdesc.h:144
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:420
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:421
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:414
#define AV_PIX_FMT_BGR48
Definition: pixfmt.h:390
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:415
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:389
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:416
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:385
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:240
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:92
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:94
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:239
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:238
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:237
#define AV_PIX_FMT_BGRA64
Definition: pixfmt.h:394
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:419
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:418
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:417
#define td
Definition: regdef.h:70
#define FF_ARRAY_ELEMS(a)
Describe the class of an AVClass context structure.
Definition: log.h:67
An instance of a filter.
Definition: avfilter.h:341
A list of supported formats for one end of a filter link.
Definition: formats.h:65
A filter pad used for either input or output.
Definition: internal.h:54
const char * name
Pad name.
Definition: internal.h:60
Filter definition.
Definition: avfilter.h:145
const char * name
Filter name.
Definition: avfilter.h:149
AVFormatInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1699
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
AVOption.
Definition: opt.h:248
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
int parsed_psfile
Definition: vf_curves.c:75
char * comp_points_str_all
Definition: vf_curves.c:65
char * plot_filename
Definition: vf_curves.c:71
uint16_t * graph[NB_COMP+1]
Definition: vf_curves.c:66
char * psfile
Definition: vf_curves.c:68
char * comp_points_str[NB_COMP+1]
Definition: vf_curves.c:64
int saved_plot
Definition: vf_curves.c:72
int(* filter_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_curves.c:77
uint8_t rgba_map[4]
Definition: vf_curves.c:69
Used for passing data between threads.
Definition: dsddec.c:67
AVFrame * out
Definition: af_adeclick.c:502
AVFrame * in
Definition: af_adenorm.c:223
struct keypoint * next
Definition: vf_curves.c:41
double x
Definition: vf_curves.c:40
double y
Definition: vf_curves.c:40
#define av_free(p)
#define av_freep(p)
#define av_malloc(s)
#define av_log(a,...)
#define src
Definition: vp8dsp.c:255
FILE * out
Definition: movenc.c:54
AVFormatContext * ctx
Definition: movenc.c:48
static int64_t pts
int size
const char * b
Definition: vf_curves.c:118
#define B
Definition: vf_curves.c:36
static int interpolate(void *log_ctx, uint16_t *y, const struct keypoint *points, int nbits)
Definition: vf_curves.c:219
const char * g
Definition: vf_curves.c:117
static int parse_points_str(AVFilterContext *ctx, struct keypoint **points, const char *s, int lut_size)
Definition: vf_curves.c:157
static av_cold int curves_init(AVFilterContext *ctx)
Definition: vf_curves.c:472
const char * master
Definition: vf_curves.c:119
const char * r
Definition: vf_curves.c:116
static int filter_slice_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_curves.c:540
static int get_nb_points(const struct keypoint *d)
Definition: vf_curves.c:201
static int query_formats(AVFilterContext *ctx)
Definition: vf_curves.c:516
#define R
Definition: vf_curves.c:34
static int config_input(AVFilterLink *inlink)
Definition: vf_curves.c:654
#define FLAGS
Definition: vf_curves.c:85
AVFilter ff_vf_curves
Definition: vf_curves.c:816
#define NB_COMP
Definition: vf_curves.c:44
static int filter_slice_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_curves.c:588
preset
Definition: vf_curves.c:46
@ PRESET_NEGATIVE
Definition: vf_curves.c:55
@ PRESET_LINEAR_CONTRAST
Definition: vf_curves.c:53
@ PRESET_COLOR_NEGATIVE
Definition: vf_curves.c:48
@ PRESET_VINTAGE
Definition: vf_curves.c:57
@ PRESET_MEDIUM_CONTRAST
Definition: vf_curves.c:54
@ PRESET_LIGHTER
Definition: vf_curves.c:52
@ PRESET_INCREASE_CONTRAST
Definition: vf_curves.c:51
@ PRESET_CROSS_PROCESS
Definition: vf_curves.c:49
@ PRESET_STRONG_CONTRAST
Definition: vf_curves.c:56
@ NB_PRESETS
Definition: vf_curves.c:58
@ PRESET_NONE
Definition: vf_curves.c:47
@ PRESET_DARKER
Definition: vf_curves.c:50
#define READ16(dst)
static const AVFilterPad curves_outputs[]
Definition: vf_curves.c:808
static const struct @218 curves_presets[]
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_curves.c:724
#define BD
#define A
Definition: vf_curves.c:37
static int parse_psfile(AVFilterContext *ctx, const char *fname)
Definition: vf_curves.c:355
#define DECLARE_INTERPOLATE_FUNC(nbits)
Definition: vf_curves.c:341
#define AD
#define MD
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition: vf_curves.c:753
#define CLIP(v)
Natural cubic spline interpolation Finding curves using Cubic Splines notes by Steven Rauch and John ...
Definition: vf_curves.c:217
static const AVFilterPad curves_inputs[]
Definition: vf_curves.c:798
static const AVOption curves_options[]
Definition: vf_curves.c:86
AVFILTER_DEFINE_CLASS(curves)
#define OFFSET(x)
Definition: vf_curves.c:84
#define SET_COMP_IF_NOT_SET(n, name)
static av_cold void curves_uninit(AVFilterContext *ctx)
Definition: vf_curves.c:789
static int dump_curves(const char *fname, uint16_t *graph[NB_COMP+1], struct keypoint *comp_points[NB_COMP+1], int lut_size)
Definition: vf_curves.c:411
#define G
Definition: vf_curves.c:35
static struct keypoint * make_point(double x, double y, struct keypoint *next)
Definition: vf_curves.c:145
static const Curve curves[]
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:104
static double c[64]