FFmpeg  4.4.8
vf_colorchannelmixer.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 <float.h>
22 
23 #include "libavutil/opt.h"
24 #include "libavutil/pixdesc.h"
25 #include "avfilter.h"
26 #include "filters.h"
27 #include "drawutils.h"
28 #include "formats.h"
29 #include "internal.h"
30 #include "video.h"
31 
32 #define R 0
33 #define G 1
34 #define B 2
35 #define A 3
36 
37 typedef struct ThreadData {
38  AVFrame *in, *out;
39 } ThreadData;
40 
41 typedef struct ColorChannelMixerContext {
42  const AVClass *class;
43  double rr, rg, rb, ra;
44  double gr, gg, gb, ga;
45  double br, bg, bb, ba;
46  double ar, ag, ab, aa;
47  double sr, sg, sb;
49 
50  int *lut[4][4];
51 
52  int *buffer;
53 
55 
56  int (*filter_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
58 
59 #define OFFSET(x) offsetof(ColorChannelMixerContext, x)
60 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
61 
63  { "rr", "set the red gain for the red channel", OFFSET(rr), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS },
64  { "rg", "set the green gain for the red channel", OFFSET(rg), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
65  { "rb", "set the blue gain for the red channel", OFFSET(rb), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
66  { "ra", "set the alpha gain for the red channel", OFFSET(ra), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
67  { "gr", "set the red gain for the green channel", OFFSET(gr), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
68  { "gg", "set the green gain for the green channel", OFFSET(gg), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS },
69  { "gb", "set the blue gain for the green channel", OFFSET(gb), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
70  { "ga", "set the alpha gain for the green channel", OFFSET(ga), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
71  { "br", "set the red gain for the blue channel", OFFSET(br), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
72  { "bg", "set the green gain for the blue channel", OFFSET(bg), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
73  { "bb", "set the blue gain for the blue channel", OFFSET(bb), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS },
74  { "ba", "set the alpha gain for the blue channel", OFFSET(ba), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
75  { "ar", "set the red gain for the alpha channel", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
76  { "ag", "set the green gain for the alpha channel", OFFSET(ag), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
77  { "ab", "set the blue gain for the alpha channel", OFFSET(ab), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS },
78  { "aa", "set the alpha gain for the alpha channel", OFFSET(aa), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS },
79  { "pl", "preserve lightness", OFFSET(preserve_lightness), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 1, FLAGS },
80  { NULL }
81 };
82 
83 AVFILTER_DEFINE_CLASS(colorchannelmixer);
84 
86 {
87  static const enum AVPixelFormat pix_fmts[] = {
102  };
103 
105  if (!fmts_list)
106  return AVERROR(ENOMEM);
107  return ff_set_common_formats(ctx, fmts_list);
108 }
109 
110 static float lerpf(float v0, float v1, float f)
111 {
112  return v0 + (v1 - v0) * f;
113 }
114 
115 static void preservel(float *r, float *g, float *b, float lin, float lout)
116 {
117  *r *= lout / lin;
118  *g *= lout / lin;
119  *b *= lout / lin;
120 }
121 
122 static av_always_inline int filter_slice_rgba_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs,
123  int have_alpha, int pl)
124 {
125  ColorChannelMixerContext *s = ctx->priv;
126  ThreadData *td = arg;
127  AVFrame *in = td->in;
128  AVFrame *out = td->out;
129  const float l = s->preserve_lightness;
130  const float sr = s->sr;
131  const float sg = s->sg;
132  const float sb = s->sb;
133  const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs);
134  const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs);
135  const uint8_t *srcg = in->data[0] + slice_start * in->linesize[0];
136  const uint8_t *srcb = in->data[1] + slice_start * in->linesize[1];
137  const uint8_t *srcr = in->data[2] + slice_start * in->linesize[2];
138  const uint8_t *srca = in->data[3] + slice_start * in->linesize[3];
139  uint8_t *dstg = out->data[0] + slice_start * out->linesize[0];
140  uint8_t *dstb = out->data[1] + slice_start * out->linesize[1];
141  uint8_t *dstr = out->data[2] + slice_start * out->linesize[2];
142  uint8_t *dsta = out->data[3] + slice_start * out->linesize[3];
143  int i, j;
144 
145  for (i = slice_start; i < slice_end; i++) {
146  for (j = 0; j < out->width; j++) {
147  const uint8_t rin = srcr[j];
148  const uint8_t gin = srcg[j];
149  const uint8_t bin = srcb[j];
150  const uint8_t ain = have_alpha ? srca[j] : 0;
151  int rout, gout, bout;
152  float lin;
153 
154  if (pl)
155  lin = FFMAX3(rin, gin, bin) + FFMIN3(rin, gin, bin);
156 
157  rout = s->lut[R][R][rin] +
158  s->lut[R][G][gin] +
159  s->lut[R][B][bin] +
160  (have_alpha == 1 ? s->lut[R][A][ain] : 0);
161  gout = s->lut[G][R][rin] +
162  s->lut[G][G][gin] +
163  s->lut[G][B][bin] +
164  (have_alpha == 1 ? s->lut[G][A][ain] : 0);
165  bout = s->lut[B][R][rin] +
166  s->lut[B][G][gin] +
167  s->lut[B][B][bin] +
168  (have_alpha == 1 ? s->lut[B][A][ain] : 0);
169 
170  if (pl) {
171  float frout = rout / sr;
172  float fgout = gout / sg;
173  float fbout = bout / sb;
174  float lout = FFMAX3(frout, fgout, fbout) + FFMIN3(frout, fgout, fbout);
175 
176  preservel(&frout, &fgout, &fbout, lin, lout);
177 
178  rout = lrintf(lerpf(rout, frout, l));
179  gout = lrintf(lerpf(gout, fgout, l));
180  bout = lrintf(lerpf(bout, fbout, l));
181  }
182 
183  dstr[j] = av_clip_uint8(rout);
184  dstg[j] = av_clip_uint8(gout);
185  dstb[j] = av_clip_uint8(bout);
186 
187  if (have_alpha == 1) {
188  dsta[j] = av_clip_uint8(s->lut[A][R][rin] +
189  s->lut[A][G][gin] +
190  s->lut[A][B][bin] +
191  s->lut[A][A][ain]);
192  }
193  }
194 
195  srcg += in->linesize[0];
196  srcb += in->linesize[1];
197  srcr += in->linesize[2];
198  srca += in->linesize[3];
199  dstg += out->linesize[0];
200  dstb += out->linesize[1];
201  dstr += out->linesize[2];
202  dsta += out->linesize[3];
203  }
204 
205  return 0;
206 }
207 
208 static av_always_inline int filter_slice_rgba16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs,
209  int have_alpha, int depth, int pl)
210 {
211  ColorChannelMixerContext *s = ctx->priv;
212  ThreadData *td = arg;
213  AVFrame *in = td->in;
214  AVFrame *out = td->out;
215  const float l = s->preserve_lightness;
216  const float sr = s->sr;
217  const float sg = s->sg;
218  const float sb = s->sb;
219  const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs);
220  const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs);
221  const uint16_t *srcg = (const uint16_t *)(in->data[0] + slice_start * in->linesize[0]);
222  const uint16_t *srcb = (const uint16_t *)(in->data[1] + slice_start * in->linesize[1]);
223  const uint16_t *srcr = (const uint16_t *)(in->data[2] + slice_start * in->linesize[2]);
224  const uint16_t *srca = (const uint16_t *)(in->data[3] + slice_start * in->linesize[3]);
225  uint16_t *dstg = (uint16_t *)(out->data[0] + slice_start * out->linesize[0]);
226  uint16_t *dstb = (uint16_t *)(out->data[1] + slice_start * out->linesize[1]);
227  uint16_t *dstr = (uint16_t *)(out->data[2] + slice_start * out->linesize[2]);
228  uint16_t *dsta = (uint16_t *)(out->data[3] + slice_start * out->linesize[3]);
229  int i, j;
230 
231  for (i = slice_start; i < slice_end; i++) {
232  for (j = 0; j < out->width; j++) {
233  const uint16_t rin = srcr[j];
234  const uint16_t gin = srcg[j];
235  const uint16_t bin = srcb[j];
236  const uint16_t ain = have_alpha ? srca[j] : 0;
237  int rout, gout, bout;
238  float lin;
239 
240  if (pl)
241  lin = FFMAX3(rin, gin, bin) + FFMIN3(rin, gin, bin);
242 
243  rout = s->lut[R][R][rin] +
244  s->lut[R][G][gin] +
245  s->lut[R][B][bin] +
246  (have_alpha == 1 ? s->lut[R][A][ain] : 0);
247  gout = s->lut[G][R][rin] +
248  s->lut[G][G][gin] +
249  s->lut[G][B][bin] +
250  (have_alpha == 1 ? s->lut[G][A][ain] : 0);
251  bout = s->lut[B][R][rin] +
252  s->lut[B][G][gin] +
253  s->lut[B][B][bin] +
254  (have_alpha == 1 ? s->lut[B][A][ain] : 0);
255 
256  if (pl) {
257  float frout = rout / sr;
258  float fgout = gout / sg;
259  float fbout = bout / sb;
260  float lout = FFMAX3(frout, fgout, fbout) + FFMIN3(frout, fgout, fbout);
261 
262  preservel(&frout, &fgout, &fbout, lin, lout);
263 
264  rout = lrintf(lerpf(rout, frout, l));
265  gout = lrintf(lerpf(gout, fgout, l));
266  bout = lrintf(lerpf(bout, fbout, l));
267  }
268 
269  dstr[j] = av_clip_uintp2(rout, depth);
270  dstg[j] = av_clip_uintp2(gout, depth);
271  dstb[j] = av_clip_uintp2(bout, depth);
272 
273  if (have_alpha == 1) {
274  dsta[j] = av_clip_uintp2(s->lut[A][R][rin] +
275  s->lut[A][G][gin] +
276  s->lut[A][B][bin] +
277  s->lut[A][A][ain], depth);
278  }
279  }
280 
281  srcg += in->linesize[0] / 2;
282  srcb += in->linesize[1] / 2;
283  srcr += in->linesize[2] / 2;
284  srca += in->linesize[3] / 2;
285  dstg += out->linesize[0] / 2;
286  dstb += out->linesize[1] / 2;
287  dstr += out->linesize[2] / 2;
288  dsta += out->linesize[3] / 2;
289  }
290 
291  return 0;
292 }
293 
294 static int filter_slice_gbrp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
295 {
296  return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 0, 0);
297 }
298 
299 static int filter_slice_gbrap(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
300 {
301  return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 1, 0);
302 }
303 
304 static int filter_slice_gbrp_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
305 {
306  return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 0, 1);
307 }
308 
309 static int filter_slice_gbrap_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
310 {
311  return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 1, 1);
312 }
313 
314 static int filter_slice_gbrp9(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
315 {
316  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 9, 0);
317 }
318 
319 static int filter_slice_gbrp10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
320 {
321  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 10, 0);
322 }
323 
324 static int filter_slice_gbrap10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
325 {
326  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 10, 0);
327 }
328 
329 static int filter_slice_gbrp12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
330 {
331  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 12, 0);
332 }
333 
334 static int filter_slice_gbrap12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
335 {
336  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 12, 0);
337 }
338 
339 static int filter_slice_gbrp14(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
340 {
341  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 14, 0);
342 }
343 
344 static int filter_slice_gbrp16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
345 {
346  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 16, 0);
347 }
348 
349 static int filter_slice_gbrap16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
350 {
351  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 16, 0);
352 }
353 
354 static int filter_slice_gbrp9_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
355 {
356  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 9, 1);
357 }
358 
359 static int filter_slice_gbrp10_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
360 {
361  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 10, 1);
362 }
363 
364 static int filter_slice_gbrap10_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
365 {
366  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 10, 1);
367 }
368 
369 static int filter_slice_gbrp12_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
370 {
371  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 12, 1);
372 }
373 
374 static int filter_slice_gbrap12_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
375 {
376  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 12, 1);
377 }
378 
379 static int filter_slice_gbrp14_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
380 {
381  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 14, 1);
382 }
383 
384 static int filter_slice_gbrp16_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
385 {
386  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 16, 1);
387 }
388 
389 static int filter_slice_gbrap16_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
390 {
391  return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 16, 1);
392 }
393 
394 static av_always_inline int filter_slice_rgba_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs,
395  int have_alpha, int step, int pl)
396 {
397  ColorChannelMixerContext *s = ctx->priv;
398  ThreadData *td = arg;
399  AVFrame *in = td->in;
400  AVFrame *out = td->out;
401  const float l = s->preserve_lightness;
402  const float sr = s->sr;
403  const float sg = s->sg;
404  const float sb = s->sb;
405  const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs);
406  const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs);
407  const uint8_t roffset = s->rgba_map[R];
408  const uint8_t goffset = s->rgba_map[G];
409  const uint8_t boffset = s->rgba_map[B];
410  const uint8_t aoffset = s->rgba_map[A];
411  const uint8_t *srcrow = in->data[0] + slice_start * in->linesize[0];
412  uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0];
413  int i, j;
414 
415  for (i = slice_start; i < slice_end; i++) {
416  const uint8_t *src = srcrow;
417  uint8_t *dst = dstrow;
418 
419  for (j = 0; j < out->width * step; j += step) {
420  const uint8_t rin = src[j + roffset];
421  const uint8_t gin = src[j + goffset];
422  const uint8_t bin = src[j + boffset];
423  const uint8_t ain = src[j + aoffset];
424  int rout, gout, bout;
425  float lin;
426 
427  if (pl)
428  lin = FFMAX3(rin, gin, bin) + FFMIN3(rin, gin, bin);
429 
430  rout = s->lut[R][R][rin] +
431  s->lut[R][G][gin] +
432  s->lut[R][B][bin] +
433  (have_alpha == 1 ? s->lut[R][A][ain] : 0);
434  gout = s->lut[G][R][rin] +
435  s->lut[G][G][gin] +
436  s->lut[G][B][bin] +
437  (have_alpha == 1 ? s->lut[G][A][ain] : 0);
438  bout = s->lut[B][R][rin] +
439  s->lut[B][G][gin] +
440  s->lut[B][B][bin] +
441  (have_alpha == 1 ? s->lut[B][A][ain] : 0);
442 
443  if (pl) {
444  float frout = rout / sr;
445  float fgout = gout / sg;
446  float fbout = bout / sb;
447  float lout = FFMAX3(frout, fgout, fbout) + FFMIN3(frout, fgout, fbout);
448 
449  preservel(&frout, &fgout, &fbout, lin, lout);
450 
451  rout = lrintf(lerpf(rout, frout, l));
452  gout = lrintf(lerpf(gout, fgout, l));
453  bout = lrintf(lerpf(bout, fbout, l));
454  }
455 
456  dst[j + roffset] = av_clip_uint8(rout);
457  dst[j + goffset] = av_clip_uint8(gout);
458  dst[j + boffset] = av_clip_uint8(bout);
459 
460  if (have_alpha == 1) {
461  dst[j + aoffset] = av_clip_uint8(s->lut[A][R][rin] +
462  s->lut[A][G][gin] +
463  s->lut[A][B][bin] +
464  s->lut[A][A][ain]);
465  } else if (have_alpha == -1 && in != out)
466  dst[j + aoffset] = 0;
467  }
468 
469  srcrow += in->linesize[0];
470  dstrow += out->linesize[0];
471  }
472 
473  return 0;
474 }
475 
476 static av_always_inline int filter_slice_rgba16_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs,
477  int have_alpha, int step, int pl)
478 {
479  ColorChannelMixerContext *s = ctx->priv;
480  ThreadData *td = arg;
481  AVFrame *in = td->in;
482  AVFrame *out = td->out;
483  const float l = s->preserve_lightness;
484  const float sr = s->sr;
485  const float sg = s->sg;
486  const float sb = s->sb;
487  const int slice_start = ff_slice_pos(out->height, jobnr, nb_jobs);
488  const int slice_end = ff_slice_pos(out->height, jobnr + 1, nb_jobs);
489  const uint8_t roffset = s->rgba_map[R];
490  const uint8_t goffset = s->rgba_map[G];
491  const uint8_t boffset = s->rgba_map[B];
492  const uint8_t aoffset = s->rgba_map[A];
493  const uint8_t *srcrow = in->data[0] + slice_start * in->linesize[0];
494  uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0];
495  int i, j;
496 
497  for (i = slice_start; i < slice_end; i++) {
498  const uint16_t *src = (const uint16_t *)srcrow;
499  uint16_t *dst = (uint16_t *)dstrow;
500 
501  for (j = 0; j < out->width * step; j += step) {
502  const uint16_t rin = src[j + roffset];
503  const uint16_t gin = src[j + goffset];
504  const uint16_t bin = src[j + boffset];
505  const uint16_t ain = src[j + aoffset];
506  int rout, gout, bout;
507  float lin;
508 
509  if (pl)
510  lin = FFMAX3(rin, gin, bin) + FFMIN3(rin, gin, bin);
511 
512  rout = s->lut[R][R][rin] +
513  s->lut[R][G][gin] +
514  s->lut[R][B][bin] +
515  (have_alpha == 1 ? s->lut[R][A][ain] : 0);
516  gout = s->lut[G][R][rin] +
517  s->lut[G][G][gin] +
518  s->lut[G][B][bin] +
519  (have_alpha == 1 ? s->lut[G][A][ain] : 0);
520  bout = s->lut[B][R][rin] +
521  s->lut[B][G][gin] +
522  s->lut[B][B][bin] +
523  (have_alpha == 1 ? s->lut[B][A][ain] : 0);
524 
525  if (pl) {
526  float frout = rout / sr;
527  float fgout = gout / sg;
528  float fbout = bout / sb;
529  float lout = FFMAX3(frout, fgout, fbout) + FFMIN3(frout, fgout, fbout);
530 
531  preservel(&frout, &fgout, &fbout, lin, lout);
532 
533  rout = lrintf(lerpf(rout, frout, l));
534  gout = lrintf(lerpf(gout, fgout, l));
535  bout = lrintf(lerpf(bout, fbout, l));
536  }
537 
538  dst[j + roffset] = av_clip_uint16(rout);
539  dst[j + goffset] = av_clip_uint16(gout);
540  dst[j + boffset] = av_clip_uint16(bout);
541 
542  if (have_alpha == 1) {
543  dst[j + aoffset] = av_clip_uint16(s->lut[A][R][rin] +
544  s->lut[A][G][gin] +
545  s->lut[A][B][bin] +
546  s->lut[A][A][ain]);
547  }
548  }
549 
550  srcrow += in->linesize[0];
551  dstrow += out->linesize[0];
552  }
553 
554  return 0;
555 }
556 
557 static int filter_slice_rgba64(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
558 {
559  return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 0);
560 }
561 
562 static int filter_slice_rgb48(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
563 {
564  return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 0);
565 }
566 
567 static int filter_slice_rgba64_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
568 {
569  return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 1);
570 }
571 
572 static int filter_slice_rgb48_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
573 {
574  return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 1);
575 }
576 
577 static int filter_slice_rgba(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
578 {
579  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 0);
580 }
581 
582 static int filter_slice_rgb24(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
583 {
584  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 0);
585 }
586 
587 static int filter_slice_rgb0(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
588 {
589  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, -1, 4, 0);
590 }
591 
592 static int filter_slice_rgba_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
593 {
594  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 1);
595 }
596 
597 static int filter_slice_rgb24_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
598 {
599  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 1);
600 }
601 
602 static int filter_slice_rgb0_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
603 {
604  return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, -1, 4, 1);
605 }
606 
607 static int config_output(AVFilterLink *outlink)
608 {
609  AVFilterContext *ctx = outlink->src;
610  ColorChannelMixerContext *s = ctx->priv;
612  const int depth = desc->comp[0].depth;
613  int i, j, size, *buffer = s->buffer;
614 
615  ff_fill_rgba_map(s->rgba_map, outlink->format);
616 
617  size = 1 << depth;
618  if (!s->buffer) {
619  s->buffer = buffer = av_malloc(16 * size * sizeof(*s->buffer));
620  if (!s->buffer)
621  return AVERROR(ENOMEM);
622 
623  for (i = 0; i < 4; i++)
624  for (j = 0; j < 4; j++, buffer += size)
625  s->lut[i][j] = buffer;
626  }
627 
628  s->sr = s->rr + s->rg + s->rb + s->ra;
629  s->sg = s->gr + s->gg + s->gb + s->ga;
630  s->sb = s->br + s->bg + s->bb + s->ba;
631 
632  if (fabs(s->sr) <= DBL_EPSILON)
633  s->sr = 1.;
634 
635  if (fabs(s->sg) <= DBL_EPSILON)
636  s->sg = 1.;
637 
638  if (fabs(s->sb) <= DBL_EPSILON)
639  s->sb = 1.;
640 
641  for (i = 0; i < size; i++) {
642  s->lut[R][R][i] = lrint(i * s->rr);
643  s->lut[R][G][i] = lrint(i * s->rg);
644  s->lut[R][B][i] = lrint(i * s->rb);
645  s->lut[R][A][i] = lrint(i * s->ra);
646 
647  s->lut[G][R][i] = lrint(i * s->gr);
648  s->lut[G][G][i] = lrint(i * s->gg);
649  s->lut[G][B][i] = lrint(i * s->gb);
650  s->lut[G][A][i] = lrint(i * s->ga);
651 
652  s->lut[B][R][i] = lrint(i * s->br);
653  s->lut[B][G][i] = lrint(i * s->bg);
654  s->lut[B][B][i] = lrint(i * s->bb);
655  s->lut[B][A][i] = lrint(i * s->ba);
656 
657  s->lut[A][R][i] = lrint(i * s->ar);
658  s->lut[A][G][i] = lrint(i * s->ag);
659  s->lut[A][B][i] = lrint(i * s->ab);
660  s->lut[A][A][i] = lrint(i * s->aa);
661  }
662 
663  switch (outlink->format) {
664  case AV_PIX_FMT_BGR24:
665  case AV_PIX_FMT_RGB24:
666  s->filter_slice[0] = filter_slice_rgb24;
667  s->filter_slice[1] = filter_slice_rgb24_pl;
668  break;
669  case AV_PIX_FMT_0BGR:
670  case AV_PIX_FMT_0RGB:
671  case AV_PIX_FMT_BGR0:
672  case AV_PIX_FMT_RGB0:
673  s->filter_slice[0] = filter_slice_rgb0;
674  s->filter_slice[1] = filter_slice_rgb0_pl;
675  break;
676  case AV_PIX_FMT_ABGR:
677  case AV_PIX_FMT_ARGB:
678  case AV_PIX_FMT_BGRA:
679  case AV_PIX_FMT_RGBA:
680  s->filter_slice[0] = filter_slice_rgba;
681  s->filter_slice[1] = filter_slice_rgba_pl;
682  break;
683  case AV_PIX_FMT_BGR48:
684  case AV_PIX_FMT_RGB48:
685  s->filter_slice[0] = filter_slice_rgb48;
686  s->filter_slice[1] = filter_slice_rgb48_pl;
687  break;
688  case AV_PIX_FMT_BGRA64:
689  case AV_PIX_FMT_RGBA64:
690  s->filter_slice[0] = filter_slice_rgba64;
691  s->filter_slice[1] = filter_slice_rgba64_pl;
692  break;
693  case AV_PIX_FMT_GBRP:
694  s->filter_slice[0] = filter_slice_gbrp;
695  s->filter_slice[1] = filter_slice_gbrp_pl;
696  break;
697  case AV_PIX_FMT_GBRAP:
698  s->filter_slice[0] = filter_slice_gbrap;
699  s->filter_slice[1] = filter_slice_gbrap_pl;
700  break;
701  case AV_PIX_FMT_GBRP9:
702  s->filter_slice[0] = filter_slice_gbrp9;
703  s->filter_slice[1] = filter_slice_gbrp9_pl;
704  break;
705  case AV_PIX_FMT_GBRP10:
706  s->filter_slice[0] = filter_slice_gbrp10;
707  s->filter_slice[1] = filter_slice_gbrp10_pl;
708  break;
709  case AV_PIX_FMT_GBRAP10:
710  s->filter_slice[0] = filter_slice_gbrap10;
711  s->filter_slice[1] = filter_slice_gbrap10_pl;
712  break;
713  case AV_PIX_FMT_GBRP12:
714  s->filter_slice[0] = filter_slice_gbrp12;
715  s->filter_slice[1] = filter_slice_gbrp12_pl;
716  break;
717  case AV_PIX_FMT_GBRAP12:
718  s->filter_slice[0] = filter_slice_gbrap12;
719  s->filter_slice[1] = filter_slice_gbrap12_pl;
720  break;
721  case AV_PIX_FMT_GBRP14:
722  s->filter_slice[0] = filter_slice_gbrp14;
723  s->filter_slice[1] = filter_slice_gbrp14_pl;
724  break;
725  case AV_PIX_FMT_GBRP16:
726  s->filter_slice[0] = filter_slice_gbrp16;
727  s->filter_slice[1] = filter_slice_gbrp16_pl;
728  break;
729  case AV_PIX_FMT_GBRAP16:
730  s->filter_slice[0] = filter_slice_gbrap16;
731  s->filter_slice[1] = filter_slice_gbrap16_pl;
732  break;
733  }
734 
735  return 0;
736 }
737 
738 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
739 {
740  AVFilterContext *ctx = inlink->dst;
741  ColorChannelMixerContext *s = ctx->priv;
742  AVFilterLink *outlink = ctx->outputs[0];
743  const int pl = s->preserve_lightness > 0.;
744  ThreadData td;
745  AVFrame *out;
746 
747  if (av_frame_is_writable(in)) {
748  out = in;
749  } else {
750  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
751  if (!out) {
752  av_frame_free(&in);
753  return AVERROR(ENOMEM);
754  }
756  }
757 
758  td.in = in;
759  td.out = out;
760  ctx->internal->execute(ctx, s->filter_slice[pl], &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
761 
762  if (in != out)
763  av_frame_free(&in);
764  return ff_filter_frame(outlink, out);
765 }
766 
767 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
768  char *res, int res_len, int flags)
769 {
770  int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
771 
772  if (ret < 0)
773  return ret;
774 
775  return config_output(ctx->outputs[0]);
776 }
777 
779 {
780  ColorChannelMixerContext *s = ctx->priv;
781 
782  av_freep(&s->buffer);
783 }
784 
786  {
787  .name = "default",
788  .type = AVMEDIA_TYPE_VIDEO,
789  .filter_frame = filter_frame,
790  },
791  { NULL }
792 };
793 
795  {
796  .name = "default",
797  .type = AVMEDIA_TYPE_VIDEO,
798  .config_props = config_output,
799  },
800  { NULL }
801 };
802 
804  .name = "colorchannelmixer",
805  .description = NULL_IF_CONFIG_SMALL("Adjust colors by mixing color channels."),
806  .priv_size = sizeof(ColorChannelMixerContext),
807  .priv_class = &colorchannelmixer_class,
808  .uninit = uninit,
814 };
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
#define av_always_inline
Definition: attributes.h:45
#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
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.
#define flags(name, subs,...)
Definition: cbs_av1.c:572
#define s(width, name)
Definition: cbs_vp9.c:257
#define f(width, name)
Definition: cbs_vp9.c:255
#define FFMAX3(a, b, c)
Definition: common.h:104
#define FFMIN(a, b)
Definition: common.h:105
#define av_clip_uint8
Definition: common.h:128
#define av_clip_uint16
Definition: common.h:134
#define av_clip_uintp2
Definition: common.h:146
#define FFMIN3(a, b, c)
Definition: common.h:106
#define NULL
Definition: coverity.c:32
static __device__ float fabs(float a)
Definition: cuda_runtime.h:182
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:35
misc drawing utilities
int
static int ff_slice_pos(int total, int jobnr, int nb_jobs)
Compute the boundary index for a slice when work of size total is split into nb_jobs slices.
Definition: filters.h:271
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_DOUBLE
Definition: opt.h:227
#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 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
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
int i
Definition: input.c:407
const char * arg
Definition: jacosubdec.c:66
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
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:309
#define lrintf(x)
Definition: libm_mips.h:70
const char * desc
Definition: libsvtav1.c:79
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2033
AVOptions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2573
#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 v0
Definition: regdef.h:26
#define ra
Definition: regdef.h:57
#define td
Definition: regdef.h:70
static char buffer[20]
Definition: seek.c:32
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(* filter_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Used for passing data between threads.
Definition: dsddec.c:67
AVFrame * out
Definition: af_adeclick.c:502
AVFrame * in
Definition: af_adenorm.c:223
#define lrint
Definition: tablegen.h:53
#define av_freep(p)
#define av_malloc(s)
#define src
Definition: vp8dsp.c:255
FILE * out
Definition: movenc.c:54
AVFormatContext * ctx
Definition: movenc.c:48
int size
static int filter_slice_gbrap12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static av_always_inline int filter_slice_rgba_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha, int step, int pl)
static int filter_slice_gbrp9_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define B
static av_always_inline int filter_slice_rgba16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha, int depth, int pl)
static const AVFilterPad colorchannelmixer_outputs[]
static const AVFilterPad colorchannelmixer_inputs[]
static int filter_slice_gbrap(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_gbrap10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_rgb24_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_rgb24(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_gbrap_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AVFilter ff_vf_colorchannelmixer
static int filter_slice_gbrp9(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_gbrap12_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_rgb0(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int query_formats(AVFilterContext *ctx)
#define R
static int filter_slice_rgba64_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_rgba_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_gbrp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_rgba64(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define FLAGS
static int filter_slice_gbrp14_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_gbrp10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
AVFILTER_DEFINE_CLASS(colorchannelmixer)
static int filter_slice_rgb48(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_gbrp12_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
#define A
static int filter_slice_gbrap16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_rgb0_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static av_always_inline int filter_slice_rgba16_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha, int step, int pl)
static float lerpf(float v0, float v1, float f)
static int filter_slice_gbrp10_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static const AVOption colorchannelmixer_options[]
static int filter_slice_gbrp16_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_rgb48_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
static av_always_inline int filter_slice_rgba_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, int have_alpha, int pl)
static void preservel(float *r, float *g, float *b, float lin, float lout)
static av_cold void uninit(AVFilterContext *ctx)
static int filter_slice_gbrap10_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define OFFSET(x)
static int config_output(AVFilterLink *outlink)
static int filter_slice_gbrap16_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_gbrp_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_gbrp16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#define G
static int filter_slice_rgba(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_gbrp14(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static int filter_slice_gbrp12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
const char * b
Definition: vf_curves.c:119
const char * g
Definition: vf_curves.c:118
const char * r
Definition: vf_curves.c:117
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