Go to the documentation of this file.
27 #include "config_components.h"
48 #define OFFSET(x) offsetof(LUT3DContext, x)
49 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
50 #define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
51 #define COMMON_OPTIONS \
52 { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, NB_INTERP_MODE-1, TFLAGS, "interp_mode" }, \
53 { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_NEAREST}, 0, 0, TFLAGS, "interp_mode" }, \
54 { "trilinear", "interpolate values using the 8 points defining a cube", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TRILINEAR}, 0, 0, TFLAGS, "interp_mode" }, \
55 { "tetrahedral", "interpolate values using a tetrahedron", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, 0, TFLAGS, "interp_mode" }, \
56 { "pyramid", "interpolate values using a pyramid", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PYRAMID}, 0, 0, TFLAGS, "interp_mode" }, \
57 { "prism", "interpolate values using a prism", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PRISM}, 0, 0, TFLAGS, "interp_mode" }, \
60 #define EXPONENT_MASK 0x7F800000
61 #define MANTISSA_MASK 0x007FFFFF
62 #define SIGN_MASK 0x80000000
84 static inline float lerpf(
float v0,
float v1,
float f)
86 return v0 + (v1 -
v0) *
f;
97 #define NEAR(x) ((int)((x) + .5))
98 #define PREV(x) ((int)(x))
99 #define NEXT(x) (FFMIN((int)(x) + 1, lut3d->lutsize - 1))
107 return lut3d->lut[
NEAR(
s->r) * lut3d->lutsize2 +
NEAR(
s->g) * lut3d->lutsize +
NEAR(
s->b)];
117 const int lutsize2 = lut3d->lutsize2;
118 const int lutsize = lut3d->lutsize;
121 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
122 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
123 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
124 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
125 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
126 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
127 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
128 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
129 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
143 const int lutsize2 = lut3d->lutsize2;
144 const int lutsize = lut3d->lutsize;
147 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
148 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
149 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
152 if (
d.g >
d.r &&
d.b >
d.r) {
153 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
154 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
155 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
157 c.r = c000.
r + (c111.
r - c011.
r) *
d.r + (c010.
r - c000.
r) *
d.g + (c001.
r - c000.
r) *
d.b +
158 (c011.
r - c001.
r - c010.
r + c000.
r) *
d.g *
d.b;
159 c.g = c000.
g + (c111.
g - c011.
g) *
d.r + (c010.
g - c000.
g) *
d.g + (c001.
g - c000.
g) *
d.b +
160 (c011.
g - c001.
g - c010.
g + c000.
g) *
d.g *
d.b;
161 c.b = c000.
b + (c111.
b - c011.
b) *
d.r + (c010.
b - c000.
b) *
d.g + (c001.
b - c000.
b) *
d.b +
162 (c011.
b - c001.
b - c010.
b + c000.
b) *
d.g *
d.b;
163 }
else if (
d.r >
d.g &&
d.b >
d.g) {
164 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
165 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
166 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
168 c.r = c000.
r + (c100.
r - c000.
r) *
d.r + (c111.
r - c101.
r) *
d.g + (c001.
r - c000.
r) *
d.b +
169 (c101.
r - c001.
r - c100.
r + c000.
r) *
d.r *
d.b;
170 c.g = c000.
g + (c100.
g - c000.
g) *
d.r + (c111.
g - c101.
g) *
d.g + (c001.
g - c000.
g) *
d.b +
171 (c101.
g - c001.
g - c100.
g + c000.
g) *
d.r *
d.b;
172 c.b = c000.
b + (c100.
b - c000.
b) *
d.r + (c111.
b - c101.
b) *
d.g + (c001.
b - c000.
b) *
d.b +
173 (c101.
b - c001.
b - c100.
b + c000.
b) *
d.r *
d.b;
175 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
176 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
177 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
179 c.r = c000.
r + (c100.
r - c000.
r) *
d.r + (c010.
r - c000.
r) *
d.g + (c111.
r - c110.
r) *
d.b +
180 (c110.
r - c100.
r - c010.
r + c000.
r) *
d.r *
d.g;
181 c.g = c000.
g + (c100.
g - c000.
g) *
d.r + (c010.
g - c000.
g) *
d.g + (c111.
g - c110.
g) *
d.b +
182 (c110.
g - c100.
g - c010.
g + c000.
g) *
d.r *
d.g;
183 c.b = c000.
b + (c100.
b - c000.
b) *
d.r + (c010.
b - c000.
b) *
d.g + (c111.
b - c110.
b) *
d.b +
184 (c110.
b - c100.
b - c010.
b + c000.
b) *
d.r *
d.g;
193 const int lutsize2 = lut3d->lutsize2;
194 const int lutsize = lut3d->lutsize;
197 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
198 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
199 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
200 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
201 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
205 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
206 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
208 c.r = c000.
r + (c001.
r - c000.
r) *
d.b + (c101.
r - c001.
r) *
d.r + (c010.
r - c000.
r) *
d.g +
209 (c000.
r - c010.
r - c001.
r + c011.
r) *
d.b *
d.g +
210 (c001.
r - c011.
r - c101.
r + c111.
r) *
d.r *
d.g;
211 c.g = c000.
g + (c001.
g - c000.
g) *
d.b + (c101.
g - c001.
g) *
d.r + (c010.
g - c000.
g) *
d.g +
212 (c000.
g - c010.
g - c001.
g + c011.
g) *
d.b *
d.g +
213 (c001.
g - c011.
g - c101.
g + c111.
g) *
d.r *
d.g;
214 c.b = c000.
b + (c001.
b - c000.
b) *
d.b + (c101.
b - c001.
b) *
d.r + (c010.
b - c000.
b) *
d.g +
215 (c000.
b - c010.
b - c001.
b + c011.
b) *
d.b *
d.g +
216 (c001.
b - c011.
b - c101.
b + c111.
b) *
d.r *
d.g;
218 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
219 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
221 c.r = c000.
r + (c101.
r - c100.
r) *
d.b + (c100.
r - c000.
r) *
d.r + (c010.
r - c000.
r) *
d.g +
222 (c100.
r - c110.
r - c101.
r + c111.
r) *
d.b *
d.g +
223 (c000.
r - c010.
r - c100.
r + c110.
r) *
d.r *
d.g;
224 c.g = c000.
g + (c101.
g - c100.
g) *
d.b + (c100.
g - c000.
g) *
d.r + (c010.
g - c000.
g) *
d.g +
225 (c100.
g - c110.
g - c101.
g + c111.
g) *
d.b *
d.g +
226 (c000.
g - c010.
g - c100.
g + c110.
g) *
d.r *
d.g;
227 c.b = c000.
b + (c101.
b - c100.
b) *
d.b + (c100.
b - c000.
b) *
d.r + (c010.
b - c000.
b) *
d.g +
228 (c100.
b - c110.
b - c101.
b + c111.
b) *
d.b *
d.g +
229 (c000.
b - c010.
b - c100.
b + c110.
b) *
d.r *
d.g;
242 const int lutsize2 = lut3d->lutsize2;
243 const int lutsize = lut3d->lutsize;
246 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
247 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
248 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
252 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
253 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
254 c.r = (1-
d.r) * c000.
r + (
d.r-
d.g) * c100.
r + (
d.g-
d.b) * c110.
r + (
d.b) * c111.
r;
255 c.g = (1-
d.r) * c000.
g + (
d.r-
d.g) * c100.
g + (
d.g-
d.b) * c110.
g + (
d.b) * c111.
g;
256 c.b = (1-
d.r) * c000.
b + (
d.r-
d.g) * c100.
b + (
d.g-
d.b) * c110.
b + (
d.b) * c111.
b;
257 }
else if (
d.r >
d.b) {
258 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
259 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
260 c.r = (1-
d.r) * c000.
r + (
d.r-
d.b) * c100.
r + (
d.b-
d.g) * c101.
r + (
d.g) * c111.
r;
261 c.g = (1-
d.r) * c000.
g + (
d.r-
d.b) * c100.
g + (
d.b-
d.g) * c101.
g + (
d.g) * c111.
g;
262 c.b = (1-
d.r) * c000.
b + (
d.r-
d.b) * c100.
b + (
d.b-
d.g) * c101.
b + (
d.g) * c111.
b;
264 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
265 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
266 c.r = (1-
d.b) * c000.
r + (
d.b-
d.r) * c001.
r + (
d.r-
d.g) * c101.
r + (
d.g) * c111.
r;
267 c.g = (1-
d.b) * c000.
g + (
d.b-
d.r) * c001.
g + (
d.r-
d.g) * c101.
g + (
d.g) * c111.
g;
268 c.b = (1-
d.b) * c000.
b + (
d.b-
d.r) * c001.
b + (
d.r-
d.g) * c101.
b + (
d.g) * c111.
b;
272 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
273 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
274 c.r = (1-
d.b) * c000.
r + (
d.b-
d.g) * c001.
r + (
d.g-
d.r) * c011.
r + (
d.r) * c111.
r;
275 c.g = (1-
d.b) * c000.
g + (
d.b-
d.g) * c001.
g + (
d.g-
d.r) * c011.
g + (
d.r) * c111.
g;
276 c.b = (1-
d.b) * c000.
b + (
d.b-
d.g) * c001.
b + (
d.g-
d.r) * c011.
b + (
d.r) * c111.
b;
277 }
else if (
d.b >
d.r) {
278 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
279 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
280 c.r = (1-
d.g) * c000.
r + (
d.g-
d.b) * c010.
r + (
d.b-
d.r) * c011.
r + (
d.r) * c111.
r;
281 c.g = (1-
d.g) * c000.
g + (
d.g-
d.b) * c010.
g + (
d.b-
d.r) * c011.
g + (
d.r) * c111.
g;
282 c.b = (1-
d.g) * c000.
b + (
d.g-
d.b) * c010.
b + (
d.b-
d.r) * c011.
b + (
d.r) * c111.
b;
284 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
285 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
286 c.r = (1-
d.g) * c000.
r + (
d.g-
d.r) * c010.
r + (
d.r-
d.b) * c110.
r + (
d.b) * c111.
r;
287 c.g = (1-
d.g) * c000.
g + (
d.g-
d.r) * c010.
g + (
d.r-
d.b) * c110.
g + (
d.b) * c111.
g;
288 c.b = (1-
d.g) * c000.
b + (
d.g-
d.r) * c010.
b + (
d.r-
d.b) * c110.
b + (
d.b) * c111.
b;
295 int idx,
const float s)
297 const int lut_max = prelut->
size - 1;
298 const float scaled = (
s - prelut->
min[idx]) * prelut->
scale[idx];
299 const float x =
av_clipf(scaled, 0.0
f, lut_max);
300 const int prev =
PREV(x);
301 const int next =
FFMIN((
int)(x) + 1, lut_max);
302 const float p = prelut->
lut[idx][prev];
303 const float n = prelut->
lut[idx][next];
304 const float d = x - (
float)prev;
313 if (prelut->size <= 0)
322 #define DEFINE_INTERP_FUNC_PLANAR(name, nbits, depth) \
323 static int interp_##nbits##_##name##_p##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
326 const LUT3DContext *lut3d = ctx->priv; \
327 const Lut3DPreLut *prelut = &lut3d->prelut; \
328 const ThreadData *td = arg; \
329 const AVFrame *in = td->in; \
330 const AVFrame *out = td->out; \
331 const int direct = out == in; \
332 const int slice_start = (in->height * jobnr ) / nb_jobs; \
333 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
334 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
335 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
336 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
337 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
338 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
339 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
340 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
341 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
342 const float lut_max = lut3d->lutsize - 1; \
343 const float scale_f = 1.0f / ((1<<depth) - 1); \
344 const float scale_r = lut3d->scale.r * lut_max; \
345 const float scale_g = lut3d->scale.g * lut_max; \
346 const float scale_b = lut3d->scale.b * lut_max; \
348 for (y = slice_start; y < slice_end; y++) { \
349 uint##nbits##_t *dstg = (uint##nbits##_t *)grow; \
350 uint##nbits##_t *dstb = (uint##nbits##_t *)brow; \
351 uint##nbits##_t *dstr = (uint##nbits##_t *)rrow; \
352 uint##nbits##_t *dsta = (uint##nbits##_t *)arow; \
353 const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow; \
354 const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow; \
355 const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow; \
356 const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow; \
357 for (x = 0; x < in->width; x++) { \
358 const struct rgbvec rgb = {srcr[x] * scale_f, \
360 srcb[x] * scale_f}; \
361 const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \
362 const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \
363 av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \
364 av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \
365 struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
366 dstr[x] = av_clip_uintp2(vec.r * (float)((1<<depth) - 1), depth); \
367 dstg[x] = av_clip_uintp2(vec.g * (float)((1<<depth) - 1), depth); \
368 dstb[x] = av_clip_uintp2(vec.b * (float)((1<<depth) - 1), depth); \
369 if (!direct && in->linesize[3]) \
372 grow += out->linesize[0]; \
373 brow += out->linesize[1]; \
374 rrow += out->linesize[2]; \
375 arow += out->linesize[3]; \
376 srcgrow += in->linesize[0]; \
377 srcbrow += in->linesize[1]; \
378 srcrrow += in->linesize[2]; \
379 srcarow += in->linesize[3]; \
420 #define DEFINE_INTERP_FUNC_PLANAR_FLOAT(name, depth) \
421 static int interp_##name##_pf##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
424 const LUT3DContext *lut3d = ctx->priv; \
425 const Lut3DPreLut *prelut = &lut3d->prelut; \
426 const ThreadData *td = arg; \
427 const AVFrame *in = td->in; \
428 const AVFrame *out = td->out; \
429 const int direct = out == in; \
430 const int slice_start = (in->height * jobnr ) / nb_jobs; \
431 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
432 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
433 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
434 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
435 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
436 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
437 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
438 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
439 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
440 const float lut_max = lut3d->lutsize - 1; \
441 const float scale_r = lut3d->scale.r * lut_max; \
442 const float scale_g = lut3d->scale.g * lut_max; \
443 const float scale_b = lut3d->scale.b * lut_max; \
445 for (y = slice_start; y < slice_end; y++) { \
446 float *dstg = (float *)grow; \
447 float *dstb = (float *)brow; \
448 float *dstr = (float *)rrow; \
449 float *dsta = (float *)arow; \
450 const float *srcg = (const float *)srcgrow; \
451 const float *srcb = (const float *)srcbrow; \
452 const float *srcr = (const float *)srcrrow; \
453 const float *srca = (const float *)srcarow; \
454 for (x = 0; x < in->width; x++) { \
455 const struct rgbvec rgb = {sanitizef(srcr[x]), \
456 sanitizef(srcg[x]), \
457 sanitizef(srcb[x])}; \
458 const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \
459 const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \
460 av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \
461 av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \
462 struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
466 if (!direct && in->linesize[3]) \
469 grow += out->linesize[0]; \
470 brow += out->linesize[1]; \
471 rrow += out->linesize[2]; \
472 arow += out->linesize[3]; \
473 srcgrow += in->linesize[0]; \
474 srcbrow += in->linesize[1]; \
475 srcrrow += in->linesize[2]; \
476 srcarow += in->linesize[3]; \
487 #define DEFINE_INTERP_FUNC(name, nbits) \
488 static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
491 const LUT3DContext *lut3d = ctx->priv; \
492 const Lut3DPreLut *prelut = &lut3d->prelut; \
493 const ThreadData *td = arg; \
494 const AVFrame *in = td->in; \
495 const AVFrame *out = td->out; \
496 const int direct = out == in; \
497 const int step = lut3d->step; \
498 const uint8_t r = lut3d->rgba_map[R]; \
499 const uint8_t g = lut3d->rgba_map[G]; \
500 const uint8_t b = lut3d->rgba_map[B]; \
501 const uint8_t a = lut3d->rgba_map[A]; \
502 const int slice_start = (in->height * jobnr ) / nb_jobs; \
503 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
504 uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \
505 const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \
506 const float lut_max = lut3d->lutsize - 1; \
507 const float scale_f = 1.0f / ((1<<nbits) - 1); \
508 const float scale_r = lut3d->scale.r * lut_max; \
509 const float scale_g = lut3d->scale.g * lut_max; \
510 const float scale_b = lut3d->scale.b * lut_max; \
512 for (y = slice_start; y < slice_end; y++) { \
513 uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \
514 const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \
515 for (x = 0; x < in->width * step; x += step) { \
516 const struct rgbvec rgb = {src[x + r] * scale_f, \
517 src[x + g] * scale_f, \
518 src[x + b] * scale_f}; \
519 const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \
520 const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \
521 av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \
522 av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \
523 struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
524 dst[x + r] = av_clip_uint##nbits(vec.r * (float)((1<<nbits) - 1)); \
525 dst[x + g] = av_clip_uint##nbits(vec.g * (float)((1<<nbits) - 1)); \
526 dst[x + b] = av_clip_uint##nbits(vec.b * (float)((1<<nbits) - 1)); \
527 if (!direct && step == 4) \
528 dst[x + a] = src[x + a]; \
530 dstrow += out->linesize[0]; \
531 srcrow += in ->linesize[0]; \
548 #define MAX_LINE_SIZE 512
554 return !*p || *p ==
'#';
565 while ((
c = fgetc(
f)) != EOF) {
576 if ((
c = fgetc(
f)) == EOF)
591 #define NEXT_LINE(loop_cond) do { \
592 if (!fgets(line, sizeof(line), f)) { \
593 av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n"); \
594 return AVERROR_INVALIDDATA; \
598 #define NEXT_LINE_OR_GOTO(loop_cond, label) do { \
599 if (!fgets(line, sizeof(line), f)) { \
600 av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n"); \
601 ret = AVERROR_INVALIDDATA; \
610 if (lutsize < 2 || lutsize >
MAX_LEVEL) {
622 for (
i = 0;
i < 3;
i++) {
630 for (
i = 0;
i < 3;
i++) {
635 lut3d->
lutsize2 = lutsize * lutsize;
651 if (!strncmp(
line,
"3DLUTSIZE ", 10)) {
661 for (k = 0; k <
size; k++) {
662 for (j = 0; j <
size; j++) {
665 if (k != 0 || j != 0 ||
i != 0)
680 float min[3] = {0.0, 0.0, 0.0};
681 float max[3] = {1.0, 1.0, 1.0};
684 if (!strncmp(
line,
"LUT_3D_SIZE", 11)) {
693 for (k = 0; k <
size; k++) {
694 for (j = 0; j <
size; j++) {
701 if (!strncmp(
line,
"DOMAIN_", 7)) {
703 if (!strncmp(
line + 7,
"MIN ", 4)) vals =
min;
704 else if (!strncmp(
line + 7,
"MAX ", 4)) vals =
max;
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++) {
1117 int depth, is16bit, isfloat,
planar;
1121 depth =
desc->comp[0].depth;
1122 is16bit =
desc->comp[0].depth > 8;
1128 #define SET_FUNC(name) do { \
1129 if (planar && !isfloat) { \
1131 case 8: lut3d->interp = interp_8_##name##_p8; break; \
1132 case 9: lut3d->interp = interp_16_##name##_p9; break; \
1133 case 10: lut3d->interp = interp_16_##name##_p10; break; \
1134 case 12: lut3d->interp = interp_16_##name##_p12; break; \
1135 case 14: lut3d->interp = interp_16_##name##_p14; break; \
1136 case 16: lut3d->interp = interp_16_##name##_p16; break; \
1138 } else if (isfloat) { lut3d->interp = interp_##name##_pf32; \
1139 } else if (is16bit) { lut3d->interp = interp_16_##name; \
1140 } else { lut3d->interp = interp_8_##name; } \
1200 char *res,
int res_len,
int flags)
1211 #if CONFIG_LUT3D_FILTER || CONFIG_HALDCLUT_FILTER
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
1229 #if CONFIG_LUT3D_FILTER
1253 ext = strrchr(lut3d->
file,
'.');
1292 for (
i = 0;
i < 3;
i++) {
1322 .priv_class = &lut3d_class,
1328 #if CONFIG_HALDCLUT_FILTER
1333 const int linesize =
frame->linesize[0];
1334 const int w = lut3d->clut_width;
1335 const int step = lut3d->clut_step;
1336 const uint8_t *rgba_map = lut3d->clut_rgba_map;
1338 const int level2 = lut3d->
lutsize2;
1340 #define LOAD_CLUT(nbits) do { \
1341 int i, j, k, x = 0, y = 0; \
1343 for (k = 0; k < level; k++) { \
1344 for (j = 0; j < level; j++) { \
1345 for (i = 0; i < level; i++) { \
1346 const uint##nbits##_t *src = (const uint##nbits##_t *) \
1347 (data + y*linesize + x*step); \
1348 struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \
1349 vec->r = src[rgba_map[0]] / (float)((1<<(nbits)) - 1); \
1350 vec->g = src[rgba_map[1]] / (float)((1<<(nbits)) - 1); \
1351 vec->b = src[rgba_map[2]] / (float)((1<<(nbits)) - 1); \
1361 switch (lut3d->clut_bits) {
1362 case 8: LOAD_CLUT(8);
break;
1363 case 16: LOAD_CLUT(16);
break;
1369 const uint8_t *datag =
frame->data[0];
1370 const uint8_t *datab =
frame->data[1];
1371 const uint8_t *datar =
frame->data[2];
1372 const int glinesize =
frame->linesize[0];
1373 const int blinesize =
frame->linesize[1];
1374 const int rlinesize =
frame->linesize[2];
1375 const int w = lut3d->clut_width;
1377 const int level2 = lut3d->
lutsize2;
1379 #define LOAD_CLUT_PLANAR(nbits, depth) do { \
1380 int i, j, k, x = 0, y = 0; \
1382 for (k = 0; k < level; k++) { \
1383 for (j = 0; j < level; j++) { \
1384 for (i = 0; i < level; i++) { \
1385 const uint##nbits##_t *gsrc = (const uint##nbits##_t *) \
1386 (datag + y*glinesize); \
1387 const uint##nbits##_t *bsrc = (const uint##nbits##_t *) \
1388 (datab + y*blinesize); \
1389 const uint##nbits##_t *rsrc = (const uint##nbits##_t *) \
1390 (datar + y*rlinesize); \
1391 struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \
1392 vec->r = gsrc[x] / (float)((1<<(depth)) - 1); \
1393 vec->g = bsrc[x] / (float)((1<<(depth)) - 1); \
1394 vec->b = rsrc[x] / (float)((1<<(depth)) - 1); \
1404 switch (lut3d->clut_bits) {
1405 case 8: LOAD_CLUT_PLANAR(8, 8);
break;
1406 case 9: LOAD_CLUT_PLANAR(16, 9);
break;
1407 case 10: LOAD_CLUT_PLANAR(16, 10);
break;
1408 case 12: LOAD_CLUT_PLANAR(16, 12);
break;
1409 case 14: LOAD_CLUT_PLANAR(16, 14);
break;
1410 case 16: LOAD_CLUT_PLANAR(16, 16);
break;
1416 const uint8_t *datag =
frame->data[0];
1417 const uint8_t *datab =
frame->data[1];
1418 const uint8_t *datar =
frame->data[2];
1419 const int glinesize =
frame->linesize[0];
1420 const int blinesize =
frame->linesize[1];
1421 const int rlinesize =
frame->linesize[2];
1422 const int w = lut3d->clut_width;
1424 const int level2 = lut3d->
lutsize2;
1426 int i, j, k, x = 0, y = 0;
1428 for (k = 0; k <
level; k++) {
1429 for (j = 0; j <
level; j++) {
1431 const float *gsrc = (
const float *)(datag + y*glinesize);
1432 const float *bsrc = (
const float *)(datab + y*blinesize);
1433 const float *rsrc = (
const float *)(datar + y*rlinesize);
1456 outlink->
w =
ctx->inputs[0]->w;
1457 outlink->
h =
ctx->inputs[0]->h;
1479 lut3d->clut_bits =
desc->comp[0].depth;
1503 const int max_clut_level = sqrt(
MAX_LEVEL);
1504 const int max_clut_size = max_clut_level*max_clut_level*max_clut_level;
1506 "(maximum level is %d, or %dx%d CLUT)\n",
1507 max_clut_level, max_clut_size, max_clut_size);
1527 if (lut3d->clut || !lut3d->got_clut) {
1528 if (lut3d->clut_float)
1529 update_clut_float(
ctx->priv, second);
1530 else if (lut3d->clut_planar)
1531 update_clut_planar(
ctx->priv, second);
1533 update_clut_packed(
ctx->priv, second);
1534 lut3d->got_clut = 1;
1544 lut3d->fs.on_event = update_apply_clut;
1556 &lut3d_haldclut_options[COMMON_OPTIONS_OFFSET]);
1566 .config_props = config_clut,
1582 .
preinit = haldclut_framesync_preinit,
1583 .
init = haldclut_init,
1584 .
uninit = haldclut_uninit,
1589 .priv_class = &haldclut_class,
1597 #if CONFIG_LUT1D_FILTER
1599 enum interp_1d_mode {
1600 INTERPOLATE_1D_NEAREST,
1601 INTERPOLATE_1D_LINEAR,
1602 INTERPOLATE_1D_CUBIC,
1603 INTERPOLATE_1D_COSINE,
1604 INTERPOLATE_1D_SPLINE,
1608 #define MAX_1D_LEVEL 65536
1610 typedef struct LUT1DContext {
1615 uint8_t rgba_map[4];
1617 float lut[3][MAX_1D_LEVEL];
1623 #define OFFSET(x) offsetof(LUT1DContext, x)
1625 static void set_identity_matrix_1d(LUT1DContext *lut1d,
int size)
1627 const float c = 1. / (
size - 1);
1630 lut1d->lutsize =
size;
1632 lut1d->lut[0][
i] =
i *
c;
1633 lut1d->lut[1][
i] =
i *
c;
1634 lut1d->lut[2][
i] =
i *
c;
1640 LUT1DContext *lut1d =
ctx->priv;
1642 float in_min[3] = {0.0, 0.0, 0.0};
1643 float in_max[3] = {1.0, 1.0, 1.0};
1644 float out_min[3] = {0.0, 0.0, 0.0};
1645 float out_max[3] = {1.0, 1.0, 1.0};
1646 int inside_metadata = 0,
size;
1649 if (strncmp(
line,
"CSPLUTV100", 10)) {
1655 if (strncmp(
line,
"1D", 2)) {
1663 if (!strncmp(
line,
"BEGIN METADATA", 14)) {
1664 inside_metadata = 1;
1667 if (!strncmp(
line,
"END METADATA", 12)) {
1668 inside_metadata = 0;
1671 if (inside_metadata == 0) {
1672 for (
int i = 0;
i < 3;
i++) {
1673 int npoints = strtol(
line,
NULL, 0);
1691 if (size < 2 || size > MAX_1D_LEVEL) {
1696 lut1d->lutsize =
size;
1698 for (
int i = 0;
i <
size;
i++) {
1700 if (
av_sscanf(
line,
"%f %f %f", &lut1d->lut[0][
i], &lut1d->lut[1][
i], &lut1d->lut[2][
i]) != 3)
1702 lut1d->lut[0][
i] *= out_max[0] - out_min[0];
1703 lut1d->lut[1][
i] *= out_max[1] - out_min[1];
1704 lut1d->lut[2][
i] *= out_max[2] - out_min[2];
1711 lut1d->scale.r =
av_clipf(1. / (in_max[0] - in_min[0]), 0.
f, 1.
f);
1712 lut1d->scale.g =
av_clipf(1. / (in_max[1] - in_min[1]), 0.
f, 1.
f);
1713 lut1d->scale.b =
av_clipf(1. / (in_max[2] - in_min[2]), 0.
f, 1.
f);
1720 LUT1DContext *lut1d =
ctx->priv;
1722 float min[3] = {0.0, 0.0, 0.0};
1723 float max[3] = {1.0, 1.0, 1.0};
1726 if (!strncmp(
line,
"LUT_1D_SIZE", 11)) {
1730 if (size < 2 || size > MAX_1D_LEVEL) {
1734 lut1d->lutsize =
size;
1739 if (!strncmp(
line,
"DOMAIN_", 7)) {
1741 if (!strncmp(
line + 7,
"MIN ", 4)) vals =
min;
1742 else if (!strncmp(
line + 7,
"MAX ", 4)) vals =
max;
1749 }
else if (!strncmp(
line,
"LUT_1D_INPUT_RANGE ", 19)) {
1754 }
else if (!strncmp(
line,
"TITLE", 5)) {
1758 if (
av_sscanf(
line,
"%f %f %f", &lut1d->lut[0][
i], &lut1d->lut[1][
i], &lut1d->lut[2][
i]) != 3)
1772 static const AVOption lut1d_options[] = {
1775 {
"nearest",
"use values from the nearest defined points", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_NEAREST}, 0, 0,
TFLAGS,
"interp_mode" },
1776 {
"linear",
"use values from the linear interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_LINEAR}, 0, 0,
TFLAGS,
"interp_mode" },
1777 {
"cosine",
"use values from the cosine interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_COSINE}, 0, 0,
TFLAGS,
"interp_mode" },
1778 {
"cubic",
"use values from the cubic interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_CUBIC}, 0, 0,
TFLAGS,
"interp_mode" },
1779 {
"spline",
"use values from the spline interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_SPLINE}, 0, 0,
TFLAGS,
"interp_mode" },
1785 static inline float interp_1d_nearest(
const LUT1DContext *lut1d,
1786 int idx,
const float s)
1788 return lut1d->lut[idx][
NEAR(
s)];
1791 #define NEXT1D(x) (FFMIN((int)(x) + 1, lut1d->lutsize - 1))
1793 static inline float interp_1d_linear(
const LUT1DContext *lut1d,
1794 int idx,
const float s)
1796 const int prev =
PREV(
s);
1797 const int next = NEXT1D(
s);
1798 const float d =
s - prev;
1799 const float p = lut1d->lut[idx][prev];
1800 const float n = lut1d->lut[idx][next];
1805 static inline float interp_1d_cosine(
const LUT1DContext *lut1d,
1806 int idx,
const float s)
1808 const int prev =
PREV(
s);
1809 const int next = NEXT1D(
s);
1810 const float d =
s - prev;
1811 const float p = lut1d->lut[idx][prev];
1812 const float n = lut1d->lut[idx][next];
1813 const float m = (1.f -
cosf(
d *
M_PI)) * .5
f;
1815 return lerpf(p, n, m);
1818 static inline float interp_1d_cubic(
const LUT1DContext *lut1d,
1819 int idx,
const float s)
1821 const int prev =
PREV(
s);
1822 const int next = NEXT1D(
s);
1823 const float mu =
s - prev;
1826 float y0 = lut1d->lut[idx][
FFMAX(prev - 1, 0)];
1827 float y1 = lut1d->lut[idx][prev];
1828 float y2 = lut1d->lut[idx][next];
1829 float y3 = lut1d->lut[idx][
FFMIN(next + 1, lut1d->lutsize - 1)];
1833 a0 = y3 - y2 - y0 + y1;
1838 return a0 * mu * mu2 +
a1 * mu2 +
a2 * mu +
a3;
1841 static inline float interp_1d_spline(
const LUT1DContext *lut1d,
1842 int idx,
const float s)
1844 const int prev =
PREV(
s);
1845 const int next = NEXT1D(
s);
1846 const float x =
s - prev;
1847 float c0,
c1,
c2, c3;
1849 float y0 = lut1d->lut[idx][
FFMAX(prev - 1, 0)];
1850 float y1 = lut1d->lut[idx][prev];
1851 float y2 = lut1d->lut[idx][next];
1852 float y3 = lut1d->lut[idx][
FFMIN(next + 1, lut1d->lutsize - 1)];
1855 c1 = .5f * (y2 - y0);
1856 c2 = y0 - 2.5f * y1 + 2.f * y2 - .5f * y3;
1857 c3 = .5f * (y3 - y0) + 1.5
f * (y1 - y2);
1859 return ((c3 * x +
c2) * x +
c1) * x + c0;
1862 #define DEFINE_INTERP_FUNC_PLANAR_1D(name, nbits, depth) \
1863 static int interp_1d_##nbits##_##name##_p##depth(AVFilterContext *ctx, \
1864 void *arg, int jobnr, \
1868 const LUT1DContext *lut1d = ctx->priv; \
1869 const ThreadData *td = arg; \
1870 const AVFrame *in = td->in; \
1871 const AVFrame *out = td->out; \
1872 const int direct = out == in; \
1873 const int slice_start = (in->height * jobnr ) / nb_jobs; \
1874 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
1875 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
1876 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
1877 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
1878 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
1879 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
1880 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
1881 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
1882 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
1883 const float factor = (1 << depth) - 1; \
1884 const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1); \
1885 const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1); \
1886 const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1); \
1888 for (y = slice_start; y < slice_end; y++) { \
1889 uint##nbits##_t *dstg = (uint##nbits##_t *)grow; \
1890 uint##nbits##_t *dstb = (uint##nbits##_t *)brow; \
1891 uint##nbits##_t *dstr = (uint##nbits##_t *)rrow; \
1892 uint##nbits##_t *dsta = (uint##nbits##_t *)arow; \
1893 const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow; \
1894 const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow; \
1895 const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow; \
1896 const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow; \
1897 for (x = 0; x < in->width; x++) { \
1898 float r = srcr[x] * scale_r; \
1899 float g = srcg[x] * scale_g; \
1900 float b = srcb[x] * scale_b; \
1901 r = interp_1d_##name(lut1d, 0, r); \
1902 g = interp_1d_##name(lut1d, 1, g); \
1903 b = interp_1d_##name(lut1d, 2, b); \
1904 dstr[x] = av_clip_uintp2(r * factor, depth); \
1905 dstg[x] = av_clip_uintp2(g * factor, depth); \
1906 dstb[x] = av_clip_uintp2(b * factor, depth); \
1907 if (!direct && in->linesize[3]) \
1908 dsta[x] = srca[x]; \
1910 grow += out->linesize[0]; \
1911 brow += out->linesize[1]; \
1912 rrow += out->linesize[2]; \
1913 arow += out->linesize[3]; \
1914 srcgrow += in->linesize[0]; \
1915 srcbrow += in->linesize[1]; \
1916 srcrrow += in->linesize[2]; \
1917 srcarow += in->linesize[3]; \
1922 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 8, 8)
1923 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 8, 8)
1924 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 8, 8)
1925 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 8, 8)
1926 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 8, 8)
1928 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 9)
1929 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 9)
1930 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 9)
1931 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 9)
1932 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 9)
1934 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 10)
1935 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 10)
1936 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 10)
1937 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 10)
1938 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 10)
1940 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 12)
1941 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 12)
1942 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 12)
1943 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 12)
1944 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 12)
1946 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 14)
1947 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 14)
1948 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 14)
1949 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 14)
1950 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 14)
1952 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 16)
1953 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 16)
1954 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 16)
1955 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 16)
1956 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 16)
1958 #define DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(name, depth) \
1959 static int interp_1d_##name##_pf##depth(AVFilterContext *ctx, \
1960 void *arg, int jobnr, \
1964 const LUT1DContext *lut1d = ctx->priv; \
1965 const ThreadData *td = arg; \
1966 const AVFrame *in = td->in; \
1967 const AVFrame *out = td->out; \
1968 const int direct = out == in; \
1969 const int slice_start = (in->height * jobnr ) / nb_jobs; \
1970 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
1971 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
1972 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
1973 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
1974 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
1975 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
1976 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
1977 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
1978 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
1979 const float lutsize = lut1d->lutsize - 1; \
1980 const float scale_r = lut1d->scale.r * lutsize; \
1981 const float scale_g = lut1d->scale.g * lutsize; \
1982 const float scale_b = lut1d->scale.b * lutsize; \
1984 for (y = slice_start; y < slice_end; y++) { \
1985 float *dstg = (float *)grow; \
1986 float *dstb = (float *)brow; \
1987 float *dstr = (float *)rrow; \
1988 float *dsta = (float *)arow; \
1989 const float *srcg = (const float *)srcgrow; \
1990 const float *srcb = (const float *)srcbrow; \
1991 const float *srcr = (const float *)srcrrow; \
1992 const float *srca = (const float *)srcarow; \
1993 for (x = 0; x < in->width; x++) { \
1994 float r = av_clipf(sanitizef(srcr[x]) * scale_r, 0.0f, lutsize); \
1995 float g = av_clipf(sanitizef(srcg[x]) * scale_g, 0.0f, lutsize); \
1996 float b = av_clipf(sanitizef(srcb[x]) * scale_b, 0.0f, lutsize); \
1997 r = interp_1d_##name(lut1d, 0, r); \
1998 g = interp_1d_##name(lut1d, 1, g); \
1999 b = interp_1d_##name(lut1d, 2, b); \
2003 if (!direct && in->linesize[3]) \
2004 dsta[x] = srca[x]; \
2006 grow += out->linesize[0]; \
2007 brow += out->linesize[1]; \
2008 rrow += out->linesize[2]; \
2009 arow += out->linesize[3]; \
2010 srcgrow += in->linesize[0]; \
2011 srcbrow += in->linesize[1]; \
2012 srcrrow += in->linesize[2]; \
2013 srcarow += in->linesize[3]; \
2018 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(nearest, 32)
2019 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(
linear, 32)
2020 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cosine, 32)
2021 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cubic, 32)
2022 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(spline, 32)
2024 #define DEFINE_INTERP_FUNC_1D(name, nbits) \
2025 static int interp_1d_##nbits##_##name(AVFilterContext *ctx, void *arg, \
2026 int jobnr, int nb_jobs) \
2029 const LUT1DContext *lut1d = ctx->priv; \
2030 const ThreadData *td = arg; \
2031 const AVFrame *in = td->in; \
2032 const AVFrame *out = td->out; \
2033 const int direct = out == in; \
2034 const int step = lut1d->step; \
2035 const uint8_t r = lut1d->rgba_map[R]; \
2036 const uint8_t g = lut1d->rgba_map[G]; \
2037 const uint8_t b = lut1d->rgba_map[B]; \
2038 const uint8_t a = lut1d->rgba_map[A]; \
2039 const int slice_start = (in->height * jobnr ) / nb_jobs; \
2040 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
2041 uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \
2042 const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \
2043 const float factor = (1 << nbits) - 1; \
2044 const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1); \
2045 const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1); \
2046 const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1); \
2048 for (y = slice_start; y < slice_end; y++) { \
2049 uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \
2050 const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \
2051 for (x = 0; x < in->width * step; x += step) { \
2052 float rr = src[x + r] * scale_r; \
2053 float gg = src[x + g] * scale_g; \
2054 float bb = src[x + b] * scale_b; \
2055 rr = interp_1d_##name(lut1d, 0, rr); \
2056 gg = interp_1d_##name(lut1d, 1, gg); \
2057 bb = interp_1d_##name(lut1d, 2, bb); \
2058 dst[x + r] = av_clip_uint##nbits(rr * factor); \
2059 dst[x + g] = av_clip_uint##nbits(gg * factor); \
2060 dst[x + b] = av_clip_uint##nbits(bb * factor); \
2061 if (!direct && step == 4) \
2062 dst[x + a] = src[x + a]; \
2064 dstrow += out->linesize[0]; \
2065 srcrow += in ->linesize[0]; \
2070 DEFINE_INTERP_FUNC_1D(nearest, 8)
2071 DEFINE_INTERP_FUNC_1D(
linear, 8)
2072 DEFINE_INTERP_FUNC_1D(cosine, 8)
2073 DEFINE_INTERP_FUNC_1D(cubic, 8)
2074 DEFINE_INTERP_FUNC_1D(spline, 8)
2076 DEFINE_INTERP_FUNC_1D(nearest, 16)
2077 DEFINE_INTERP_FUNC_1D(
linear, 16)
2078 DEFINE_INTERP_FUNC_1D(cosine, 16)
2079 DEFINE_INTERP_FUNC_1D(cubic, 16)
2080 DEFINE_INTERP_FUNC_1D(spline, 16)
2084 int depth, is16bit, isfloat,
planar;
2085 LUT1DContext *lut1d =
inlink->dst->priv;
2088 depth =
desc->comp[0].depth;
2089 is16bit =
desc->comp[0].depth > 8;
2095 #define SET_FUNC_1D(name) do { \
2096 if (planar && !isfloat) { \
2098 case 8: lut1d->interp = interp_1d_8_##name##_p8; break; \
2099 case 9: lut1d->interp = interp_1d_16_##name##_p9; break; \
2100 case 10: lut1d->interp = interp_1d_16_##name##_p10; break; \
2101 case 12: lut1d->interp = interp_1d_16_##name##_p12; break; \
2102 case 14: lut1d->interp = interp_1d_16_##name##_p14; break; \
2103 case 16: lut1d->interp = interp_1d_16_##name##_p16; break; \
2105 } else if (isfloat) { lut1d->interp = interp_1d_##name##_pf32; \
2106 } else if (is16bit) { lut1d->interp = interp_1d_16_##name; \
2107 } else { lut1d->interp = interp_1d_8_##name; } \
2110 switch (lut1d->interpolation) {
2111 case INTERPOLATE_1D_NEAREST: SET_FUNC_1D(nearest);
break;
2112 case INTERPOLATE_1D_LINEAR: SET_FUNC_1D(
linear);
break;
2113 case INTERPOLATE_1D_COSINE: SET_FUNC_1D(cosine);
break;
2114 case INTERPOLATE_1D_CUBIC: SET_FUNC_1D(cubic);
break;
2115 case INTERPOLATE_1D_SPLINE: SET_FUNC_1D(spline);
break;
2128 LUT1DContext *lut1d =
ctx->priv;
2130 lut1d->scale.r = lut1d->scale.g = lut1d->scale.b = 1.f;
2133 set_identity_matrix_1d(lut1d, 32);
2144 ext = strrchr(lut1d->file,
'.');
2155 ret = parse_cinespace_1d(
ctx,
f);
2161 if (!
ret && !lut1d->lutsize) {
2174 LUT1DContext *lut1d =
ctx->priv;
2210 static int lut1d_process_command(
AVFilterContext *
ctx,
const char *cmd,
const char *args,
2211 char *res,
int res_len,
int flags)
2213 LUT1DContext *lut1d =
ctx->priv;
2222 set_identity_matrix_1d(lut1d, 32);
2225 return config_input_1d(
ctx->inputs[0]);
2232 .filter_frame = filter_frame_1d,
2233 .config_props = config_input_1d,
2247 .priv_size =
sizeof(LUT1DContext),
2252 .priv_class = &lut1d_class,
2254 .process_command = lut1d_process_command,
static AVFrame * apply_lut(AVFilterLink *inlink, AVFrame *in)
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
static int config_input(AVFilterLink *inlink)
#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)
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)
#define FILTER_PIXFMTS_ARRAY(array)
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.
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.
#define AVFILTER_DEFINE_CLASS_EXT(name, desc, options)
static int parse_cube(AVFilterContext *ctx, FILE *f)
A link between two filters.
const AVFilter ff_vf_lut3d
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
static int parse_3dl(AVFilterContext *ctx, FILE *f)
#define AV_PIX_FMT_GBRP14
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
#define AV_PIX_FMT_GBRP10
static double val(void *priv, double ch)
static av_always_inline float scale(float x, float s)
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[]
static int config_output(AVFilterLink *outlink)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#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_INPUTS(array)
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
#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.
#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
@ 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
@ 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 ...
#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
@ 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_DEFINE_CLASS(fname)
#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...
#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
#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...
#define FILTER_OUTPUTS(array)
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 av_cold int uninit(AVCodecContext *avctx)
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)
static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
int interpolation
interp_mode
static int nearest_sample_index(float *data, float x, int low, int hi)