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