FFmpeg
vf_colorlevels.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 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 "libavutil/imgutils.h"
22 #include "libavutil/opt.h"
23 #include "libavutil/pixdesc.h"
24 #include "avfilter.h"
25 #include "drawutils.h"
26 #include "formats.h"
27 #include "internal.h"
28 #include "video.h"
29 #include "preserve_color.h"
30 
31 #define R 0
32 #define G 1
33 #define B 2
34 #define A 3
35 
36 typedef struct Range {
37  double in_min, in_max;
38  double out_min, out_max;
39 } Range;
40 
41 typedef struct ColorLevelsContext {
42  const AVClass *class;
45 
46  int nb_comp;
47  int depth;
48  int max;
49  int planar;
50  int bpp;
51  int step;
52  uint8_t rgba_map[4];
53  int linesize;
54 
55  int (*colorlevels_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
57 
58 #define OFFSET(x) offsetof(ColorLevelsContext, x)
59 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
60 static const AVOption colorlevels_options[] = {
61  { "rimin", "set input red black point", OFFSET(range[R].in_min), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS },
62  { "gimin", "set input green black point", OFFSET(range[G].in_min), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS },
63  { "bimin", "set input blue black point", OFFSET(range[B].in_min), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS },
64  { "aimin", "set input alpha black point", OFFSET(range[A].in_min), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS },
65  { "rimax", "set input red white point", OFFSET(range[R].in_max), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -1, 1, FLAGS },
66  { "gimax", "set input green white point", OFFSET(range[G].in_max), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -1, 1, FLAGS },
67  { "bimax", "set input blue white point", OFFSET(range[B].in_max), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -1, 1, FLAGS },
68  { "aimax", "set input alpha white point", OFFSET(range[A].in_max), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -1, 1, FLAGS },
69  { "romin", "set output red black point", OFFSET(range[R].out_min), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 1, FLAGS },
70  { "gomin", "set output green black point", OFFSET(range[G].out_min), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 1, FLAGS },
71  { "bomin", "set output blue black point", OFFSET(range[B].out_min), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 1, FLAGS },
72  { "aomin", "set output alpha black point", OFFSET(range[A].out_min), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 1, FLAGS },
73  { "romax", "set output red white point", OFFSET(range[R].out_max), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS },
74  { "gomax", "set output green white point", OFFSET(range[G].out_max), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS },
75  { "bomax", "set output blue white point", OFFSET(range[B].out_max), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS },
76  { "aomax", "set output alpha white point", OFFSET(range[A].out_max), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS },
77  { "preserve", "set preserve color mode", OFFSET(preserve_color), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_PRESERVE-1, FLAGS, "preserve" },
78  { "none", "disabled", 0, AV_OPT_TYPE_CONST, {.i64=P_NONE}, 0, 0, FLAGS, "preserve" },
79  { "lum", "luminance", 0, AV_OPT_TYPE_CONST, {.i64=P_LUM}, 0, 0, FLAGS, "preserve" },
80  { "max", "max", 0, AV_OPT_TYPE_CONST, {.i64=P_MAX}, 0, 0, FLAGS, "preserve" },
81  { "avg", "average", 0, AV_OPT_TYPE_CONST, {.i64=P_AVG}, 0, 0, FLAGS, "preserve" },
82  { "sum", "sum", 0, AV_OPT_TYPE_CONST, {.i64=P_SUM}, 0, 0, FLAGS, "preserve" },
83  { "nrm", "norm", 0, AV_OPT_TYPE_CONST, {.i64=P_NRM}, 0, 0, FLAGS, "preserve" },
84  { "pwr", "power", 0, AV_OPT_TYPE_CONST, {.i64=P_PWR}, 0, 0, FLAGS, "preserve" },
85  { NULL }
86 };
87 
88 AVFILTER_DEFINE_CLASS(colorlevels);
89 
90 typedef struct ThreadData {
91  const uint8_t *srcrow[4];
92  uint8_t *dstrow[4];
94  int src_linesize;
95 
96  float coeff[4];
97 
98  int h;
99 
100  int imin[4];
101  int omin[4];
102 } ThreadData;
103 
104 #define DO_COMMON(type, clip, preserve, planar) \
105  const ThreadData *td = arg; \
106  const int linesize = s->linesize; \
107  const int step = s->step; \
108  const int process_h = td->h; \
109  const int slice_start = (process_h * jobnr ) / nb_jobs; \
110  const int slice_end = (process_h * (jobnr+1)) / nb_jobs; \
111  const int src_linesize = td->src_linesize / sizeof(type); \
112  const int dst_linesize = td->dst_linesize / sizeof(type); \
113  const type *src_r = (const type *)(td->srcrow[R]) + src_linesize * slice_start; \
114  const type *src_g = (const type *)(td->srcrow[G]) + src_linesize * slice_start; \
115  const type *src_b = (const type *)(td->srcrow[B]) + src_linesize * slice_start; \
116  const type *src_a = (const type *)(td->srcrow[A]) + src_linesize * slice_start; \
117  type *dst_r = (type *)(td->dstrow[R]) + src_linesize * slice_start; \
118  type *dst_g = (type *)(td->dstrow[G]) + src_linesize * slice_start; \
119  type *dst_b = (type *)(td->dstrow[B]) + src_linesize * slice_start; \
120  type *dst_a = (type *)(td->dstrow[A]) + src_linesize * slice_start; \
121  const int imin_r = td->imin[R]; \
122  const int imin_g = td->imin[G]; \
123  const int imin_b = td->imin[B]; \
124  const int imin_a = td->imin[A]; \
125  const int omin_r = td->omin[R]; \
126  const int omin_g = td->omin[G]; \
127  const int omin_b = td->omin[B]; \
128  const int omin_a = td->omin[A]; \
129  const float coeff_r = td->coeff[R]; \
130  const float coeff_g = td->coeff[G]; \
131  const float coeff_b = td->coeff[B]; \
132  const float coeff_a = td->coeff[A]; \
133  \
134  for (int y = slice_start; y < slice_end; y++) { \
135  for (int x = 0; x < linesize; x += step) { \
136  int ir, ig, ib, or, og, ob; \
137  ir = src_r[x]; \
138  ig = src_g[x]; \
139  ib = src_b[x]; \
140  if (preserve) { \
141  float ratio, icolor, ocolor, max = s->max; \
142  \
143  or = (ir - imin_r) * coeff_r + omin_r; \
144  og = (ig - imin_g) * coeff_g + omin_g; \
145  ob = (ib - imin_b) * coeff_b + omin_b; \
146  \
147  preserve_color(s->preserve_color, ir, ig, ib, or, og, ob, max, \
148  &icolor, &ocolor); \
149  if (ocolor > 0.f) { \
150  ratio = icolor / ocolor; \
151  \
152  or *= ratio; \
153  og *= ratio; \
154  ob *= ratio; \
155  } \
156  \
157  dst_r[x] = clip(or, depth); \
158  dst_g[x] = clip(og, depth); \
159  dst_b[x] = clip(ob, depth); \
160  } else { \
161  dst_r[x] = clip((ir - imin_r) * coeff_r + omin_r, depth); \
162  dst_g[x] = clip((ig - imin_g) * coeff_g + omin_g, depth); \
163  dst_b[x] = clip((ib - imin_b) * coeff_b + omin_b, depth); \
164  } \
165  } \
166  \
167  for (int x = 0; x < linesize && s->nb_comp == 4; x += step) \
168  dst_a[x] = clip((src_a[x] - imin_a) * coeff_a + omin_a, depth); \
169  \
170  src_r += src_linesize; \
171  src_g += src_linesize; \
172  src_b += src_linesize; \
173  src_a += src_linesize; \
174  \
175  dst_r += dst_linesize; \
176  dst_g += dst_linesize; \
177  dst_b += dst_linesize; \
178  dst_a += dst_linesize; \
179  }
180 
181 #define CLIP8(x, depth) av_clip_uint8(x)
182 #define CLIP16(x, depth) av_clip_uint16(x)
183 
184 static int colorlevels_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
185 {
186  ColorLevelsContext *s = ctx->priv;
187  DO_COMMON(uint8_t, CLIP8, 0, 0)
188  return 0;
189 }
190 
191 static int colorlevels_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
192 {
193  ColorLevelsContext *s = ctx->priv;\
194  DO_COMMON(uint16_t, CLIP16, 0, 0)
195  return 0;
196 }
197 
198 static int colorlevels_preserve_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
199 {
200  ColorLevelsContext *s = ctx->priv;
201  DO_COMMON(uint8_t, CLIP8, 1, 0)
202  return 0;
203 }
204 
205 static int colorlevels_preserve_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
206 {
207  ColorLevelsContext *s = ctx->priv;
208  DO_COMMON(uint16_t, CLIP16, 1, 0)
209  return 0;
210 }
211 
212 static int colorlevels_slice_8_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
213 {
214  ColorLevelsContext *s = ctx->priv;
215  DO_COMMON(uint8_t, CLIP8, 0, 1)
216  return 0;
217 }
218 
219 static int colorlevels_slice_9_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
220 {
221  ColorLevelsContext *s = ctx->priv;
222  const int depth = 9;
223  DO_COMMON(uint16_t, av_clip_uintp2, 0, 1)
224  return 0;
225 }
226 
227 static int colorlevels_slice_10_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
228 {
229  ColorLevelsContext *s = ctx->priv;
230  const int depth = 10;
231  DO_COMMON(uint16_t, av_clip_uintp2, 0, 1)
232  return 0;
233 }
234 
235 static int colorlevels_slice_12_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
236 {
237  ColorLevelsContext *s = ctx->priv;
238  const int depth = 12;
239  DO_COMMON(uint16_t, av_clip_uintp2, 0, 1)
240  return 0;
241 }
242 
243 static int colorlevels_slice_14_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
244 {
245  ColorLevelsContext *s = ctx->priv;
246  const int depth = 14;
247  DO_COMMON(uint16_t, av_clip_uintp2, 0, 1)
248  return 0;
249 }
250 
251 static int colorlevels_slice_16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
252 {
253  ColorLevelsContext *s = ctx->priv;
254  DO_COMMON(uint16_t, CLIP16, 0, 1)
255  return 0;
256 }
257 
258 static int colorlevels_preserve_slice_8_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
259 {
260  ColorLevelsContext *s = ctx->priv;
261  DO_COMMON(uint8_t, CLIP8, 1, 1)
262  return 0;
263 }
264 
265 static int colorlevels_preserve_slice_9_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
266 {
267  ColorLevelsContext *s = ctx->priv;
268  const int depth = 9;
269  DO_COMMON(uint16_t, av_clip_uintp2, 1, 1)
270  return 0;
271 }
272 
273 static int colorlevels_preserve_slice_10_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
274 {
275  ColorLevelsContext *s = ctx->priv;
276  const int depth = 10;
277  DO_COMMON(uint16_t, av_clip_uintp2, 1, 1)
278  return 0;
279 }
280 
281 static int colorlevels_preserve_slice_12_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
282 {
283  ColorLevelsContext *s = ctx->priv;
284  const int depth = 12;
285  DO_COMMON(uint16_t, av_clip_uintp2, 1, 1)
286  return 0;
287 }
288 
289 static int colorlevels_preserve_slice_14_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
290 {
291  ColorLevelsContext *s = ctx->priv;
292  const int depth = 14;
293  DO_COMMON(uint16_t, av_clip_uintp2, 1, 1)
294  return 0;
295 }
296 
297 static int colorlevels_preserve_slice_16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
298 {
299  ColorLevelsContext *s = ctx->priv;
300  DO_COMMON(uint16_t, CLIP16, 1, 1)
301  return 0;
302 }
303 
305 {
306  AVFilterContext *ctx = inlink->dst;
307  ColorLevelsContext *s = ctx->priv;
309 
310  s->nb_comp = desc->nb_components;
311  s->planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR;
312  s->depth = desc->comp[0].depth;
313  s->max = (1 << s->depth) - 1;
314  s->bpp = (desc->comp[0].depth + 7) >> 3;
315  s->step = s->planar ? 1 : av_get_padded_bits_per_pixel(desc) >> (3 + (s->bpp == 2));
316  s->linesize = inlink->w * s->step;
317  ff_fill_rgba_map(s->rgba_map, inlink->format);
318 
319  if (!s->planar) {
320  s->colorlevels_slice[0] = colorlevels_slice_8;
321  s->colorlevels_slice[1] = colorlevels_preserve_slice_8;
322  if (s->bpp == 2) {
323  s->colorlevels_slice[0] = colorlevels_slice_16;
324  s->colorlevels_slice[1] = colorlevels_preserve_slice_16;
325  }
326  } else {
327  switch (s->depth) {
328  case 8:
329  s->colorlevels_slice[0] = colorlevels_slice_8_planar;
330  s->colorlevels_slice[1] = colorlevels_preserve_slice_8_planar;
331  break;
332  case 9:
333  s->colorlevels_slice[0] = colorlevels_slice_9_planar;
334  s->colorlevels_slice[1] = colorlevels_preserve_slice_9_planar;
335  break;
336  case 10:
337  s->colorlevels_slice[0] = colorlevels_slice_10_planar;
338  s->colorlevels_slice[1] = colorlevels_preserve_slice_10_planar;
339  break;
340  case 12:
341  s->colorlevels_slice[0] = colorlevels_slice_12_planar;
342  s->colorlevels_slice[1] = colorlevels_preserve_slice_12_planar;
343  break;
344  case 14:
345  s->colorlevels_slice[0] = colorlevels_slice_14_planar;
346  s->colorlevels_slice[1] = colorlevels_preserve_slice_14_planar;
347  break;
348  case 16:
349  s->colorlevels_slice[0] = colorlevels_slice_16_planar;
350  s->colorlevels_slice[1] = colorlevels_preserve_slice_16_planar;
351  break;
352  }
353  }
354 
355  return 0;
356 }
357 
359 {
360  AVFilterContext *ctx = inlink->dst;
361  ColorLevelsContext *s = ctx->priv;
362  AVFilterLink *outlink = ctx->outputs[0];
363  const int step = s->step;
364  ThreadData td;
365  AVFrame *out;
366 
367  if (av_frame_is_writable(in)) {
368  out = in;
369  } else {
370  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
371  if (!out) {
372  av_frame_free(&in);
373  return AVERROR(ENOMEM);
374  }
376  }
377 
378  td.h = inlink->h;
379  td.dst_linesize = out->linesize[0];
380  td.src_linesize = in->linesize[0];
381  if (s->planar) {
382  td.srcrow[R] = in->data[2];
383  td.dstrow[R] = out->data[2];
384  td.srcrow[G] = in->data[0];
385  td.dstrow[G] = out->data[0];
386  td.srcrow[B] = in->data[1];
387  td.dstrow[B] = out->data[1];
388  td.srcrow[A] = in->data[3];
389  td.dstrow[A] = out->data[3];
390  } else {
391  td.srcrow[R] = in->data[0] + s->rgba_map[R] * s->bpp;
392  td.dstrow[R] = out->data[0] + s->rgba_map[R] * s->bpp;
393  td.srcrow[G] = in->data[0] + s->rgba_map[G] * s->bpp;
394  td.dstrow[G] = out->data[0] + s->rgba_map[G] * s->bpp;
395  td.srcrow[B] = in->data[0] + s->rgba_map[B] * s->bpp;
396  td.dstrow[B] = out->data[0] + s->rgba_map[B] * s->bpp;
397  td.srcrow[A] = in->data[0] + s->rgba_map[A] * s->bpp;
398  td.dstrow[A] = out->data[0] + s->rgba_map[A] * s->bpp;
399  }
400 
401  switch (s->bpp) {
402  case 1:
403  for (int i = 0; i < s->nb_comp; i++) {
404  Range *r = &s->range[i];
405  const uint8_t offset = s->rgba_map[i];
406  const uint8_t *srcrow = in->data[0];
407  int imin = lrint(r->in_min * UINT8_MAX);
408  int imax = lrint(r->in_max * UINT8_MAX);
409  int omin = lrint(r->out_min * UINT8_MAX);
410  int omax = lrint(r->out_max * UINT8_MAX);
411  float coeff;
412 
413  if (imin < 0) {
414  imin = UINT8_MAX;
415  for (int y = 0; y < inlink->h; y++) {
416  const uint8_t *src = srcrow;
417 
418  for (int x = 0; x < s->linesize; x += step)
419  imin = FFMIN(imin, src[x + offset]);
420  srcrow += in->linesize[0];
421  }
422  }
423  if (imax < 0) {
424  srcrow = in->data[0];
425  imax = 0;
426  for (int y = 0; y < inlink->h; y++) {
427  const uint8_t *src = srcrow;
428 
429  for (int x = 0; x < s->linesize; x += step)
430  imax = FFMAX(imax, src[x + offset]);
431  srcrow += in->linesize[0];
432  }
433  }
434 
435  coeff = (omax - omin) / (double)(imax - imin);
436 
437  td.coeff[i] = coeff;
438  td.imin[i] = imin;
439  td.omin[i] = omin;
440  }
441  break;
442  case 2:
443  for (int i = 0; i < s->nb_comp; i++) {
444  Range *r = &s->range[i];
445  const uint8_t offset = s->rgba_map[i];
446  const uint8_t *srcrow = in->data[0];
447  int imin = lrint(r->in_min * UINT16_MAX);
448  int imax = lrint(r->in_max * UINT16_MAX);
449  int omin = lrint(r->out_min * UINT16_MAX);
450  int omax = lrint(r->out_max * UINT16_MAX);
451  float coeff;
452 
453  if (imin < 0) {
454  imin = UINT16_MAX;
455  for (int y = 0; y < inlink->h; y++) {
456  const uint16_t *src = (const uint16_t *)srcrow;
457 
458  for (int x = 0; x < s->linesize; x += step)
459  imin = FFMIN(imin, src[x + offset]);
460  srcrow += in->linesize[0];
461  }
462  }
463  if (imax < 0) {
464  srcrow = in->data[0];
465  imax = 0;
466  for (int y = 0; y < inlink->h; y++) {
467  const uint16_t *src = (const uint16_t *)srcrow;
468 
469  for (int x = 0; x < s->linesize; x += step)
470  imax = FFMAX(imax, src[x + offset]);
471  srcrow += in->linesize[0];
472  }
473  }
474 
475  coeff = (omax - omin) / (double)(imax - imin);
476 
477  td.coeff[i] = coeff;
478  td.imin[i] = imin;
479  td.omin[i] = omin;
480  }
481  break;
482  }
483 
484  ff_filter_execute(ctx, s->colorlevels_slice[s->preserve_color > 0], &td, NULL,
486 
487  if (in != out)
488  av_frame_free(&in);
489  return ff_filter_frame(outlink, out);
490 }
491 
492 static const AVFilterPad colorlevels_inputs[] = {
493  {
494  .name = "default",
495  .type = AVMEDIA_TYPE_VIDEO,
496  .filter_frame = filter_frame,
497  .config_props = config_input,
498  },
499 };
500 
502  {
503  .name = "default",
504  .type = AVMEDIA_TYPE_VIDEO,
505  },
506 };
507 
509  .name = "colorlevels",
510  .description = NULL_IF_CONFIG_SMALL("Adjust the color levels."),
511  .priv_size = sizeof(ColorLevelsContext),
512  .priv_class = &colorlevels_class,
529  .process_command = ff_filter_process_command,
530 };
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:101
AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:481
colorlevels_slice_8_planar
static int colorlevels_slice_8_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:212
td
#define td
Definition: regdef.h:70
ThreadData::coeff
float coeff[4]
Definition: vf_colorlevels.c:96
ColorLevelsContext::linesize
int linesize
Definition: vf_colorlevels.c:53
r
const char * r
Definition: vf_curves.c:126
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
preserve_color.h
out
FILE * out
Definition: movenc.c:54
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1009
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2858
av_clip_uintp2
#define av_clip_uintp2
Definition: common.h:119
colorlevels_slice_16_planar
static int colorlevels_slice_16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:251
colorlevels_preserve_slice_16
static int colorlevels_preserve_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:205
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_colorlevels.c:358
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
ColorLevelsContext::preserve_color
int preserve_color
Definition: vf_colorlevels.c:44
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:116
P_AVG
@ P_AVG
Definition: preserve_color.h:30
ThreadData::srcrow
const uint8_t * srcrow[4]
Definition: vf_colorlevels.c:91
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:325
pixdesc.h
colorlevels_inputs
static const AVFilterPad colorlevels_inputs[]
Definition: vf_colorlevels.c:492
step
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
Definition: rate_distortion.txt:58
preserve_color
static void preserve_color(int preserve_color, float ir, float ig, float ib, float r, float g, float b, float max, float *icolor, float *ocolor)
Definition: preserve_color.h:53
AVOption
AVOption.
Definition: opt.h:251
P_NONE
@ P_NONE
Definition: preserve_color.h:27
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
colorlevels_slice_9_planar
static int colorlevels_slice_9_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:219
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:175
video.h
colorlevels_preserve_slice_12_planar
static int colorlevels_preserve_slice_12_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:281
config_input
static int config_input(AVFilterLink *inlink)
Definition: vf_colorlevels.c:304
A
#define A
Definition: vf_colorlevels.c:34
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:346
P_LUM
@ P_LUM
Definition: preserve_color.h:28
formats.h
ff_vf_colorlevels
const AVFilter ff_vf_colorlevels
Definition: vf_colorlevels.c:508
AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:477
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:205
AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:475
P_SUM
@ P_SUM
Definition: preserve_color.h:31
colorlevels_preserve_slice_8_planar
static int colorlevels_preserve_slice_8_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:258
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:49
ColorLevelsContext
Definition: vf_colorlevels.c:41
ThreadData::imin
int imin[4]
Definition: vf_colorlevels.c:100
lrint
#define lrint
Definition: tablegen.h:53
colorlevels_slice_10_planar
static int colorlevels_slice_10_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:227
AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:479
s
#define s(width, name)
Definition: cbs_vp9.c:256
AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:480
colorlevels_preserve_slice_8
static int colorlevels_preserve_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:198
colorlevels_slice_16
static int colorlevels_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:191
Range::in_min
double in_min
Definition: vf_colorlevels.c:37
AV_OPT_TYPE_DOUBLE
@ AV_OPT_TYPE_DOUBLE
Definition: opt.h:227
colorlevels_preserve_slice_14_planar
static int colorlevels_preserve_slice_14_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:289
ctx
AVFormatContext * ctx
Definition: movenc.c:48
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:190
ThreadData::h
int h
Definition: vf_blend.c:59
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
arg
const char * arg
Definition: jacosubdec.c:67
AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:478
ColorLevelsContext::range
Range range[4]
Definition: vf_colorlevels.c:43
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:449
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
AV_PIX_FMT_BGR48
#define AV_PIX_FMT_BGR48
Definition: pixfmt.h:450
NULL
#define NULL
Definition: coverity.c:32
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:603
colorlevels_preserve_slice_16_planar
static int colorlevels_preserve_slice_16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:297
ColorLevelsContext::planar
int planar
Definition: vf_colorlevels.c:49
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:258
AV_PIX_FMT_GBRP9
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:474
AV_PIX_FMT_ABGR
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:94
Range
Definition: vf_colorbalance.c:38
CLIP8
#define CLIP8(x, depth)
Definition: vf_colorlevels.c:181
G
#define G
Definition: vf_colorlevels.c:32
OFFSET
#define OFFSET(x)
Definition: vf_colorlevels.c:58
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:115
ColorLevelsContext::rgba_map
uint8_t rgba_map[4]
Definition: vf_colorlevels.c:52
av_get_padded_bits_per_pixel
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:2823
FILTER_PIXFMTS
#define FILTER_PIXFMTS(...)
Definition: internal.h:176
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:445
av_frame_is_writable
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:533
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(colorlevels)
ff_filter_process_command
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:873
B
#define B
Definition: vf_colorlevels.c:33
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:256
P_MAX
@ P_MAX
Definition: preserve_color.h:29
internal.h
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
#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:152
AV_PIX_FMT_ARGB
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:92
colorlevels_slice_8
static int colorlevels_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:184
AV_PIX_FMT_BGRA64
#define AV_PIX_FMT_BGRA64
Definition: pixfmt.h:454
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:476
ColorLevelsContext::bpp
int bpp
Definition: vf_colorlevels.c:50
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:793
ThreadData
Used for passing data between threads.
Definition: dsddec.c:69
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:55
ColorLevelsContext::nb_comp
int nb_comp
Definition: vf_colorlevels.c:46
Range::out_min
double out_min
Definition: vf_colorlevels.c:38
colorlevels_preserve_slice_9_planar
static int colorlevels_preserve_slice_9_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:265
AVFilter
Filter definition.
Definition: avfilter.h:171
AV_PIX_FMT_0BGR
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:257
ThreadData::dstrow
uint8_t * dstrow[4]
Definition: vf_colorlevels.c:92
colorlevels_outputs
static const AVFilterPad colorlevels_outputs[]
Definition: vf_colorlevels.c:501
ColorLevelsContext::colorlevels_slice
int(* colorlevels_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:55
ThreadData::src_linesize
int src_linesize
Definition: vf_bm3d.c:56
colorlevels_options
static const AVOption colorlevels_options[]
Definition: vf_colorlevels.c:60
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
avfilter.h
ColorLevelsContext::step
int step
Definition: vf_colorlevels.c:51
P_NRM
@ P_NRM
Definition: preserve_color.h:32
AV_PIX_FMT_FLAG_PLANAR
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
Definition: pixdesc.h:132
ColorLevelsContext::max
int max
Definition: vf_colorlevels.c:48
P_PWR
@ P_PWR
Definition: preserve_color.h:33
AVFilterContext
An instance of a filter.
Definition: avfilter.h:415
FLAGS
#define FLAGS
Definition: vf_colorlevels.c:59
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:158
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:127
ColorLevelsContext::depth
int depth
Definition: vf_colorlevels.c:47
desc
const char * desc
Definition: libsvtav1.c:83
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
colorlevels_slice_12_planar
static int colorlevels_slice_12_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:235
ThreadData::dst_linesize
int dst_linesize
Definition: vf_colorlevels.c:93
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
ThreadData::omin
int omin[4]
Definition: vf_colorlevels.c:101
colorlevels_preserve_slice_10_planar
static int colorlevels_preserve_slice_10_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:273
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:191
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
ff_fill_rgba_map
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:35
imgutils.h
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:370
AV_PIX_FMT_0RGB
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:255
coeff
static const double coeff[2][5]
Definition: vf_owdenoise.c:78
colorlevels_slice_14_planar
static int colorlevels_slice_14_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_colorlevels.c:243
drawutils.h
ff_filter_execute
static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: internal.h:142
int
int
Definition: ffmpeg_filter.c:156
NB_PRESERVE
@ NB_PRESERVE
Definition: preserve_color.h:34
DO_COMMON
#define DO_COMMON(type, clip, preserve, planar)
Definition: vf_colorlevels.c:104
Range::in_max
double in_max
Definition: vf_colorlevels.c:37
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
Range::out_max
double out_max
Definition: vf_colorlevels.c:38
CLIP16
#define CLIP16(x, depth)
Definition: vf_colorlevels.c:182
R
#define R
Definition: vf_colorlevels.c:31