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