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