Go to the documentation of this file.
64 #define PRELUT_SIZE 65536
86 #if CONFIG_HALDCLUT_FILTER
101 #define OFFSET(x) offsetof(LUT3DContext, x)
102 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
103 #define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
104 #define COMMON_OPTIONS \
105 { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, NB_INTERP_MODE-1, TFLAGS, "interp_mode" }, \
106 { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_NEAREST}, 0, 0, TFLAGS, "interp_mode" }, \
107 { "trilinear", "interpolate values using the 8 points defining a cube", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TRILINEAR}, 0, 0, TFLAGS, "interp_mode" }, \
108 { "tetrahedral", "interpolate values using a tetrahedron", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, 0, TFLAGS, "interp_mode" }, \
109 { "pyramid", "interpolate values using a pyramid", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PYRAMID}, 0, 0, TFLAGS, "interp_mode" }, \
110 { "prism", "interpolate values using a prism", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PRISM}, 0, 0, TFLAGS, "interp_mode" }, \
113 #define EXPONENT_MASK 0x7F800000
114 #define MANTISSA_MASK 0x007FFFFF
115 #define SIGN_MASK 0x80000000
137 static inline float lerpf(
float v0,
float v1,
float f)
139 return v0 + (v1 -
v0) *
f;
150 #define NEAR(x) ((int)((x) + .5))
151 #define PREV(x) ((int)(x))
152 #define NEXT(x) (FFMIN((int)(x) + 1, lut3d->lutsize - 1))
160 return lut3d->lut[
NEAR(
s->r) * lut3d->lutsize2 +
NEAR(
s->g) * lut3d->lutsize +
NEAR(
s->b)];
170 const int lutsize2 = lut3d->lutsize2;
171 const int lutsize = lut3d->lutsize;
174 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
175 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
176 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
177 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
178 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
179 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
180 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
181 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
182 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
196 const int lutsize2 = lut3d->lutsize2;
197 const int lutsize = lut3d->lutsize;
200 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
201 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
202 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
205 if (d.
g > d.
r && d.
b > d.
r) {
206 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
207 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
208 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
210 c.r = c000.
r + (c111.
r - c011.
r) * d.
r + (c010.
r - c000.
r) * d.
g + (c001.
r - c000.
r) * d.
b +
211 (c011.
r - c001.
r - c010.
r + c000.
r) * d.
g * d.
b;
212 c.g = c000.
g + (c111.
g - c011.
g) * d.
r + (c010.
g - c000.
g) * d.
g + (c001.
g - c000.
g) * d.
b +
213 (c011.
g - c001.
g - c010.
g + c000.
g) * d.
g * d.
b;
214 c.b = c000.
b + (c111.
b - c011.
b) * d.
r + (c010.
b - c000.
b) * d.
g + (c001.
b - c000.
b) * d.
b +
215 (c011.
b - c001.
b - c010.
b + c000.
b) * d.
g * d.
b;
216 }
else if (d.
r > d.
g && d.
b > d.
g) {
217 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
218 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
219 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
221 c.r = c000.
r + (c100.
r - c000.
r) * d.
r + (c111.
r - c101.
r) * d.
g + (c001.
r - c000.
r) * d.
b +
222 (c101.
r - c001.
r - c100.
r + c000.
r) * d.
r * d.
b;
223 c.g = c000.
g + (c100.
g - c000.
g) * d.
r + (c111.
g - c101.
g) * d.
g + (c001.
g - c000.
g) * d.
b +
224 (c101.
g - c001.
g - c100.
g + c000.
g) * d.
r * d.
b;
225 c.b = c000.
b + (c100.
b - c000.
b) * d.
r + (c111.
b - c101.
b) * d.
g + (c001.
b - c000.
b) * d.
b +
226 (c101.
b - c001.
b - c100.
b + c000.
b) * d.
r * d.
b;
228 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
229 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
230 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
232 c.r = c000.
r + (c100.
r - c000.
r) * d.
r + (c010.
r - c000.
r) * d.
g + (c111.
r - c110.
r) * d.
b +
233 (c110.
r - c100.
r - c010.
r + c000.
r) * d.
r * d.
g;
234 c.g = c000.
g + (c100.
g - c000.
g) * d.
r + (c010.
g - c000.
g) * d.
g + (c111.
g - c110.
g) * d.
b +
235 (c110.
g - c100.
g - c010.
g + c000.
g) * d.
r * d.
g;
236 c.b = c000.
b + (c100.
b - c000.
b) * d.
r + (c010.
b - c000.
b) * d.
g + (c111.
b - c110.
b) * d.
b +
237 (c110.
b - c100.
b - c010.
b + c000.
b) * d.
r * d.
g;
246 const int lutsize2 = lut3d->lutsize2;
247 const int lutsize = lut3d->lutsize;
250 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
251 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
252 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
253 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
254 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
258 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
259 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
261 c.r = c000.
r + (c001.
r - c000.
r) * d.
b + (c101.
r - c001.
r) * d.
r + (c010.
r - c000.
r) * d.
g +
262 (c000.
r - c010.
r - c001.
r + c011.
r) * d.
b * d.
g +
263 (c001.
r - c011.
r - c101.
r + c111.
r) * d.
r * d.
g;
264 c.g = c000.
g + (c001.
g - c000.
g) * d.
b + (c101.
g - c001.
g) * d.
r + (c010.
g - c000.
g) * d.
g +
265 (c000.
g - c010.
g - c001.
g + c011.
g) * d.
b * d.
g +
266 (c001.
g - c011.
g - c101.
g + c111.
g) * d.
r * d.
g;
267 c.b = c000.
b + (c001.
b - c000.
b) * d.
b + (c101.
b - c001.
b) * d.
r + (c010.
b - c000.
b) * d.
g +
268 (c000.
b - c010.
b - c001.
b + c011.
b) * d.
b * d.
g +
269 (c001.
b - c011.
b - c101.
b + c111.
b) * d.
r * d.
g;
271 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
272 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
274 c.r = c000.
r + (c101.
r - c100.
r) * d.
b + (c100.
r - c000.
r) * d.
r + (c010.
r - c000.
r) * d.
g +
275 (c100.
r - c110.
r - c101.
r + c111.
r) * d.
b * d.
g +
276 (c000.
r - c010.
r - c100.
r + c110.
r) * d.
r * d.
g;
277 c.g = c000.
g + (c101.
g - c100.
g) * d.
b + (c100.
g - c000.
g) * d.
r + (c010.
g - c000.
g) * d.
g +
278 (c100.
g - c110.
g - c101.
g + c111.
g) * d.
b * d.
g +
279 (c000.
g - c010.
g - c100.
g + c110.
g) * d.
r * d.
g;
280 c.b = c000.
b + (c101.
b - c100.
b) * d.
b + (c100.
b - c000.
b) * d.
r + (c010.
b - c000.
b) * d.
g +
281 (c100.
b - c110.
b - c101.
b + c111.
b) * d.
b * d.
g +
282 (c000.
b - c010.
b - c100.
b + c110.
b) * d.
r * d.
g;
295 const int lutsize2 = lut3d->lutsize2;
296 const int lutsize = lut3d->lutsize;
299 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
300 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
301 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
305 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
306 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
307 c.r = (1-d.
r) * c000.
r + (d.
r-d.
g) * c100.
r + (d.
g-d.
b) * c110.
r + (d.
b) * c111.
r;
308 c.g = (1-d.
r) * c000.
g + (d.
r-d.
g) * c100.
g + (d.
g-d.
b) * c110.
g + (d.
b) * c111.
g;
309 c.b = (1-d.
r) * c000.
b + (d.
r-d.
g) * c100.
b + (d.
g-d.
b) * c110.
b + (d.
b) * c111.
b;
310 }
else if (d.
r > d.
b) {
311 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
312 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
313 c.r = (1-d.
r) * c000.
r + (d.
r-d.
b) * c100.
r + (d.
b-d.
g) * c101.
r + (d.
g) * c111.
r;
314 c.g = (1-d.
r) * c000.
g + (d.
r-d.
b) * c100.
g + (d.
b-d.
g) * c101.
g + (d.
g) * c111.
g;
315 c.b = (1-d.
r) * c000.
b + (d.
r-d.
b) * c100.
b + (d.
b-d.
g) * c101.
b + (d.
g) * c111.
b;
317 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
318 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
319 c.r = (1-d.
b) * c000.
r + (d.
b-d.
r) * c001.
r + (d.
r-d.
g) * c101.
r + (d.
g) * c111.
r;
320 c.g = (1-d.
b) * c000.
g + (d.
b-d.
r) * c001.
g + (d.
r-d.
g) * c101.
g + (d.
g) * c111.
g;
321 c.b = (1-d.
b) * c000.
b + (d.
b-d.
r) * c001.
b + (d.
r-d.
g) * c101.
b + (d.
g) * c111.
b;
325 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
326 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
327 c.r = (1-d.
b) * c000.
r + (d.
b-d.
g) * c001.
r + (d.
g-d.
r) * c011.
r + (d.
r) * c111.
r;
328 c.g = (1-d.
b) * c000.
g + (d.
b-d.
g) * c001.
g + (d.
g-d.
r) * c011.
g + (d.
r) * c111.
g;
329 c.b = (1-d.
b) * c000.
b + (d.
b-d.
g) * c001.
b + (d.
g-d.
r) * c011.
b + (d.
r) * c111.
b;
330 }
else if (d.
b > d.
r) {
331 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
332 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
333 c.r = (1-d.
g) * c000.
r + (d.
g-d.
b) * c010.
r + (d.
b-d.
r) * c011.
r + (d.
r) * c111.
r;
334 c.g = (1-d.
g) * c000.
g + (d.
g-d.
b) * c010.
g + (d.
b-d.
r) * c011.
g + (d.
r) * c111.
g;
335 c.b = (1-d.
g) * c000.
b + (d.
g-d.
b) * c010.
b + (d.
b-d.
r) * c011.
b + (d.
r) * c111.
b;
337 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
338 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
339 c.r = (1-d.
g) * c000.
r + (d.
g-d.
r) * c010.
r + (d.
r-d.
b) * c110.
r + (d.
b) * c111.
r;
340 c.g = (1-d.
g) * c000.
g + (d.
g-d.
r) * c010.
g + (d.
r-d.
b) * c110.
g + (d.
b) * c111.
g;
341 c.b = (1-d.
g) * c000.
b + (d.
g-d.
r) * c010.
b + (d.
r-d.
b) * c110.
b + (d.
b) * c111.
b;
348 int idx,
const float s)
350 const int lut_max = prelut->
size - 1;
351 const float scaled = (
s - prelut->
min[idx]) * prelut->
scale[idx];
352 const float x =
av_clipf(scaled, 0.0
f, lut_max);
353 const int prev =
PREV(x);
354 const int next =
FFMIN((
int)(x) + 1, lut_max);
355 const float p = prelut->
lut[idx][prev];
356 const float n = prelut->
lut[idx][next];
357 const float d = x - (float)prev;
358 return lerpf(p, n, d);
366 if (prelut->size <= 0)
375 #define DEFINE_INTERP_FUNC_PLANAR(name, nbits, depth) \
376 static int interp_##nbits##_##name##_p##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
379 const LUT3DContext *lut3d = ctx->priv; \
380 const Lut3DPreLut *prelut = &lut3d->prelut; \
381 const ThreadData *td = arg; \
382 const AVFrame *in = td->in; \
383 const AVFrame *out = td->out; \
384 const int direct = out == in; \
385 const int slice_start = (in->height * jobnr ) / nb_jobs; \
386 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
387 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
388 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
389 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
390 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
391 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
392 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
393 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
394 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
395 const float lut_max = lut3d->lutsize - 1; \
396 const float scale_f = 1.0f / ((1<<depth) - 1); \
397 const float scale_r = lut3d->scale.r * lut_max; \
398 const float scale_g = lut3d->scale.g * lut_max; \
399 const float scale_b = lut3d->scale.b * lut_max; \
401 for (y = slice_start; y < slice_end; y++) { \
402 uint##nbits##_t *dstg = (uint##nbits##_t *)grow; \
403 uint##nbits##_t *dstb = (uint##nbits##_t *)brow; \
404 uint##nbits##_t *dstr = (uint##nbits##_t *)rrow; \
405 uint##nbits##_t *dsta = (uint##nbits##_t *)arow; \
406 const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow; \
407 const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow; \
408 const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow; \
409 const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow; \
410 for (x = 0; x < in->width; x++) { \
411 const struct rgbvec rgb = {srcr[x] * scale_f, \
413 srcb[x] * scale_f}; \
414 const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \
415 const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \
416 av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \
417 av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \
418 struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
419 dstr[x] = av_clip_uintp2(vec.r * (float)((1<<depth) - 1), depth); \
420 dstg[x] = av_clip_uintp2(vec.g * (float)((1<<depth) - 1), depth); \
421 dstb[x] = av_clip_uintp2(vec.b * (float)((1<<depth) - 1), depth); \
422 if (!direct && in->linesize[3]) \
425 grow += out->linesize[0]; \
426 brow += out->linesize[1]; \
427 rrow += out->linesize[2]; \
428 arow += out->linesize[3]; \
429 srcgrow += in->linesize[0]; \
430 srcbrow += in->linesize[1]; \
431 srcrrow += in->linesize[2]; \
432 srcarow += in->linesize[3]; \
473 #define DEFINE_INTERP_FUNC_PLANAR_FLOAT(name, depth) \
474 static int interp_##name##_pf##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
477 const LUT3DContext *lut3d = ctx->priv; \
478 const Lut3DPreLut *prelut = &lut3d->prelut; \
479 const ThreadData *td = arg; \
480 const AVFrame *in = td->in; \
481 const AVFrame *out = td->out; \
482 const int direct = out == in; \
483 const int slice_start = (in->height * jobnr ) / nb_jobs; \
484 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
485 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
486 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
487 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
488 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
489 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
490 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
491 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
492 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
493 const float lut_max = lut3d->lutsize - 1; \
494 const float scale_r = lut3d->scale.r * lut_max; \
495 const float scale_g = lut3d->scale.g * lut_max; \
496 const float scale_b = lut3d->scale.b * lut_max; \
498 for (y = slice_start; y < slice_end; y++) { \
499 float *dstg = (float *)grow; \
500 float *dstb = (float *)brow; \
501 float *dstr = (float *)rrow; \
502 float *dsta = (float *)arow; \
503 const float *srcg = (const float *)srcgrow; \
504 const float *srcb = (const float *)srcbrow; \
505 const float *srcr = (const float *)srcrrow; \
506 const float *srca = (const float *)srcarow; \
507 for (x = 0; x < in->width; x++) { \
508 const struct rgbvec rgb = {sanitizef(srcr[x]), \
509 sanitizef(srcg[x]), \
510 sanitizef(srcb[x])}; \
511 const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \
512 const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \
513 av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \
514 av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \
515 struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
519 if (!direct && in->linesize[3]) \
522 grow += out->linesize[0]; \
523 brow += out->linesize[1]; \
524 rrow += out->linesize[2]; \
525 arow += out->linesize[3]; \
526 srcgrow += in->linesize[0]; \
527 srcbrow += in->linesize[1]; \
528 srcrrow += in->linesize[2]; \
529 srcarow += in->linesize[3]; \
540 #define DEFINE_INTERP_FUNC(name, nbits) \
541 static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
544 const LUT3DContext *lut3d = ctx->priv; \
545 const Lut3DPreLut *prelut = &lut3d->prelut; \
546 const ThreadData *td = arg; \
547 const AVFrame *in = td->in; \
548 const AVFrame *out = td->out; \
549 const int direct = out == in; \
550 const int step = lut3d->step; \
551 const uint8_t r = lut3d->rgba_map[R]; \
552 const uint8_t g = lut3d->rgba_map[G]; \
553 const uint8_t b = lut3d->rgba_map[B]; \
554 const uint8_t a = lut3d->rgba_map[A]; \
555 const int slice_start = (in->height * jobnr ) / nb_jobs; \
556 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
557 uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \
558 const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \
559 const float lut_max = lut3d->lutsize - 1; \
560 const float scale_f = 1.0f / ((1<<nbits) - 1); \
561 const float scale_r = lut3d->scale.r * lut_max; \
562 const float scale_g = lut3d->scale.g * lut_max; \
563 const float scale_b = lut3d->scale.b * lut_max; \
565 for (y = slice_start; y < slice_end; y++) { \
566 uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \
567 const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \
568 for (x = 0; x < in->width * step; x += step) { \
569 const struct rgbvec rgb = {src[x + r] * scale_f, \
570 src[x + g] * scale_f, \
571 src[x + b] * scale_f}; \
572 const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \
573 const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \
574 av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \
575 av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \
576 struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
577 dst[x + r] = av_clip_uint##nbits(vec.r * (float)((1<<nbits) - 1)); \
578 dst[x + g] = av_clip_uint##nbits(vec.g * (float)((1<<nbits) - 1)); \
579 dst[x + b] = av_clip_uint##nbits(vec.b * (float)((1<<nbits) - 1)); \
580 if (!direct && step == 4) \
581 dst[x + a] = src[x + a]; \
583 dstrow += out->linesize[0]; \
584 srcrow += in ->linesize[0]; \
601 #define MAX_LINE_SIZE 512
607 return !*p || *p ==
'#';
618 while ((
c = fgetc(
f)) != EOF) {
629 if ((
c = fgetc(
f)) == EOF)
644 #define NEXT_LINE(loop_cond) do { \
645 if (!fgets(line, sizeof(line), f)) { \
646 av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n"); \
647 return AVERROR_INVALIDDATA; \
651 #define NEXT_LINE_OR_GOTO(loop_cond, label) do { \
652 if (!fgets(line, sizeof(line), f)) { \
653 av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n"); \
654 ret = AVERROR_INVALIDDATA; \
663 if (lutsize < 2 || lutsize >
MAX_LEVEL) {
675 for (
i = 0;
i < 3;
i++) {
683 for (
i = 0;
i < 3;
i++) {
688 lut3d->
lutsize2 = lutsize * lutsize;
704 if (!strncmp(
line,
"3DLUTSIZE ", 10)) {
714 for (k = 0; k <
size; k++) {
715 for (j = 0; j <
size; j++) {
718 if (k != 0 || j != 0 ||
i != 0)
733 float min[3] = {0.0, 0.0, 0.0};
734 float max[3] = {1.0, 1.0, 1.0};
737 if (!strncmp(
line,
"LUT_3D_SIZE", 11)) {
746 for (k = 0; k <
size; k++) {
747 for (j = 0; j <
size; j++) {
754 if (!strncmp(
line,
"DOMAIN_", 7)) {
756 if (!strncmp(
line + 7,
"MIN ", 4)) vals =
min;
757 else if (!strncmp(
line + 7,
"MAX ", 4)) vals =
max;
764 }
else if (!strncmp(
line,
"TITLE", 5)) {
792 const int size2 = 17 * 17;
793 const float scale = 16*16*16;
802 for (k = 0; k <
size; k++) {
803 for (j = 0; j <
size; j++) {
827 uint8_t rgb_map[3] = {0, 1, 2};
832 else if (!strncmp(
line,
"values", 6)) {
833 const char *p =
line + 6;
834 #define SET_COLOR(id) do { \
835 while (av_isspace(*p)) \
838 case 'r': rgb_map[id] = 0; break; \
839 case 'g': rgb_map[id] = 1; break; \
840 case 'b': rgb_map[id] = 2; break; \
842 while (*p && !av_isspace(*p)) \
852 if (
in == -1 ||
out == -1) {
856 if (
in < 2 ||
out < 2 ||
870 scale = 1. / (
out - 1);
872 for (k = 0; k <
size; k++) {
873 for (j = 0; j <
size; j++) {
881 vec->
r =
val[rgb_map[0]] * scale;
882 vec->
g =
val[rgb_map[1]] * scale;
883 vec->
b =
val[rgb_map[2]] * scale;
907 mid = (low + hi) / 2;
918 #define NEXT_FLOAT_OR_GOTO(value, label) \
919 if (!fget_next_word(line, sizeof(line) ,f)) { \
920 ret = AVERROR_INVALIDDATA; \
923 if (av_sscanf(line, "%f", &value) != 1) { \
924 ret = AVERROR_INVALIDDATA; \
932 float in_min[3] = {0.0, 0.0, 0.0};
933 float in_max[3] = {1.0, 1.0, 1.0};
934 float out_min[3] = {0.0, 0.0, 0.0};
935 float out_max[3] = {1.0, 1.0, 1.0};
936 int inside_metadata = 0,
size, size2;
940 int prelut_sizes[3] = {0, 0, 0};
945 if (strncmp(
line,
"CSPLUTV100", 10)) {
952 if (strncmp(
line,
"3D", 2)) {
961 if (!strncmp(
line,
"BEGIN METADATA", 14)) {
965 if (!strncmp(
line,
"END METADATA", 12)) {
969 if (inside_metadata == 0) {
970 int size_r, size_g, size_b;
972 for (
int i = 0;
i < 3;
i++) {
973 int npoints = strtol(
line,
NULL, 0);
984 if (in_prelut[
i] || out_prelut[
i]) {
990 in_prelut[
i] = (
float*)
av_malloc(npoints *
sizeof(
float));
991 out_prelut[
i] = (
float*)
av_malloc(npoints *
sizeof(
float));
992 if (!in_prelut[
i] || !out_prelut[
i]) {
997 prelut_sizes[
i] = npoints;
999 in_max[
i] = -FLT_MAX;
1000 out_min[
i] = FLT_MAX;
1001 out_max[
i] = -FLT_MAX;
1003 for (
int j = 0; j < npoints; j++) {
1005 in_min[
i] =
FFMIN(in_min[
i], v);
1006 in_max[
i] =
FFMAX(in_max[
i], v);
1007 in_prelut[
i][j] = v;
1008 if (j > 0 && v < last) {
1016 for (
int j = 0; j < npoints; j++) {
1018 out_min[
i] =
FFMIN(out_min[
i], v);
1019 out_max[
i] =
FFMAX(out_max[
i], v);
1020 out_prelut[
i][j] = v;
1023 }
else if (npoints == 2) {
1044 if (
av_sscanf(
line,
"%d %d %d", &size_r, &size_g, &size_b) != 3) {
1048 if (size_r != size_g || size_r != size_b) {
1057 if (prelut_sizes[0] && prelut_sizes[1] && prelut_sizes[2])
1064 for (
int k = 0; k <
size; k++) {
1065 for (
int j = 0; j <
size; j++) {
1066 for (
int i = 0;
i <
size;
i++) {
1075 vec->
r *= out_max[0] - out_min[0];
1076 vec->
g *= out_max[1] - out_min[1];
1077 vec->
b *= out_max[2] - out_min[2];
1087 for (
int c = 0;
c < 3;
c++) {
1100 a = out_prelut[
c][idx + 0];
1101 b = out_prelut[
c][idx + 1];
1102 mix = x - in_prelut[
c][idx];
1118 for (
int c = 0;
c < 3;
c++) {
1130 const float c = 1. / (
size - 1);
1136 for (k = 0; k <
size; k++) {
1137 for (j = 0; j <
size; j++) {
1177 int depth, is16bit, isfloat,
planar;
1181 depth =
desc->comp[0].depth;
1182 is16bit =
desc->comp[0].depth > 8;
1188 #define SET_FUNC(name) do { \
1189 if (planar && !isfloat) { \
1191 case 8: lut3d->interp = interp_8_##name##_p8; break; \
1192 case 9: lut3d->interp = interp_16_##name##_p9; break; \
1193 case 10: lut3d->interp = interp_16_##name##_p10; break; \
1194 case 12: lut3d->interp = interp_16_##name##_p12; break; \
1195 case 14: lut3d->interp = interp_16_##name##_p14; break; \
1196 case 16: lut3d->interp = interp_16_##name##_p16; break; \
1198 } else if (isfloat) { lut3d->interp = interp_##name##_pf32; \
1199 } else if (is16bit) { lut3d->interp = interp_16_##name; \
1200 } else { lut3d->interp = interp_8_##name; } \
1255 char *res,
int res_len,
int flags)
1266 #if CONFIG_LUT3D_FILTER
1267 static const AVOption lut3d_options[] = {
1294 ext = strrchr(lut3d->
file,
'.');
1333 for (
i = 0;
i < 3;
i++) {
1365 .priv_class = &lut3d_class,
1371 #if CONFIG_HALDCLUT_FILTER
1376 const int linesize =
frame->linesize[0];
1377 const int w = lut3d->clut_width;
1378 const int step = lut3d->clut_step;
1379 const uint8_t *rgba_map = lut3d->clut_rgba_map;
1381 const int level2 = lut3d->
lutsize2;
1383 #define LOAD_CLUT(nbits) do { \
1384 int i, j, k, x = 0, y = 0; \
1386 for (k = 0; k < level; k++) { \
1387 for (j = 0; j < level; j++) { \
1388 for (i = 0; i < level; i++) { \
1389 const uint##nbits##_t *src = (const uint##nbits##_t *) \
1390 (data + y*linesize + x*step); \
1391 struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \
1392 vec->r = src[rgba_map[0]] / (float)((1<<(nbits)) - 1); \
1393 vec->g = src[rgba_map[1]] / (float)((1<<(nbits)) - 1); \
1394 vec->b = src[rgba_map[2]] / (float)((1<<(nbits)) - 1); \
1404 switch (lut3d->clut_bits) {
1405 case 8: LOAD_CLUT(8);
break;
1406 case 16: LOAD_CLUT(16);
break;
1415 const int glinesize =
frame->linesize[0];
1416 const int blinesize =
frame->linesize[1];
1417 const int rlinesize =
frame->linesize[2];
1418 const int w = lut3d->clut_width;
1420 const int level2 = lut3d->
lutsize2;
1422 #define LOAD_CLUT_PLANAR(nbits, depth) do { \
1423 int i, j, k, x = 0, y = 0; \
1425 for (k = 0; k < level; k++) { \
1426 for (j = 0; j < level; j++) { \
1427 for (i = 0; i < level; i++) { \
1428 const uint##nbits##_t *gsrc = (const uint##nbits##_t *) \
1429 (datag + y*glinesize); \
1430 const uint##nbits##_t *bsrc = (const uint##nbits##_t *) \
1431 (datab + y*blinesize); \
1432 const uint##nbits##_t *rsrc = (const uint##nbits##_t *) \
1433 (datar + y*rlinesize); \
1434 struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \
1435 vec->r = gsrc[x] / (float)((1<<(depth)) - 1); \
1436 vec->g = bsrc[x] / (float)((1<<(depth)) - 1); \
1437 vec->b = rsrc[x] / (float)((1<<(depth)) - 1); \
1447 switch (lut3d->clut_bits) {
1448 case 8: LOAD_CLUT_PLANAR(8, 8);
break;
1449 case 9: LOAD_CLUT_PLANAR(16, 9);
break;
1450 case 10: LOAD_CLUT_PLANAR(16, 10);
break;
1451 case 12: LOAD_CLUT_PLANAR(16, 12);
break;
1452 case 14: LOAD_CLUT_PLANAR(16, 14);
break;
1453 case 16: LOAD_CLUT_PLANAR(16, 16);
break;
1462 const int glinesize =
frame->linesize[0];
1463 const int blinesize =
frame->linesize[1];
1464 const int rlinesize =
frame->linesize[2];
1465 const int w = lut3d->clut_width;
1467 const int level2 = lut3d->
lutsize2;
1469 int i, j, k, x = 0, y = 0;
1471 for (k = 0; k <
level; k++) {
1472 for (j = 0; j <
level; j++) {
1474 const float *
gsrc = (
const float *)(datag + y*glinesize);
1475 const float *
bsrc = (
const float *)(datab + y*blinesize);
1476 const float *
rsrc = (
const float *)(datar + y*rlinesize);
1499 outlink->
w =
ctx->inputs[0]->w;
1500 outlink->
h =
ctx->inputs[0]->h;
1522 lut3d->clut_bits =
desc->comp[0].depth;
1546 const int max_clut_level = sqrt(
MAX_LEVEL);
1547 const int max_clut_size = max_clut_level*max_clut_level*max_clut_level;
1549 "(maximum level is %d, or %dx%d CLUT)\n",
1550 max_clut_level, max_clut_size, max_clut_size);
1570 if (lut3d->clut_float)
1571 update_clut_float(
ctx->priv, second);
1572 else if (lut3d->clut_planar)
1573 update_clut_planar(
ctx->priv, second);
1575 update_clut_packed(
ctx->priv, second);
1584 lut3d->fs.on_event = update_apply_clut;
1595 static const AVOption haldclut_options[] = {
1609 .config_props = config_clut,
1627 .preinit = haldclut_framesync_preinit,
1628 .
init = haldclut_init,
1629 .
uninit = haldclut_uninit,
1632 .
inputs = haldclut_inputs,
1634 .priv_class = &haldclut_class,
1640 #if CONFIG_LUT1D_FILTER
1642 enum interp_1d_mode {
1643 INTERPOLATE_1D_NEAREST,
1644 INTERPOLATE_1D_LINEAR,
1645 INTERPOLATE_1D_CUBIC,
1646 INTERPOLATE_1D_COSINE,
1647 INTERPOLATE_1D_SPLINE,
1651 #define MAX_1D_LEVEL 65536
1653 typedef struct LUT1DContext {
1660 float lut[3][MAX_1D_LEVEL];
1666 #define OFFSET(x) offsetof(LUT1DContext, x)
1668 static void set_identity_matrix_1d(LUT1DContext *lut1d,
int size)
1670 const float c = 1. / (
size - 1);
1673 lut1d->lutsize =
size;
1675 lut1d->lut[0][
i] =
i *
c;
1676 lut1d->lut[1][
i] =
i *
c;
1677 lut1d->lut[2][
i] =
i *
c;
1683 LUT1DContext *lut1d =
ctx->priv;
1685 float in_min[3] = {0.0, 0.0, 0.0};
1686 float in_max[3] = {1.0, 1.0, 1.0};
1687 float out_min[3] = {0.0, 0.0, 0.0};
1688 float out_max[3] = {1.0, 1.0, 1.0};
1689 int inside_metadata = 0,
size;
1692 if (strncmp(
line,
"CSPLUTV100", 10)) {
1698 if (strncmp(
line,
"1D", 2)) {
1706 if (!strncmp(
line,
"BEGIN METADATA", 14)) {
1707 inside_metadata = 1;
1710 if (!strncmp(
line,
"END METADATA", 12)) {
1711 inside_metadata = 0;
1714 if (inside_metadata == 0) {
1715 for (
int i = 0;
i < 3;
i++) {
1716 int npoints = strtol(
line,
NULL, 0);
1734 if (size < 2 || size > MAX_1D_LEVEL) {
1739 lut1d->lutsize =
size;
1741 for (
int i = 0;
i <
size;
i++) {
1743 if (
av_sscanf(
line,
"%f %f %f", &lut1d->lut[0][
i], &lut1d->lut[1][
i], &lut1d->lut[2][
i]) != 3)
1745 lut1d->lut[0][
i] *= out_max[0] - out_min[0];
1746 lut1d->lut[1][
i] *= out_max[1] - out_min[1];
1747 lut1d->lut[2][
i] *= out_max[2] - out_min[2];
1754 lut1d->scale.r =
av_clipf(1. / (in_max[0] - in_min[0]), 0.
f, 1.
f);
1755 lut1d->scale.g =
av_clipf(1. / (in_max[1] - in_min[1]), 0.
f, 1.
f);
1756 lut1d->scale.b =
av_clipf(1. / (in_max[2] - in_min[2]), 0.
f, 1.
f);
1763 LUT1DContext *lut1d =
ctx->priv;
1765 float min[3] = {0.0, 0.0, 0.0};
1766 float max[3] = {1.0, 1.0, 1.0};
1769 if (!strncmp(
line,
"LUT_1D_SIZE", 11)) {
1773 if (size < 2 || size > MAX_1D_LEVEL) {
1777 lut1d->lutsize =
size;
1782 if (!strncmp(
line,
"DOMAIN_", 7)) {
1784 if (!strncmp(
line + 7,
"MIN ", 4)) vals =
min;
1785 else if (!strncmp(
line + 7,
"MAX ", 4)) vals =
max;
1792 }
else if (!strncmp(
line,
"LUT_1D_INPUT_RANGE ", 19)) {
1797 }
else if (!strncmp(
line,
"TITLE", 5)) {
1801 if (
av_sscanf(
line,
"%f %f %f", &lut1d->lut[0][
i], &lut1d->lut[1][
i], &lut1d->lut[2][
i]) != 3)
1815 static const AVOption lut1d_options[] = {
1818 {
"nearest",
"use values from the nearest defined points", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_NEAREST}, 0, 0,
TFLAGS,
"interp_mode" },
1819 {
"linear",
"use values from the linear interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_LINEAR}, 0, 0,
TFLAGS,
"interp_mode" },
1820 {
"cosine",
"use values from the cosine interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_COSINE}, 0, 0,
TFLAGS,
"interp_mode" },
1821 {
"cubic",
"use values from the cubic interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_CUBIC}, 0, 0,
TFLAGS,
"interp_mode" },
1822 {
"spline",
"use values from the spline interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_SPLINE}, 0, 0,
TFLAGS,
"interp_mode" },
1828 static inline float interp_1d_nearest(
const LUT1DContext *lut1d,
1829 int idx,
const float s)
1831 return lut1d->lut[idx][
NEAR(
s)];
1834 #define NEXT1D(x) (FFMIN((int)(x) + 1, lut1d->lutsize - 1))
1836 static inline float interp_1d_linear(
const LUT1DContext *lut1d,
1837 int idx,
const float s)
1839 const int prev =
PREV(
s);
1840 const int next = NEXT1D(
s);
1841 const float d =
s - prev;
1842 const float p = lut1d->lut[idx][prev];
1843 const float n = lut1d->lut[idx][next];
1845 return lerpf(p, n, d);
1848 static inline float interp_1d_cosine(
const LUT1DContext *lut1d,
1849 int idx,
const float s)
1851 const int prev =
PREV(
s);
1852 const int next = NEXT1D(
s);
1853 const float d =
s - prev;
1854 const float p = lut1d->lut[idx][prev];
1855 const float n = lut1d->lut[idx][next];
1856 const float m = (1.f -
cosf(d *
M_PI)) * .5
f;
1858 return lerpf(p, n, m);
1861 static inline float interp_1d_cubic(
const LUT1DContext *lut1d,
1862 int idx,
const float s)
1864 const int prev =
PREV(
s);
1865 const int next = NEXT1D(
s);
1866 const float mu =
s - prev;
1869 float y0 = lut1d->lut[idx][
FFMAX(prev - 1, 0)];
1870 float y1 = lut1d->lut[idx][prev];
1871 float y2 = lut1d->lut[idx][next];
1872 float y3 = lut1d->lut[idx][
FFMIN(next + 1, lut1d->lutsize - 1)];
1876 a0 = y3 - y2 - y0 + y1;
1881 return a0 * mu * mu2 +
a1 * mu2 +
a2 * mu +
a3;
1884 static inline float interp_1d_spline(
const LUT1DContext *lut1d,
1885 int idx,
const float s)
1887 const int prev =
PREV(
s);
1888 const int next = NEXT1D(
s);
1889 const float x =
s - prev;
1890 float c0,
c1,
c2, c3;
1892 float y0 = lut1d->lut[idx][
FFMAX(prev - 1, 0)];
1893 float y1 = lut1d->lut[idx][prev];
1894 float y2 = lut1d->lut[idx][next];
1895 float y3 = lut1d->lut[idx][
FFMIN(next + 1, lut1d->lutsize - 1)];
1898 c1 = .5f * (y2 - y0);
1899 c2 = y0 - 2.5f * y1 + 2.f * y2 - .5f * y3;
1900 c3 = .5f * (y3 - y0) + 1.5
f * (y1 - y2);
1902 return ((c3 * x +
c2) * x +
c1) * x + c0;
1905 #define DEFINE_INTERP_FUNC_PLANAR_1D(name, nbits, depth) \
1906 static int interp_1d_##nbits##_##name##_p##depth(AVFilterContext *ctx, \
1907 void *arg, int jobnr, \
1911 const LUT1DContext *lut1d = ctx->priv; \
1912 const ThreadData *td = arg; \
1913 const AVFrame *in = td->in; \
1914 const AVFrame *out = td->out; \
1915 const int direct = out == in; \
1916 const int slice_start = (in->height * jobnr ) / nb_jobs; \
1917 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
1918 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
1919 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
1920 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
1921 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
1922 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
1923 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
1924 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
1925 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
1926 const float factor = (1 << depth) - 1; \
1927 const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1); \
1928 const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1); \
1929 const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1); \
1931 for (y = slice_start; y < slice_end; y++) { \
1932 uint##nbits##_t *dstg = (uint##nbits##_t *)grow; \
1933 uint##nbits##_t *dstb = (uint##nbits##_t *)brow; \
1934 uint##nbits##_t *dstr = (uint##nbits##_t *)rrow; \
1935 uint##nbits##_t *dsta = (uint##nbits##_t *)arow; \
1936 const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow; \
1937 const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow; \
1938 const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow; \
1939 const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow; \
1940 for (x = 0; x < in->width; x++) { \
1941 float r = srcr[x] * scale_r; \
1942 float g = srcg[x] * scale_g; \
1943 float b = srcb[x] * scale_b; \
1944 r = interp_1d_##name(lut1d, 0, r); \
1945 g = interp_1d_##name(lut1d, 1, g); \
1946 b = interp_1d_##name(lut1d, 2, b); \
1947 dstr[x] = av_clip_uintp2(r * factor, depth); \
1948 dstg[x] = av_clip_uintp2(g * factor, depth); \
1949 dstb[x] = av_clip_uintp2(b * factor, depth); \
1950 if (!direct && in->linesize[3]) \
1951 dsta[x] = srca[x]; \
1953 grow += out->linesize[0]; \
1954 brow += out->linesize[1]; \
1955 rrow += out->linesize[2]; \
1956 arow += out->linesize[3]; \
1957 srcgrow += in->linesize[0]; \
1958 srcbrow += in->linesize[1]; \
1959 srcrrow += in->linesize[2]; \
1960 srcarow += in->linesize[3]; \
1965 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 8, 8)
1966 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 8, 8)
1967 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 8, 8)
1968 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 8, 8)
1969 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 8, 8)
1971 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 9)
1972 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 9)
1973 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 9)
1974 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 9)
1975 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 9)
1977 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 10)
1978 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 10)
1979 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 10)
1980 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 10)
1981 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 10)
1983 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 12)
1984 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 12)
1985 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 12)
1986 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 12)
1987 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 12)
1989 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 14)
1990 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 14)
1991 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 14)
1992 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 14)
1993 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 14)
1995 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 16)
1996 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 16)
1997 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 16)
1998 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 16)
1999 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 16)
2001 #define DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(name, depth) \
2002 static int interp_1d_##name##_pf##depth(AVFilterContext *ctx, \
2003 void *arg, int jobnr, \
2007 const LUT1DContext *lut1d = ctx->priv; \
2008 const ThreadData *td = arg; \
2009 const AVFrame *in = td->in; \
2010 const AVFrame *out = td->out; \
2011 const int direct = out == in; \
2012 const int slice_start = (in->height * jobnr ) / nb_jobs; \
2013 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
2014 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \
2015 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \
2016 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \
2017 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \
2018 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \
2019 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \
2020 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \
2021 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \
2022 const float lutsize = lut1d->lutsize - 1; \
2023 const float scale_r = lut1d->scale.r * lutsize; \
2024 const float scale_g = lut1d->scale.g * lutsize; \
2025 const float scale_b = lut1d->scale.b * lutsize; \
2027 for (y = slice_start; y < slice_end; y++) { \
2028 float *dstg = (float *)grow; \
2029 float *dstb = (float *)brow; \
2030 float *dstr = (float *)rrow; \
2031 float *dsta = (float *)arow; \
2032 const float *srcg = (const float *)srcgrow; \
2033 const float *srcb = (const float *)srcbrow; \
2034 const float *srcr = (const float *)srcrrow; \
2035 const float *srca = (const float *)srcarow; \
2036 for (x = 0; x < in->width; x++) { \
2037 float r = av_clipf(sanitizef(srcr[x]) * scale_r, 0.0f, lutsize); \
2038 float g = av_clipf(sanitizef(srcg[x]) * scale_g, 0.0f, lutsize); \
2039 float b = av_clipf(sanitizef(srcb[x]) * scale_b, 0.0f, lutsize); \
2040 r = interp_1d_##name(lut1d, 0, r); \
2041 g = interp_1d_##name(lut1d, 1, g); \
2042 b = interp_1d_##name(lut1d, 2, b); \
2046 if (!direct && in->linesize[3]) \
2047 dsta[x] = srca[x]; \
2049 grow += out->linesize[0]; \
2050 brow += out->linesize[1]; \
2051 rrow += out->linesize[2]; \
2052 arow += out->linesize[3]; \
2053 srcgrow += in->linesize[0]; \
2054 srcbrow += in->linesize[1]; \
2055 srcrrow += in->linesize[2]; \
2056 srcarow += in->linesize[3]; \
2061 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(nearest, 32)
2062 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(
linear, 32)
2063 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cosine, 32)
2064 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cubic, 32)
2065 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(spline, 32)
2067 #define DEFINE_INTERP_FUNC_1D(name, nbits) \
2068 static int interp_1d_##nbits##_##name(AVFilterContext *ctx, void *arg, \
2069 int jobnr, int nb_jobs) \
2072 const LUT1DContext *lut1d = ctx->priv; \
2073 const ThreadData *td = arg; \
2074 const AVFrame *in = td->in; \
2075 const AVFrame *out = td->out; \
2076 const int direct = out == in; \
2077 const int step = lut1d->step; \
2078 const uint8_t r = lut1d->rgba_map[R]; \
2079 const uint8_t g = lut1d->rgba_map[G]; \
2080 const uint8_t b = lut1d->rgba_map[B]; \
2081 const uint8_t a = lut1d->rgba_map[A]; \
2082 const int slice_start = (in->height * jobnr ) / nb_jobs; \
2083 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
2084 uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \
2085 const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \
2086 const float factor = (1 << nbits) - 1; \
2087 const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1); \
2088 const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1); \
2089 const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1); \
2091 for (y = slice_start; y < slice_end; y++) { \
2092 uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \
2093 const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \
2094 for (x = 0; x < in->width * step; x += step) { \
2095 float rr = src[x + r] * scale_r; \
2096 float gg = src[x + g] * scale_g; \
2097 float bb = src[x + b] * scale_b; \
2098 rr = interp_1d_##name(lut1d, 0, rr); \
2099 gg = interp_1d_##name(lut1d, 1, gg); \
2100 bb = interp_1d_##name(lut1d, 2, bb); \
2101 dst[x + r] = av_clip_uint##nbits(rr * factor); \
2102 dst[x + g] = av_clip_uint##nbits(gg * factor); \
2103 dst[x + b] = av_clip_uint##nbits(bb * factor); \
2104 if (!direct && step == 4) \
2105 dst[x + a] = src[x + a]; \
2107 dstrow += out->linesize[0]; \
2108 srcrow += in ->linesize[0]; \
2113 DEFINE_INTERP_FUNC_1D(nearest, 8)
2114 DEFINE_INTERP_FUNC_1D(
linear, 8)
2115 DEFINE_INTERP_FUNC_1D(cosine, 8)
2116 DEFINE_INTERP_FUNC_1D(cubic, 8)
2117 DEFINE_INTERP_FUNC_1D(spline, 8)
2119 DEFINE_INTERP_FUNC_1D(nearest, 16)
2120 DEFINE_INTERP_FUNC_1D(
linear, 16)
2121 DEFINE_INTERP_FUNC_1D(cosine, 16)
2122 DEFINE_INTERP_FUNC_1D(cubic, 16)
2123 DEFINE_INTERP_FUNC_1D(spline, 16)
2127 int depth, is16bit, isfloat,
planar;
2128 LUT1DContext *lut1d =
inlink->dst->priv;
2131 depth =
desc->comp[0].depth;
2132 is16bit =
desc->comp[0].depth > 8;
2138 #define SET_FUNC_1D(name) do { \
2139 if (planar && !isfloat) { \
2141 case 8: lut1d->interp = interp_1d_8_##name##_p8; break; \
2142 case 9: lut1d->interp = interp_1d_16_##name##_p9; break; \
2143 case 10: lut1d->interp = interp_1d_16_##name##_p10; break; \
2144 case 12: lut1d->interp = interp_1d_16_##name##_p12; break; \
2145 case 14: lut1d->interp = interp_1d_16_##name##_p14; break; \
2146 case 16: lut1d->interp = interp_1d_16_##name##_p16; break; \
2148 } else if (isfloat) { lut1d->interp = interp_1d_##name##_pf32; \
2149 } else if (is16bit) { lut1d->interp = interp_1d_16_##name; \
2150 } else { lut1d->interp = interp_1d_8_##name; } \
2153 switch (lut1d->interpolation) {
2154 case INTERPOLATE_1D_NEAREST: SET_FUNC_1D(nearest);
break;
2155 case INTERPOLATE_1D_LINEAR: SET_FUNC_1D(
linear);
break;
2156 case INTERPOLATE_1D_COSINE: SET_FUNC_1D(cosine);
break;
2157 case INTERPOLATE_1D_CUBIC: SET_FUNC_1D(cubic);
break;
2158 case INTERPOLATE_1D_SPLINE: SET_FUNC_1D(spline);
break;
2171 LUT1DContext *lut1d =
ctx->priv;
2173 lut1d->scale.r = lut1d->scale.g = lut1d->scale.b = 1.f;
2176 set_identity_matrix_1d(lut1d, 32);
2187 ext = strrchr(lut1d->file,
'.');
2198 ret = parse_cinespace_1d(
ctx,
f);
2204 if (!
ret && !lut1d->lutsize) {
2217 LUT1DContext *lut1d =
ctx->priv;
2252 static int lut1d_process_command(
AVFilterContext *
ctx,
const char *cmd,
const char *args,
2253 char *res,
int res_len,
int flags)
2255 LUT1DContext *lut1d =
ctx->priv;
2264 set_identity_matrix_1d(lut1d, 32);
2267 return config_input_1d(
ctx->inputs[0]);
2274 .filter_frame = filter_frame_1d,
2275 .config_props = config_input_1d,
2291 .priv_size =
sizeof(LUT1DContext),
2296 .priv_class = &lut1d_class,
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 av_cold int init(AVCodecContext *avctx)
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)
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)
#define FRAMESYNC_DEFINE_CLASS(name, context, field)
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 struct rgbvec interp_prism(const LUT3DContext *lut3d, const struct rgbvec *s)
const char * name
Filter name.
static int parse_cube(AVFilterContext *ctx, FILE *f)
AVFormatInternal * internal
An opaque field for libavformat internal usage.
A link between two filters.
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
@ INTERPOLATE_TETRAHEDRAL
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 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 int config_output(AVFilterLink *outlink)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
FILE * av_fopen_utf8(const char *path, const char *mode)
Open a file using a UTF-8 filename.
#define AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_GBRAP12
#define av_assert0(cond)
assert() equivalent, that is always enabled.
static const AVFilterPad outputs[]
static enum AVPixelFormat pix_fmts[]
#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)
@ 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
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... 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 inputs
@ 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_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
#define AVFILTER_DEFINE_CLASS(fname)
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
#define AV_PIX_FMT_BGRA64
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.
static struct rgbvec interp_pyramid(const LUT3DContext *lut3d, const struct rgbvec *s)
const char * name
Pad name.
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)
static int query_formats(AVFilterContext *ctx)
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...
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
#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.
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
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;} } if(HAVE_X86ASM &&1) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);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
int interpolation
interp_mode
static int nearest_sample_index(float *data, float x, int low, int hi)