62 #define PRELUT_SIZE 65536 84 #if CONFIG_HALDCLUT_FILTER 99 #define OFFSET(x) offsetof(LUT3DContext, x) 100 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM 101 #define COMMON_OPTIONS \ 102 { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, NB_INTERP_MODE-1, FLAGS, "interp_mode" }, \ 103 { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_NEAREST}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ 104 { "trilinear", "interpolate values using the 8 points defining a cube", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TRILINEAR}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ 105 { "tetrahedral", "interpolate values using a tetrahedron", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TETRAHEDRAL}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ 108 #define EXPONENT_MASK 0x7F800000 109 #define MANTISSA_MASK 0x007FFFFF 110 #define SIGN_MASK 0x80000000 132 static inline float lerpf(
float v0,
float v1,
float f)
134 return v0 + (v1 -
v0) * f;
145 #define NEAR(x) ((int)((x) + .5)) 146 #define PREV(x) ((int)(x)) 147 #define NEXT(x) (FFMIN((int)(x) + 1, lut3d->lutsize - 1)) 155 return lut3d->lut[
NEAR(
s->r) * lut3d->lutsize2 +
NEAR(
s->g) * lut3d->lutsize +
NEAR(
s->b)];
165 const int lutsize2 = lut3d->lutsize2;
166 const int lutsize = lut3d->lutsize;
169 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
170 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
171 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
172 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
173 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
174 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
175 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
176 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
177 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
195 const int lutsize2 = lut3d->lutsize2;
196 const int lutsize = lut3d->lutsize;
199 const struct rgbvec d = {
s->r - prev[0],
s->g - prev[1],
s->b - prev[2]};
200 const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]];
201 const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]];
205 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
206 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
207 c.
r = (1-d.
r) * c000.
r + (d.
r-d.
g) * c100.
r + (d.
g-d.
b) * c110.
r + (d.
b) * c111.
r;
208 c.
g = (1-d.
r) * c000.
g + (d.
r-d.
g) * c100.
g + (d.
g-d.
b) * c110.
g + (d.
b) * c111.
g;
209 c.
b = (1-d.
r) * c000.
b + (d.
r-d.
g) * c100.
b + (d.
g-d.
b) * c110.
b + (d.
b) * c111.
b;
210 }
else if (d.
r > d.
b) {
211 const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]];
212 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
213 c.
r = (1-d.
r) * c000.
r + (d.
r-d.
b) * c100.
r + (d.
b-d.
g) * c101.
r + (d.
g) * c111.
r;
214 c.
g = (1-d.
r) * c000.
g + (d.
r-d.
b) * c100.
g + (d.
b-d.
g) * c101.
g + (d.
g) * c111.
g;
215 c.
b = (1-d.
r) * c000.
b + (d.
r-d.
b) * c100.
b + (d.
b-d.
g) * c101.
b + (d.
g) * c111.
b;
217 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
218 const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]];
219 c.
r = (1-d.
b) * c000.
r + (d.
b-d.
r) * c001.
r + (d.
r-d.
g) * c101.
r + (d.
g) * c111.
r;
220 c.
g = (1-d.
b) * c000.
g + (d.
b-d.
r) * c001.
g + (d.
r-d.
g) * c101.
g + (d.
g) * c111.
g;
221 c.
b = (1-d.
b) * c000.
b + (d.
b-d.
r) * c001.
b + (d.
r-d.
g) * c101.
b + (d.
g) * c111.
b;
225 const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]];
226 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
227 c.
r = (1-d.
b) * c000.
r + (d.
b-d.
g) * c001.
r + (d.
g-d.
r) * c011.
r + (d.
r) * c111.
r;
228 c.
g = (1-d.
b) * c000.
g + (d.
b-d.
g) * c001.
g + (d.
g-d.
r) * c011.
g + (d.
r) * c111.
g;
229 c.
b = (1-d.
b) * c000.
b + (d.
b-d.
g) * c001.
b + (d.
g-d.
r) * c011.
b + (d.
r) * c111.
b;
230 }
else if (d.
b > d.
r) {
231 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
232 const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]];
233 c.
r = (1-d.
g) * c000.
r + (d.
g-d.
b) * c010.
r + (d.
b-d.
r) * c011.
r + (d.
r) * c111.
r;
234 c.
g = (1-d.
g) * c000.
g + (d.
g-d.
b) * c010.
g + (d.
b-d.
r) * c011.
g + (d.
r) * c111.
g;
235 c.
b = (1-d.
g) * c000.
b + (d.
g-d.
b) * c010.
b + (d.
b-d.
r) * c011.
b + (d.
r) * c111.
b;
237 const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]];
238 const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]];
239 c.
r = (1-d.
g) * c000.
r + (d.
g-d.
r) * c010.
r + (d.
r-d.
b) * c110.
r + (d.
b) * c111.
r;
240 c.
g = (1-d.
g) * c000.
g + (d.
g-d.
r) * c010.
g + (d.
r-d.
b) * c110.
g + (d.
b) * c111.
g;
241 c.
b = (1-d.
g) * c000.
b + (d.
g-d.
r) * c010.
b + (d.
r-d.
b) * c110.
b + (d.
b) * c111.
b;
248 int idx,
const float s)
250 const int lut_max = prelut->
size - 1;
251 const float scaled = (s - prelut->
min[idx]) * prelut->
scale[idx];
252 const float x = av_clipf(scaled, 0.0
f, lut_max);
253 const int prev =
PREV(x);
254 const int next =
FFMIN((
int)(x) + 1, lut_max);
255 const float p = prelut->
lut[idx][prev];
256 const float n = prelut->
lut[idx][next];
257 const float d = x - (float)prev;
258 return lerpf(p, n, d);
266 if (prelut->size <= 0)
275 #define DEFINE_INTERP_FUNC_PLANAR(name, nbits, depth) \ 276 static int interp_##nbits##_##name##_p##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ 279 const LUT3DContext *lut3d = ctx->priv; \ 280 const Lut3DPreLut *prelut = &lut3d->prelut; \ 281 const ThreadData *td = arg; \ 282 const AVFrame *in = td->in; \ 283 const AVFrame *out = td->out; \ 284 const int direct = out == in; \ 285 const int slice_start = (in->height * jobnr ) / nb_jobs; \ 286 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \ 287 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \ 288 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \ 289 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \ 290 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \ 291 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \ 292 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \ 293 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \ 294 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \ 295 const float lut_max = lut3d->lutsize - 1; \ 296 const float scale_f = 1.0f / ((1<<depth) - 1); \ 297 const float scale_r = lut3d->scale.r * lut_max; \ 298 const float scale_g = lut3d->scale.g * lut_max; \ 299 const float scale_b = lut3d->scale.b * lut_max; \ 301 for (y = slice_start; y < slice_end; y++) { \ 302 uint##nbits##_t *dstg = (uint##nbits##_t *)grow; \ 303 uint##nbits##_t *dstb = (uint##nbits##_t *)brow; \ 304 uint##nbits##_t *dstr = (uint##nbits##_t *)rrow; \ 305 uint##nbits##_t *dsta = (uint##nbits##_t *)arow; \ 306 const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow; \ 307 const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow; \ 308 const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow; \ 309 const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow; \ 310 for (x = 0; x < in->width; x++) { \ 311 const struct rgbvec rgb = {srcr[x] * scale_f, \ 313 srcb[x] * scale_f}; \ 314 const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \ 315 const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \ 316 av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \ 317 av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \ 318 struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \ 319 dstr[x] = av_clip_uintp2(vec.r * (float)((1<<depth) - 1), depth); \ 320 dstg[x] = av_clip_uintp2(vec.g * (float)((1<<depth) - 1), depth); \ 321 dstb[x] = av_clip_uintp2(vec.b * (float)((1<<depth) - 1), depth); \ 322 if (!direct && in->linesize[3]) \ 325 grow += out->linesize[0]; \ 326 brow += out->linesize[1]; \ 327 rrow += out->linesize[2]; \ 328 arow += out->linesize[3]; \ 329 srcgrow += in->linesize[0]; \ 330 srcbrow += in->linesize[1]; \ 331 srcrrow += in->linesize[2]; \ 332 srcarow += in->linesize[3]; \ 361 #define DEFINE_INTERP_FUNC_PLANAR_FLOAT(name, depth) \ 362 static int interp_##name##_pf##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ 365 const LUT3DContext *lut3d = ctx->priv; \ 366 const Lut3DPreLut *prelut = &lut3d->prelut; \ 367 const ThreadData *td = arg; \ 368 const AVFrame *in = td->in; \ 369 const AVFrame *out = td->out; \ 370 const int direct = out == in; \ 371 const int slice_start = (in->height * jobnr ) / nb_jobs; \ 372 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \ 373 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \ 374 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \ 375 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \ 376 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \ 377 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \ 378 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \ 379 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \ 380 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \ 381 const float lut_max = lut3d->lutsize - 1; \ 382 const float scale_r = lut3d->scale.r * lut_max; \ 383 const float scale_g = lut3d->scale.g * lut_max; \ 384 const float scale_b = lut3d->scale.b * lut_max; \ 386 for (y = slice_start; y < slice_end; y++) { \ 387 float *dstg = (float *)grow; \ 388 float *dstb = (float *)brow; \ 389 float *dstr = (float *)rrow; \ 390 float *dsta = (float *)arow; \ 391 const float *srcg = (const float *)srcgrow; \ 392 const float *srcb = (const float *)srcbrow; \ 393 const float *srcr = (const float *)srcrrow; \ 394 const float *srca = (const float *)srcarow; \ 395 for (x = 0; x < in->width; x++) { \ 396 const struct rgbvec rgb = {sanitizef(srcr[x]), \ 397 sanitizef(srcg[x]), \ 398 sanitizef(srcb[x])}; \ 399 const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \ 400 const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \ 401 av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \ 402 av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \ 403 struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \ 407 if (!direct && in->linesize[3]) \ 410 grow += out->linesize[0]; \ 411 brow += out->linesize[1]; \ 412 rrow += out->linesize[2]; \ 413 arow += out->linesize[3]; \ 414 srcgrow += in->linesize[0]; \ 415 srcbrow += in->linesize[1]; \ 416 srcrrow += in->linesize[2]; \ 417 srcarow += in->linesize[3]; \ 426 #define DEFINE_INTERP_FUNC(name, nbits) \ 427 static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ 430 const LUT3DContext *lut3d = ctx->priv; \ 431 const Lut3DPreLut *prelut = &lut3d->prelut; \ 432 const ThreadData *td = arg; \ 433 const AVFrame *in = td->in; \ 434 const AVFrame *out = td->out; \ 435 const int direct = out == in; \ 436 const int step = lut3d->step; \ 437 const uint8_t r = lut3d->rgba_map[R]; \ 438 const uint8_t g = lut3d->rgba_map[G]; \ 439 const uint8_t b = lut3d->rgba_map[B]; \ 440 const uint8_t a = lut3d->rgba_map[A]; \ 441 const int slice_start = (in->height * jobnr ) / nb_jobs; \ 442 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \ 443 uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \ 444 const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \ 445 const float lut_max = lut3d->lutsize - 1; \ 446 const float scale_f = 1.0f / ((1<<nbits) - 1); \ 447 const float scale_r = lut3d->scale.r * lut_max; \ 448 const float scale_g = lut3d->scale.g * lut_max; \ 449 const float scale_b = lut3d->scale.b * lut_max; \ 451 for (y = slice_start; y < slice_end; y++) { \ 452 uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \ 453 const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \ 454 for (x = 0; x < in->width * step; x += step) { \ 455 const struct rgbvec rgb = {src[x + r] * scale_f, \ 456 src[x + g] * scale_f, \ 457 src[x + b] * scale_f}; \ 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); \ 463 dst[x + r] = av_clip_uint##nbits(vec.r * (float)((1<<nbits) - 1)); \ 464 dst[x + g] = av_clip_uint##nbits(vec.g * (float)((1<<nbits) - 1)); \ 465 dst[x + b] = av_clip_uint##nbits(vec.b * (float)((1<<nbits) - 1)); \ 466 if (!direct && step == 4) \ 467 dst[x + a] = src[x + a]; \ 469 dstrow += out->linesize[0]; \ 470 srcrow += in ->linesize[0]; \ 483 #define MAX_LINE_SIZE 512 489 return !*p || *p ==
'#';
500 while ((c = fgetc(f)) != EOF) {
510 for (; max > 0; max--) {
511 if ((c = fgetc(f)) == EOF)
526 #define NEXT_LINE(loop_cond) do { \ 527 if (!fgets(line, sizeof(line), f)) { \ 528 av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n"); \ 529 return AVERROR_INVALIDDATA; \ 533 #define NEXT_LINE_OR_GOTO(loop_cond, label) do { \ 534 if (!fgets(line, sizeof(line), f)) { \ 535 av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n"); \ 536 ret = AVERROR_INVALIDDATA; \ 545 if (lutsize < 2 || lutsize >
MAX_LEVEL) {
557 for (i = 0; i < 3; i++) {
565 for (i = 0; i < 3; i++) {
570 lut3d->
lutsize2 = lutsize * lutsize;
586 if (!strncmp(line,
"3DLUTSIZE ", 10)) {
587 size = strtol(line + 10,
NULL, 0);
596 for (k = 0; k <
size; k++) {
597 for (j = 0; j <
size; j++) {
598 for (i = 0; i <
size; i++) {
599 struct rgbvec *vec = &lut3d->
lut[k * size2 + j * size +
i];
600 if (k != 0 || j != 0 || i != 0)
602 if (
av_sscanf(line,
"%f %f %f", &vec->
r, &vec->
g, &vec->
b) != 3)
615 float min[3] = {0.0, 0.0, 0.0};
616 float max[3] = {1.0, 1.0, 1.0};
618 while (fgets(line,
sizeof(line), f)) {
619 if (!strncmp(line,
"LUT_3D_SIZE", 11)) {
621 const int size = strtol(line + 12,
NULL, 0);
622 const int size2 = size *
size;
628 for (k = 0; k <
size; k++) {
629 for (j = 0; j <
size; j++) {
630 for (i = 0; i <
size; i++) {
631 struct rgbvec *vec = &lut3d->
lut[i * size2 + j * size + k];
636 if (!strncmp(line,
"DOMAIN_", 7)) {
638 if (!strncmp(line + 7,
"MIN ", 4)) vals =
min;
639 else if (!strncmp(line + 7,
"MAX ", 4)) vals =
max;
642 av_sscanf(line + 11,
"%f %f %f", vals, vals + 1, vals + 2);
644 min[0], min[1], min[2], max[0], max[1], max[2]);
646 }
else if (!strncmp(line,
"TITLE", 5)) {
650 if (
av_sscanf(line,
"%f %f %f", &vec->
r, &vec->
g, &vec->
b) != 3)
659 lut3d->
scale.
r = av_clipf(1. / (max[0] - min[0]), 0.f, 1.f);
660 lut3d->
scale.
g = av_clipf(1. / (max[1] - min[1]), 0.f, 1.f);
661 lut3d->
scale.
b = av_clipf(1. / (max[2] - min[2]), 0.f, 1.f);
674 const int size2 = 17 * 17;
675 const float scale = 16*16*16;
684 for (k = 0; k <
size; k++) {
685 for (j = 0; j <
size; j++) {
686 for (i = 0; i <
size; i++) {
688 struct rgbvec *vec = &lut3d->
lut[k * size2 + j * size +
i];
691 if (
av_sscanf(line,
"%d %d %d", &r, &g, &b) != 3)
709 uint8_t rgb_map[3] = {0, 1, 2};
711 while (fgets(line,
sizeof(line), f)) {
712 if (!strncmp(line,
"in", 2)) in = strtol(line + 2,
NULL, 0);
713 else if (!strncmp(line,
"out", 3))
out = strtol(line + 3,
NULL, 0);
714 else if (!strncmp(line,
"values", 6)) {
715 const char *p = line + 6;
716 #define SET_COLOR(id) do { \ 717 while (av_isspace(*p)) \ 720 case 'r': rgb_map[id] = 0; break; \ 721 case 'g': rgb_map[id] = 1; break; \ 722 case 'b': rgb_map[id] = 2; break; \ 724 while (*p && !av_isspace(*p)) \ 734 if (in == -1 ||
out == -1) {
738 if (in < 2 ||
out < 2 ||
744 for (size = 1; size*size*size <
in; size++);
752 scale = 1. / (
out - 1);
754 for (k = 0; k <
size; k++) {
755 for (j = 0; j <
size; j++) {
756 for (i = 0; i <
size; i++) {
757 struct rgbvec *vec = &lut3d->
lut[k * size2 + j * size +
i];
761 if (
av_sscanf(line,
"%f %f %f", val, val + 1, val + 2) != 3)
763 vec->
r = val[rgb_map[0]] * scale;
764 vec->
g = val[rgb_map[1]] * scale;
765 vec->
b = val[rgb_map[2]] * scale;
789 mid = (low + hi) / 2;
800 #define NEXT_FLOAT_OR_GOTO(value, label) \ 801 if (!fget_next_word(line, sizeof(line) ,f)) { \ 802 ret = AVERROR_INVALIDDATA; \ 805 if (av_sscanf(line, "%f", &value) != 1) { \ 806 ret = AVERROR_INVALIDDATA; \ 814 float in_min[3] = {0.0, 0.0, 0.0};
815 float in_max[3] = {1.0, 1.0, 1.0};
816 float out_min[3] = {0.0, 0.0, 0.0};
817 float out_max[3] = {1.0, 1.0, 1.0};
818 int inside_metadata = 0,
size, size2;
822 int prelut_sizes[3] = {0, 0, 0};
823 float *in_prelut[3] = {
NULL,
NULL, NULL};
824 float *out_prelut[3] = {
NULL,
NULL, NULL};
827 if (strncmp(line,
"CSPLUTV100", 10)) {
834 if (strncmp(line,
"3D", 2)) {
843 if (!strncmp(line,
"BEGIN METADATA", 14)) {
847 if (!strncmp(line,
"END METADATA", 12)) {
851 if (inside_metadata == 0) {
852 int size_r, size_g, size_b;
854 for (
int i = 0;
i < 3;
i++) {
855 int npoints = strtol(line, NULL, 0);
866 if (in_prelut[
i] || out_prelut[
i]) {
872 in_prelut[
i] = (
float*)
av_malloc(npoints *
sizeof(
float));
873 out_prelut[
i] = (
float*)
av_malloc(npoints *
sizeof(
float));
874 if (!in_prelut[i] || !out_prelut[i]) {
879 prelut_sizes[
i] = npoints;
881 in_max[
i] = -FLT_MAX;
882 out_min[
i] = FLT_MAX;
883 out_max[
i] = -FLT_MAX;
885 for (
int j = 0; j < npoints; j++) {
887 in_min[
i] =
FFMIN(in_min[i], v);
888 in_max[
i] =
FFMAX(in_max[i], v);
890 if (j > 0 && v < last) {
898 for (
int j = 0; j < npoints; j++) {
900 out_min[
i] =
FFMIN(out_min[i], v);
901 out_max[
i] =
FFMAX(out_max[i], v);
902 out_prelut[
i][j] = v;
905 }
else if (npoints == 2) {
907 if (
av_sscanf(line,
"%f %f", &in_min[
i], &in_max[i]) != 2) {
912 if (
av_sscanf(line,
"%f %f", &out_min[i], &out_max[i]) != 2) {
926 if (
av_sscanf(line,
"%d %d %d", &size_r, &size_g, &size_b) != 3) {
930 if (size_r != size_g || size_r != size_b) {
931 av_log(ctx,
AV_LOG_ERROR,
"Unsupported size combination: %dx%dx%d.\n", size_r, size_g, size_b);
939 if (prelut_sizes[0] && prelut_sizes[1] && prelut_sizes[2])
946 for (
int k = 0; k <
size; k++) {
947 for (
int j = 0; j <
size; j++) {
948 for (
int i = 0;
i <
size;
i++) {
949 struct rgbvec *vec = &lut3d->
lut[
i * size2 + j * size + k];
952 if (
av_sscanf(line,
"%f %f %f", &vec->
r, &vec->
g, &vec->
b) != 3) {
957 vec->
r *= out_max[0] - out_min[0];
958 vec->
g *= out_max[1] - out_min[1];
959 vec->
b *= out_max[2] - out_min[2];
969 for (
int c = 0;
c < 3;
c++) {
977 float x =
lerpf(in_min[c], in_max[c], mix),
a,
b;
982 a = out_prelut[
c][idx + 0];
983 b = out_prelut[
c][idx + 1];
984 mix = x - in_prelut[
c][idx];
994 lut3d->
scale.
r = av_clipf(1. / (in_max[0] - in_min[0]), 0.f, 1.f);
995 lut3d->
scale.
g = av_clipf(1. / (in_max[1] - in_min[1]), 0.f, 1.f);
996 lut3d->
scale.
b = av_clipf(1. / (in_max[2] - in_min[2]), 0.f, 1.f);
1000 for (
int c = 0;
c < 3;
c++) {
1011 const int size2 = size *
size;
1012 const float c = 1. / (size - 1);
1018 for (k = 0; k <
size; k++) {
1019 for (j = 0; j <
size; j++) {
1020 for (i = 0; i <
size; i++) {
1021 struct rgbvec *vec = &lut3d->
lut[k * size2 + j * size +
i];
1059 int depth, is16bit, isfloat,
planar;
1070 #define SET_FUNC(name) do { \ 1071 if (planar && !isfloat) { \ 1073 case 8: lut3d->interp = interp_8_##name##_p8; break; \ 1074 case 9: lut3d->interp = interp_16_##name##_p9; break; \ 1075 case 10: lut3d->interp = interp_16_##name##_p10; break; \ 1076 case 12: lut3d->interp = interp_16_##name##_p12; break; \ 1077 case 14: lut3d->interp = interp_16_##name##_p14; break; \ 1078 case 16: lut3d->interp = interp_16_##name##_p16; break; \ 1080 } else if (isfloat) { lut3d->interp = interp_##name##_pf32; \ 1081 } else if (is16bit) { lut3d->interp = interp_16_##name; \ 1082 } else { lut3d->interp = interp_8_##name; } \ 1134 #if CONFIG_LUT3D_FILTER 1135 static const AVOption lut3d_options[] = {
1162 ext = strrchr(lut3d->
file,
'.');
1185 if (!ret && !lut3d->
lutsize) {
1201 for (i = 0; i < 3; i++) {
1233 .priv_class = &lut3d_class,
1238 #if CONFIG_HALDCLUT_FILTER 1243 const int linesize = frame->
linesize[0];
1244 const int w = lut3d->clut_width;
1245 const int step = lut3d->clut_step;
1246 const uint8_t *rgba_map = lut3d->clut_rgba_map;
1248 const int level2 = lut3d->
lutsize2;
1250 #define LOAD_CLUT(nbits) do { \ 1251 int i, j, k, x = 0, y = 0; \ 1253 for (k = 0; k < level; k++) { \ 1254 for (j = 0; j < level; j++) { \ 1255 for (i = 0; i < level; i++) { \ 1256 const uint##nbits##_t *src = (const uint##nbits##_t *) \ 1257 (data + y*linesize + x*step); \ 1258 struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \ 1259 vec->r = src[rgba_map[0]] / (float)((1<<(nbits)) - 1); \ 1260 vec->g = src[rgba_map[1]] / (float)((1<<(nbits)) - 1); \ 1261 vec->b = src[rgba_map[2]] / (float)((1<<(nbits)) - 1); \ 1271 switch (lut3d->clut_bits) {
1272 case 8: LOAD_CLUT(8);
break;
1273 case 16: LOAD_CLUT(16);
break;
1282 const int glinesize = frame->
linesize[0];
1283 const int blinesize = frame->
linesize[1];
1284 const int rlinesize = frame->
linesize[2];
1285 const int w = lut3d->clut_width;
1287 const int level2 = lut3d->
lutsize2;
1289 #define LOAD_CLUT_PLANAR(nbits, depth) do { \ 1290 int i, j, k, x = 0, y = 0; \ 1292 for (k = 0; k < level; k++) { \ 1293 for (j = 0; j < level; j++) { \ 1294 for (i = 0; i < level; i++) { \ 1295 const uint##nbits##_t *gsrc = (const uint##nbits##_t *) \ 1296 (datag + y*glinesize); \ 1297 const uint##nbits##_t *bsrc = (const uint##nbits##_t *) \ 1298 (datab + y*blinesize); \ 1299 const uint##nbits##_t *rsrc = (const uint##nbits##_t *) \ 1300 (datar + y*rlinesize); \ 1301 struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \ 1302 vec->r = gsrc[x] / (float)((1<<(depth)) - 1); \ 1303 vec->g = bsrc[x] / (float)((1<<(depth)) - 1); \ 1304 vec->b = rsrc[x] / (float)((1<<(depth)) - 1); \ 1314 switch (lut3d->clut_bits) {
1315 case 8: LOAD_CLUT_PLANAR(8, 8);
break;
1316 case 9: LOAD_CLUT_PLANAR(16, 9);
break;
1317 case 10: LOAD_CLUT_PLANAR(16, 10);
break;
1318 case 12: LOAD_CLUT_PLANAR(16, 12);
break;
1319 case 14: LOAD_CLUT_PLANAR(16, 14);
break;
1320 case 16: LOAD_CLUT_PLANAR(16, 16);
break;
1329 const int glinesize = frame->
linesize[0];
1330 const int blinesize = frame->
linesize[1];
1331 const int rlinesize = frame->
linesize[2];
1332 const int w = lut3d->clut_width;
1334 const int level2 = lut3d->
lutsize2;
1336 int i, j, k, x = 0, y = 0;
1338 for (k = 0; k <
level; k++) {
1339 for (j = 0; j <
level; j++) {
1340 for (i = 0; i <
level; i++) {
1341 const float *
gsrc = (
const float *)(datag + y*glinesize);
1342 const float *
bsrc = (
const float *)(datab + y*blinesize);
1343 const float *
rsrc = (
const float *)(datar + y*rlinesize);
1344 struct rgbvec *vec = &lut3d->
lut[i * level2 + j * level + k];
1396 if (inlink->
w > inlink->
h)
1398 "Hald CLUT will be ignored\n", inlink->
w - inlink->
h);
1399 else if (inlink->
w < inlink->
h)
1401 "Hald CLUT will be ignored\n", inlink->
h - inlink->
w);
1402 lut3d->clut_width = w = h =
FFMIN(inlink->
w, inlink->
h);
1404 for (level = 1; level*level*level <
w; level++);
1405 size = level*level*
level;
1413 const int max_clut_level = sqrt(
MAX_LEVEL);
1414 const int max_clut_size = max_clut_level*max_clut_level*max_clut_level;
1416 "(maximum level is %d, or %dx%d CLUT)\n",
1417 max_clut_level, max_clut_size, max_clut_size);
1437 if (lut3d->clut_float)
1438 update_clut_float(ctx->
priv, second);
1439 else if (lut3d->clut_planar)
1440 update_clut_planar(ctx->
priv, second);
1442 update_clut_packed(ctx->
priv, second);
1451 lut3d->fs.on_event = update_apply_clut;
1462 static const AVOption haldclut_options[] = {
1476 .config_props = config_clut,
1494 .preinit = haldclut_framesync_preinit,
1495 .
init = haldclut_init,
1496 .
uninit = haldclut_uninit,
1499 .
inputs = haldclut_inputs,
1501 .priv_class = &haldclut_class,
1506 #if CONFIG_LUT1D_FILTER 1508 enum interp_1d_mode {
1509 INTERPOLATE_1D_NEAREST,
1510 INTERPOLATE_1D_LINEAR,
1511 INTERPOLATE_1D_CUBIC,
1512 INTERPOLATE_1D_COSINE,
1513 INTERPOLATE_1D_SPLINE,
1517 #define MAX_1D_LEVEL 65536 1519 typedef struct LUT1DContext {
1526 float lut[3][MAX_1D_LEVEL];
1532 #define OFFSET(x) offsetof(LUT1DContext, x) 1534 static void set_identity_matrix_1d(LUT1DContext *lut1d,
int size)
1536 const float c = 1. / (size - 1);
1539 lut1d->lutsize =
size;
1540 for (i = 0; i <
size; i++) {
1541 lut1d->lut[0][
i] = i *
c;
1542 lut1d->lut[1][
i] = i *
c;
1543 lut1d->lut[2][
i] = i *
c;
1549 LUT1DContext *lut1d = ctx->
priv;
1551 float in_min[3] = {0.0, 0.0, 0.0};
1552 float in_max[3] = {1.0, 1.0, 1.0};
1553 float out_min[3] = {0.0, 0.0, 0.0};
1554 float out_max[3] = {1.0, 1.0, 1.0};
1555 int inside_metadata = 0,
size;
1558 if (strncmp(line,
"CSPLUTV100", 10)) {
1564 if (strncmp(line,
"1D", 2)) {
1572 if (!strncmp(line,
"BEGIN METADATA", 14)) {
1573 inside_metadata = 1;
1576 if (!strncmp(line,
"END METADATA", 12)) {
1577 inside_metadata = 0;
1580 if (inside_metadata == 0) {
1581 for (
int i = 0;
i < 3;
i++) {
1582 int npoints = strtol(line,
NULL, 0);
1590 if (
av_sscanf(line,
"%f %f", &in_min[
i], &in_max[i]) != 2)
1593 if (
av_sscanf(line,
"%f %f", &out_min[i], &out_max[i]) != 2)
1598 size = strtol(line,
NULL, 0);
1605 lut1d->lutsize =
size;
1607 for (
int i = 0;
i <
size;
i++) {
1609 if (
av_sscanf(line,
"%f %f %f", &lut1d->lut[0][
i], &lut1d->lut[1][
i], &lut1d->lut[2][
i]) != 3)
1611 lut1d->lut[0][
i] *= out_max[0] - out_min[0];
1612 lut1d->lut[1][
i] *= out_max[1] - out_min[1];
1613 lut1d->lut[2][
i] *= out_max[2] - out_min[2];
1620 lut1d->scale.r = av_clipf(1. / (in_max[0] - in_min[0]), 0.f, 1.f);
1621 lut1d->scale.g = av_clipf(1. / (in_max[1] - in_min[1]), 0.f, 1.f);
1622 lut1d->scale.b = av_clipf(1. / (in_max[2] - in_min[2]), 0.f, 1.f);
1629 LUT1DContext *lut1d = ctx->
priv;
1631 float min[3] = {0.0, 0.0, 0.0};
1632 float max[3] = {1.0, 1.0, 1.0};
1634 while (fgets(line,
sizeof(line), f)) {
1635 if (!strncmp(line,
"LUT_1D_SIZE", 11)) {
1636 const int size = strtol(line + 12,
NULL, 0);
1643 lut1d->lutsize =
size;
1644 for (i = 0; i <
size; i++) {
1648 if (!strncmp(line,
"DOMAIN_", 7)) {
1650 if (!strncmp(line + 7,
"MIN ", 4)) vals =
min;
1651 else if (!strncmp(line + 7,
"MAX ", 4)) vals =
max;
1654 av_sscanf(line + 11,
"%f %f %f", vals, vals + 1, vals + 2);
1656 min[0], min[1], min[2], max[0], max[1], max[2]);
1658 }
else if (!strncmp(line,
"LUT_1D_INPUT_RANGE ", 19)) {
1659 av_sscanf(line + 19,
"%f %f", min, max);
1660 min[1] = min[2] = min[0];
1661 max[1] = max[2] = max[0];
1663 }
else if (!strncmp(line,
"TITLE", 5)) {
1667 if (
av_sscanf(line,
"%f %f %f", &lut1d->lut[0][i], &lut1d->lut[1][i], &lut1d->lut[2][i]) != 3)
1674 lut1d->scale.r = av_clipf(1. / (max[0] - min[0]), 0.f, 1.f);
1675 lut1d->scale.g = av_clipf(1. / (max[1] - min[1]), 0.f, 1.f);
1676 lut1d->scale.b = av_clipf(1. / (max[2] - min[2]), 0.f, 1.f);
1681 static const AVOption lut1d_options[] = {
1684 {
"nearest",
"use values from the nearest defined points", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_NEAREST}, INT_MIN, INT_MAX,
FLAGS,
"interp_mode" },
1685 {
"linear",
"use values from the linear interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_LINEAR}, INT_MIN, INT_MAX,
FLAGS,
"interp_mode" },
1686 {
"cosine",
"use values from the cosine interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_COSINE}, INT_MIN, INT_MAX,
FLAGS,
"interp_mode" },
1687 {
"cubic",
"use values from the cubic interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_CUBIC}, INT_MIN, INT_MAX,
FLAGS,
"interp_mode" },
1688 {
"spline",
"use values from the spline interpolation", 0,
AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_SPLINE}, INT_MIN, INT_MAX,
FLAGS,
"interp_mode" },
1694 static inline float interp_1d_nearest(
const LUT1DContext *lut1d,
1695 int idx,
const float s)
1697 return lut1d->lut[idx][
NEAR(s)];
1700 #define NEXT1D(x) (FFMIN((int)(x) + 1, lut1d->lutsize - 1)) 1702 static inline float interp_1d_linear(
const LUT1DContext *lut1d,
1703 int idx,
const float s)
1705 const int prev =
PREV(s);
1706 const int next = NEXT1D(s);
1707 const float d = s - prev;
1708 const float p = lut1d->lut[idx][prev];
1709 const float n = lut1d->lut[idx][next];
1711 return lerpf(p, n, d);
1714 static inline float interp_1d_cosine(
const LUT1DContext *lut1d,
1715 int idx,
const float s)
1717 const int prev =
PREV(s);
1718 const int next = NEXT1D(s);
1719 const float d = s - prev;
1720 const float p = lut1d->lut[idx][prev];
1721 const float n = lut1d->lut[idx][next];
1722 const float m = (1.f -
cosf(d *
M_PI)) * .5f;
1724 return lerpf(p, n, m);
1727 static inline float interp_1d_cubic(
const LUT1DContext *lut1d,
1728 int idx,
const float s)
1730 const int prev =
PREV(s);
1731 const int next = NEXT1D(s);
1732 const float mu = s - prev;
1735 float y0 = lut1d->lut[idx][
FFMAX(prev - 1, 0)];
1736 float y1 = lut1d->lut[idx][prev];
1737 float y2 = lut1d->lut[idx][next];
1738 float y3 = lut1d->lut[idx][
FFMIN(next + 1, lut1d->lutsize - 1)];
1742 a0 = y3 - y2 - y0 + y1;
1747 return a0 * mu * mu2 + a1 * mu2 + a2 * mu +
a3;
1750 static inline float interp_1d_spline(
const LUT1DContext *lut1d,
1751 int idx,
const float s)
1753 const int prev =
PREV(s);
1754 const int next = NEXT1D(s);
1755 const float x = s - prev;
1756 float c0,
c1,
c2, c3;
1758 float y0 = lut1d->lut[idx][
FFMAX(prev - 1, 0)];
1759 float y1 = lut1d->lut[idx][prev];
1760 float y2 = lut1d->lut[idx][next];
1761 float y3 = lut1d->lut[idx][
FFMIN(next + 1, lut1d->lutsize - 1)];
1764 c1 = .5f * (y2 - y0);
1765 c2 = y0 - 2.5f * y1 + 2.f * y2 - .5f * y3;
1766 c3 = .5f * (y3 - y0) + 1.5f * (y1 - y2);
1768 return ((c3 * x + c2) * x +
c1) * x + c0;
1771 #define DEFINE_INTERP_FUNC_PLANAR_1D(name, nbits, depth) \ 1772 static int interp_1d_##nbits##_##name##_p##depth(AVFilterContext *ctx, \ 1773 void *arg, int jobnr, \ 1777 const LUT1DContext *lut1d = ctx->priv; \ 1778 const ThreadData *td = arg; \ 1779 const AVFrame *in = td->in; \ 1780 const AVFrame *out = td->out; \ 1781 const int direct = out == in; \ 1782 const int slice_start = (in->height * jobnr ) / nb_jobs; \ 1783 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \ 1784 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \ 1785 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \ 1786 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \ 1787 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \ 1788 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \ 1789 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \ 1790 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \ 1791 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \ 1792 const float factor = (1 << depth) - 1; \ 1793 const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1); \ 1794 const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1); \ 1795 const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1); \ 1797 for (y = slice_start; y < slice_end; y++) { \ 1798 uint##nbits##_t *dstg = (uint##nbits##_t *)grow; \ 1799 uint##nbits##_t *dstb = (uint##nbits##_t *)brow; \ 1800 uint##nbits##_t *dstr = (uint##nbits##_t *)rrow; \ 1801 uint##nbits##_t *dsta = (uint##nbits##_t *)arow; \ 1802 const uint##nbits##_t *srcg = (const uint##nbits##_t *)srcgrow; \ 1803 const uint##nbits##_t *srcb = (const uint##nbits##_t *)srcbrow; \ 1804 const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow; \ 1805 const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow; \ 1806 for (x = 0; x < in->width; x++) { \ 1807 float r = srcr[x] * scale_r; \ 1808 float g = srcg[x] * scale_g; \ 1809 float b = srcb[x] * scale_b; \ 1810 r = interp_1d_##name(lut1d, 0, r); \ 1811 g = interp_1d_##name(lut1d, 1, g); \ 1812 b = interp_1d_##name(lut1d, 2, b); \ 1813 dstr[x] = av_clip_uintp2(r * factor, depth); \ 1814 dstg[x] = av_clip_uintp2(g * factor, depth); \ 1815 dstb[x] = av_clip_uintp2(b * factor, depth); \ 1816 if (!direct && in->linesize[3]) \ 1817 dsta[x] = srca[x]; \ 1819 grow += out->linesize[0]; \ 1820 brow += out->linesize[1]; \ 1821 rrow += out->linesize[2]; \ 1822 arow += out->linesize[3]; \ 1823 srcgrow += in->linesize[0]; \ 1824 srcbrow += in->linesize[1]; \ 1825 srcrrow += in->linesize[2]; \ 1826 srcarow += in->linesize[3]; \ 1831 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 8, 8)
1832 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 8, 8)
1833 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 8, 8)
1834 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 8, 8)
1835 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 8, 8)
1837 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 9)
1838 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 9)
1839 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 9)
1840 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 9)
1841 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 9)
1843 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 10)
1844 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 10)
1845 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 10)
1846 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 10)
1847 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 10)
1849 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 12)
1850 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 12)
1851 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 12)
1852 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 12)
1853 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 12)
1855 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 14)
1856 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 14)
1857 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 14)
1858 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 14)
1859 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 14)
1861 DEFINE_INTERP_FUNC_PLANAR_1D(nearest, 16, 16)
1862 DEFINE_INTERP_FUNC_PLANAR_1D(
linear, 16, 16)
1863 DEFINE_INTERP_FUNC_PLANAR_1D(cosine, 16, 16)
1864 DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 16)
1865 DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 16)
1867 #define DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(name, depth) \ 1868 static int interp_1d_##name##_pf##depth(AVFilterContext *ctx, \ 1869 void *arg, int jobnr, \ 1873 const LUT1DContext *lut1d = ctx->priv; \ 1874 const ThreadData *td = arg; \ 1875 const AVFrame *in = td->in; \ 1876 const AVFrame *out = td->out; \ 1877 const int direct = out == in; \ 1878 const int slice_start = (in->height * jobnr ) / nb_jobs; \ 1879 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \ 1880 uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \ 1881 uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \ 1882 uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \ 1883 uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \ 1884 const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \ 1885 const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \ 1886 const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \ 1887 const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \ 1888 const float lutsize = lut1d->lutsize - 1; \ 1889 const float scale_r = lut1d->scale.r * lutsize; \ 1890 const float scale_g = lut1d->scale.g * lutsize; \ 1891 const float scale_b = lut1d->scale.b * lutsize; \ 1893 for (y = slice_start; y < slice_end; y++) { \ 1894 float *dstg = (float *)grow; \ 1895 float *dstb = (float *)brow; \ 1896 float *dstr = (float *)rrow; \ 1897 float *dsta = (float *)arow; \ 1898 const float *srcg = (const float *)srcgrow; \ 1899 const float *srcb = (const float *)srcbrow; \ 1900 const float *srcr = (const float *)srcrrow; \ 1901 const float *srca = (const float *)srcarow; \ 1902 for (x = 0; x < in->width; x++) { \ 1903 float r = av_clipf(sanitizef(srcr[x]) * scale_r, 0.0f, lutsize); \ 1904 float g = av_clipf(sanitizef(srcg[x]) * scale_g, 0.0f, lutsize); \ 1905 float b = av_clipf(sanitizef(srcb[x]) * scale_b, 0.0f, lutsize); \ 1906 r = interp_1d_##name(lut1d, 0, r); \ 1907 g = interp_1d_##name(lut1d, 1, g); \ 1908 b = interp_1d_##name(lut1d, 2, b); \ 1912 if (!direct && in->linesize[3]) \ 1913 dsta[x] = srca[x]; \ 1915 grow += out->linesize[0]; \ 1916 brow += out->linesize[1]; \ 1917 rrow += out->linesize[2]; \ 1918 arow += out->linesize[3]; \ 1919 srcgrow += in->linesize[0]; \ 1920 srcbrow += in->linesize[1]; \ 1921 srcrrow += in->linesize[2]; \ 1922 srcarow += in->linesize[3]; \ 1927 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(nearest, 32)
1928 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(
linear, 32)
1929 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cosine, 32)
1930 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cubic, 32)
1931 DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(spline, 32)
1933 #define DEFINE_INTERP_FUNC_1D(name, nbits) \ 1934 static int interp_1d_##nbits##_##name(AVFilterContext *ctx, void *arg, \ 1935 int jobnr, int nb_jobs) \ 1938 const LUT1DContext *lut1d = ctx->priv; \ 1939 const ThreadData *td = arg; \ 1940 const AVFrame *in = td->in; \ 1941 const AVFrame *out = td->out; \ 1942 const int direct = out == in; \ 1943 const int step = lut1d->step; \ 1944 const uint8_t r = lut1d->rgba_map[R]; \ 1945 const uint8_t g = lut1d->rgba_map[G]; \ 1946 const uint8_t b = lut1d->rgba_map[B]; \ 1947 const uint8_t a = lut1d->rgba_map[A]; \ 1948 const int slice_start = (in->height * jobnr ) / nb_jobs; \ 1949 const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \ 1950 uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \ 1951 const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \ 1952 const float factor = (1 << nbits) - 1; \ 1953 const float scale_r = (lut1d->scale.r / factor) * (lut1d->lutsize - 1); \ 1954 const float scale_g = (lut1d->scale.g / factor) * (lut1d->lutsize - 1); \ 1955 const float scale_b = (lut1d->scale.b / factor) * (lut1d->lutsize - 1); \ 1957 for (y = slice_start; y < slice_end; y++) { \ 1958 uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \ 1959 const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \ 1960 for (x = 0; x < in->width * step; x += step) { \ 1961 float rr = src[x + r] * scale_r; \ 1962 float gg = src[x + g] * scale_g; \ 1963 float bb = src[x + b] * scale_b; \ 1964 rr = interp_1d_##name(lut1d, 0, rr); \ 1965 gg = interp_1d_##name(lut1d, 1, gg); \ 1966 bb = interp_1d_##name(lut1d, 2, bb); \ 1967 dst[x + r] = av_clip_uint##nbits(rr * factor); \ 1968 dst[x + g] = av_clip_uint##nbits(gg * factor); \ 1969 dst[x + b] = av_clip_uint##nbits(bb * factor); \ 1970 if (!direct && step == 4) \ 1971 dst[x + a] = src[x + a]; \ 1973 dstrow += out->linesize[0]; \ 1974 srcrow += in ->linesize[0]; \ 1979 DEFINE_INTERP_FUNC_1D(nearest, 8)
1980 DEFINE_INTERP_FUNC_1D(
linear, 8)
1981 DEFINE_INTERP_FUNC_1D(cosine, 8)
1982 DEFINE_INTERP_FUNC_1D(cubic, 8)
1983 DEFINE_INTERP_FUNC_1D(spline, 8)
1985 DEFINE_INTERP_FUNC_1D(nearest, 16)
1986 DEFINE_INTERP_FUNC_1D(
linear, 16)
1987 DEFINE_INTERP_FUNC_1D(cosine, 16)
1988 DEFINE_INTERP_FUNC_1D(cubic, 16)
1989 DEFINE_INTERP_FUNC_1D(spline, 16)
1993 int depth, is16bit, isfloat,
planar;
1994 LUT1DContext *lut1d = inlink->
dst->
priv;
2004 #define SET_FUNC_1D(name) do { \ 2005 if (planar && !isfloat) { \ 2007 case 8: lut1d->interp = interp_1d_8_##name##_p8; break; \ 2008 case 9: lut1d->interp = interp_1d_16_##name##_p9; break; \ 2009 case 10: lut1d->interp = interp_1d_16_##name##_p10; break; \ 2010 case 12: lut1d->interp = interp_1d_16_##name##_p12; break; \ 2011 case 14: lut1d->interp = interp_1d_16_##name##_p14; break; \ 2012 case 16: lut1d->interp = interp_1d_16_##name##_p16; break; \ 2014 } else if (isfloat) { lut1d->interp = interp_1d_##name##_pf32; \ 2015 } else if (is16bit) { lut1d->interp = interp_1d_16_##name; \ 2016 } else { lut1d->interp = interp_1d_8_##name; } \ 2019 switch (lut1d->interpolation) {
2020 case INTERPOLATE_1D_NEAREST: SET_FUNC_1D(nearest);
break;
2021 case INTERPOLATE_1D_LINEAR: SET_FUNC_1D(
linear);
break;
2022 case INTERPOLATE_1D_COSINE: SET_FUNC_1D(cosine);
break;
2023 case INTERPOLATE_1D_CUBIC: SET_FUNC_1D(cubic);
break;
2024 case INTERPOLATE_1D_SPLINE: SET_FUNC_1D(spline);
break;
2037 LUT1DContext *lut1d = ctx->
priv;
2039 lut1d->scale.r = lut1d->scale.g = lut1d->scale.b = 1.f;
2042 set_identity_matrix_1d(lut1d, 32);
2053 ext = strrchr(lut1d->file,
'.');
2062 ret = parse_cube_1d(ctx, f);
2064 ret = parse_cinespace_1d(ctx, f);
2070 if (!ret && !lut1d->lutsize) {
2083 LUT1DContext *lut1d = ctx->
priv;
2122 .filter_frame = filter_frame_1d,
2123 .config_props = config_input_1d,
2139 .priv_size =
sizeof(LUT1DContext),
2144 .priv_class = &lut1d_class,
static float prelut_interp_1d_linear(const Lut3DPreLut *prelut, int idx, const float s)
#define FRAMESYNC_DEFINE_CLASS(name, context, field)
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
static int config_input(AVFilterLink *inlink)
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
This structure describes decoded (raw) audio or video data.
static struct rgbvec interp_trilinear(const LUT3DContext *lut3d, const struct rgbvec *s)
Interpolate using the 8 vertices of a cube.
ptrdiff_t const GLvoid * data
#define AV_PIX_FMT_GBRAP10
static int linear(InterplayACMContext *s, unsigned ind, unsigned col)
#define AV_LOG_WARNING
Something somehow does not look correct.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Main libavfilter public API header.
packed RGB 8:8:8, 24bpp, RGBRGB...
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
static av_cold int init(AVCodecContext *avctx)
#define AV_PIX_FMT_RGBA64
int h
agreed upon image height
FILE * av_fopen_utf8(const char *path, const char *mode)
Open a file using a UTF-8 filename.
static int skip_line(const char *p)
#define AV_PIX_FMT_GBRP10
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
#define AV_PIX_FMT_BGRA64
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
static int parse_cube(AVFilterContext *ctx, FILE *f)
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
#define NEXT_LINE_OR_GOTO(loop_cond, label)
static int set_identity_matrix(AVFilterContext *ctx, int size)
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
const char * name
Pad name.
AVFilterContext * parent
Parent filter context.
AVFilterLink ** inputs
array of pointers to input links
#define av_assert0(cond)
assert() equivalent, that is always enabled.
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
static float lerpf(float v0, float v1, float f)
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
static av_cold int uninit(AVCodecContext *avctx)
#define fs(width, name, subs,...)
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
filter_frame For filters that do not use the activate() callback
#define AV_PIX_FMT_FLAG_FLOAT
The pixel format contains IEEE-754 floating point values.
static av_cold int end(AVCodecContext *avctx)
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
static int parse_cinespace(AVFilterContext *ctx, FILE *f)
static int allocate_3dlut(AVFilterContext *ctx, int lutsize, int prelut)
A filter pad used for either input or output.
A link between two filters.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
#define DEFINE_INTERP_FUNC(name, nbits)
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
void * priv
private data for use by the filter
int av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc)
Return the number of bits per pixel for the pixel format described by pixdesc, including any padding ...
static struct rgbvec interp_nearest(const LUT3DContext *lut3d, const struct rgbvec *s)
Get the nearest defined point.
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link...
#define AV_PIX_FMT_GBRAP12
simple assert() macros that are a bit more flexible than ISO C assert().
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
#define AV_PIX_FMT_GBRAP16
int av_sscanf(const char *string, const char *format,...)
See libc sscanf manual for more information.
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
#define NEXT_FLOAT_OR_GOTO(value, label)
int w
agreed upon image width
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
#define AV_PIX_FMT_GBRP16
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
static int interpolation(DeclickChannel *c, const double *src, int ar_order, double *acoefficients, int *index, int nb_errors, double *auxiliary, double *interpolated)
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
#define DEFINE_INTERP_FUNC_PLANAR(name, nbits, depth)
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
packed RGB 8:8:8, 24bpp, BGRBGR...
AVFilterContext * src
source filter
#define DEFINE_INTERP_FUNC_PLANAR_FLOAT(name, depth)
#define AV_PIX_FMT_GBRP14
static AVFrame * apply_lut(AVFilterLink *inlink, AVFrame *in)
static const AVFilterPad outputs[]
int format
agreed upon media format
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...
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
static int mix(int c0, int c1)
#define AV_LOG_INFO
Standard information.
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Used for passing data between threads.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
static struct rgbvec lerp(const struct rgbvec *v0, const struct rgbvec *v1, float f)
int interpolation
interp_mode
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
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
Describe the class of an AVClass context structure.
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
const char * name
Filter name.
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will have its filter_frame() c...
static struct rgbvec interp_tetrahedral(const LUT3DContext *lut3d, const struct rgbvec *s)
Tetrahedral interpolation.
AVFilterLink ** outputs
array of pointers to output links
static enum AVPixelFormat pix_fmts[]
#define AV_PIX_FMT_GBRP12
#define flags(name, subs,...)
AVFilterInternal * internal
An opaque struct for libavfilter internal use.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
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
#define AV_PIX_FMT_GBRPF32
#define AV_PIX_FMT_GBRAPF32
planar GBRA 4:4:4:4 32bpp
#define NEXT_LINE(loop_cond)
static int parse_m3d(AVFilterContext *ctx, FILE *f)
static int parse_3dl(AVFilterContext *ctx, FILE *f)
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
avfilter_execute_func * execute
static struct rgbvec apply_prelut(const Lut3DPreLut *prelut, const struct rgbvec *s)
static int parse_dat(AVFilterContext *ctx, FILE *f)
AVFilterContext * dst
dest filter
#define AVFILTER_DEFINE_CLASS(fname)
#define av_malloc_array(a, b)
static int query_formats(AVFilterContext *ctx)
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
int depth
Number of bits in the component.
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
AVPixelFormat
Pixel format.
static double val(void *priv, double ch)
static char * fget_next_word(char *dst, int max, FILE *f)
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
static int nearest_sample_index(float *data, float x, int low, int hi)
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
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 float sanitizef(float f)
static int config_output(AVFilterLink *outlink)
avfilter_action_func * interp