]> git.sesse.net Git - ffmpeg/blob - libavfilter/vf_lut3d.c
Merge commit 'f25117a4286505b38c12466ef04459471de3c1b0'
[ffmpeg] / libavfilter / vf_lut3d.c
1 /*
2  * Copyright (c) 2013 Clément Bœsch
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 /**
22  * @file
23  * 3D Lookup table filter
24  */
25
26 #include "libavutil/opt.h"
27 #include "libavutil/file.h"
28 #include "libavutil/intreadwrite.h"
29 #include "libavutil/avassert.h"
30 #include "libavutil/pixdesc.h"
31 #include "libavutil/avstring.h"
32 #include "avfilter.h"
33 #include "drawutils.h"
34 #include "formats.h"
35 #include "framesync.h"
36 #include "internal.h"
37 #include "video.h"
38
39 #define R 0
40 #define G 1
41 #define B 2
42 #define A 3
43
44 enum interp_mode {
45     INTERPOLATE_NEAREST,
46     INTERPOLATE_TRILINEAR,
47     INTERPOLATE_TETRAHEDRAL,
48     NB_INTERP_MODE
49 };
50
51 struct rgbvec {
52     float r, g, b;
53 };
54
55 /* 3D LUT don't often go up to level 32, but it is common to have a Hald CLUT
56  * of 512x512 (64x64x64) */
57 #define MAX_LEVEL 64
58
59 typedef struct LUT3DContext {
60     const AVClass *class;
61     int interpolation;          ///<interp_mode
62     char *file;
63     uint8_t rgba_map[4];
64     int step;
65     avfilter_action_func *interp;
66     struct rgbvec lut[MAX_LEVEL][MAX_LEVEL][MAX_LEVEL];
67     int lutsize;
68 #if CONFIG_HALDCLUT_FILTER
69     uint8_t clut_rgba_map[4];
70     int clut_step;
71     int clut_bits;
72     int clut_planar;
73     int clut_width;
74     FFFrameSync fs;
75 #endif
76 } LUT3DContext;
77
78 typedef struct ThreadData {
79     AVFrame *in, *out;
80 } ThreadData;
81
82 #define OFFSET(x) offsetof(LUT3DContext, x)
83 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
84 #define COMMON_OPTIONS \
85     { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, NB_INTERP_MODE-1, FLAGS, "interp_mode" }, \
86         { "nearest",     "use values from the nearest defined points",            0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_NEAREST},     INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \
87         { "trilinear",   "interpolate values using the 8 points defining a cube", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TRILINEAR},   INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \
88         { "tetrahedral", "interpolate values using a tetrahedron",                0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TETRAHEDRAL}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \
89     { NULL }
90
91 static inline float lerpf(float v0, float v1, float f)
92 {
93     return v0 + (v1 - v0) * f;
94 }
95
96 static inline struct rgbvec lerp(const struct rgbvec *v0, const struct rgbvec *v1, float f)
97 {
98     struct rgbvec v = {
99         lerpf(v0->r, v1->r, f), lerpf(v0->g, v1->g, f), lerpf(v0->b, v1->b, f)
100     };
101     return v;
102 }
103
104 #define NEAR(x) ((int)((x) + .5))
105 #define PREV(x) ((int)(x))
106 #define NEXT(x) (FFMIN((int)(x) + 1, lut3d->lutsize - 1))
107
108 /**
109  * Get the nearest defined point
110  */
111 static inline struct rgbvec interp_nearest(const LUT3DContext *lut3d,
112                                            const struct rgbvec *s)
113 {
114     return lut3d->lut[NEAR(s->r)][NEAR(s->g)][NEAR(s->b)];
115 }
116
117 /**
118  * Interpolate using the 8 vertices of a cube
119  * @see https://en.wikipedia.org/wiki/Trilinear_interpolation
120  */
121 static inline struct rgbvec interp_trilinear(const LUT3DContext *lut3d,
122                                              const struct rgbvec *s)
123 {
124     const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)};
125     const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)};
126     const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]};
127     const struct rgbvec c000 = lut3d->lut[prev[0]][prev[1]][prev[2]];
128     const struct rgbvec c001 = lut3d->lut[prev[0]][prev[1]][next[2]];
129     const struct rgbvec c010 = lut3d->lut[prev[0]][next[1]][prev[2]];
130     const struct rgbvec c011 = lut3d->lut[prev[0]][next[1]][next[2]];
131     const struct rgbvec c100 = lut3d->lut[next[0]][prev[1]][prev[2]];
132     const struct rgbvec c101 = lut3d->lut[next[0]][prev[1]][next[2]];
133     const struct rgbvec c110 = lut3d->lut[next[0]][next[1]][prev[2]];
134     const struct rgbvec c111 = lut3d->lut[next[0]][next[1]][next[2]];
135     const struct rgbvec c00  = lerp(&c000, &c100, d.r);
136     const struct rgbvec c10  = lerp(&c010, &c110, d.r);
137     const struct rgbvec c01  = lerp(&c001, &c101, d.r);
138     const struct rgbvec c11  = lerp(&c011, &c111, d.r);
139     const struct rgbvec c0   = lerp(&c00,  &c10,  d.g);
140     const struct rgbvec c1   = lerp(&c01,  &c11,  d.g);
141     const struct rgbvec c    = lerp(&c0,   &c1,   d.b);
142     return c;
143 }
144
145 /**
146  * Tetrahedral interpolation. Based on code found in Truelight Software Library paper.
147  * @see http://www.filmlight.ltd.uk/pdf/whitepapers/FL-TL-TN-0057-SoftwareLib.pdf
148  */
149 static inline struct rgbvec interp_tetrahedral(const LUT3DContext *lut3d,
150                                                const struct rgbvec *s)
151 {
152     const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)};
153     const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)};
154     const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]};
155     const struct rgbvec c000 = lut3d->lut[prev[0]][prev[1]][prev[2]];
156     const struct rgbvec c111 = lut3d->lut[next[0]][next[1]][next[2]];
157     struct rgbvec c;
158     if (d.r > d.g) {
159         if (d.g > d.b) {
160             const struct rgbvec c100 = lut3d->lut[next[0]][prev[1]][prev[2]];
161             const struct rgbvec c110 = lut3d->lut[next[0]][next[1]][prev[2]];
162             c.r = (1-d.r) * c000.r + (d.r-d.g) * c100.r + (d.g-d.b) * c110.r + (d.b) * c111.r;
163             c.g = (1-d.r) * c000.g + (d.r-d.g) * c100.g + (d.g-d.b) * c110.g + (d.b) * c111.g;
164             c.b = (1-d.r) * c000.b + (d.r-d.g) * c100.b + (d.g-d.b) * c110.b + (d.b) * c111.b;
165         } else if (d.r > d.b) {
166             const struct rgbvec c100 = lut3d->lut[next[0]][prev[1]][prev[2]];
167             const struct rgbvec c101 = lut3d->lut[next[0]][prev[1]][next[2]];
168             c.r = (1-d.r) * c000.r + (d.r-d.b) * c100.r + (d.b-d.g) * c101.r + (d.g) * c111.r;
169             c.g = (1-d.r) * c000.g + (d.r-d.b) * c100.g + (d.b-d.g) * c101.g + (d.g) * c111.g;
170             c.b = (1-d.r) * c000.b + (d.r-d.b) * c100.b + (d.b-d.g) * c101.b + (d.g) * c111.b;
171         } else {
172             const struct rgbvec c001 = lut3d->lut[prev[0]][prev[1]][next[2]];
173             const struct rgbvec c101 = lut3d->lut[next[0]][prev[1]][next[2]];
174             c.r = (1-d.b) * c000.r + (d.b-d.r) * c001.r + (d.r-d.g) * c101.r + (d.g) * c111.r;
175             c.g = (1-d.b) * c000.g + (d.b-d.r) * c001.g + (d.r-d.g) * c101.g + (d.g) * c111.g;
176             c.b = (1-d.b) * c000.b + (d.b-d.r) * c001.b + (d.r-d.g) * c101.b + (d.g) * c111.b;
177         }
178     } else {
179         if (d.b > d.g) {
180             const struct rgbvec c001 = lut3d->lut[prev[0]][prev[1]][next[2]];
181             const struct rgbvec c011 = lut3d->lut[prev[0]][next[1]][next[2]];
182             c.r = (1-d.b) * c000.r + (d.b-d.g) * c001.r + (d.g-d.r) * c011.r + (d.r) * c111.r;
183             c.g = (1-d.b) * c000.g + (d.b-d.g) * c001.g + (d.g-d.r) * c011.g + (d.r) * c111.g;
184             c.b = (1-d.b) * c000.b + (d.b-d.g) * c001.b + (d.g-d.r) * c011.b + (d.r) * c111.b;
185         } else if (d.b > d.r) {
186             const struct rgbvec c010 = lut3d->lut[prev[0]][next[1]][prev[2]];
187             const struct rgbvec c011 = lut3d->lut[prev[0]][next[1]][next[2]];
188             c.r = (1-d.g) * c000.r + (d.g-d.b) * c010.r + (d.b-d.r) * c011.r + (d.r) * c111.r;
189             c.g = (1-d.g) * c000.g + (d.g-d.b) * c010.g + (d.b-d.r) * c011.g + (d.r) * c111.g;
190             c.b = (1-d.g) * c000.b + (d.g-d.b) * c010.b + (d.b-d.r) * c011.b + (d.r) * c111.b;
191         } else {
192             const struct rgbvec c010 = lut3d->lut[prev[0]][next[1]][prev[2]];
193             const struct rgbvec c110 = lut3d->lut[next[0]][next[1]][prev[2]];
194             c.r = (1-d.g) * c000.r + (d.g-d.r) * c010.r + (d.r-d.b) * c110.r + (d.b) * c111.r;
195             c.g = (1-d.g) * c000.g + (d.g-d.r) * c010.g + (d.r-d.b) * c110.g + (d.b) * c111.g;
196             c.b = (1-d.g) * c000.b + (d.g-d.r) * c010.b + (d.r-d.b) * c110.b + (d.b) * c111.b;
197         }
198     }
199     return c;
200 }
201
202 #define DEFINE_INTERP_FUNC_PLANAR(name, nbits, depth)                                                  \
203 static int interp_##nbits##_##name##_p##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
204 {                                                                                                      \
205     int x, y;                                                                                          \
206     const LUT3DContext *lut3d = ctx->priv;                                                             \
207     const ThreadData *td = arg;                                                                        \
208     const AVFrame *in  = td->in;                                                                       \
209     const AVFrame *out = td->out;                                                                      \
210     const int direct = out == in;                                                                      \
211     const int slice_start = (in->height *  jobnr   ) / nb_jobs;                                        \
212     const int slice_end   = (in->height * (jobnr+1)) / nb_jobs;                                        \
213     uint8_t *grow = out->data[0] + slice_start * out->linesize[0];                                     \
214     uint8_t *brow = out->data[1] + slice_start * out->linesize[1];                                     \
215     uint8_t *rrow = out->data[2] + slice_start * out->linesize[2];                                     \
216     uint8_t *arow = out->data[3] + slice_start * out->linesize[3];                                     \
217     const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0];                              \
218     const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1];                              \
219     const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2];                              \
220     const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3];                              \
221     const float scale = (1. / ((1<<depth) - 1)) * (lut3d->lutsize - 1);                                \
222                                                                                                        \
223     for (y = slice_start; y < slice_end; y++) {                                                        \
224         uint##nbits##_t *dstg = (uint##nbits##_t *)grow;                                               \
225         uint##nbits##_t *dstb = (uint##nbits##_t *)brow;                                               \
226         uint##nbits##_t *dstr = (uint##nbits##_t *)rrow;                                               \
227         uint##nbits##_t *dsta = (uint##nbits##_t *)arow;                                               \
228         const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow;                                \
229         const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow;                                \
230         const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow;                                \
231         const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow;                                \
232         for (x = 0; x < in->width; x++) {                                                              \
233             const struct rgbvec scaled_rgb = {srcr[x] * scale,                                         \
234                                               srcg[x] * scale,                                         \
235                                               srcb[x] * scale};                                        \
236             struct rgbvec vec = interp_##name(lut3d, &scaled_rgb);                                     \
237             dstr[x] = av_clip_uintp2(vec.r * (float)((1<<depth) - 1), depth);                          \
238             dstg[x] = av_clip_uintp2(vec.g * (float)((1<<depth) - 1), depth);                          \
239             dstb[x] = av_clip_uintp2(vec.b * (float)((1<<depth) - 1), depth);                          \
240             if (!direct && in->linesize[3])                                                            \
241                 dsta[x] = srca[x];                                                                     \
242         }                                                                                              \
243         grow += out->linesize[0];                                                                      \
244         brow += out->linesize[1];                                                                      \
245         rrow += out->linesize[2];                                                                      \
246         arow += out->linesize[3];                                                                      \
247         srcgrow += in->linesize[0];                                                                    \
248         srcbrow += in->linesize[1];                                                                    \
249         srcrrow += in->linesize[2];                                                                    \
250         srcarow += in->linesize[3];                                                                    \
251     }                                                                                                  \
252     return 0;                                                                                          \
253 }
254
255 DEFINE_INTERP_FUNC_PLANAR(nearest,     8, 8)
256 DEFINE_INTERP_FUNC_PLANAR(trilinear,   8, 8)
257 DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 8, 8)
258
259 DEFINE_INTERP_FUNC_PLANAR(nearest,     16, 9)
260 DEFINE_INTERP_FUNC_PLANAR(trilinear,   16, 9)
261 DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 9)
262
263 DEFINE_INTERP_FUNC_PLANAR(nearest,     16, 10)
264 DEFINE_INTERP_FUNC_PLANAR(trilinear,   16, 10)
265 DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 10)
266
267 DEFINE_INTERP_FUNC_PLANAR(nearest,     16, 12)
268 DEFINE_INTERP_FUNC_PLANAR(trilinear,   16, 12)
269 DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 12)
270
271 DEFINE_INTERP_FUNC_PLANAR(nearest,     16, 14)
272 DEFINE_INTERP_FUNC_PLANAR(trilinear,   16, 14)
273 DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 14)
274
275 DEFINE_INTERP_FUNC_PLANAR(nearest,     16, 16)
276 DEFINE_INTERP_FUNC_PLANAR(trilinear,   16, 16)
277 DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 16)
278
279 #define DEFINE_INTERP_FUNC(name, nbits)                                                             \
280 static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)         \
281 {                                                                                                   \
282     int x, y;                                                                                       \
283     const LUT3DContext *lut3d = ctx->priv;                                                          \
284     const ThreadData *td = arg;                                                                     \
285     const AVFrame *in  = td->in;                                                                    \
286     const AVFrame *out = td->out;                                                                   \
287     const int direct = out == in;                                                                   \
288     const int step = lut3d->step;                                                                   \
289     const uint8_t r = lut3d->rgba_map[R];                                                           \
290     const uint8_t g = lut3d->rgba_map[G];                                                           \
291     const uint8_t b = lut3d->rgba_map[B];                                                           \
292     const uint8_t a = lut3d->rgba_map[A];                                                           \
293     const int slice_start = (in->height *  jobnr   ) / nb_jobs;                                     \
294     const int slice_end   = (in->height * (jobnr+1)) / nb_jobs;                                     \
295     uint8_t       *dstrow = out->data[0] + slice_start * out->linesize[0];                          \
296     const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0];                          \
297     const float scale = (1. / ((1<<nbits) - 1)) * (lut3d->lutsize - 1);                             \
298                                                                                                     \
299     for (y = slice_start; y < slice_end; y++) {                                                     \
300         uint##nbits##_t *dst = (uint##nbits##_t *)dstrow;                                           \
301         const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow;                               \
302         for (x = 0; x < in->width * step; x += step) {                                              \
303             const struct rgbvec scaled_rgb = {src[x + r] * scale,                                   \
304                                               src[x + g] * scale,                                   \
305                                               src[x + b] * scale};                                  \
306             struct rgbvec vec = interp_##name(lut3d, &scaled_rgb);                                  \
307             dst[x + r] = av_clip_uint##nbits(vec.r * (float)((1<<nbits) - 1));                      \
308             dst[x + g] = av_clip_uint##nbits(vec.g * (float)((1<<nbits) - 1));                      \
309             dst[x + b] = av_clip_uint##nbits(vec.b * (float)((1<<nbits) - 1));                      \
310             if (!direct && step == 4)                                                               \
311                 dst[x + a] = src[x + a];                                                            \
312         }                                                                                           \
313         dstrow += out->linesize[0];                                                                 \
314         srcrow += in ->linesize[0];                                                                 \
315     }                                                                                               \
316     return 0;                                                                                       \
317 }
318
319 DEFINE_INTERP_FUNC(nearest,     8)
320 DEFINE_INTERP_FUNC(trilinear,   8)
321 DEFINE_INTERP_FUNC(tetrahedral, 8)
322
323 DEFINE_INTERP_FUNC(nearest,     16)
324 DEFINE_INTERP_FUNC(trilinear,   16)
325 DEFINE_INTERP_FUNC(tetrahedral, 16)
326
327 #define MAX_LINE_SIZE 512
328
329 static int skip_line(const char *p)
330 {
331     while (*p && av_isspace(*p))
332         p++;
333     return !*p || *p == '#';
334 }
335
336 #define NEXT_LINE(loop_cond) do {                           \
337     if (!fgets(line, sizeof(line), f)) {                    \
338         av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n");      \
339         return AVERROR_INVALIDDATA;                         \
340     }                                                       \
341 } while (loop_cond)
342
343 /* Basically r g and b float values on each line, with a facultative 3DLUTSIZE
344  * directive; seems to be generated by Davinci */
345 static int parse_dat(AVFilterContext *ctx, FILE *f)
346 {
347     LUT3DContext *lut3d = ctx->priv;
348     char line[MAX_LINE_SIZE];
349     int i, j, k, size;
350
351     lut3d->lutsize = size = 33;
352
353     NEXT_LINE(skip_line(line));
354     if (!strncmp(line, "3DLUTSIZE ", 10)) {
355         size = strtol(line + 10, NULL, 0);
356         if (size < 2 || size > MAX_LEVEL) {
357             av_log(ctx, AV_LOG_ERROR, "Too large or invalid 3D LUT size\n");
358             return AVERROR(EINVAL);
359         }
360         lut3d->lutsize = size;
361         NEXT_LINE(skip_line(line));
362     }
363     for (k = 0; k < size; k++) {
364         for (j = 0; j < size; j++) {
365             for (i = 0; i < size; i++) {
366                 struct rgbvec *vec = &lut3d->lut[k][j][i];
367                 if (k != 0 || j != 0 || i != 0)
368                     NEXT_LINE(skip_line(line));
369                 if (sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3)
370                     return AVERROR_INVALIDDATA;
371             }
372         }
373     }
374     return 0;
375 }
376
377 /* Iridas format */
378 static int parse_cube(AVFilterContext *ctx, FILE *f)
379 {
380     LUT3DContext *lut3d = ctx->priv;
381     char line[MAX_LINE_SIZE];
382     float min[3] = {0.0, 0.0, 0.0};
383     float max[3] = {1.0, 1.0, 1.0};
384
385     while (fgets(line, sizeof(line), f)) {
386         if (!strncmp(line, "LUT_3D_SIZE ", 12)) {
387             int i, j, k;
388             const int size = strtol(line + 12, NULL, 0);
389
390             if (size < 2 || size > MAX_LEVEL) {
391                 av_log(ctx, AV_LOG_ERROR, "Too large or invalid 3D LUT size\n");
392                 return AVERROR(EINVAL);
393             }
394             lut3d->lutsize = size;
395             for (k = 0; k < size; k++) {
396                 for (j = 0; j < size; j++) {
397                     for (i = 0; i < size; i++) {
398                         struct rgbvec *vec = &lut3d->lut[i][j][k];
399
400                         do {
401 try_again:
402                             NEXT_LINE(0);
403                             if (!strncmp(line, "DOMAIN_", 7)) {
404                                 float *vals = NULL;
405                                 if      (!strncmp(line + 7, "MIN ", 4)) vals = min;
406                                 else if (!strncmp(line + 7, "MAX ", 4)) vals = max;
407                                 if (!vals)
408                                     return AVERROR_INVALIDDATA;
409                                 sscanf(line + 11, "%f %f %f", vals, vals + 1, vals + 2);
410                                 av_log(ctx, AV_LOG_DEBUG, "min: %f %f %f | max: %f %f %f\n",
411                                        min[0], min[1], min[2], max[0], max[1], max[2]);
412                                 goto try_again;
413                             }
414                         } while (skip_line(line));
415                         if (sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3)
416                             return AVERROR_INVALIDDATA;
417                         vec->r *= max[0] - min[0];
418                         vec->g *= max[1] - min[1];
419                         vec->b *= max[2] - min[2];
420                     }
421                 }
422             }
423             break;
424         }
425     }
426     return 0;
427 }
428
429 /* Assume 17x17x17 LUT with a 16-bit depth
430  * FIXME: it seems there are various 3dl formats */
431 static int parse_3dl(AVFilterContext *ctx, FILE *f)
432 {
433     char line[MAX_LINE_SIZE];
434     LUT3DContext *lut3d = ctx->priv;
435     int i, j, k;
436     const int size = 17;
437     const float scale = 16*16*16;
438
439     lut3d->lutsize = size;
440     NEXT_LINE(skip_line(line));
441     for (k = 0; k < size; k++) {
442         for (j = 0; j < size; j++) {
443             for (i = 0; i < size; i++) {
444                 int r, g, b;
445                 struct rgbvec *vec = &lut3d->lut[k][j][i];
446
447                 NEXT_LINE(skip_line(line));
448                 if (sscanf(line, "%d %d %d", &r, &g, &b) != 3)
449                     return AVERROR_INVALIDDATA;
450                 vec->r = r / scale;
451                 vec->g = g / scale;
452                 vec->b = b / scale;
453             }
454         }
455     }
456     return 0;
457 }
458
459 /* Pandora format */
460 static int parse_m3d(AVFilterContext *ctx, FILE *f)
461 {
462     LUT3DContext *lut3d = ctx->priv;
463     float scale;
464     int i, j, k, size, in = -1, out = -1;
465     char line[MAX_LINE_SIZE];
466     uint8_t rgb_map[3] = {0, 1, 2};
467
468     while (fgets(line, sizeof(line), f)) {
469         if      (!strncmp(line, "in",  2)) in  = strtol(line + 2, NULL, 0);
470         else if (!strncmp(line, "out", 3)) out = strtol(line + 3, NULL, 0);
471         else if (!strncmp(line, "values", 6)) {
472             const char *p = line + 6;
473 #define SET_COLOR(id) do {                  \
474     while (av_isspace(*p))                  \
475         p++;                                \
476     switch (*p) {                           \
477     case 'r': rgb_map[id] = 0; break;       \
478     case 'g': rgb_map[id] = 1; break;       \
479     case 'b': rgb_map[id] = 2; break;       \
480     }                                       \
481     while (*p && !av_isspace(*p))           \
482         p++;                                \
483 } while (0)
484             SET_COLOR(0);
485             SET_COLOR(1);
486             SET_COLOR(2);
487             break;
488         }
489     }
490
491     if (in == -1 || out == -1) {
492         av_log(ctx, AV_LOG_ERROR, "in and out must be defined\n");
493         return AVERROR_INVALIDDATA;
494     }
495     if (in < 2 || out < 2 ||
496         in  > MAX_LEVEL*MAX_LEVEL*MAX_LEVEL ||
497         out > MAX_LEVEL*MAX_LEVEL*MAX_LEVEL) {
498         av_log(ctx, AV_LOG_ERROR, "invalid in (%d) or out (%d)\n", in, out);
499         return AVERROR_INVALIDDATA;
500     }
501     for (size = 1; size*size*size < in; size++);
502     lut3d->lutsize = size;
503     scale = 1. / (out - 1);
504
505     for (k = 0; k < size; k++) {
506         for (j = 0; j < size; j++) {
507             for (i = 0; i < size; i++) {
508                 struct rgbvec *vec = &lut3d->lut[k][j][i];
509                 float val[3];
510
511                 NEXT_LINE(0);
512                 if (sscanf(line, "%f %f %f", val, val + 1, val + 2) != 3)
513                     return AVERROR_INVALIDDATA;
514                 vec->r = val[rgb_map[0]] * scale;
515                 vec->g = val[rgb_map[1]] * scale;
516                 vec->b = val[rgb_map[2]] * scale;
517             }
518         }
519     }
520     return 0;
521 }
522
523 static void set_identity_matrix(LUT3DContext *lut3d, int size)
524 {
525     int i, j, k;
526     const float c = 1. / (size - 1);
527
528     lut3d->lutsize = size;
529     for (k = 0; k < size; k++) {
530         for (j = 0; j < size; j++) {
531             for (i = 0; i < size; i++) {
532                 struct rgbvec *vec = &lut3d->lut[k][j][i];
533                 vec->r = k * c;
534                 vec->g = j * c;
535                 vec->b = i * c;
536             }
537         }
538     }
539 }
540
541 static int query_formats(AVFilterContext *ctx)
542 {
543     static const enum AVPixelFormat pix_fmts[] = {
544         AV_PIX_FMT_RGB24,  AV_PIX_FMT_BGR24,
545         AV_PIX_FMT_RGBA,   AV_PIX_FMT_BGRA,
546         AV_PIX_FMT_ARGB,   AV_PIX_FMT_ABGR,
547         AV_PIX_FMT_0RGB,   AV_PIX_FMT_0BGR,
548         AV_PIX_FMT_RGB0,   AV_PIX_FMT_BGR0,
549         AV_PIX_FMT_RGB48,  AV_PIX_FMT_BGR48,
550         AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64,
551         AV_PIX_FMT_GBRP,   AV_PIX_FMT_GBRAP,
552         AV_PIX_FMT_GBRP9,
553         AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10,
554         AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
555         AV_PIX_FMT_GBRP14,
556         AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16,
557         AV_PIX_FMT_NONE
558     };
559     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
560     if (!fmts_list)
561         return AVERROR(ENOMEM);
562     return ff_set_common_formats(ctx, fmts_list);
563 }
564
565 static int config_input(AVFilterLink *inlink)
566 {
567     int depth, is16bit = 0, planar = 0;
568     LUT3DContext *lut3d = inlink->dst->priv;
569     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
570
571     depth = desc->comp[0].depth;
572
573     switch (inlink->format) {
574     case AV_PIX_FMT_RGB48:
575     case AV_PIX_FMT_BGR48:
576     case AV_PIX_FMT_RGBA64:
577     case AV_PIX_FMT_BGRA64:
578         is16bit = 1;
579         break;
580     case AV_PIX_FMT_GBRP9:
581     case AV_PIX_FMT_GBRP10:
582     case AV_PIX_FMT_GBRP12:
583     case AV_PIX_FMT_GBRP14:
584     case AV_PIX_FMT_GBRP16:
585     case AV_PIX_FMT_GBRAP10:
586     case AV_PIX_FMT_GBRAP12:
587     case AV_PIX_FMT_GBRAP16:
588         is16bit = 1;
589     case AV_PIX_FMT_GBRP:
590     case AV_PIX_FMT_GBRAP:
591         planar = 1;
592         break;
593     }
594
595     ff_fill_rgba_map(lut3d->rgba_map, inlink->format);
596     lut3d->step = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit);
597
598 #define SET_FUNC(name) do {                                     \
599     if (planar) {                                               \
600         switch (depth) {                                        \
601         case  8: lut3d->interp = interp_8_##name##_p8;   break; \
602         case  9: lut3d->interp = interp_16_##name##_p9;  break; \
603         case 10: lut3d->interp = interp_16_##name##_p10; break; \
604         case 12: lut3d->interp = interp_16_##name##_p12; break; \
605         case 14: lut3d->interp = interp_16_##name##_p14; break; \
606         case 16: lut3d->interp = interp_16_##name##_p16; break; \
607         }                                                       \
608     } else if (is16bit) { lut3d->interp = interp_16_##name;     \
609     } else {       lut3d->interp = interp_8_##name; }           \
610 } while (0)
611
612     switch (lut3d->interpolation) {
613     case INTERPOLATE_NEAREST:     SET_FUNC(nearest);        break;
614     case INTERPOLATE_TRILINEAR:   SET_FUNC(trilinear);      break;
615     case INTERPOLATE_TETRAHEDRAL: SET_FUNC(tetrahedral);    break;
616     default:
617         av_assert0(0);
618     }
619
620     return 0;
621 }
622
623 static AVFrame *apply_lut(AVFilterLink *inlink, AVFrame *in)
624 {
625     AVFilterContext *ctx = inlink->dst;
626     LUT3DContext *lut3d = ctx->priv;
627     AVFilterLink *outlink = inlink->dst->outputs[0];
628     AVFrame *out;
629     ThreadData td;
630
631     if (av_frame_is_writable(in)) {
632         out = in;
633     } else {
634         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
635         if (!out) {
636             av_frame_free(&in);
637             return NULL;
638         }
639         av_frame_copy_props(out, in);
640     }
641
642     td.in  = in;
643     td.out = out;
644     ctx->internal->execute(ctx, lut3d->interp, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
645
646     if (out != in)
647         av_frame_free(&in);
648
649     return out;
650 }
651
652 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
653 {
654     AVFilterLink *outlink = inlink->dst->outputs[0];
655     AVFrame *out = apply_lut(inlink, in);
656     if (!out)
657         return AVERROR(ENOMEM);
658     return ff_filter_frame(outlink, out);
659 }
660
661 #if CONFIG_LUT3D_FILTER
662 static const AVOption lut3d_options[] = {
663     { "file", "set 3D LUT file name", OFFSET(file), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
664     COMMON_OPTIONS
665 };
666
667 AVFILTER_DEFINE_CLASS(lut3d);
668
669 static av_cold int lut3d_init(AVFilterContext *ctx)
670 {
671     int ret;
672     FILE *f;
673     const char *ext;
674     LUT3DContext *lut3d = ctx->priv;
675
676     if (!lut3d->file) {
677         set_identity_matrix(lut3d, 32);
678         return 0;
679     }
680
681     f = fopen(lut3d->file, "r");
682     if (!f) {
683         ret = AVERROR(errno);
684         av_log(ctx, AV_LOG_ERROR, "%s: %s\n", lut3d->file, av_err2str(ret));
685         return ret;
686     }
687
688     ext = strrchr(lut3d->file, '.');
689     if (!ext) {
690         av_log(ctx, AV_LOG_ERROR, "Unable to guess the format from the extension\n");
691         ret = AVERROR_INVALIDDATA;
692         goto end;
693     }
694     ext++;
695
696     if (!av_strcasecmp(ext, "dat")) {
697         ret = parse_dat(ctx, f);
698     } else if (!av_strcasecmp(ext, "3dl")) {
699         ret = parse_3dl(ctx, f);
700     } else if (!av_strcasecmp(ext, "cube")) {
701         ret = parse_cube(ctx, f);
702     } else if (!av_strcasecmp(ext, "m3d")) {
703         ret = parse_m3d(ctx, f);
704     } else {
705         av_log(ctx, AV_LOG_ERROR, "Unrecognized '.%s' file type\n", ext);
706         ret = AVERROR(EINVAL);
707     }
708
709     if (!ret && !lut3d->lutsize) {
710         av_log(ctx, AV_LOG_ERROR, "3D LUT is empty\n");
711         ret = AVERROR_INVALIDDATA;
712     }
713
714 end:
715     fclose(f);
716     return ret;
717 }
718
719 static const AVFilterPad lut3d_inputs[] = {
720     {
721         .name         = "default",
722         .type         = AVMEDIA_TYPE_VIDEO,
723         .filter_frame = filter_frame,
724         .config_props = config_input,
725     },
726     { NULL }
727 };
728
729 static const AVFilterPad lut3d_outputs[] = {
730     {
731         .name = "default",
732         .type = AVMEDIA_TYPE_VIDEO,
733     },
734     { NULL }
735 };
736
737 AVFilter ff_vf_lut3d = {
738     .name          = "lut3d",
739     .description   = NULL_IF_CONFIG_SMALL("Adjust colors using a 3D LUT."),
740     .priv_size     = sizeof(LUT3DContext),
741     .init          = lut3d_init,
742     .query_formats = query_formats,
743     .inputs        = lut3d_inputs,
744     .outputs       = lut3d_outputs,
745     .priv_class    = &lut3d_class,
746     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
747 };
748 #endif
749
750 #if CONFIG_HALDCLUT_FILTER
751
752 static void update_clut_packed(LUT3DContext *lut3d, const AVFrame *frame)
753 {
754     const uint8_t *data = frame->data[0];
755     const int linesize  = frame->linesize[0];
756     const int w = lut3d->clut_width;
757     const int step = lut3d->clut_step;
758     const uint8_t *rgba_map = lut3d->clut_rgba_map;
759     const int level = lut3d->lutsize;
760
761 #define LOAD_CLUT(nbits) do {                                           \
762     int i, j, k, x = 0, y = 0;                                          \
763                                                                         \
764     for (k = 0; k < level; k++) {                                       \
765         for (j = 0; j < level; j++) {                                   \
766             for (i = 0; i < level; i++) {                               \
767                 const uint##nbits##_t *src = (const uint##nbits##_t *)  \
768                     (data + y*linesize + x*step);                       \
769                 struct rgbvec *vec = &lut3d->lut[i][j][k];              \
770                 vec->r = src[rgba_map[0]] / (float)((1<<(nbits)) - 1);  \
771                 vec->g = src[rgba_map[1]] / (float)((1<<(nbits)) - 1);  \
772                 vec->b = src[rgba_map[2]] / (float)((1<<(nbits)) - 1);  \
773                 if (++x == w) {                                         \
774                     x = 0;                                              \
775                     y++;                                                \
776                 }                                                       \
777             }                                                           \
778         }                                                               \
779     }                                                                   \
780 } while (0)
781
782     switch (lut3d->clut_bits) {
783     case  8: LOAD_CLUT(8);  break;
784     case 16: LOAD_CLUT(16); break;
785     }
786 }
787
788 static void update_clut_planar(LUT3DContext *lut3d, const AVFrame *frame)
789 {
790     const uint8_t *datag = frame->data[0];
791     const uint8_t *datab = frame->data[1];
792     const uint8_t *datar = frame->data[2];
793     const int glinesize  = frame->linesize[0];
794     const int blinesize  = frame->linesize[1];
795     const int rlinesize  = frame->linesize[2];
796     const int w = lut3d->clut_width;
797     const int level = lut3d->lutsize;
798
799 #define LOAD_CLUT_PLANAR(nbits, depth) do {                             \
800     int i, j, k, x = 0, y = 0;                                          \
801                                                                         \
802     for (k = 0; k < level; k++) {                                       \
803         for (j = 0; j < level; j++) {                                   \
804             for (i = 0; i < level; i++) {                               \
805                 const uint##nbits##_t *gsrc = (const uint##nbits##_t *) \
806                     (datag + y*glinesize);                              \
807                 const uint##nbits##_t *bsrc = (const uint##nbits##_t *) \
808                     (datab + y*blinesize);                              \
809                 const uint##nbits##_t *rsrc = (const uint##nbits##_t *) \
810                     (datar + y*rlinesize);                              \
811                 struct rgbvec *vec = &lut3d->lut[i][j][k];              \
812                 vec->r = gsrc[x] / (float)((1<<(depth)) - 1);           \
813                 vec->g = bsrc[x] / (float)((1<<(depth)) - 1);           \
814                 vec->b = rsrc[x] / (float)((1<<(depth)) - 1);           \
815                 if (++x == w) {                                         \
816                     x = 0;                                              \
817                     y++;                                                \
818                 }                                                       \
819             }                                                           \
820         }                                                               \
821     }                                                                   \
822 } while (0)
823
824     switch (lut3d->clut_bits) {
825     case  8: LOAD_CLUT_PLANAR(8, 8);   break;
826     case  9: LOAD_CLUT_PLANAR(16, 9);  break;
827     case 10: LOAD_CLUT_PLANAR(16, 10); break;
828     case 12: LOAD_CLUT_PLANAR(16, 12); break;
829     case 14: LOAD_CLUT_PLANAR(16, 14); break;
830     case 16: LOAD_CLUT_PLANAR(16, 16); break;
831     }
832 }
833
834 static int config_output(AVFilterLink *outlink)
835 {
836     AVFilterContext *ctx = outlink->src;
837     LUT3DContext *lut3d = ctx->priv;
838     int ret;
839
840     ret = ff_framesync_init_dualinput(&lut3d->fs, ctx);
841     if (ret < 0)
842         return ret;
843     outlink->w = ctx->inputs[0]->w;
844     outlink->h = ctx->inputs[0]->h;
845     outlink->time_base = ctx->inputs[0]->time_base;
846     if ((ret = ff_framesync_configure(&lut3d->fs)) < 0)
847         return ret;
848     return 0;
849 }
850
851 static int activate(AVFilterContext *ctx)
852 {
853     LUT3DContext *s = ctx->priv;
854     return ff_framesync_activate(&s->fs);
855 }
856
857 static int config_clut(AVFilterLink *inlink)
858 {
859     int size, level, w, h;
860     AVFilterContext *ctx = inlink->dst;
861     LUT3DContext *lut3d = ctx->priv;
862     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
863
864     av_assert0(desc);
865
866     lut3d->clut_bits = desc->comp[0].depth;
867     lut3d->clut_planar = av_pix_fmt_count_planes(inlink->format) > 1;
868
869     lut3d->clut_step = av_get_padded_bits_per_pixel(desc) >> 3;
870     ff_fill_rgba_map(lut3d->clut_rgba_map, inlink->format);
871
872     if (inlink->w > inlink->h)
873         av_log(ctx, AV_LOG_INFO, "Padding on the right (%dpx) of the "
874                "Hald CLUT will be ignored\n", inlink->w - inlink->h);
875     else if (inlink->w < inlink->h)
876         av_log(ctx, AV_LOG_INFO, "Padding at the bottom (%dpx) of the "
877                "Hald CLUT will be ignored\n", inlink->h - inlink->w);
878     lut3d->clut_width = w = h = FFMIN(inlink->w, inlink->h);
879
880     for (level = 1; level*level*level < w; level++);
881     size = level*level*level;
882     if (size != w) {
883         av_log(ctx, AV_LOG_WARNING, "The Hald CLUT width does not match the level\n");
884         return AVERROR_INVALIDDATA;
885     }
886     av_assert0(w == h && w == size);
887     level *= level;
888     if (level > MAX_LEVEL) {
889         const int max_clut_level = sqrt(MAX_LEVEL);
890         const int max_clut_size  = max_clut_level*max_clut_level*max_clut_level;
891         av_log(ctx, AV_LOG_ERROR, "Too large Hald CLUT "
892                "(maximum level is %d, or %dx%d CLUT)\n",
893                max_clut_level, max_clut_size, max_clut_size);
894         return AVERROR(EINVAL);
895     }
896     lut3d->lutsize = level;
897
898     return 0;
899 }
900
901 static int update_apply_clut(FFFrameSync *fs)
902 {
903     AVFilterContext *ctx = fs->parent;
904     LUT3DContext *lut3d = ctx->priv;
905     AVFilterLink *inlink = ctx->inputs[0];
906     AVFrame *master, *second, *out;
907     int ret;
908
909     ret = ff_framesync_dualinput_get(fs, &master, &second);
910     if (ret < 0)
911         return ret;
912     if (!second)
913         return ff_filter_frame(ctx->outputs[0], master);
914     if (lut3d->clut_planar)
915         update_clut_planar(ctx->priv, second);
916     else
917         update_clut_packed(ctx->priv, second);
918     out = apply_lut(inlink, master);
919     return ff_filter_frame(ctx->outputs[0], out);
920 }
921
922 static av_cold int haldclut_init(AVFilterContext *ctx)
923 {
924     LUT3DContext *lut3d = ctx->priv;
925     lut3d->fs.on_event = update_apply_clut;
926     return 0;
927 }
928
929 static av_cold void haldclut_uninit(AVFilterContext *ctx)
930 {
931     LUT3DContext *lut3d = ctx->priv;
932     ff_framesync_uninit(&lut3d->fs);
933 }
934
935 static const AVOption haldclut_options[] = {
936     COMMON_OPTIONS
937 };
938
939 FRAMESYNC_DEFINE_CLASS(haldclut, LUT3DContext, fs);
940
941 static const AVFilterPad haldclut_inputs[] = {
942     {
943         .name         = "main",
944         .type         = AVMEDIA_TYPE_VIDEO,
945         .config_props = config_input,
946     },{
947         .name         = "clut",
948         .type         = AVMEDIA_TYPE_VIDEO,
949         .config_props = config_clut,
950     },
951     { NULL }
952 };
953
954 static const AVFilterPad haldclut_outputs[] = {
955     {
956         .name          = "default",
957         .type          = AVMEDIA_TYPE_VIDEO,
958         .config_props  = config_output,
959     },
960     { NULL }
961 };
962
963 AVFilter ff_vf_haldclut = {
964     .name          = "haldclut",
965     .description   = NULL_IF_CONFIG_SMALL("Adjust colors using a Hald CLUT."),
966     .priv_size     = sizeof(LUT3DContext),
967     .preinit       = haldclut_framesync_preinit,
968     .init          = haldclut_init,
969     .uninit        = haldclut_uninit,
970     .query_formats = query_formats,
971     .activate      = activate,
972     .inputs        = haldclut_inputs,
973     .outputs       = haldclut_outputs,
974     .priv_class    = &haldclut_class,
975     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
976 };
977 #endif