Go to the documentation of this file.
29 #include "config_components.h"
47 #define OFFSET(x) offsetof(LUT3DContext, x)
48 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
49 #define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
50 #define COMMON_OPTIONS \
51 { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, NB_INTERP_MODE-1, TFLAGS, .unit = "interp_mode" }, \
52 { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_NEAREST}, 0, 0, TFLAGS, .unit = "interp_mode" }, \
53 { "trilinear", "interpolate values using the 8 points defining a cube", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TRILINEAR}, 0, 0, TFLAGS, .unit = "interp_mode" }, \
54 { "tetrahedral", "interpolate values using a tetrahedron", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, 0, TFLAGS, .unit = "interp_mode" }, \
55 { "pyramid", "interpolate values using a pyramid", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PYRAMID}, 0, 0, TFLAGS, .unit = "interp_mode" }, \
56 { "prism", "interpolate values using a prism", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PRISM}, 0, 0, TFLAGS, .unit = "interp_mode" }, \
59 #define EXPONENT_MASK 0x7F800000
60 #define MANTISSA_MASK 0x007FFFFF
61 #define SIGN_MASK 0x80000000
83 static inline float lerpf(
float v0,
float v1,
float f)
85 return v0 + (v1 - v0) *
f;
96 #define NEAR(x) ((int)((x) + .5))
97 #define PREV(x) ((int)(x))
98 #define NEXT(x) (FFMIN((int)(x) + 1, lut3d->lutsize - 1))
106 return lut3d->lut[
NEAR(
s->r) * lut3d->lutsize2 +
NEAR(
s->g) * lut3d->lutsize +
NEAR(
s->b)];
116 const int lutsize2 = lut3d->lutsize2;
117 const int lutsize = lut3d->lutsize;
120 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
121 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
122 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
123 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
124 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
125 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
126 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
127 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
128 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
142 const int lutsize2 = lut3d->lutsize2;
143 const int lutsize = lut3d->lutsize;
146 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
147 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
148 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
151 if (
d.g >
d.r &&
d.b >
d.r) {
152 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
153 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
154 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
156 c.r = c000.
r + (c111.
r - c011.
r) *
d.r + (c010.
r - c000.
r) *
d.g + (c001.
r - c000.
r) *
d.b +
157 (c011.
r - c001.
r - c010.
r + c000.
r) *
d.g *
d.b;
158 c.g = c000.
g + (c111.
g - c011.
g) *
d.r + (c010.
g - c000.
g) *
d.g + (c001.
g - c000.
g) *
d.b +
159 (c011.
g - c001.
g - c010.
g + c000.
g) *
d.g *
d.b;
160 c.b = c000.
b + (c111.
b - c011.
b) *
d.r + (c010.
b - c000.
b) *
d.g + (c001.
b - c000.
b) *
d.b +
161 (c011.
b - c001.
b - c010.
b + c000.
b) *
d.g *
d.b;
162 }
else if (
d.r >
d.g &&
d.b >
d.g) {
163 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
164 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
165 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
167 c.r = c000.
r + (c100.
r - c000.
r) *
d.r + (c111.
r - c101.
r) *
d.g + (c001.
r - c000.
r) *
d.b +
168 (c101.
r - c001.
r - c100.
r + c000.
r) *
d.r *
d.b;
169 c.g = c000.
g + (c100.
g - c000.
g) *
d.r + (c111.
g - c101.
g) *
d.g + (c001.
g - c000.
g) *
d.b +
170 (c101.
g - c001.
g - c100.
g + c000.
g) *
d.r *
d.b;
171 c.b = c000.
b + (c100.
b - c000.
b) *
d.r + (c111.
b - c101.
b) *
d.g + (c001.
b - c000.
b) *
d.b +
172 (c101.
b - c001.
b - c100.
b + c000.
b) *
d.r *
d.b;
174 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
175 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
176 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
178 c.r = c000.
r + (c100.
r - c000.
r) *
d.r + (c010.
r - c000.
r) *
d.g + (c111.
r - c110.
r) *
d.b +
179 (c110.
r - c100.
r - c010.
r + c000.
r) *
d.r *
d.g;
180 c.g = c000.
g + (c100.
g - c000.
g) *
d.r + (c010.
g - c000.
g) *
d.g + (c111.
g - c110.
g) *
d.b +
181 (c110.
g - c100.
g - c010.
g + c000.
g) *
d.r *
d.g;
182 c.b = c000.
b + (c100.
b - c000.
b) *
d.r + (c010.
b - c000.
b) *
d.g + (c111.
b - c110.
b) *
d.b +
183 (c110.
b - c100.
b - c010.
b + c000.
b) *
d.r *
d.g;
192 const int lutsize2 = lut3d->lutsize2;
193 const int lutsize = lut3d->lutsize;
196 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
197 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
198 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
199 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
200 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
204 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
205 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
207 c.r = c000.
r + (c001.
r - c000.
r) *
d.b + (c101.
r - c001.
r) *
d.r + (c010.
r - c000.
r) *
d.g +
208 (c000.
r - c010.
r - c001.
r + c011.
r) *
d.b *
d.g +
209 (c001.
r - c011.
r - c101.
r + c111.
r) *
d.r *
d.g;
210 c.g = c000.
g + (c001.
g - c000.
g) *
d.b + (c101.
g - c001.
g) *
d.r + (c010.
g - c000.
g) *
d.g +
211 (c000.
g - c010.
g - c001.
g + c011.
g) *
d.b *
d.g +
212 (c001.
g - c011.
g - c101.
g + c111.
g) *
d.r *
d.g;
213 c.b = c000.
b + (c001.
b - c000.
b) *
d.b + (c101.
b - c001.
b) *
d.r + (c010.
b - c000.
b) *
d.g +
214 (c000.
b - c010.
b - c001.
b + c011.
b) *
d.b *
d.g +
215 (c001.
b - c011.
b - c101.
b + c111.
b) *
d.r *
d.g;
217 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
218 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
220 c.r = c000.
r + (c101.
r - c100.
r) *
d.b + (c100.
r - c000.
r) *
d.r + (c010.
r - c000.
r) *
d.g +
221 (c100.
r - c110.
r - c101.
r + c111.
r) *
d.b *
d.g +
222 (c000.
r - c010.
r - c100.
r + c110.
r) *
d.r *
d.g;
223 c.g = c000.
g + (c101.
g - c100.
g) *
d.b + (c100.
g - c000.
g) *
d.r + (c010.
g - c000.
g) *
d.g +
224 (c100.
g - c110.
g - c101.
g + c111.
g) *
d.b *
d.g +
225 (c000.
g - c010.
g - c100.
g + c110.
g) *
d.r *
d.g;
226 c.b = c000.
b + (c101.
b - c100.
b) *
d.b + (c100.
b - c000.
b) *
d.r + (c010.
b - c000.
b) *
d.g +
227 (c100.
b - c110.
b - c101.
b + c111.
b) *
d.b *
d.g +
228 (c000.
b - c010.
b - c100.
b + c110.
b) *
d.r *
d.g;
241 const int lutsize2 = lut3d->lutsize2;
242 const int lutsize = lut3d->lutsize;
245 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
246 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
247 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
251 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
252 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
253 c.r = (1-
d.r) * c000.
r + (
d.r-
d.g) * c100.
r + (
d.g-
d.b) * c110.
r + (
d.b) * c111.
r;
254 c.g = (1-
d.r) * c000.
g + (
d.r-
d.g) * c100.
g + (
d.g-
d.b) * c110.
g + (
d.b) * c111.
g;
255 c.b = (1-
d.r) * c000.
b + (
d.r-
d.g) * c100.
b + (
d.g-
d.b) * c110.
b + (
d.b) * c111.
b;
256 }
else if (
d.r >
d.b) {
257 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
258 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
259 c.r = (1-
d.r) * c000.
r + (
d.r-
d.b) * c100.
r + (
d.b-
d.g) * c101.
r + (
d.g) * c111.
r;
260 c.g = (1-
d.r) * c000.
g + (
d.r-
d.b) * c100.
g + (
d.b-
d.g) * c101.
g + (
d.g) * c111.
g;
261 c.b = (1-
d.r) * c000.
b + (
d.r-
d.b) * c100.
b + (
d.b-
d.g) * c101.
b + (
d.g) * c111.
b;
263 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
264 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
265 c.r = (1-
d.b) * c000.
r + (
d.b-
d.r) * c001.
r + (
d.r-
d.g) * c101.
r + (
d.g) * c111.
r;
266 c.g = (1-
d.b) * c000.
g + (
d.b-
d.r) * c001.
g + (
d.r-
d.g) * c101.
g + (
d.g) * c111.
g;
267 c.b = (1-
d.b) * c000.
b + (
d.b-
d.r) * c001.
b + (
d.r-
d.g) * c101.
b + (
d.g) * c111.
b;
271 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
272 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
273 c.r = (1-
d.b) * c000.
r + (
d.b-
d.g) * c001.
r + (
d.g-
d.r) * c011.
r + (
d.r) * c111.
r;
274 c.g = (1-
d.b) * c000.
g + (
d.b-
d.g) * c001.
g + (
d.g-
d.r) * c011.
g + (
d.r) * c111.
g;
275 c.b = (1-
d.b) * c000.
b + (
d.b-
d.g) * c001.
b + (
d.g-
d.r) * c011.
b + (
d.r) * c111.
b;
276 }
else if (
d.b >
d.r) {
277 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
278 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
279 c.r = (1-
d.g) * c000.
r + (
d.g-
d.b) * c010.
r + (
d.b-
d.r) * c011.
r + (
d.r) * c111.
r;
280 c.g = (1-
d.g) * c000.
g + (
d.g-
d.b) * c010.
g + (
d.b-
d.r) * c011.
g + (
d.r) * c111.
g;
281 c.b = (1-
d.g) * c000.
b + (
d.g-
d.b) * c010.
b + (
d.b-
d.r) * c011.
b + (
d.r) * c111.
b;
283 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
284 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
285 c.r = (1-
d.g) * c000.
r + (
d.g-
d.r) * c010.
r + (
d.r-
d.b) * c110.
r + (
d.b) * c111.
r;
286 c.g = (1-
d.g) * c000.
g + (
d.g-
d.r) * c010.
g + (
d.r-
d.b) * c110.
g + (
d.b) * c111.
g;
287 c.b = (1-
d.g) * c000.
b + (
d.g-
d.r) * c010.
b + (
d.r-
d.b) * c110.
b + (
d.b) * c111.
b;
294 int idx,
const float s)
296 const int lut_max = prelut->
size - 1;
297 const float scaled = (
s - prelut->
min[idx]) * prelut->
scale[idx];
298 const float x =
av_clipf(scaled, 0.0
f, lut_max);
299 const int prev =
PREV(x);
300 const int next =
FFMIN((
int)(x) + 1, lut_max);
301 const float p = prelut->
lut[idx][prev];
302 const float n = prelut->
lut[idx][next];
303 const float d = x - (
float)prev;
312 if (prelut->size <= 0)
321 #define DEFINE_INTERP_FUNC_PLANAR(name, nbits, depth) \
322 static int interp_##nbits##_##name##_p##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
325 const LUT3DContext *lut3d = ctx->priv; \
326 const Lut3DPreLut *prelut = &lut3d->prelut; \
327 const ThreadData *td = arg; \
328 const AVFrame *in = td->in; \
329 const AVFrame *out = td->out; \
330 const int direct = out == in; \
331 const int slice_start = (in->height * jobnr ) / nb_jobs; \
332 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
333 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
334 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
335 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
336 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
337 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
338 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
339 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
340 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
341 const float lut_max = lut3d->lutsize - 1; \
342 const float scale_f = 1.0f / ((1<<depth) - 1); \
343 const float scale_r = lut3d->scale.r * lut_max; \
344 const float scale_g = lut3d->scale.g * lut_max; \
345 const float scale_b = lut3d->scale.b * lut_max; \
347 for (y = slice_start; y < slice_end; y++) { \
348 uint##nbits##_t *dstg = (uint##nbits##_t *)grow; \
349 uint##nbits##_t *dstb = (uint##nbits##_t *)brow; \
350 uint##nbits##_t *dstr = (uint##nbits##_t *)rrow; \
351 uint##nbits##_t *dsta = (uint##nbits##_t *)arow; \
352 const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow; \
353 const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow; \
354 const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow; \
355 const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow; \
356 for (x = 0; x < in->width; x++) { \
357 const struct rgbvec rgb = {srcr[x] * scale_f, \
359 srcb[x] * scale_f}; \
360 const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \
361 const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \
362 av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \
363 av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \
364 struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
365 dstr[x] = av_clip_uintp2(vec.r * (float)((1<<depth) - 1), depth); \
366 dstg[x] = av_clip_uintp2(vec.g * (float)((1<<depth) - 1), depth); \
367 dstb[x] = av_clip_uintp2(vec.b * (float)((1<<depth) - 1), depth); \
368 if (!direct && in->linesize[3]) \
371 grow += out->linesize[0]; \
372 brow += out->linesize[1]; \
373 rrow += out->linesize[2]; \
374 arow += out->linesize[3]; \
375 srcgrow += in->linesize[0]; \
376 srcbrow += in->linesize[1]; \
377 srcrrow += in->linesize[2]; \
378 srcarow += in->linesize[3]; \
419 #define DEFINE_INTERP_FUNC_PLANAR_FLOAT(name, depth) \
420 static int interp_##name##_pf##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
423 const LUT3DContext *lut3d = ctx->priv; \
424 const Lut3DPreLut *prelut = &lut3d->prelut; \
425 const ThreadData *td = arg; \
426 const AVFrame *in = td->in; \
427 const AVFrame *out = td->out; \
428 const int direct = out == in; \
429 const int slice_start = (in->height * jobnr ) / nb_jobs; \
430 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
431 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
432 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
433 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
434 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
435 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
436 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
437 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
438 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
439 const float lut_max = lut3d->lutsize - 1; \
440 const float scale_r = lut3d->scale.r * lut_max; \
441 const float scale_g = lut3d->scale.g * lut_max; \
442 const float scale_b = lut3d->scale.b * lut_max; \
444 for (y = slice_start; y < slice_end; y++) { \
445 float *dstg = (float *)grow; \
446 float *dstb = (float *)brow; \
447 float *dstr = (float *)rrow; \
448 float *dsta = (float *)arow; \
449 const float *srcg = (const float *)srcgrow; \
450 const float *srcb = (const float *)srcbrow; \
451 const float *srcr = (const float *)srcrrow; \
452 const float *srca = (const float *)srcarow; \
453 for (x = 0; x < in->width; x++) { \
454 const struct rgbvec rgb = {sanitizef(srcr[x]), \
455 sanitizef(srcg[x]), \
456 sanitizef(srcb[x])}; \
457 const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \
458 const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \
459 av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \
460 av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \
461 struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
465 if (!direct && in->linesize[3]) \
468 grow += out->linesize[0]; \
469 brow += out->linesize[1]; \
470 rrow += out->linesize[2]; \
471 arow += out->linesize[3]; \
472 srcgrow += in->linesize[0]; \
473 srcbrow += in->linesize[1]; \
474 srcrrow += in->linesize[2]; \
475 srcarow += in->linesize[3]; \
486 #define DEFINE_INTERP_FUNC(name, nbits) \
487 static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
490 const LUT3DContext *lut3d = ctx->priv; \
491 const Lut3DPreLut *prelut = &lut3d->prelut; \
492 const ThreadData *td = arg; \
493 const AVFrame *in = td->in; \
494 const AVFrame *out = td->out; \
495 const int direct = out == in; \
496 const int step = lut3d->step; \
497 const uint8_t r = lut3d->rgba_map[R]; \
498 const uint8_t g = lut3d->rgba_map[G]; \
499 const uint8_t b = lut3d->rgba_map[B]; \
500 const uint8_t a = lut3d->rgba_map[A]; \
501 const int slice_start = (in->height * jobnr ) / nb_jobs; \
502 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
503 uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \
504 const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \
505 const float lut_max = lut3d->lutsize - 1; \
506 const float scale_f = 1.0f / ((1<<nbits) - 1); \
507 const float scale_r = lut3d->scale.r * lut_max; \
508 const float scale_g = lut3d->scale.g * lut_max; \
509 const float scale_b = lut3d->scale.b * lut_max; \
511 for (y = slice_start; y < slice_end; y++) { \
512 uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \
513 const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \
514 for (x = 0; x < in->width * step; x += step) { \
515 const struct rgbvec rgb = {src[x + r] * scale_f, \
516 src[x + g] * scale_f, \
517 src[x + b] * scale_f}; \
518 const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \
519 const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \
520 av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \
521 av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \
522 struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
523 dst[x + r] = av_clip_uint##nbits(vec.r * (float)((1<<nbits) - 1)); \
524 dst[x + g] = av_clip_uint##nbits(vec.g * (float)((1<<nbits) - 1)); \
525 dst[x + b] = av_clip_uint##nbits(vec.b * (float)((1<<nbits) - 1)); \
526 if (!direct && step == 4) \
527 dst[x + a] = src[x + a]; \
529 dstrow += out->linesize[0]; \
530 srcrow += in ->linesize[0]; \
547 #define MAX_LINE_SIZE 512
553 return !*p || *p ==
'#';
564 while ((
c = fgetc(
f)) != EOF) {
575 if ((
c = fgetc(
f)) == EOF)
590 #define NEXT_LINE(loop_cond) do { \
591 if (!fgets(line, sizeof(line), f)) { \
592 av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n"); \
593 return AVERROR_INVALIDDATA; \
597 #define NEXT_LINE_OR_GOTO(loop_cond, label) do { \
598 if (!fgets(line, sizeof(line), f)) { \
599 av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n"); \
600 ret = AVERROR_INVALIDDATA; \
609 if (lutsize < 2 || lutsize >
MAX_LEVEL) {
621 for (
i = 0;
i < 3;
i++) {
629 for (
i = 0;
i < 3;
i++) {
634 lut3d->
lutsize2 = lutsize * lutsize;
650 if (!strncmp(
line,
"3DLUTSIZE ", 10)) {
660 for (k = 0; k <
size; k++) {
661 for (j = 0; j <
size; j++) {
664 if (k != 0 || j != 0 ||
i != 0)
679 float min[3] = {0.0, 0.0, 0.0};
680 float max[3] = {1.0, 1.0, 1.0};
683 if (!strncmp(
line,
"LUT_3D_SIZE", 11)) {
692 for (k = 0; k <
size; k++) {
693 for (j = 0; j <
size; j++) {
700 if (!strncmp(
line,
"DOMAIN_", 7)) {
702 if (!strncmp(
line + 7,
"MIN ", 4)) vals =
min;
703 else if (!strncmp(
line + 7,
"MAX ", 4)) vals =
max;
706 if (
av_sscanf(
line + 11,
"%f %f %f", vals, vals + 1, vals + 2) != 3)
711 }
else if (!strncmp(
line,
"TITLE", 5)) {
739 const int size2 = 17 * 17;
740 const float scale = 16*16*16;
749 for (k = 0; k <
size; k++) {
750 for (j = 0; j <
size; j++) {
774 uint8_t rgb_map[3] = {0, 1, 2};
777 if (!strncmp(
line,
"in", 2)) in = strtol(
line + 2,
NULL, 0);
779 else if (!strncmp(
line,
"values", 6)) {
780 const char *p =
line + 6;
781 #define SET_COLOR(id) do { \
782 while (av_isspace(*p)) \
785 case 'r': rgb_map[id] = 0; break; \
786 case 'g': rgb_map[id] = 1; break; \
787 case 'b': rgb_map[id] = 2; break; \
789 while (*p && !av_isspace(*p)) \
799 if (in == -1 ||
out == -1) {
803 if (in < 2 ||
out < 2 ||
819 for (k = 0; k <
size; k++) {
820 for (j = 0; j <
size; j++) {
854 mid = (low + hi) / 2;
865 #define NEXT_FLOAT_OR_GOTO(value, label) \
866 if (!fget_next_word(line, sizeof(line) ,f)) { \
867 ret = AVERROR_INVALIDDATA; \
870 if (av_sscanf(line, "%f", &value) != 1) { \
871 ret = AVERROR_INVALIDDATA; \
879 float in_min[3] = {0.0, 0.0, 0.0};
880 float in_max[3] = {1.0, 1.0, 1.0};
881 float out_min[3] = {0.0, 0.0, 0.0};
882 float out_max[3] = {1.0, 1.0, 1.0};
883 int inside_metadata = 0,
size, size2;
887 int prelut_sizes[3] = {0, 0, 0};
892 if (strncmp(
line,
"CSPLUTV100", 10)) {
899 if (strncmp(
line,
"3D", 2)) {
908 if (!strncmp(
line,
"BEGIN METADATA", 14)) {
912 if (!strncmp(
line,
"END METADATA", 12)) {
916 if (inside_metadata == 0) {
917 int size_r, size_g, size_b;
919 for (
int i = 0;
i < 3;
i++) {
920 int npoints = strtol(
line,
NULL, 0);
931 if (in_prelut[
i] || out_prelut[
i]) {
937 in_prelut[
i] = (
float*)
av_malloc(npoints *
sizeof(
float));
938 out_prelut[
i] = (
float*)
av_malloc(npoints *
sizeof(
float));
939 if (!in_prelut[
i] || !out_prelut[
i]) {
944 prelut_sizes[
i] = npoints;
946 in_max[
i] = -FLT_MAX;
947 out_min[
i] = FLT_MAX;
948 out_max[
i] = -FLT_MAX;
950 for (
int j = 0; j < npoints; j++) {
952 in_min[
i] =
FFMIN(in_min[
i], v);
953 in_max[
i] =
FFMAX(in_max[
i], v);
955 if (j > 0 && v < last) {
963 for (
int j = 0; j < npoints; j++) {
965 out_min[
i] =
FFMIN(out_min[
i], v);
966 out_max[
i] =
FFMAX(out_max[
i], v);
967 out_prelut[
i][j] = v;
970 }
else if (npoints == 2) {
991 if (
av_sscanf(
line,
"%d %d %d", &size_r, &size_g, &size_b) != 3) {
995 if (size_r != size_g || size_r != size_b) {
1004 if (prelut_sizes[0] && prelut_sizes[1] && prelut_sizes[2])
1011 for (
int k = 0; k <
size; k++) {
1012 for (
int j = 0; j <
size; j++) {
1013 for (
int i = 0;
i <
size;
i++) {
1022 vec->
r *= out_max[0] - out_min[0];
1023 vec->
g *= out_max[1] - out_min[1];
1024 vec->
b *= out_max[2] - out_min[2];
1034 for (
int c = 0;
c < 3;
c++) {
1047 a = out_prelut[
c][idx + 0];
1048 b = out_prelut[
c][idx + 1];
1049 mix = x - in_prelut[
c][idx];
1065 for (
int c = 0;
c < 3;
c++) {
1077 const float c = 1. / (
size - 1);
1083 for (k = 0; k <
size; k++) {
1084 for (j = 0; j <
size; j++) {
1115 #if CONFIG_LUT3D_FILTER || CONFIG_HALDCLUT_FILTER
1119 int depth, is16bit, isfloat,
planar;
1123 depth =
desc->comp[0].depth;
1124 is16bit =
desc->comp[0].depth > 8;
1130 #define SET_FUNC(name) do { \
1131 if (planar && !isfloat) { \
1133 case 8: lut3d->interp = interp_8_##name##_p8; break; \
1134 case 9: lut3d->interp = interp_16_##name##_p9; break; \
1135 case 10: lut3d->interp = interp_16_##name##_p10; break; \
1136 case 12: lut3d->interp = interp_16_##name##_p12; break; \
1137 case 14: lut3d->interp = interp_16_##name##_p14; break; \
1138 case 16: lut3d->interp = interp_16_##name##_p16; break; \
1140 } else if (isfloat) { lut3d->interp = interp_##name##_pf32; \
1141 } else if (is16bit) { lut3d->interp = interp_16_##name; \
1142 } else { lut3d->interp = interp_8_##name; } \
1202 char *res,
int res_len,
int flags)
1216 #define COMMON_OPTIONS_OFFSET CONFIG_LUT3D_FILTER
1217 static const AVOption lut3d_haldclut_options[] = {
1218 #if CONFIG_LUT3D_FILTER
1221 #if CONFIG_HALDCLUT_FILTER
1223 {
"first",
"process only first CLUT, ignore rest", 0,
AV_OPT_TYPE_CONST, {.i64=0}, .flags =
TFLAGS, .unit =
"clut" },
1229 #if CONFIG_LUT3D_FILTER
1253 ext = strrchr(lut3d->
file,
'.');
1292 for (
i = 0;
i < 3;
i++) {
1315 .priv_class = &lut3d_class,
1321 #if CONFIG_HALDCLUT_FILTER
1326 const ptrdiff_t linesize =
frame->linesize[0];
1327 const int w = lut3d->clut_width;
1328 const int step = lut3d->clut_step;
1329 const uint8_t *rgba_map = lut3d->clut_rgba_map;
1331 const int level2 = lut3d->
lutsize2;
1333 #define LOAD_CLUT(nbits) do { \
1334 int i, j, k, x = 0, y = 0; \
1336 for (k = 0; k < level; k++) { \
1337 for (j = 0; j < level; j++) { \
1338 for (i = 0; i < level; i++) { \
1339 const uint##nbits##_t *src = (const uint##nbits##_t *) \
1340 (data + y*linesize + x*step); \
1341 struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \
1342 vec->r = src[rgba_map[0]] / (float)((1<<(nbits)) - 1); \
1343 vec->g = src[rgba_map[1]] / (float)((1<<(nbits)) - 1); \
1344 vec->b = src[rgba_map[2]] / (float)((1<<(nbits)) - 1); \
1354 switch (lut3d->clut_bits) {
1355 case 8: LOAD_CLUT(8);
break;
1356 case 16: LOAD_CLUT(16);
break;
1362 const uint8_t *datag =
frame->data[0];
1363 const uint8_t *datab =
frame->data[1];
1364 const uint8_t *datar =
frame->data[2];
1365 const ptrdiff_t glinesize =
frame->linesize[0];
1366 const ptrdiff_t blinesize =
frame->linesize[1];
1367 const ptrdiff_t rlinesize =
frame->linesize[2];
1368 const int w = lut3d->clut_width;
1370 const int level2 = lut3d->
lutsize2;
1372 #define LOAD_CLUT_PLANAR(nbits, depth) do { \
1373 int i, j, k, x = 0, y = 0; \
1375 for (k = 0; k < level; k++) { \
1376 for (j = 0; j < level; j++) { \
1377 for (i = 0; i < level; i++) { \
1378 const uint##nbits##_t *gsrc = (const uint##nbits##_t *) \
1379 (datag + y*glinesize); \
1380 const uint##nbits##_t *bsrc = (const uint##nbits##_t *) \
1381 (datab + y*blinesize); \
1382 const uint##nbits##_t *rsrc = (const uint##nbits##_t *) \
1383 (datar + y*rlinesize); \
1384 struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \
1385 vec->r = gsrc[x] / (float)((1<<(depth)) - 1); \
1386 vec->g = bsrc[x] / (float)((1<<(depth)) - 1); \
1387 vec->b = rsrc[x] / (float)((1<<(depth)) - 1); \
1397 switch (lut3d->clut_bits) {
1398 case 8: LOAD_CLUT_PLANAR(8, 8);
break;
1399 case 9: LOAD_CLUT_PLANAR(16, 9);
break;
1400 case 10: LOAD_CLUT_PLANAR(16, 10);
break;
1401 case 12: LOAD_CLUT_PLANAR(16, 12);
break;
1402 case 14: LOAD_CLUT_PLANAR(16, 14);
break;
1403 case 16: LOAD_CLUT_PLANAR(16, 16);
break;
1409 const uint8_t *datag =
frame->data[0];
1410 const uint8_t *datab =
frame->data[1];
1411 const uint8_t *datar =
frame->data[2];
1412 const ptrdiff_t glinesize =
frame->linesize[0];
1413 const ptrdiff_t blinesize =
frame->linesize[1];
1414 const ptrdiff_t rlinesize =
frame->linesize[2];
1415 const int w = lut3d->clut_width;
1417 const int level2 = lut3d->
lutsize2;
1419 int i, j, k, x = 0, y = 0;
1421 for (k = 0; k <
level; k++) {
1422 for (j = 0; j <
level; j++) {
1424 const float *gsrc = (
const float *)(datag + y*glinesize);
1425 const float *bsrc = (
const float *)(datab + y*blinesize);
1426 const float *rsrc = (
const float *)(datar + y*rlinesize);
1449 outlink->
w =
ctx->inputs[0]->w;
1450 outlink->
h =
ctx->inputs[0]->h;
1472 lut3d->clut_bits =
desc->comp[0].depth;
1496 const int max_clut_level = sqrt(
MAX_LEVEL);
1497 const int max_clut_size = max_clut_level*max_clut_level*max_clut_level;
1499 "(maximum level is %d, or %dx%d CLUT)\n",
1500 max_clut_level, max_clut_size, max_clut_size);
1520 if (lut3d->clut || !lut3d->got_clut) {
1521 if (lut3d->clut_float)
1522 update_clut_float(
ctx->priv, second);
1523 else if (lut3d->clut_planar)
1524 update_clut_planar(
ctx->priv, second);
1526 update_clut_packed(
ctx->priv, second);
1527 lut3d->got_clut = 1;
1537 lut3d->fs.on_event = update_apply_clut;
1549 &lut3d_haldclut_options[COMMON_OPTIONS_OFFSET]);
1559 .config_props = config_clut,
1575 .
preinit = haldclut_framesync_preinit,
1576 .
init = haldclut_init,
1577 .
uninit = haldclut_uninit,
1582 .priv_class = &haldclut_class,
1590 #if CONFIG_LUT1D_FILTER
1592 enum interp_1d_mode {
1593 INTERPOLATE_1D_NEAREST,
1594 INTERPOLATE_1D_LINEAR,
1595 INTERPOLATE_1D_CUBIC,
1596 INTERPOLATE_1D_COSINE,
1597 INTERPOLATE_1D_SPLINE,
1601 #define MAX_1D_LEVEL 65536
1603 typedef struct LUT1DContext {
1608 uint8_t rgba_map[4];
1610 float lut[3][MAX_1D_LEVEL];
1616 #define OFFSET(x) offsetof(LUT1DContext, x)
1618 static void set_identity_matrix_1d(LUT1DContext *lut1d,
int size)
1620 const float c = 1. / (
size - 1);
1623 lut1d->lutsize =
size;
1625 lut1d->lut[0][
i] =
i *
c;
1626 lut1d->lut[1][
i] =
i *
c;
1627 lut1d->lut[2][
i] =
i *
c;
1633 LUT1DContext *lut1d =
ctx->priv;
1635 float in_min[3] = {0.0, 0.0, 0.0};
1636 float in_max[3] = {1.0, 1.0, 1.0};
1637 float out_min[3] = {0.0, 0.0, 0.0};
1638 float out_max[3] = {1.0, 1.0, 1.0};
1639 int inside_metadata = 0,
size;
1642 if (strncmp(
line,
"CSPLUTV100", 10)) {
1648 if (strncmp(
line,
"1D", 2)) {
1656 if (!strncmp(
line,
"BEGIN METADATA", 14)) {
1657 inside_metadata = 1;
1660 if (!strncmp(
line,
"END METADATA", 12)) {
1661 inside_metadata = 0;
1664 if (inside_metadata == 0) {
1665 for (
int i = 0;
i < 3;
i++) {
1666 int npoints = strtol(
line,
NULL, 0);
1684 if (size < 2 || size > MAX_1D_LEVEL) {
1689 lut1d->lutsize =
size;
1691 for (
int i = 0;
i <
size;
i++) {
1693 if (
av_sscanf(
line,
"%f %f %f", &lut1d->lut[0][
i], &lut1d->lut[1][
i], &lut1d->lut[2][
i]) != 3)
1695 lut1d->lut[0][
i] *= out_max[0] - out_min[0];
1696 lut1d->lut[1][
i] *= out_max[1] - out_min[1];
1697 lut1d->lut[2][
i] *= out_max[2] - out_min[2];
1704 lut1d->scale.r =
av_clipf(1. / (in_max[0] - in_min[0]), 0.
f, 1.
f);
1705 lut1d->scale.g =
av_clipf(1. / (in_max[1] - in_min[1]), 0.
f, 1.
f);
1706 lut1d->scale.b =
av_clipf(1. / (in_max[2] - in_min[2]), 0.
f, 1.
f);
1713 LUT1DContext *lut1d =
ctx->priv;
1715 float min[3] = {0.0, 0.0, 0.0};
1716 float max[3] = {1.0, 1.0, 1.0};
1719 if (!strncmp(
line,
"LUT_1D_SIZE", 11)) {
1723 if (size < 2 || size > MAX_1D_LEVEL) {
1727 lut1d->lutsize =
size;
1732 if (!strncmp(
line,
"DOMAIN_", 7)) {
1734 if (!strncmp(
line + 7,
"MIN ", 4)) vals =
min;
1735 else if (!strncmp(
line + 7,
"MAX ", 4)) vals =
max;
1738 if (
av_sscanf(
line + 11,
"%f %f %f", vals, vals + 1, vals + 2) != 3)
1743 }
else if (!strncmp(
line,
"LUT_1D_INPUT_RANGE ", 19)) {
1749 }
else if (!strncmp(
line,
"TITLE", 5)) {
1753 if (
av_sscanf(
line,
"%f %f %f", &lut1d->lut[0][
i], &lut1d->lut[1][
i], &lut1d->lut[2][
i]) != 3)
1767 static const AVOption lut1d_options[] = {
1770 {
"nearest",
"use values from the nearest defined points", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_NEAREST}, 0, 0,
TFLAGS, .unit =
"interp_mode" },
1771 {
"linear",
"use values from the linear interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_LINEAR}, 0, 0,
TFLAGS, .unit =
"interp_mode" },
1772 {
"cosine",
"use values from the cosine interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_COSINE}, 0, 0,
TFLAGS, .unit =
"interp_mode" },
1773 {
"cubic",
"use values from the cubic interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_CUBIC}, 0, 0,
TFLAGS, .unit =
"interp_mode" },
1774 {
"spline",
"use values from the spline interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_SPLINE}, 0, 0,
TFLAGS, .unit =
"interp_mode" },
1780 static inline float interp_1d_nearest(
const LUT1DContext *lut1d,
1781 int idx,
const float s)
1783 return lut1d->lut[idx][
NEAR(
s)];
1786 #define NEXT1D(x) (FFMIN((int)(x) + 1, lut1d->lutsize - 1))
1788 static inline float interp_1d_linear(
const LUT1DContext *lut1d,
1789 int idx,
const float s)
1791 const int prev =
PREV(
s);
1792 const int next = NEXT1D(
s);
1793 const float d =
s - prev;
1794 const float p = lut1d->lut[idx][prev];
1795 const float n = lut1d->lut[idx][next];
1800 static inline float interp_1d_cosine(
const LUT1DContext *lut1d,
1801 int idx,
const float s)
1803 const int prev =
PREV(
s);
1804 const int next = NEXT1D(
s);
1805 const float d =
s - prev;
1806 const float p = lut1d->lut[idx][prev];
1807 const float n = lut1d->lut[idx][next];
1808 const float m = (1.f -
cosf(
d *
M_PI)) * .5
f;
1810 return lerpf(p, n, m);
1813 static inline float interp_1d_cubic(
const LUT1DContext *lut1d,
1814 int idx,
const float s)
1816 const int prev =
PREV(
s);
1817 const int next = NEXT1D(
s);
1818 const float mu =
s - prev;
1821 float y0 = lut1d->lut[idx][
FFMAX(prev - 1, 0)];
1822 float y1 = lut1d->lut[idx][prev];
1823 float y2 = lut1d->lut[idx][next];
1824 float y3 = lut1d->lut[idx][
FFMIN(next + 1, lut1d->lutsize - 1)];
1828 a0 = y3 - y2 - y0 + y1;
1833 return a0 * mu * mu2 +
a1 * mu2 +
a2 * mu +
a3;
1836 static inline float interp_1d_spline(
const LUT1DContext *lut1d,
1837 int idx,
const float s)
1839 const int prev =
PREV(
s);
1840 const int next = NEXT1D(
s);
1841 const float x =
s - prev;
1842 float c0,
c1,
c2, c3;
1844 float y0 = lut1d->lut[idx][
FFMAX(prev - 1, 0)];
1845 float y1 = lut1d->lut[idx][prev];
1846 float y2 = lut1d->lut[idx][next];
1847 float y3 = lut1d->lut[idx][
FFMIN(next + 1, lut1d->lutsize - 1)];
1850 c1 = .5f * (y2 - y0);
1851 c2 = y0 - 2.5f * y1 + 2.f * y2 - .5f * y3;
1852 c3 = .5f * (y3 - y0) + 1.5
f * (y1 - y2);
1854 return ((c3 * x +
c2) * x +
c1) * x + c0;
1857 #define DEFINE_INTERP_FUNC_PLANAR_1D(name, nbits, depth) \
1858 static int interp_1d_##nbits##_##name##_p##depth(AVFilterContext *ctx, \
1859 void *arg, int jobnr, \
1863 const LUT1DContext *lut1d = ctx->priv; \
1864 const ThreadData *td = arg; \
1865 const AVFrame *in = td->in; \
1866 const AVFrame *out = td->out; \
1867 const int direct = out == in; \
1868 const int slice_start = (in->height * jobnr ) / nb_jobs; \
1869 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
1870 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
1871 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
1872 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
1873 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
1874 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
1875 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
1876 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
1877 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
1878 const float factor = (1 << depth) - 1; \
1879 const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1); \
1880 const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1); \
1881 const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1); \
1883 for (y = slice_start; y < slice_end; y++) { \
1884 uint##nbits##_t *dstg = (uint##nbits##_t *)grow; \
1885 uint##nbits##_t *dstb = (uint##nbits##_t *)brow; \
1886 uint##nbits##_t *dstr = (uint##nbits##_t *)rrow; \
1887 uint##nbits##_t *dsta = (uint##nbits##_t *)arow; \
1888 const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow; \
1889 const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow; \
1890 const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow; \
1891 const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow; \
1892 for (x = 0; x < in->width; x++) { \
1893 float r = srcr[x] * scale_r; \
1894 float g = srcg[x] * scale_g; \
1895 float b = srcb[x] * scale_b; \
1896 r = interp_1d_##name(lut1d, 0, r); \
1897 g = interp_1d_##name(lut1d, 1, g); \
1898 b = interp_1d_##name(lut1d, 2, b); \
1899 dstr[x] = av_clip_uintp2(r * factor, depth); \
1900 dstg[x] = av_clip_uintp2(g * factor, depth); \
1901 dstb[x] = av_clip_uintp2(b * factor, depth); \
1902 if (!direct && in->linesize[3]) \
1903 dsta[x] = srca[x]; \
1905 grow += out->linesize[0]; \
1906 brow += out->linesize[1]; \
1907 rrow += out->linesize[2]; \
1908 arow += out->linesize[3]; \
1909 srcgrow += in->linesize[0]; \
1910 srcbrow += in->linesize[1]; \
1911 srcrrow += in->linesize[2]; \
1912 srcarow += in->linesize[3]; \
1917 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 8, 8)
1918 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 8, 8)
1919 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 8, 8)
1920 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 8, 8)
1921 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 8, 8)
1923 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 9)
1924 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 9)
1925 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 9)
1926 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 9)
1927 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 9)
1929 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 10)
1930 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 10)
1931 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 10)
1932 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 10)
1933 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 10)
1935 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 12)
1936 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 12)
1937 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 12)
1938 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 12)
1939 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 12)
1941 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 14)
1942 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 14)
1943 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 14)
1944 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 14)
1945 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 14)
1947 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 16)
1948 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 16)
1949 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 16)
1950 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 16)
1951 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 16)
1953 #define DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(name, depth) \
1954 static int interp_1d_##name##_pf##depth(AVFilterContext *ctx, \
1955 void *arg, int jobnr, \
1959 const LUT1DContext *lut1d = ctx->priv; \
1960 const ThreadData *td = arg; \
1961 const AVFrame *in = td->in; \
1962 const AVFrame *out = td->out; \
1963 const int direct = out == in; \
1964 const int slice_start = (in->height * jobnr ) / nb_jobs; \
1965 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
1966 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
1967 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
1968 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
1969 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
1970 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
1971 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
1972 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
1973 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
1974 const float lutsize = lut1d->lutsize - 1; \
1975 const float scale_r = lut1d->scale.r * lutsize; \
1976 const float scale_g = lut1d->scale.g * lutsize; \
1977 const float scale_b = lut1d->scale.b * lutsize; \
1979 for (y = slice_start; y < slice_end; y++) { \
1980 float *dstg = (float *)grow; \
1981 float *dstb = (float *)brow; \
1982 float *dstr = (float *)rrow; \
1983 float *dsta = (float *)arow; \
1984 const float *srcg = (const float *)srcgrow; \
1985 const float *srcb = (const float *)srcbrow; \
1986 const float *srcr = (const float *)srcrrow; \
1987 const float *srca = (const float *)srcarow; \
1988 for (x = 0; x < in->width; x++) { \
1989 float r = av_clipf(sanitizef(srcr[x]) * scale_r, 0.0f, lutsize); \
1990 float g = av_clipf(sanitizef(srcg[x]) * scale_g, 0.0f, lutsize); \
1991 float b = av_clipf(sanitizef(srcb[x]) * scale_b, 0.0f, lutsize); \
1992 r = interp_1d_##name(lut1d, 0, r); \
1993 g = interp_1d_##name(lut1d, 1, g); \
1994 b = interp_1d_##name(lut1d, 2, b); \
1998 if (!direct && in->linesize[3]) \
1999 dsta[x] = srca[x]; \
2001 grow += out->linesize[0]; \
2002 brow += out->linesize[1]; \
2003 rrow += out->linesize[2]; \
2004 arow += out->linesize[3]; \
2005 srcgrow += in->linesize[0]; \
2006 srcbrow += in->linesize[1]; \
2007 srcrrow += in->linesize[2]; \
2008 srcarow += in->linesize[3]; \
2013 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(nearest, 32)
2014 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(
linear, 32)
2015 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cosine, 32)
2016 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cubic, 32)
2017 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(spline, 32)
2019 #define DEFINE_INTERP_FUNC_1D(name, nbits) \
2020 static int interp_1d_##nbits##_##name(AVFilterContext *ctx, void *arg, \
2021 int jobnr, int nb_jobs) \
2024 const LUT1DContext *lut1d = ctx->priv; \
2025 const ThreadData *td = arg; \
2026 const AVFrame *in = td->in; \
2027 const AVFrame *out = td->out; \
2028 const int direct = out == in; \
2029 const int step = lut1d->step; \
2030 const uint8_t r = lut1d->rgba_map[R]; \
2031 const uint8_t g = lut1d->rgba_map[G]; \
2032 const uint8_t b = lut1d->rgba_map[B]; \
2033 const uint8_t a = lut1d->rgba_map[A]; \
2034 const int slice_start = (in->height * jobnr ) / nb_jobs; \
2035 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
2036 uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \
2037 const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \
2038 const float factor = (1 << nbits) - 1; \
2039 const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1); \
2040 const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1); \
2041 const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1); \
2043 for (y = slice_start; y < slice_end; y++) { \
2044 uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \
2045 const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \
2046 for (x = 0; x < in->width * step; x += step) { \
2047 float rr = src[x + r] * scale_r; \
2048 float gg = src[x + g] * scale_g; \
2049 float bb = src[x + b] * scale_b; \
2050 rr = interp_1d_##name(lut1d, 0, rr); \
2051 gg = interp_1d_##name(lut1d, 1, gg); \
2052 bb = interp_1d_##name(lut1d, 2, bb); \
2053 dst[x + r] = av_clip_uint##nbits(rr * factor); \
2054 dst[x + g] = av_clip_uint##nbits(gg * factor); \
2055 dst[x + b] = av_clip_uint##nbits(bb * factor); \
2056 if (!direct && step == 4) \
2057 dst[x + a] = src[x + a]; \
2059 dstrow += out->linesize[0]; \
2060 srcrow += in ->linesize[0]; \
2065 DEFINE_INTERP_FUNC_1D(nearest, 8)
2066 DEFINE_INTERP_FUNC_1D(
linear, 8)
2067 DEFINE_INTERP_FUNC_1D(cosine, 8)
2068 DEFINE_INTERP_FUNC_1D(cubic, 8)
2069 DEFINE_INTERP_FUNC_1D(spline, 8)
2071 DEFINE_INTERP_FUNC_1D(nearest, 16)
2072 DEFINE_INTERP_FUNC_1D(
linear, 16)
2073 DEFINE_INTERP_FUNC_1D(cosine, 16)
2074 DEFINE_INTERP_FUNC_1D(cubic, 16)
2075 DEFINE_INTERP_FUNC_1D(spline, 16)
2079 int depth, is16bit, isfloat,
planar;
2080 LUT1DContext *lut1d =
inlink->dst->priv;
2083 depth =
desc->comp[0].depth;
2084 is16bit =
desc->comp[0].depth > 8;
2090 #define SET_FUNC_1D(name) do { \
2091 if (planar && !isfloat) { \
2093 case 8: lut1d->interp = interp_1d_8_##name##_p8; break; \
2094 case 9: lut1d->interp = interp_1d_16_##name##_p9; break; \
2095 case 10: lut1d->interp = interp_1d_16_##name##_p10; break; \
2096 case 12: lut1d->interp = interp_1d_16_##name##_p12; break; \
2097 case 14: lut1d->interp = interp_1d_16_##name##_p14; break; \
2098 case 16: lut1d->interp = interp_1d_16_##name##_p16; break; \
2100 } else if (isfloat) { lut1d->interp = interp_1d_##name##_pf32; \
2101 } else if (is16bit) { lut1d->interp = interp_1d_16_##name; \
2102 } else { lut1d->interp = interp_1d_8_##name; } \
2105 switch (lut1d->interpolation) {
2106 case INTERPOLATE_1D_NEAREST: SET_FUNC_1D(nearest);
break;
2107 case INTERPOLATE_1D_LINEAR: SET_FUNC_1D(
linear);
break;
2108 case INTERPOLATE_1D_COSINE: SET_FUNC_1D(cosine);
break;
2109 case INTERPOLATE_1D_CUBIC: SET_FUNC_1D(cubic);
break;
2110 case INTERPOLATE_1D_SPLINE: SET_FUNC_1D(spline);
break;
2123 LUT1DContext *lut1d =
ctx->priv;
2125 lut1d->scale.r = lut1d->scale.g = lut1d->scale.b = 1.f;
2128 set_identity_matrix_1d(lut1d, 32);
2139 ext = strrchr(lut1d->file,
'.');
2150 ret = parse_cinespace_1d(
ctx,
f);
2156 if (!
ret && !lut1d->lutsize) {
2169 LUT1DContext *lut1d =
ctx->priv;
2205 static int lut1d_process_command(
AVFilterContext *
ctx,
const char *cmd,
const char *args,
2206 char *res,
int res_len,
int flags)
2208 LUT1DContext *lut1d =
ctx->priv;
2217 set_identity_matrix_1d(lut1d, 32);
2220 return config_input_1d(
ctx->inputs[0]);
2227 .filter_frame = filter_frame_1d,
2228 .config_props = config_input_1d,
2235 .priv_size =
sizeof(LUT1DContext),
2240 .priv_class = &lut1d_class,
2242 .process_command = lut1d_process_command,
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
#define AV_PIX_FMT_GBRAP16
#define DEFINE_INTERP_FUNC_PLANAR_FLOAT(name, depth)
static float lerpf(float v0, float v1, float f)
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
#define AV_LOG_WARNING
Something somehow does not look correct.
AVPixelFormat
Pixel format.
static int mix(int c0, int c1)
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
static int parse_m3d(AVFilterContext *ctx, FILE *f)
#define FILTER_PIXFMTS_ARRAY(array)
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
#define NEXT_FLOAT_OR_GOTO(value, label)
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
int() avfilter_action_func(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
A function pointer passed to the AVFilterGraph::execute callback to be executed multiple times,...
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
static struct rgbvec apply_prelut(const Lut3DPreLut *prelut, const struct rgbvec *s)
static struct rgbvec lerp(const struct rgbvec *v0, const struct rgbvec *v1, float f)
static int parse_dat(AVFilterContext *ctx, FILE *f)
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
#define AV_PIX_FMT_FLAG_FLOAT
The pixel format contains IEEE-754 floating point values.
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define AVFILTER_DEFINE_CLASS_EXT(name, desc, options)
#define FILTER_INPUTS(array)
This structure describes decoded (raw) audio or video data.
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
static int skip_line(const char *p)
static int linear(InterplayACMContext *s, unsigned ind, unsigned col)
static struct rgbvec interp_tetrahedral(const LUT3DContext *lut3d, const struct rgbvec *s)
Tetrahedral interpolation.
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
static av_cold int preinit(AVFilterContext *ctx)
static struct rgbvec interp_prism(const LUT3DContext *lut3d, const struct rgbvec *s)
const char * name
Filter name.
static int parse_cube(AVFilterContext *ctx, FILE *f)
A link between two filters.
const AVFilter ff_vf_lut3d
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
static int parse_3dl(AVFilterContext *ctx, FILE *f)
#define AV_PIX_FMT_GBRP14
static void apply_lut(const uint16_t *lut, uint16_t *dst, int dsize)
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
#define AV_PIX_FMT_GBRP10
static double val(void *priv, double ch)
static double a2(void *priv, double x, double y)
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(const uint8_t *) pi - 0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(const int16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1<< 16)) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(const int16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(const int32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(const int32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(const int64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64, *(const int64_t *) pi *(1.0f/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64, *(const int64_t *) pi *(1.0/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float *) pi *(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double *) pi *(UINT64_C(1)<< 63))) #define FMT_PAIR_FUNC(out, in) static conv_func_type *const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={ FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64), };static void cpy1(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, len);} static void cpy2(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 2 *len);} static void cpy4(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 4 *len);} static void cpy8(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 8 *len);} AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags) { AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) return NULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) return NULL;if(channels==1){ in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);} ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map) { switch(av_get_bytes_per_sample(in_fmt)){ case 1:ctx->simd_f=cpy1;break;case 2:ctx->simd_f=cpy2;break;case 4:ctx->simd_f=cpy4;break;case 8:ctx->simd_f=cpy8;break;} } return ctx;} void swri_audio_convert_free(AudioConvert **ctx) { av_freep(ctx);} int swri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, int len) { int ch;int off=0;const int os=(out->planar ? 1 :out->ch_count) *out->bps;unsigned misaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask) { int planes=in->planar ? in->ch_count :1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;} if(ctx->out_simd_align_mask) { int planes=out->planar ? out->ch_count :1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;} if(ctx->simd_f &&!ctx->ch_map &&!misaligned){ off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){ if(out->planar==in->planar){ int planes=out->planar ? out->ch_count :1;for(ch=0;ch< planes;ch++){ ctx->simd_f(out->ch+ch,(const uint8_t **) in->ch+ch, off *(out-> planar
static struct rgbvec interp_trilinear(const LUT3DContext *lut3d, const struct rgbvec *s)
Interpolate using the 8 vertices of a cube.
A filter pad used for either input or output.
static enum AVPixelFormat pix_fmts[]
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.
#define AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_GBRAP12
#define av_assert0(cond)
assert() equivalent, that is always enabled.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
static char * fget_next_word(char *dst, int max, FILE *f)
#define DEFINE_INTERP_FUNC(name, nbits)
#define FILTER_OUTPUTS(array)
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
#define AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_RGBA64
int av_sscanf(const char *string, const char *format,...)
See libc sscanf manual for more information.
static float prelut_interp_1d_linear(const Lut3DPreLut *prelut, int idx, const float s)
Describe the class of an AVClass context structure.
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
static int config_input(AVFilterLink *inlink)
static double a3(void *priv, double x, double y)
#define fs(width, name, subs,...)
filter_frame For filters that do not use the activate() callback
#define FRAMESYNC_DEFINE_CLASS_EXT(name, context, field, options)
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
#define AVFILTER_DEFINE_CLASS(fname)
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
int(* init)(AVBSFContext *ctx)
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
int av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc)
Return the number of bits per pixel for the pixel format described by pixdesc, including any padding ...
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
static int config_output(AVFilterLink *outlink)
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
#define AV_PIX_FMT_GBRPF32
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
AVFilterContext * src
source filter
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
static double a0(void *priv, double x, double y)
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
static int set_identity_matrix(AVFilterContext *ctx, int size)
static int interpolation(DeclickChannel *c, const double *src, int ar_order, double *acoefficients, int *index, int nb_errors, double *auxiliary, double *interpolated)
#define AV_LOG_INFO
Standard information.
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
static void uninit(AVBSFContext *ctx)
#define AV_PIX_FMT_BGRA64
#define i(width, name, range_min, range_max)
avfilter_action_func * interp
int w
agreed upon image width
#define DEFINE_INTERP_FUNC_PLANAR(name, nbits, depth)
#define AV_PIX_FMT_GBRP12
#define av_malloc_array(a, b)
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Used for passing data between threads.
@ INTERPOLATE_TETRAHEDRAL
static struct rgbvec interp_pyramid(const LUT3DContext *lut3d, const struct rgbvec *s)
const char * name
Pad name.
FILE * avpriv_fopen_utf8(const char *path, const char *mode)
Open a file using a UTF-8 filename.
static int parse_cinespace(AVFilterContext *ctx, FILE *f)
static float sanitizef(float f)
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
static int allocate_3dlut(AVFilterContext *ctx, int lutsize, int prelut)
#define NEXT_LINE_OR_GOTO(loop_cond, label)
const AVFilter ff_vf_haldclut
int h
agreed upon image height
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
@ AV_OPT_TYPE_INT
Underlying C type is int.
#define AV_PIX_FMT_GBRAPF32
static struct rgbvec interp_nearest(const LUT3DContext *lut3d, const struct rgbvec *s)
Get the nearest defined point.
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link.
#define NEXT_LINE(loop_cond)
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
static void scale(int *out, const int *in, const int w, const int h, const int shift)
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
void ff_lut3d_init_x86(LUT3DContext *s, const AVPixFmtDescriptor *desc)
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will have its filter_frame() c...
#define flags(name, subs,...)
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
static double a1(void *priv, double x, double y)
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
const AVFilter ff_vf_lut1d
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
int interpolation
interp_mode
static int nearest_sample_index(float *data, float x, int low, int hi)