]> git.sesse.net Git - ffmpeg/blob - libavfilter/vf_lut3d.c
avfilter/vf_lut3d: use av_fopen_utf8()
[ffmpeg] / libavfilter / vf_lut3d.c
1 /*
2  * Copyright (c) 2013 Clément Bœsch
3  * Copyright (c) 2018 Paul B Mahol
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
23  * @file
24  * 3D Lookup table filter
25  */
26
27 #include "libavutil/opt.h"
28 #include "libavutil/file.h"
29 #include "libavutil/intreadwrite.h"
30 #include "libavutil/avassert.h"
31 #include "libavutil/pixdesc.h"
32 #include "libavutil/avstring.h"
33 #include "avfilter.h"
34 #include "drawutils.h"
35 #include "formats.h"
36 #include "framesync.h"
37 #include "internal.h"
38 #include "video.h"
39
40 #define R 0
41 #define G 1
42 #define B 2
43 #define A 3
44
45 enum interp_mode {
46     INTERPOLATE_NEAREST,
47     INTERPOLATE_TRILINEAR,
48     INTERPOLATE_TETRAHEDRAL,
49     NB_INTERP_MODE
50 };
51
52 struct rgbvec {
53     float r, g, b;
54 };
55
56 /* 3D LUT don't often go up to level 32, but it is common to have a Hald CLUT
57  * of 512x512 (64x64x64) */
58 #define MAX_LEVEL 256
59
60 typedef struct LUT3DContext {
61     const AVClass *class;
62     int interpolation;          ///<interp_mode
63     char *file;
64     uint8_t rgba_map[4];
65     int step;
66     avfilter_action_func *interp;
67     struct rgbvec scale;
68     struct rgbvec *lut;
69     int lutsize;
70     int lutsize2;
71 #if CONFIG_HALDCLUT_FILTER
72     uint8_t clut_rgba_map[4];
73     int clut_step;
74     int clut_bits;
75     int clut_planar;
76     int clut_width;
77     FFFrameSync fs;
78 #endif
79 } LUT3DContext;
80
81 typedef struct ThreadData {
82     AVFrame *in, *out;
83 } ThreadData;
84
85 #define OFFSET(x) offsetof(LUT3DContext, x)
86 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
87 #define COMMON_OPTIONS \
88     { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, NB_INTERP_MODE-1, FLAGS, "interp_mode" }, \
89         { "nearest",     "use values from the nearest defined points",            0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_NEAREST},     INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \
90         { "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" }, \
91         { "tetrahedral", "interpolate values using a tetrahedron",                0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TETRAHEDRAL}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \
92     { NULL }
93
94 static inline float lerpf(float v0, float v1, float f)
95 {
96     return v0 + (v1 - v0) * f;
97 }
98
99 static inline struct rgbvec lerp(const struct rgbvec *v0, const struct rgbvec *v1, float f)
100 {
101     struct rgbvec v = {
102         lerpf(v0->r, v1->r, f), lerpf(v0->g, v1->g, f), lerpf(v0->b, v1->b, f)
103     };
104     return v;
105 }
106
107 #define NEAR(x) ((int)((x) + .5))
108 #define PREV(x) ((int)(x))
109 #define NEXT(x) (FFMIN((int)(x) + 1, lut3d->lutsize - 1))
110
111 /**
112  * Get the nearest defined point
113  */
114 static inline struct rgbvec interp_nearest(const LUT3DContext *lut3d,
115                                            const struct rgbvec *s)
116 {
117     return lut3d->lut[NEAR(s->r) * lut3d->lutsize2 + NEAR(s->g) * lut3d->lutsize + NEAR(s->b)];
118 }
119
120 /**
121  * Interpolate using the 8 vertices of a cube
122  * @see https://en.wikipedia.org/wiki/Trilinear_interpolation
123  */
124 static inline struct rgbvec interp_trilinear(const LUT3DContext *lut3d,
125                                              const struct rgbvec *s)
126 {
127     const int lutsize2 = lut3d->lutsize2;
128     const int lutsize  = lut3d->lutsize;
129     const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)};
130     const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)};
131     const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]};
132     const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
133     const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
134     const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
135     const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
136     const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
137     const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
138     const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
139     const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
140     const struct rgbvec c00  = lerp(&c000, &c100, d.r);
141     const struct rgbvec c10  = lerp(&c010, &c110, d.r);
142     const struct rgbvec c01  = lerp(&c001, &c101, d.r);
143     const struct rgbvec c11  = lerp(&c011, &c111, d.r);
144     const struct rgbvec c0   = lerp(&c00,  &c10,  d.g);
145     const struct rgbvec c1   = lerp(&c01,  &c11,  d.g);
146     const struct rgbvec c    = lerp(&c0,   &c1,   d.b);
147     return c;
148 }
149
150 /**
151  * Tetrahedral interpolation. Based on code found in Truelight Software Library paper.
152  * @see http://www.filmlight.ltd.uk/pdf/whitepapers/FL-TL-TN-0057-SoftwareLib.pdf
153  */
154 static inline struct rgbvec interp_tetrahedral(const LUT3DContext *lut3d,
155                                                const struct rgbvec *s)
156 {
157     const int lutsize2 = lut3d->lutsize2;
158     const int lutsize  = lut3d->lutsize;
159     const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)};
160     const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)};
161     const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]};
162     const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
163     const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
164     struct rgbvec c;
165     if (d.r > d.g) {
166         if (d.g > d.b) {
167             const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
168             const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
169             c.r = (1-d.r) * c000.r + (d.r-d.g) * c100.r + (d.g-d.b) * c110.r + (d.b) * c111.r;
170             c.g = (1-d.r) * c000.g + (d.r-d.g) * c100.g + (d.g-d.b) * c110.g + (d.b) * c111.g;
171             c.b = (1-d.r) * c000.b + (d.r-d.g) * c100.b + (d.g-d.b) * c110.b + (d.b) * c111.b;
172         } else if (d.r > d.b) {
173             const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
174             const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
175             c.r = (1-d.r) * c000.r + (d.r-d.b) * c100.r + (d.b-d.g) * c101.r + (d.g) * c111.r;
176             c.g = (1-d.r) * c000.g + (d.r-d.b) * c100.g + (d.b-d.g) * c101.g + (d.g) * c111.g;
177             c.b = (1-d.r) * c000.b + (d.r-d.b) * c100.b + (d.b-d.g) * c101.b + (d.g) * c111.b;
178         } else {
179             const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
180             const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
181             c.r = (1-d.b) * c000.r + (d.b-d.r) * c001.r + (d.r-d.g) * c101.r + (d.g) * c111.r;
182             c.g = (1-d.b) * c000.g + (d.b-d.r) * c001.g + (d.r-d.g) * c101.g + (d.g) * c111.g;
183             c.b = (1-d.b) * c000.b + (d.b-d.r) * c001.b + (d.r-d.g) * c101.b + (d.g) * c111.b;
184         }
185     } else {
186         if (d.b > d.g) {
187             const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
188             const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
189             c.r = (1-d.b) * c000.r + (d.b-d.g) * c001.r + (d.g-d.r) * c011.r + (d.r) * c111.r;
190             c.g = (1-d.b) * c000.g + (d.b-d.g) * c001.g + (d.g-d.r) * c011.g + (d.r) * c111.g;
191             c.b = (1-d.b) * c000.b + (d.b-d.g) * c001.b + (d.g-d.r) * c011.b + (d.r) * c111.b;
192         } else if (d.b > d.r) {
193             const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
194             const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
195             c.r = (1-d.g) * c000.r + (d.g-d.b) * c010.r + (d.b-d.r) * c011.r + (d.r) * c111.r;
196             c.g = (1-d.g) * c000.g + (d.g-d.b) * c010.g + (d.b-d.r) * c011.g + (d.r) * c111.g;
197             c.b = (1-d.g) * c000.b + (d.g-d.b) * c010.b + (d.b-d.r) * c011.b + (d.r) * c111.b;
198         } else {
199             const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
200             const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
201             c.r = (1-d.g) * c000.r + (d.g-d.r) * c010.r + (d.r-d.b) * c110.r + (d.b) * c111.r;
202             c.g = (1-d.g) * c000.g + (d.g-d.r) * c010.g + (d.r-d.b) * c110.g + (d.b) * c111.g;
203             c.b = (1-d.g) * c000.b + (d.g-d.r) * c010.b + (d.r-d.b) * c110.b + (d.b) * c111.b;
204         }
205     }
206     return c;
207 }
208
209 #define DEFINE_INTERP_FUNC_PLANAR(name, nbits, depth)                                                  \
210 static int interp_##nbits##_##name##_p##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
211 {                                                                                                      \
212     int x, y;                                                                                          \
213     const LUT3DContext *lut3d = ctx->priv;                                                             \
214     const ThreadData *td = arg;                                                                        \
215     const AVFrame *in  = td->in;                                                                       \
216     const AVFrame *out = td->out;                                                                      \
217     const int direct = out == in;                                                                      \
218     const int slice_start = (in->height *  jobnr   ) / nb_jobs;                                        \
219     const int slice_end   = (in->height * (jobnr+1)) / nb_jobs;                                        \
220     uint8_t *grow = out->data[0] + slice_start * out->linesize[0];                                     \
221     uint8_t *brow = out->data[1] + slice_start * out->linesize[1];                                     \
222     uint8_t *rrow = out->data[2] + slice_start * out->linesize[2];                                     \
223     uint8_t *arow = out->data[3] + slice_start * out->linesize[3];                                     \
224     const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0];                              \
225     const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1];                              \
226     const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2];                              \
227     const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3];                              \
228     const float scale_r = (lut3d->scale.r / ((1<<depth) - 1)) * (lut3d->lutsize - 1);                  \
229     const float scale_g = (lut3d->scale.g / ((1<<depth) - 1)) * (lut3d->lutsize - 1);                  \
230     const float scale_b = (lut3d->scale.b / ((1<<depth) - 1)) * (lut3d->lutsize - 1);                  \
231                                                                                                        \
232     for (y = slice_start; y < slice_end; y++) {                                                        \
233         uint##nbits##_t *dstg = (uint##nbits##_t *)grow;                                               \
234         uint##nbits##_t *dstb = (uint##nbits##_t *)brow;                                               \
235         uint##nbits##_t *dstr = (uint##nbits##_t *)rrow;                                               \
236         uint##nbits##_t *dsta = (uint##nbits##_t *)arow;                                               \
237         const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow;                                \
238         const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow;                                \
239         const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow;                                \
240         const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow;                                \
241         for (x = 0; x < in->width; x++) {                                                              \
242             const struct rgbvec scaled_rgb = {srcr[x] * scale_r,                                       \
243                                               srcg[x] * scale_g,                                       \
244                                               srcb[x] * scale_b};                                      \
245             struct rgbvec vec = interp_##name(lut3d, &scaled_rgb);                                     \
246             dstr[x] = av_clip_uintp2(vec.r * (float)((1<<depth) - 1), depth);                          \
247             dstg[x] = av_clip_uintp2(vec.g * (float)((1<<depth) - 1), depth);                          \
248             dstb[x] = av_clip_uintp2(vec.b * (float)((1<<depth) - 1), depth);                          \
249             if (!direct && in->linesize[3])                                                            \
250                 dsta[x] = srca[x];                                                                     \
251         }                                                                                              \
252         grow += out->linesize[0];                                                                      \
253         brow += out->linesize[1];                                                                      \
254         rrow += out->linesize[2];                                                                      \
255         arow += out->linesize[3];                                                                      \
256         srcgrow += in->linesize[0];                                                                    \
257         srcbrow += in->linesize[1];                                                                    \
258         srcrrow += in->linesize[2];                                                                    \
259         srcarow += in->linesize[3];                                                                    \
260     }                                                                                                  \
261     return 0;                                                                                          \
262 }
263
264 DEFINE_INTERP_FUNC_PLANAR(nearest,     8, 8)
265 DEFINE_INTERP_FUNC_PLANAR(trilinear,   8, 8)
266 DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 8, 8)
267
268 DEFINE_INTERP_FUNC_PLANAR(nearest,     16, 9)
269 DEFINE_INTERP_FUNC_PLANAR(trilinear,   16, 9)
270 DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 9)
271
272 DEFINE_INTERP_FUNC_PLANAR(nearest,     16, 10)
273 DEFINE_INTERP_FUNC_PLANAR(trilinear,   16, 10)
274 DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 10)
275
276 DEFINE_INTERP_FUNC_PLANAR(nearest,     16, 12)
277 DEFINE_INTERP_FUNC_PLANAR(trilinear,   16, 12)
278 DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 12)
279
280 DEFINE_INTERP_FUNC_PLANAR(nearest,     16, 14)
281 DEFINE_INTERP_FUNC_PLANAR(trilinear,   16, 14)
282 DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 14)
283
284 DEFINE_INTERP_FUNC_PLANAR(nearest,     16, 16)
285 DEFINE_INTERP_FUNC_PLANAR(trilinear,   16, 16)
286 DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 16)
287
288 #define DEFINE_INTERP_FUNC(name, nbits)                                                             \
289 static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)         \
290 {                                                                                                   \
291     int x, y;                                                                                       \
292     const LUT3DContext *lut3d = ctx->priv;                                                          \
293     const ThreadData *td = arg;                                                                     \
294     const AVFrame *in  = td->in;                                                                    \
295     const AVFrame *out = td->out;                                                                   \
296     const int direct = out == in;                                                                   \
297     const int step = lut3d->step;                                                                   \
298     const uint8_t r = lut3d->rgba_map[R];                                                           \
299     const uint8_t g = lut3d->rgba_map[G];                                                           \
300     const uint8_t b = lut3d->rgba_map[B];                                                           \
301     const uint8_t a = lut3d->rgba_map[A];                                                           \
302     const int slice_start = (in->height *  jobnr   ) / nb_jobs;                                     \
303     const int slice_end   = (in->height * (jobnr+1)) / nb_jobs;                                     \
304     uint8_t       *dstrow = out->data[0] + slice_start * out->linesize[0];                          \
305     const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0];                          \
306     const float scale_r = (lut3d->scale.r / ((1<<nbits) - 1)) * (lut3d->lutsize - 1);               \
307     const float scale_g = (lut3d->scale.g / ((1<<nbits) - 1)) * (lut3d->lutsize - 1);               \
308     const float scale_b = (lut3d->scale.b / ((1<<nbits) - 1)) * (lut3d->lutsize - 1);               \
309                                                                                                     \
310     for (y = slice_start; y < slice_end; y++) {                                                     \
311         uint##nbits##_t *dst = (uint##nbits##_t *)dstrow;                                           \
312         const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow;                               \
313         for (x = 0; x < in->width * step; x += step) {                                              \
314             const struct rgbvec scaled_rgb = {src[x + r] * scale_r,                                 \
315                                               src[x + g] * scale_g,                                 \
316                                               src[x + b] * scale_b};                                \
317             struct rgbvec vec = interp_##name(lut3d, &scaled_rgb);                                  \
318             dst[x + r] = av_clip_uint##nbits(vec.r * (float)((1<<nbits) - 1));                      \
319             dst[x + g] = av_clip_uint##nbits(vec.g * (float)((1<<nbits) - 1));                      \
320             dst[x + b] = av_clip_uint##nbits(vec.b * (float)((1<<nbits) - 1));                      \
321             if (!direct && step == 4)                                                               \
322                 dst[x + a] = src[x + a];                                                            \
323         }                                                                                           \
324         dstrow += out->linesize[0];                                                                 \
325         srcrow += in ->linesize[0];                                                                 \
326     }                                                                                               \
327     return 0;                                                                                       \
328 }
329
330 DEFINE_INTERP_FUNC(nearest,     8)
331 DEFINE_INTERP_FUNC(trilinear,   8)
332 DEFINE_INTERP_FUNC(tetrahedral, 8)
333
334 DEFINE_INTERP_FUNC(nearest,     16)
335 DEFINE_INTERP_FUNC(trilinear,   16)
336 DEFINE_INTERP_FUNC(tetrahedral, 16)
337
338 #define MAX_LINE_SIZE 512
339
340 static int skip_line(const char *p)
341 {
342     while (*p && av_isspace(*p))
343         p++;
344     return !*p || *p == '#';
345 }
346
347 #define NEXT_LINE(loop_cond) do {                           \
348     if (!fgets(line, sizeof(line), f)) {                    \
349         av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n");      \
350         return AVERROR_INVALIDDATA;                         \
351     }                                                       \
352 } while (loop_cond)
353
354 static int allocate_3dlut(AVFilterContext *ctx, int lutsize)
355 {
356     LUT3DContext *lut3d = ctx->priv;
357
358     if (lutsize < 2 || lutsize > MAX_LEVEL) {
359         av_log(ctx, AV_LOG_ERROR, "Too large or invalid 3D LUT size\n");
360         return AVERROR(EINVAL);
361     }
362
363     av_freep(&lut3d->lut);
364     lut3d->lut = av_malloc_array(lutsize * lutsize * lutsize, sizeof(*lut3d->lut));
365     if (!lut3d->lut)
366         return AVERROR(ENOMEM);
367     lut3d->lutsize = lutsize;
368     lut3d->lutsize2 = lutsize * lutsize;
369     return 0;
370 }
371
372 /* Basically r g and b float values on each line, with a facultative 3DLUTSIZE
373  * directive; seems to be generated by Davinci */
374 static int parse_dat(AVFilterContext *ctx, FILE *f)
375 {
376     LUT3DContext *lut3d = ctx->priv;
377     char line[MAX_LINE_SIZE];
378     int ret, i, j, k, size, size2;
379
380     lut3d->lutsize = size = 33;
381     size2 = size * size;
382
383     NEXT_LINE(skip_line(line));
384     if (!strncmp(line, "3DLUTSIZE ", 10)) {
385         size = strtol(line + 10, NULL, 0);
386
387         NEXT_LINE(skip_line(line));
388     }
389
390     ret = allocate_3dlut(ctx, size);
391     if (ret < 0)
392         return ret;
393
394     for (k = 0; k < size; k++) {
395         for (j = 0; j < size; j++) {
396             for (i = 0; i < size; i++) {
397                 struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i];
398                 if (k != 0 || j != 0 || i != 0)
399                     NEXT_LINE(skip_line(line));
400                 if (av_sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3)
401                     return AVERROR_INVALIDDATA;
402             }
403         }
404     }
405     return 0;
406 }
407
408 /* Iridas format */
409 static int parse_cube(AVFilterContext *ctx, FILE *f)
410 {
411     LUT3DContext *lut3d = ctx->priv;
412     char line[MAX_LINE_SIZE];
413     float min[3] = {0.0, 0.0, 0.0};
414     float max[3] = {1.0, 1.0, 1.0};
415
416     while (fgets(line, sizeof(line), f)) {
417         if (!strncmp(line, "LUT_3D_SIZE", 11)) {
418             int ret, i, j, k;
419             const int size = strtol(line + 12, NULL, 0);
420             const int size2 = size * size;
421
422             ret = allocate_3dlut(ctx, size);
423             if (ret < 0)
424                 return ret;
425
426             for (k = 0; k < size; k++) {
427                 for (j = 0; j < size; j++) {
428                     for (i = 0; i < size; i++) {
429                         struct rgbvec *vec = &lut3d->lut[i * size2 + j * size + k];
430
431                         do {
432 try_again:
433                             NEXT_LINE(0);
434                             if (!strncmp(line, "DOMAIN_", 7)) {
435                                 float *vals = NULL;
436                                 if      (!strncmp(line + 7, "MIN ", 4)) vals = min;
437                                 else if (!strncmp(line + 7, "MAX ", 4)) vals = max;
438                                 if (!vals)
439                                     return AVERROR_INVALIDDATA;
440                                 av_sscanf(line + 11, "%f %f %f", vals, vals + 1, vals + 2);
441                                 av_log(ctx, AV_LOG_DEBUG, "min: %f %f %f | max: %f %f %f\n",
442                                        min[0], min[1], min[2], max[0], max[1], max[2]);
443                                 goto try_again;
444                             } else if (!strncmp(line, "TITLE", 5)) {
445                                 goto try_again;
446                             }
447                         } while (skip_line(line));
448                         if (av_sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3)
449                             return AVERROR_INVALIDDATA;
450                     }
451                 }
452             }
453             break;
454         }
455     }
456
457     lut3d->scale.r = av_clipf(1. / (max[0] - min[0]), 0.f, 1.f);
458     lut3d->scale.g = av_clipf(1. / (max[1] - min[1]), 0.f, 1.f);
459     lut3d->scale.b = av_clipf(1. / (max[2] - min[2]), 0.f, 1.f);
460
461     return 0;
462 }
463
464 /* Assume 17x17x17 LUT with a 16-bit depth
465  * FIXME: it seems there are various 3dl formats */
466 static int parse_3dl(AVFilterContext *ctx, FILE *f)
467 {
468     char line[MAX_LINE_SIZE];
469     LUT3DContext *lut3d = ctx->priv;
470     int ret, i, j, k;
471     const int size = 17;
472     const int size2 = 17 * 17;
473     const float scale = 16*16*16;
474
475     lut3d->lutsize = size;
476
477     ret = allocate_3dlut(ctx, size);
478     if (ret < 0)
479         return ret;
480
481     NEXT_LINE(skip_line(line));
482     for (k = 0; k < size; k++) {
483         for (j = 0; j < size; j++) {
484             for (i = 0; i < size; i++) {
485                 int r, g, b;
486                 struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i];
487
488                 NEXT_LINE(skip_line(line));
489                 if (av_sscanf(line, "%d %d %d", &r, &g, &b) != 3)
490                     return AVERROR_INVALIDDATA;
491                 vec->r = r / scale;
492                 vec->g = g / scale;
493                 vec->b = b / scale;
494             }
495         }
496     }
497     return 0;
498 }
499
500 /* Pandora format */
501 static int parse_m3d(AVFilterContext *ctx, FILE *f)
502 {
503     LUT3DContext *lut3d = ctx->priv;
504     float scale;
505     int ret, i, j, k, size, size2, in = -1, out = -1;
506     char line[MAX_LINE_SIZE];
507     uint8_t rgb_map[3] = {0, 1, 2};
508
509     while (fgets(line, sizeof(line), f)) {
510         if      (!strncmp(line, "in",  2)) in  = strtol(line + 2, NULL, 0);
511         else if (!strncmp(line, "out", 3)) out = strtol(line + 3, NULL, 0);
512         else if (!strncmp(line, "values", 6)) {
513             const char *p = line + 6;
514 #define SET_COLOR(id) do {                  \
515     while (av_isspace(*p))                  \
516         p++;                                \
517     switch (*p) {                           \
518     case 'r': rgb_map[id] = 0; break;       \
519     case 'g': rgb_map[id] = 1; break;       \
520     case 'b': rgb_map[id] = 2; break;       \
521     }                                       \
522     while (*p && !av_isspace(*p))           \
523         p++;                                \
524 } while (0)
525             SET_COLOR(0);
526             SET_COLOR(1);
527             SET_COLOR(2);
528             break;
529         }
530     }
531
532     if (in == -1 || out == -1) {
533         av_log(ctx, AV_LOG_ERROR, "in and out must be defined\n");
534         return AVERROR_INVALIDDATA;
535     }
536     if (in < 2 || out < 2 ||
537         in  > MAX_LEVEL*MAX_LEVEL*MAX_LEVEL ||
538         out > MAX_LEVEL*MAX_LEVEL*MAX_LEVEL) {
539         av_log(ctx, AV_LOG_ERROR, "invalid in (%d) or out (%d)\n", in, out);
540         return AVERROR_INVALIDDATA;
541     }
542     for (size = 1; size*size*size < in; size++);
543     lut3d->lutsize = size;
544     size2 = size * size;
545
546     ret = allocate_3dlut(ctx, size);
547     if (ret < 0)
548         return ret;
549
550     scale = 1. / (out - 1);
551
552     for (k = 0; k < size; k++) {
553         for (j = 0; j < size; j++) {
554             for (i = 0; i < size; i++) {
555                 struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i];
556                 float val[3];
557
558                 NEXT_LINE(0);
559                 if (av_sscanf(line, "%f %f %f", val, val + 1, val + 2) != 3)
560                     return AVERROR_INVALIDDATA;
561                 vec->r = val[rgb_map[0]] * scale;
562                 vec->g = val[rgb_map[1]] * scale;
563                 vec->b = val[rgb_map[2]] * scale;
564             }
565         }
566     }
567     return 0;
568 }
569
570 static int parse_cinespace(AVFilterContext *ctx, FILE *f)
571 {
572     LUT3DContext *lut3d = ctx->priv;
573     char line[MAX_LINE_SIZE];
574     float in_min[3]  = {0.0, 0.0, 0.0};
575     float in_max[3]  = {1.0, 1.0, 1.0};
576     float out_min[3] = {0.0, 0.0, 0.0};
577     float out_max[3] = {1.0, 1.0, 1.0};
578     int ret, inside_metadata = 0, size, size2;
579
580     NEXT_LINE(skip_line(line));
581     if (strncmp(line, "CSPLUTV100", 10)) {
582         av_log(ctx, AV_LOG_ERROR, "Not cineSpace LUT format\n");
583         return AVERROR(EINVAL);
584     }
585
586     NEXT_LINE(skip_line(line));
587     if (strncmp(line, "3D", 2)) {
588         av_log(ctx, AV_LOG_ERROR, "Not 3D LUT format\n");
589         return AVERROR(EINVAL);
590     }
591
592     while (1) {
593         NEXT_LINE(skip_line(line));
594
595         if (!strncmp(line, "BEGIN METADATA", 14)) {
596             inside_metadata = 1;
597             continue;
598         }
599         if (!strncmp(line, "END METADATA", 12)) {
600             inside_metadata = 0;
601             continue;
602         }
603         if (inside_metadata == 0) {
604             int size_r, size_g, size_b;
605
606             for (int i = 0; i < 3; i++) {
607                 int npoints = strtol(line, NULL, 0);
608
609                 if (npoints != 2) {
610                     av_log(ctx, AV_LOG_ERROR, "Unsupported number of pre-lut points.\n");
611                     return AVERROR_PATCHWELCOME;
612                 }
613
614                 NEXT_LINE(skip_line(line));
615                 if (av_sscanf(line, "%f %f", &in_min[i], &in_max[i]) != 2)
616                     return AVERROR_INVALIDDATA;
617                 NEXT_LINE(skip_line(line));
618                 if (av_sscanf(line, "%f %f", &out_min[i], &out_max[i]) != 2)
619                     return AVERROR_INVALIDDATA;
620                 NEXT_LINE(skip_line(line));
621             }
622
623             if (av_sscanf(line, "%d %d %d", &size_r, &size_g, &size_b) != 3)
624                 return AVERROR(EINVAL);
625             if (size_r != size_g || size_r != size_b) {
626                 av_log(ctx, AV_LOG_ERROR, "Unsupported size combination: %dx%dx%d.\n", size_r, size_g, size_b);
627                 return AVERROR_PATCHWELCOME;
628             }
629
630             size = size_r;
631             size2 = size * size;
632
633             ret = allocate_3dlut(ctx, size);
634             if (ret < 0)
635                 return ret;
636
637             for (int k = 0; k < size; k++) {
638                 for (int j = 0; j < size; j++) {
639                     for (int i = 0; i < size; i++) {
640                         struct rgbvec *vec = &lut3d->lut[i * size2 + j * size + k];
641                         if (k != 0 || j != 0 || i != 0)
642                             NEXT_LINE(skip_line(line));
643                         if (av_sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3)
644                             return AVERROR_INVALIDDATA;
645                         vec->r *= out_max[0] - out_min[0];
646                         vec->g *= out_max[1] - out_min[1];
647                         vec->b *= out_max[2] - out_min[2];
648                     }
649                 }
650             }
651
652             break;
653         }
654     }
655
656     lut3d->scale.r = av_clipf(1. / (in_max[0] - in_min[0]), 0.f, 1.f);
657     lut3d->scale.g = av_clipf(1. / (in_max[1] - in_min[1]), 0.f, 1.f);
658     lut3d->scale.b = av_clipf(1. / (in_max[2] - in_min[2]), 0.f, 1.f);
659
660     return 0;
661 }
662
663 static int set_identity_matrix(AVFilterContext *ctx, int size)
664 {
665     LUT3DContext *lut3d = ctx->priv;
666     int ret, i, j, k;
667     const int size2 = size * size;
668     const float c = 1. / (size - 1);
669
670     ret = allocate_3dlut(ctx, size);
671     if (ret < 0)
672         return ret;
673
674     for (k = 0; k < size; k++) {
675         for (j = 0; j < size; j++) {
676             for (i = 0; i < size; i++) {
677                 struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i];
678                 vec->r = k * c;
679                 vec->g = j * c;
680                 vec->b = i * c;
681             }
682         }
683     }
684
685     return 0;
686 }
687
688 static int query_formats(AVFilterContext *ctx)
689 {
690     static const enum AVPixelFormat pix_fmts[] = {
691         AV_PIX_FMT_RGB24,  AV_PIX_FMT_BGR24,
692         AV_PIX_FMT_RGBA,   AV_PIX_FMT_BGRA,
693         AV_PIX_FMT_ARGB,   AV_PIX_FMT_ABGR,
694         AV_PIX_FMT_0RGB,   AV_PIX_FMT_0BGR,
695         AV_PIX_FMT_RGB0,   AV_PIX_FMT_BGR0,
696         AV_PIX_FMT_RGB48,  AV_PIX_FMT_BGR48,
697         AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64,
698         AV_PIX_FMT_GBRP,   AV_PIX_FMT_GBRAP,
699         AV_PIX_FMT_GBRP9,
700         AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10,
701         AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
702         AV_PIX_FMT_GBRP14,
703         AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16,
704         AV_PIX_FMT_NONE
705     };
706     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
707     if (!fmts_list)
708         return AVERROR(ENOMEM);
709     return ff_set_common_formats(ctx, fmts_list);
710 }
711
712 static int config_input(AVFilterLink *inlink)
713 {
714     int depth, is16bit, planar;
715     LUT3DContext *lut3d = inlink->dst->priv;
716     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
717
718     depth = desc->comp[0].depth;
719     is16bit = desc->comp[0].depth > 8;
720     planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR;
721     ff_fill_rgba_map(lut3d->rgba_map, inlink->format);
722     lut3d->step = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit);
723
724 #define SET_FUNC(name) do {                                     \
725     if (planar) {                                               \
726         switch (depth) {                                        \
727         case  8: lut3d->interp = interp_8_##name##_p8;   break; \
728         case  9: lut3d->interp = interp_16_##name##_p9;  break; \
729         case 10: lut3d->interp = interp_16_##name##_p10; break; \
730         case 12: lut3d->interp = interp_16_##name##_p12; break; \
731         case 14: lut3d->interp = interp_16_##name##_p14; break; \
732         case 16: lut3d->interp = interp_16_##name##_p16; break; \
733         }                                                       \
734     } else if (is16bit) { lut3d->interp = interp_16_##name;     \
735     } else {       lut3d->interp = interp_8_##name; }           \
736 } while (0)
737
738     switch (lut3d->interpolation) {
739     case INTERPOLATE_NEAREST:     SET_FUNC(nearest);        break;
740     case INTERPOLATE_TRILINEAR:   SET_FUNC(trilinear);      break;
741     case INTERPOLATE_TETRAHEDRAL: SET_FUNC(tetrahedral);    break;
742     default:
743         av_assert0(0);
744     }
745
746     return 0;
747 }
748
749 static AVFrame *apply_lut(AVFilterLink *inlink, AVFrame *in)
750 {
751     AVFilterContext *ctx = inlink->dst;
752     LUT3DContext *lut3d = ctx->priv;
753     AVFilterLink *outlink = inlink->dst->outputs[0];
754     AVFrame *out;
755     ThreadData td;
756
757     if (av_frame_is_writable(in)) {
758         out = in;
759     } else {
760         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
761         if (!out) {
762             av_frame_free(&in);
763             return NULL;
764         }
765         av_frame_copy_props(out, in);
766     }
767
768     td.in  = in;
769     td.out = out;
770     ctx->internal->execute(ctx, lut3d->interp, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
771
772     if (out != in)
773         av_frame_free(&in);
774
775     return out;
776 }
777
778 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
779 {
780     AVFilterLink *outlink = inlink->dst->outputs[0];
781     AVFrame *out = apply_lut(inlink, in);
782     if (!out)
783         return AVERROR(ENOMEM);
784     return ff_filter_frame(outlink, out);
785 }
786
787 #if CONFIG_LUT3D_FILTER
788 static const AVOption lut3d_options[] = {
789     { "file", "set 3D LUT file name", OFFSET(file), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
790     COMMON_OPTIONS
791 };
792
793 AVFILTER_DEFINE_CLASS(lut3d);
794
795 static av_cold int lut3d_init(AVFilterContext *ctx)
796 {
797     int ret;
798     FILE *f;
799     const char *ext;
800     LUT3DContext *lut3d = ctx->priv;
801
802     lut3d->scale.r = lut3d->scale.g = lut3d->scale.b = 1.f;
803
804     if (!lut3d->file) {
805         return set_identity_matrix(ctx, 32);
806     }
807
808     f = av_fopen_utf8(lut3d->file, "r");
809     if (!f) {
810         ret = AVERROR(errno);
811         av_log(ctx, AV_LOG_ERROR, "%s: %s\n", lut3d->file, av_err2str(ret));
812         return ret;
813     }
814
815     ext = strrchr(lut3d->file, '.');
816     if (!ext) {
817         av_log(ctx, AV_LOG_ERROR, "Unable to guess the format from the extension\n");
818         ret = AVERROR_INVALIDDATA;
819         goto end;
820     }
821     ext++;
822
823     if (!av_strcasecmp(ext, "dat")) {
824         ret = parse_dat(ctx, f);
825     } else if (!av_strcasecmp(ext, "3dl")) {
826         ret = parse_3dl(ctx, f);
827     } else if (!av_strcasecmp(ext, "cube")) {
828         ret = parse_cube(ctx, f);
829     } else if (!av_strcasecmp(ext, "m3d")) {
830         ret = parse_m3d(ctx, f);
831     } else if (!av_strcasecmp(ext, "csp")) {
832         ret = parse_cinespace(ctx, f);
833     } else {
834         av_log(ctx, AV_LOG_ERROR, "Unrecognized '.%s' file type\n", ext);
835         ret = AVERROR(EINVAL);
836     }
837
838     if (!ret && !lut3d->lutsize) {
839         av_log(ctx, AV_LOG_ERROR, "3D LUT is empty\n");
840         ret = AVERROR_INVALIDDATA;
841     }
842
843 end:
844     fclose(f);
845     return ret;
846 }
847
848 static av_cold void lut3d_uninit(AVFilterContext *ctx)
849 {
850     LUT3DContext *lut3d = ctx->priv;
851
852     av_freep(&lut3d->lut);
853 }
854
855 static const AVFilterPad lut3d_inputs[] = {
856     {
857         .name         = "default",
858         .type         = AVMEDIA_TYPE_VIDEO,
859         .filter_frame = filter_frame,
860         .config_props = config_input,
861     },
862     { NULL }
863 };
864
865 static const AVFilterPad lut3d_outputs[] = {
866     {
867         .name = "default",
868         .type = AVMEDIA_TYPE_VIDEO,
869     },
870     { NULL }
871 };
872
873 AVFilter ff_vf_lut3d = {
874     .name          = "lut3d",
875     .description   = NULL_IF_CONFIG_SMALL("Adjust colors using a 3D LUT."),
876     .priv_size     = sizeof(LUT3DContext),
877     .init          = lut3d_init,
878     .uninit        = lut3d_uninit,
879     .query_formats = query_formats,
880     .inputs        = lut3d_inputs,
881     .outputs       = lut3d_outputs,
882     .priv_class    = &lut3d_class,
883     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
884 };
885 #endif
886
887 #if CONFIG_HALDCLUT_FILTER
888
889 static void update_clut_packed(LUT3DContext *lut3d, const AVFrame *frame)
890 {
891     const uint8_t *data = frame->data[0];
892     const int linesize  = frame->linesize[0];
893     const int w = lut3d->clut_width;
894     const int step = lut3d->clut_step;
895     const uint8_t *rgba_map = lut3d->clut_rgba_map;
896     const int level = lut3d->lutsize;
897     const int level2 = lut3d->lutsize2;
898
899 #define LOAD_CLUT(nbits) do {                                           \
900     int i, j, k, x = 0, y = 0;                                          \
901                                                                         \
902     for (k = 0; k < level; k++) {                                       \
903         for (j = 0; j < level; j++) {                                   \
904             for (i = 0; i < level; i++) {                               \
905                 const uint##nbits##_t *src = (const uint##nbits##_t *)  \
906                     (data + y*linesize + x*step);                       \
907                 struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \
908                 vec->r = src[rgba_map[0]] / (float)((1<<(nbits)) - 1);  \
909                 vec->g = src[rgba_map[1]] / (float)((1<<(nbits)) - 1);  \
910                 vec->b = src[rgba_map[2]] / (float)((1<<(nbits)) - 1);  \
911                 if (++x == w) {                                         \
912                     x = 0;                                              \
913                     y++;                                                \
914                 }                                                       \
915             }                                                           \
916         }                                                               \
917     }                                                                   \
918 } while (0)
919
920     switch (lut3d->clut_bits) {
921     case  8: LOAD_CLUT(8);  break;
922     case 16: LOAD_CLUT(16); break;
923     }
924 }
925
926 static void update_clut_planar(LUT3DContext *lut3d, const AVFrame *frame)
927 {
928     const uint8_t *datag = frame->data[0];
929     const uint8_t *datab = frame->data[1];
930     const uint8_t *datar = frame->data[2];
931     const int glinesize  = frame->linesize[0];
932     const int blinesize  = frame->linesize[1];
933     const int rlinesize  = frame->linesize[2];
934     const int w = lut3d->clut_width;
935     const int level = lut3d->lutsize;
936     const int level2 = lut3d->lutsize2;
937
938 #define LOAD_CLUT_PLANAR(nbits, depth) do {                             \
939     int i, j, k, x = 0, y = 0;                                          \
940                                                                         \
941     for (k = 0; k < level; k++) {                                       \
942         for (j = 0; j < level; j++) {                                   \
943             for (i = 0; i < level; i++) {                               \
944                 const uint##nbits##_t *gsrc = (const uint##nbits##_t *) \
945                     (datag + y*glinesize);                              \
946                 const uint##nbits##_t *bsrc = (const uint##nbits##_t *) \
947                     (datab + y*blinesize);                              \
948                 const uint##nbits##_t *rsrc = (const uint##nbits##_t *) \
949                     (datar + y*rlinesize);                              \
950                 struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \
951                 vec->r = gsrc[x] / (float)((1<<(depth)) - 1);           \
952                 vec->g = bsrc[x] / (float)((1<<(depth)) - 1);           \
953                 vec->b = rsrc[x] / (float)((1<<(depth)) - 1);           \
954                 if (++x == w) {                                         \
955                     x = 0;                                              \
956                     y++;                                                \
957                 }                                                       \
958             }                                                           \
959         }                                                               \
960     }                                                                   \
961 } while (0)
962
963     switch (lut3d->clut_bits) {
964     case  8: LOAD_CLUT_PLANAR(8, 8);   break;
965     case  9: LOAD_CLUT_PLANAR(16, 9);  break;
966     case 10: LOAD_CLUT_PLANAR(16, 10); break;
967     case 12: LOAD_CLUT_PLANAR(16, 12); break;
968     case 14: LOAD_CLUT_PLANAR(16, 14); break;
969     case 16: LOAD_CLUT_PLANAR(16, 16); break;
970     }
971 }
972
973 static int config_output(AVFilterLink *outlink)
974 {
975     AVFilterContext *ctx = outlink->src;
976     LUT3DContext *lut3d = ctx->priv;
977     int ret;
978
979     ret = ff_framesync_init_dualinput(&lut3d->fs, ctx);
980     if (ret < 0)
981         return ret;
982     outlink->w = ctx->inputs[0]->w;
983     outlink->h = ctx->inputs[0]->h;
984     outlink->time_base = ctx->inputs[0]->time_base;
985     if ((ret = ff_framesync_configure(&lut3d->fs)) < 0)
986         return ret;
987     return 0;
988 }
989
990 static int activate(AVFilterContext *ctx)
991 {
992     LUT3DContext *s = ctx->priv;
993     return ff_framesync_activate(&s->fs);
994 }
995
996 static int config_clut(AVFilterLink *inlink)
997 {
998     int size, level, w, h;
999     AVFilterContext *ctx = inlink->dst;
1000     LUT3DContext *lut3d = ctx->priv;
1001     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
1002
1003     av_assert0(desc);
1004
1005     lut3d->clut_bits = desc->comp[0].depth;
1006     lut3d->clut_planar = av_pix_fmt_count_planes(inlink->format) > 1;
1007
1008     lut3d->clut_step = av_get_padded_bits_per_pixel(desc) >> 3;
1009     ff_fill_rgba_map(lut3d->clut_rgba_map, inlink->format);
1010
1011     if (inlink->w > inlink->h)
1012         av_log(ctx, AV_LOG_INFO, "Padding on the right (%dpx) of the "
1013                "Hald CLUT will be ignored\n", inlink->w - inlink->h);
1014     else if (inlink->w < inlink->h)
1015         av_log(ctx, AV_LOG_INFO, "Padding at the bottom (%dpx) of the "
1016                "Hald CLUT will be ignored\n", inlink->h - inlink->w);
1017     lut3d->clut_width = w = h = FFMIN(inlink->w, inlink->h);
1018
1019     for (level = 1; level*level*level < w; level++);
1020     size = level*level*level;
1021     if (size != w) {
1022         av_log(ctx, AV_LOG_WARNING, "The Hald CLUT width does not match the level\n");
1023         return AVERROR_INVALIDDATA;
1024     }
1025     av_assert0(w == h && w == size);
1026     level *= level;
1027     if (level > MAX_LEVEL) {
1028         const int max_clut_level = sqrt(MAX_LEVEL);
1029         const int max_clut_size  = max_clut_level*max_clut_level*max_clut_level;
1030         av_log(ctx, AV_LOG_ERROR, "Too large Hald CLUT "
1031                "(maximum level is %d, or %dx%d CLUT)\n",
1032                max_clut_level, max_clut_size, max_clut_size);
1033         return AVERROR(EINVAL);
1034     }
1035
1036     return allocate_3dlut(ctx, level);
1037 }
1038
1039 static int update_apply_clut(FFFrameSync *fs)
1040 {
1041     AVFilterContext *ctx = fs->parent;
1042     LUT3DContext *lut3d = ctx->priv;
1043     AVFilterLink *inlink = ctx->inputs[0];
1044     AVFrame *master, *second, *out;
1045     int ret;
1046
1047     ret = ff_framesync_dualinput_get(fs, &master, &second);
1048     if (ret < 0)
1049         return ret;
1050     if (!second)
1051         return ff_filter_frame(ctx->outputs[0], master);
1052     if (lut3d->clut_planar)
1053         update_clut_planar(ctx->priv, second);
1054     else
1055         update_clut_packed(ctx->priv, second);
1056     out = apply_lut(inlink, master);
1057     return ff_filter_frame(ctx->outputs[0], out);
1058 }
1059
1060 static av_cold int haldclut_init(AVFilterContext *ctx)
1061 {
1062     LUT3DContext *lut3d = ctx->priv;
1063     lut3d->scale.r = lut3d->scale.g = lut3d->scale.b = 1.f;
1064     lut3d->fs.on_event = update_apply_clut;
1065     return 0;
1066 }
1067
1068 static av_cold void haldclut_uninit(AVFilterContext *ctx)
1069 {
1070     LUT3DContext *lut3d = ctx->priv;
1071     ff_framesync_uninit(&lut3d->fs);
1072     av_freep(&lut3d->lut);
1073 }
1074
1075 static const AVOption haldclut_options[] = {
1076     COMMON_OPTIONS
1077 };
1078
1079 FRAMESYNC_DEFINE_CLASS(haldclut, LUT3DContext, fs);
1080
1081 static const AVFilterPad haldclut_inputs[] = {
1082     {
1083         .name         = "main",
1084         .type         = AVMEDIA_TYPE_VIDEO,
1085         .config_props = config_input,
1086     },{
1087         .name         = "clut",
1088         .type         = AVMEDIA_TYPE_VIDEO,
1089         .config_props = config_clut,
1090     },
1091     { NULL }
1092 };
1093
1094 static const AVFilterPad haldclut_outputs[] = {
1095     {
1096         .name          = "default",
1097         .type          = AVMEDIA_TYPE_VIDEO,
1098         .config_props  = config_output,
1099     },
1100     { NULL }
1101 };
1102
1103 AVFilter ff_vf_haldclut = {
1104     .name          = "haldclut",
1105     .description   = NULL_IF_CONFIG_SMALL("Adjust colors using a Hald CLUT."),
1106     .priv_size     = sizeof(LUT3DContext),
1107     .preinit       = haldclut_framesync_preinit,
1108     .init          = haldclut_init,
1109     .uninit        = haldclut_uninit,
1110     .query_formats = query_formats,
1111     .activate      = activate,
1112     .inputs        = haldclut_inputs,
1113     .outputs       = haldclut_outputs,
1114     .priv_class    = &haldclut_class,
1115     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
1116 };
1117 #endif
1118
1119 #if CONFIG_LUT1D_FILTER
1120
1121 enum interp_1d_mode {
1122     INTERPOLATE_1D_NEAREST,
1123     INTERPOLATE_1D_LINEAR,
1124     INTERPOLATE_1D_CUBIC,
1125     INTERPOLATE_1D_COSINE,
1126     INTERPOLATE_1D_SPLINE,
1127     NB_INTERP_1D_MODE
1128 };
1129
1130 #define MAX_1D_LEVEL 65536
1131
1132 typedef struct LUT1DContext {
1133     const AVClass *class;
1134     char *file;
1135     int interpolation;          ///<interp_1d_mode
1136     struct rgbvec scale;
1137     uint8_t rgba_map[4];
1138     int step;
1139     float lut[3][MAX_1D_LEVEL];
1140     int lutsize;
1141     avfilter_action_func *interp;
1142 } LUT1DContext;
1143
1144 #undef OFFSET
1145 #define OFFSET(x) offsetof(LUT1DContext, x)
1146
1147 static void set_identity_matrix_1d(LUT1DContext *lut1d, int size)
1148 {
1149     const float c = 1. / (size - 1);
1150     int i;
1151
1152     lut1d->lutsize = size;
1153     for (i = 0; i < size; i++) {
1154         lut1d->lut[0][i] = i * c;
1155         lut1d->lut[1][i] = i * c;
1156         lut1d->lut[2][i] = i * c;
1157     }
1158 }
1159
1160 static int parse_cinespace_1d(AVFilterContext *ctx, FILE *f)
1161 {
1162     LUT1DContext *lut1d = ctx->priv;
1163     char line[MAX_LINE_SIZE];
1164     float in_min[3]  = {0.0, 0.0, 0.0};
1165     float in_max[3]  = {1.0, 1.0, 1.0};
1166     float out_min[3] = {0.0, 0.0, 0.0};
1167     float out_max[3] = {1.0, 1.0, 1.0};
1168     int inside_metadata = 0, size;
1169
1170     NEXT_LINE(skip_line(line));
1171     if (strncmp(line, "CSPLUTV100", 10)) {
1172         av_log(ctx, AV_LOG_ERROR, "Not cineSpace LUT format\n");
1173         return AVERROR(EINVAL);
1174     }
1175
1176     NEXT_LINE(skip_line(line));
1177     if (strncmp(line, "1D", 2)) {
1178         av_log(ctx, AV_LOG_ERROR, "Not 1D LUT format\n");
1179         return AVERROR(EINVAL);
1180     }
1181
1182     while (1) {
1183         NEXT_LINE(skip_line(line));
1184
1185         if (!strncmp(line, "BEGIN METADATA", 14)) {
1186             inside_metadata = 1;
1187             continue;
1188         }
1189         if (!strncmp(line, "END METADATA", 12)) {
1190             inside_metadata = 0;
1191             continue;
1192         }
1193         if (inside_metadata == 0) {
1194             for (int i = 0; i < 3; i++) {
1195                 int npoints = strtol(line, NULL, 0);
1196
1197                 if (npoints != 2) {
1198                     av_log(ctx, AV_LOG_ERROR, "Unsupported number of pre-lut points.\n");
1199                     return AVERROR_PATCHWELCOME;
1200                 }
1201
1202                 NEXT_LINE(skip_line(line));
1203                 if (av_sscanf(line, "%f %f", &in_min[i], &in_max[i]) != 2)
1204                     return AVERROR_INVALIDDATA;
1205                 NEXT_LINE(skip_line(line));
1206                 if (av_sscanf(line, "%f %f", &out_min[i], &out_max[i]) != 2)
1207                     return AVERROR_INVALIDDATA;
1208                 NEXT_LINE(skip_line(line));
1209             }
1210
1211             size = strtol(line, NULL, 0);
1212
1213             if (size < 2 || size > MAX_1D_LEVEL) {
1214                 av_log(ctx, AV_LOG_ERROR, "Too large or invalid 1D LUT size\n");
1215                 return AVERROR(EINVAL);
1216             }
1217
1218             lut1d->lutsize = size;
1219
1220             for (int i = 0; i < size; i++) {
1221                 NEXT_LINE(skip_line(line));
1222                 if (av_sscanf(line, "%f %f %f", &lut1d->lut[0][i], &lut1d->lut[1][i], &lut1d->lut[2][i]) != 3)
1223                     return AVERROR_INVALIDDATA;
1224                 lut1d->lut[0][i] *= out_max[0] - out_min[0];
1225                 lut1d->lut[1][i] *= out_max[1] - out_min[1];
1226                 lut1d->lut[2][i] *= out_max[2] - out_min[2];
1227             }
1228
1229             break;
1230         }
1231     }
1232
1233     lut1d->scale.r = av_clipf(1. / (in_max[0] - in_min[0]), 0.f, 1.f);
1234     lut1d->scale.g = av_clipf(1. / (in_max[1] - in_min[1]), 0.f, 1.f);
1235     lut1d->scale.b = av_clipf(1. / (in_max[2] - in_min[2]), 0.f, 1.f);
1236
1237     return 0;
1238 }
1239
1240 static int parse_cube_1d(AVFilterContext *ctx, FILE *f)
1241 {
1242     LUT1DContext *lut1d = ctx->priv;
1243     char line[MAX_LINE_SIZE];
1244     float min[3] = {0.0, 0.0, 0.0};
1245     float max[3] = {1.0, 1.0, 1.0};
1246
1247     while (fgets(line, sizeof(line), f)) {
1248         if (!strncmp(line, "LUT_1D_SIZE", 11)) {
1249             const int size = strtol(line + 12, NULL, 0);
1250             int i;
1251
1252             if (size < 2 || size > MAX_1D_LEVEL) {
1253                 av_log(ctx, AV_LOG_ERROR, "Too large or invalid 1D LUT size\n");
1254                 return AVERROR(EINVAL);
1255             }
1256             lut1d->lutsize = size;
1257             for (i = 0; i < size; i++) {
1258                 do {
1259 try_again:
1260                     NEXT_LINE(0);
1261                     if (!strncmp(line, "DOMAIN_", 7)) {
1262                         float *vals = NULL;
1263                         if      (!strncmp(line + 7, "MIN ", 4)) vals = min;
1264                         else if (!strncmp(line + 7, "MAX ", 4)) vals = max;
1265                         if (!vals)
1266                             return AVERROR_INVALIDDATA;
1267                         av_sscanf(line + 11, "%f %f %f", vals, vals + 1, vals + 2);
1268                         av_log(ctx, AV_LOG_DEBUG, "min: %f %f %f | max: %f %f %f\n",
1269                                min[0], min[1], min[2], max[0], max[1], max[2]);
1270                         goto try_again;
1271                     } else if (!strncmp(line, "LUT_1D_INPUT_RANGE ", 19)) {
1272                         av_sscanf(line + 19, "%f %f", min, max);
1273                         min[1] = min[2] = min[0];
1274                         max[1] = max[2] = max[0];
1275                         goto try_again;
1276                     } else if (!strncmp(line, "TITLE", 5)) {
1277                         goto try_again;
1278                     }
1279                 } while (skip_line(line));
1280                 if (av_sscanf(line, "%f %f %f", &lut1d->lut[0][i], &lut1d->lut[1][i], &lut1d->lut[2][i]) != 3)
1281                     return AVERROR_INVALIDDATA;
1282             }
1283             break;
1284         }
1285     }
1286
1287     lut1d->scale.r = av_clipf(1. / (max[0] - min[0]), 0.f, 1.f);
1288     lut1d->scale.g = av_clipf(1. / (max[1] - min[1]), 0.f, 1.f);
1289     lut1d->scale.b = av_clipf(1. / (max[2] - min[2]), 0.f, 1.f);
1290
1291     return 0;
1292 }
1293
1294 static const AVOption lut1d_options[] = {
1295     { "file", "set 1D LUT file name", OFFSET(file), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
1296     { "interp", "select interpolation mode", OFFSET(interpolation),    AV_OPT_TYPE_INT, {.i64=INTERPOLATE_1D_LINEAR}, 0, NB_INTERP_1D_MODE-1, FLAGS, "interp_mode" },
1297         { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_NEAREST},   INT_MIN, INT_MAX, FLAGS, "interp_mode" },
1298         { "linear",  "use values from the linear interpolation",   0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_LINEAR},    INT_MIN, INT_MAX, FLAGS, "interp_mode" },
1299         { "cosine",  "use values from the cosine interpolation",   0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_COSINE},    INT_MIN, INT_MAX, FLAGS, "interp_mode" },
1300         { "cubic",   "use values from the cubic interpolation",    0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_CUBIC},     INT_MIN, INT_MAX, FLAGS, "interp_mode" },
1301         { "spline",  "use values from the spline interpolation",   0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_SPLINE},    INT_MIN, INT_MAX, FLAGS, "interp_mode" },
1302     { NULL }
1303 };
1304
1305 AVFILTER_DEFINE_CLASS(lut1d);
1306
1307 static inline float interp_1d_nearest(const LUT1DContext *lut1d,
1308                                       int idx, const float s)
1309 {
1310     return lut1d->lut[idx][NEAR(s)];
1311 }
1312
1313 #define NEXT1D(x) (FFMIN((int)(x) + 1, lut1d->lutsize - 1))
1314
1315 static inline float interp_1d_linear(const LUT1DContext *lut1d,
1316                                      int idx, const float s)
1317 {
1318     const int prev = PREV(s);
1319     const int next = NEXT1D(s);
1320     const float d = s - prev;
1321     const float p = lut1d->lut[idx][prev];
1322     const float n = lut1d->lut[idx][next];
1323
1324     return lerpf(p, n, d);
1325 }
1326
1327 static inline float interp_1d_cosine(const LUT1DContext *lut1d,
1328                                      int idx, const float s)
1329 {
1330     const int prev = PREV(s);
1331     const int next = NEXT1D(s);
1332     const float d = s - prev;
1333     const float p = lut1d->lut[idx][prev];
1334     const float n = lut1d->lut[idx][next];
1335     const float m = (1.f - cosf(d * M_PI)) * .5f;
1336
1337     return lerpf(p, n, m);
1338 }
1339
1340 static inline float interp_1d_cubic(const LUT1DContext *lut1d,
1341                                     int idx, const float s)
1342 {
1343     const int prev = PREV(s);
1344     const int next = NEXT1D(s);
1345     const float mu = s - prev;
1346     float a0, a1, a2, a3, mu2;
1347
1348     float y0 = lut1d->lut[idx][FFMAX(prev - 1, 0)];
1349     float y1 = lut1d->lut[idx][prev];
1350     float y2 = lut1d->lut[idx][next];
1351     float y3 = lut1d->lut[idx][FFMIN(next + 1, lut1d->lutsize - 1)];
1352
1353
1354     mu2 = mu * mu;
1355     a0 = y3 - y2 - y0 + y1;
1356     a1 = y0 - y1 - a0;
1357     a2 = y2 - y0;
1358     a3 = y1;
1359
1360     return a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3;
1361 }
1362
1363 static inline float interp_1d_spline(const LUT1DContext *lut1d,
1364                                      int idx, const float s)
1365 {
1366     const int prev = PREV(s);
1367     const int next = NEXT1D(s);
1368     const float x = s - prev;
1369     float c0, c1, c2, c3;
1370
1371     float y0 = lut1d->lut[idx][FFMAX(prev - 1, 0)];
1372     float y1 = lut1d->lut[idx][prev];
1373     float y2 = lut1d->lut[idx][next];
1374     float y3 = lut1d->lut[idx][FFMIN(next + 1, lut1d->lutsize - 1)];
1375
1376     c0 = y1;
1377     c1 = .5f * (y2 - y0);
1378     c2 = y0 - 2.5f * y1 + 2.f * y2 - .5f * y3;
1379     c3 = .5f * (y3 - y0) + 1.5f * (y1 - y2);
1380
1381     return ((c3 * x + c2) * x + c1) * x + c0;
1382 }
1383
1384 #define DEFINE_INTERP_FUNC_PLANAR_1D(name, nbits, depth)                     \
1385 static int interp_1d_##nbits##_##name##_p##depth(AVFilterContext *ctx,       \
1386                                                  void *arg, int jobnr,       \
1387                                                  int nb_jobs)                \
1388 {                                                                            \
1389     int x, y;                                                                \
1390     const LUT1DContext *lut1d = ctx->priv;                                   \
1391     const ThreadData *td = arg;                                              \
1392     const AVFrame *in  = td->in;                                             \
1393     const AVFrame *out = td->out;                                            \
1394     const int direct = out == in;                                            \
1395     const int slice_start = (in->height *  jobnr   ) / nb_jobs;              \
1396     const int slice_end   = (in->height * (jobnr+1)) / nb_jobs;              \
1397     uint8_t *grow = out->data[0] + slice_start * out->linesize[0];           \
1398     uint8_t *brow = out->data[1] + slice_start * out->linesize[1];           \
1399     uint8_t *rrow = out->data[2] + slice_start * out->linesize[2];           \
1400     uint8_t *arow = out->data[3] + slice_start * out->linesize[3];           \
1401     const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0];    \
1402     const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1];    \
1403     const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2];    \
1404     const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3];    \
1405     const float factor = (1 << depth) - 1;                                   \
1406     const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1);  \
1407     const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1);  \
1408     const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1);  \
1409                                                                              \
1410     for (y = slice_start; y < slice_end; y++) {                              \
1411         uint##nbits##_t *dstg = (uint##nbits##_t *)grow;                     \
1412         uint##nbits##_t *dstb = (uint##nbits##_t *)brow;                     \
1413         uint##nbits##_t *dstr = (uint##nbits##_t *)rrow;                     \
1414         uint##nbits##_t *dsta = (uint##nbits##_t *)arow;                     \
1415         const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow;      \
1416         const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow;      \
1417         const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow;      \
1418         const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow;      \
1419         for (x = 0; x < in->width; x++) {                                    \
1420             float r = srcr[x] * scale_r;                                     \
1421             float g = srcg[x] * scale_g;                                     \
1422             float b = srcb[x] * scale_b;                                     \
1423             r = interp_1d_##name(lut1d, 0, r);                               \
1424             g = interp_1d_##name(lut1d, 1, g);                               \
1425             b = interp_1d_##name(lut1d, 2, b);                               \
1426             dstr[x] = av_clip_uintp2(r * factor, depth);                     \
1427             dstg[x] = av_clip_uintp2(g * factor, depth);                     \
1428             dstb[x] = av_clip_uintp2(b * factor, depth);                     \
1429             if (!direct && in->linesize[3])                                  \
1430                 dsta[x] = srca[x];                                           \
1431         }                                                                    \
1432         grow += out->linesize[0];                                            \
1433         brow += out->linesize[1];                                            \
1434         rrow += out->linesize[2];                                            \
1435         arow += out->linesize[3];                                            \
1436         srcgrow += in->linesize[0];                                          \
1437         srcbrow += in->linesize[1];                                          \
1438         srcrrow += in->linesize[2];                                          \
1439         srcarow += in->linesize[3];                                          \
1440     }                                                                        \
1441     return 0;                                                                \
1442 }
1443
1444 DEFINE_INTERP_FUNC_PLANAR_1D(nearest,     8, 8)
1445 DEFINE_INTERP_FUNC_PLANAR_1D(linear,      8, 8)
1446 DEFINE_INTERP_FUNC_PLANAR_1D(cosine,      8, 8)
1447 DEFINE_INTERP_FUNC_PLANAR_1D(cubic,       8, 8)
1448 DEFINE_INTERP_FUNC_PLANAR_1D(spline,      8, 8)
1449
1450 DEFINE_INTERP_FUNC_PLANAR_1D(nearest,     16, 9)
1451 DEFINE_INTERP_FUNC_PLANAR_1D(linear,      16, 9)
1452 DEFINE_INTERP_FUNC_PLANAR_1D(cosine,      16, 9)
1453 DEFINE_INTERP_FUNC_PLANAR_1D(cubic,       16, 9)
1454 DEFINE_INTERP_FUNC_PLANAR_1D(spline,      16, 9)
1455
1456 DEFINE_INTERP_FUNC_PLANAR_1D(nearest,     16, 10)
1457 DEFINE_INTERP_FUNC_PLANAR_1D(linear,      16, 10)
1458 DEFINE_INTERP_FUNC_PLANAR_1D(cosine,      16, 10)
1459 DEFINE_INTERP_FUNC_PLANAR_1D(cubic,       16, 10)
1460 DEFINE_INTERP_FUNC_PLANAR_1D(spline,      16, 10)
1461
1462 DEFINE_INTERP_FUNC_PLANAR_1D(nearest,     16, 12)
1463 DEFINE_INTERP_FUNC_PLANAR_1D(linear,      16, 12)
1464 DEFINE_INTERP_FUNC_PLANAR_1D(cosine,      16, 12)
1465 DEFINE_INTERP_FUNC_PLANAR_1D(cubic,       16, 12)
1466 DEFINE_INTERP_FUNC_PLANAR_1D(spline,      16, 12)
1467
1468 DEFINE_INTERP_FUNC_PLANAR_1D(nearest,     16, 14)
1469 DEFINE_INTERP_FUNC_PLANAR_1D(linear,      16, 14)
1470 DEFINE_INTERP_FUNC_PLANAR_1D(cosine,      16, 14)
1471 DEFINE_INTERP_FUNC_PLANAR_1D(cubic,       16, 14)
1472 DEFINE_INTERP_FUNC_PLANAR_1D(spline,      16, 14)
1473
1474 DEFINE_INTERP_FUNC_PLANAR_1D(nearest,     16, 16)
1475 DEFINE_INTERP_FUNC_PLANAR_1D(linear,      16, 16)
1476 DEFINE_INTERP_FUNC_PLANAR_1D(cosine,      16, 16)
1477 DEFINE_INTERP_FUNC_PLANAR_1D(cubic,       16, 16)
1478 DEFINE_INTERP_FUNC_PLANAR_1D(spline,      16, 16)
1479
1480 #define DEFINE_INTERP_FUNC_1D(name, nbits)                                   \
1481 static int interp_1d_##nbits##_##name(AVFilterContext *ctx, void *arg,       \
1482                                       int jobnr, int nb_jobs)                \
1483 {                                                                            \
1484     int x, y;                                                                \
1485     const LUT1DContext *lut1d = ctx->priv;                                   \
1486     const ThreadData *td = arg;                                              \
1487     const AVFrame *in  = td->in;                                             \
1488     const AVFrame *out = td->out;                                            \
1489     const int direct = out == in;                                            \
1490     const int step = lut1d->step;                                            \
1491     const uint8_t r = lut1d->rgba_map[R];                                    \
1492     const uint8_t g = lut1d->rgba_map[G];                                    \
1493     const uint8_t b = lut1d->rgba_map[B];                                    \
1494     const uint8_t a = lut1d->rgba_map[A];                                    \
1495     const int slice_start = (in->height *  jobnr   ) / nb_jobs;              \
1496     const int slice_end   = (in->height * (jobnr+1)) / nb_jobs;              \
1497     uint8_t       *dstrow = out->data[0] + slice_start * out->linesize[0];   \
1498     const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0];   \
1499     const float factor = (1 << nbits) - 1;                                   \
1500     const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1);  \
1501     const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1);  \
1502     const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1);  \
1503                                                                              \
1504     for (y = slice_start; y < slice_end; y++) {                              \
1505         uint##nbits##_t *dst = (uint##nbits##_t *)dstrow;                    \
1506         const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow;        \
1507         for (x = 0; x < in->width * step; x += step) {                       \
1508             float rr = src[x + r] * scale_r;                                 \
1509             float gg = src[x + g] * scale_g;                                 \
1510             float bb = src[x + b] * scale_b;                                 \
1511             rr = interp_1d_##name(lut1d, 0, rr);                             \
1512             gg = interp_1d_##name(lut1d, 1, gg);                             \
1513             bb = interp_1d_##name(lut1d, 2, bb);                             \
1514             dst[x + r] = av_clip_uint##nbits(rr * factor);                   \
1515             dst[x + g] = av_clip_uint##nbits(gg * factor);                   \
1516             dst[x + b] = av_clip_uint##nbits(bb * factor);                   \
1517             if (!direct && step == 4)                                        \
1518                 dst[x + a] = src[x + a];                                     \
1519         }                                                                    \
1520         dstrow += out->linesize[0];                                          \
1521         srcrow += in ->linesize[0];                                          \
1522     }                                                                        \
1523     return 0;                                                                \
1524 }
1525
1526 DEFINE_INTERP_FUNC_1D(nearest,     8)
1527 DEFINE_INTERP_FUNC_1D(linear,      8)
1528 DEFINE_INTERP_FUNC_1D(cosine,      8)
1529 DEFINE_INTERP_FUNC_1D(cubic,       8)
1530 DEFINE_INTERP_FUNC_1D(spline,      8)
1531
1532 DEFINE_INTERP_FUNC_1D(nearest,     16)
1533 DEFINE_INTERP_FUNC_1D(linear,      16)
1534 DEFINE_INTERP_FUNC_1D(cosine,      16)
1535 DEFINE_INTERP_FUNC_1D(cubic,       16)
1536 DEFINE_INTERP_FUNC_1D(spline,      16)
1537
1538 static int config_input_1d(AVFilterLink *inlink)
1539 {
1540     int depth, is16bit, planar;
1541     LUT1DContext *lut1d = inlink->dst->priv;
1542     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
1543
1544     depth = desc->comp[0].depth;
1545     is16bit = desc->comp[0].depth > 8;
1546     planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR;
1547     ff_fill_rgba_map(lut1d->rgba_map, inlink->format);
1548     lut1d->step = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit);
1549
1550 #define SET_FUNC_1D(name) do {                                     \
1551     if (planar) {                                                  \
1552         switch (depth) {                                           \
1553         case  8: lut1d->interp = interp_1d_8_##name##_p8;   break; \
1554         case  9: lut1d->interp = interp_1d_16_##name##_p9;  break; \
1555         case 10: lut1d->interp = interp_1d_16_##name##_p10; break; \
1556         case 12: lut1d->interp = interp_1d_16_##name##_p12; break; \
1557         case 14: lut1d->interp = interp_1d_16_##name##_p14; break; \
1558         case 16: lut1d->interp = interp_1d_16_##name##_p16; break; \
1559         }                                                          \
1560     } else if (is16bit) { lut1d->interp = interp_1d_16_##name;     \
1561     } else {              lut1d->interp = interp_1d_8_##name; }    \
1562 } while (0)
1563
1564     switch (lut1d->interpolation) {
1565     case INTERPOLATE_1D_NEAREST:     SET_FUNC_1D(nearest);  break;
1566     case INTERPOLATE_1D_LINEAR:      SET_FUNC_1D(linear);   break;
1567     case INTERPOLATE_1D_COSINE:      SET_FUNC_1D(cosine);   break;
1568     case INTERPOLATE_1D_CUBIC:       SET_FUNC_1D(cubic);    break;
1569     case INTERPOLATE_1D_SPLINE:      SET_FUNC_1D(spline);   break;
1570     default:
1571         av_assert0(0);
1572     }
1573
1574     return 0;
1575 }
1576
1577 static av_cold int lut1d_init(AVFilterContext *ctx)
1578 {
1579     int ret;
1580     FILE *f;
1581     const char *ext;
1582     LUT1DContext *lut1d = ctx->priv;
1583
1584     lut1d->scale.r = lut1d->scale.g = lut1d->scale.b = 1.f;
1585
1586     if (!lut1d->file) {
1587         set_identity_matrix_1d(lut1d, 32);
1588         return 0;
1589     }
1590
1591     f = av_fopen_utf8(lut1d->file, "r");
1592     if (!f) {
1593         ret = AVERROR(errno);
1594         av_log(ctx, AV_LOG_ERROR, "%s: %s\n", lut1d->file, av_err2str(ret));
1595         return ret;
1596     }
1597
1598     ext = strrchr(lut1d->file, '.');
1599     if (!ext) {
1600         av_log(ctx, AV_LOG_ERROR, "Unable to guess the format from the extension\n");
1601         ret = AVERROR_INVALIDDATA;
1602         goto end;
1603     }
1604     ext++;
1605
1606     if (!av_strcasecmp(ext, "cube") || !av_strcasecmp(ext, "1dlut")) {
1607         ret = parse_cube_1d(ctx, f);
1608     } else if (!av_strcasecmp(ext, "csp")) {
1609         ret = parse_cinespace_1d(ctx, f);
1610     } else {
1611         av_log(ctx, AV_LOG_ERROR, "Unrecognized '.%s' file type\n", ext);
1612         ret = AVERROR(EINVAL);
1613     }
1614
1615     if (!ret && !lut1d->lutsize) {
1616         av_log(ctx, AV_LOG_ERROR, "1D LUT is empty\n");
1617         ret = AVERROR_INVALIDDATA;
1618     }
1619
1620 end:
1621     fclose(f);
1622     return ret;
1623 }
1624
1625 static AVFrame *apply_1d_lut(AVFilterLink *inlink, AVFrame *in)
1626 {
1627     AVFilterContext *ctx = inlink->dst;
1628     LUT1DContext *lut1d = ctx->priv;
1629     AVFilterLink *outlink = inlink->dst->outputs[0];
1630     AVFrame *out;
1631     ThreadData td;
1632
1633     if (av_frame_is_writable(in)) {
1634         out = in;
1635     } else {
1636         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
1637         if (!out) {
1638             av_frame_free(&in);
1639             return NULL;
1640         }
1641         av_frame_copy_props(out, in);
1642     }
1643
1644     td.in  = in;
1645     td.out = out;
1646     ctx->internal->execute(ctx, lut1d->interp, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
1647
1648     if (out != in)
1649         av_frame_free(&in);
1650
1651     return out;
1652 }
1653
1654 static int filter_frame_1d(AVFilterLink *inlink, AVFrame *in)
1655 {
1656     AVFilterLink *outlink = inlink->dst->outputs[0];
1657     AVFrame *out = apply_1d_lut(inlink, in);
1658     if (!out)
1659         return AVERROR(ENOMEM);
1660     return ff_filter_frame(outlink, out);
1661 }
1662
1663 static const AVFilterPad lut1d_inputs[] = {
1664     {
1665         .name         = "default",
1666         .type         = AVMEDIA_TYPE_VIDEO,
1667         .filter_frame = filter_frame_1d,
1668         .config_props = config_input_1d,
1669     },
1670     { NULL }
1671 };
1672
1673 static const AVFilterPad lut1d_outputs[] = {
1674     {
1675         .name = "default",
1676         .type = AVMEDIA_TYPE_VIDEO,
1677     },
1678     { NULL }
1679 };
1680
1681 AVFilter ff_vf_lut1d = {
1682     .name          = "lut1d",
1683     .description   = NULL_IF_CONFIG_SMALL("Adjust colors using a 1D LUT."),
1684     .priv_size     = sizeof(LUT1DContext),
1685     .init          = lut1d_init,
1686     .query_formats = query_formats,
1687     .inputs        = lut1d_inputs,
1688     .outputs       = lut1d_outputs,
1689     .priv_class    = &lut1d_class,
1690     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
1691 };
1692 #endif