|
30 | 30 | #include "libswscale/swscale.h"
|
31 | 31 | #include "libswscale/utils.h"
|
32 | 32 |
|
| 33 | +#include "cms.h" |
| 34 | +#include "lut3d.h" |
33 | 35 | #include "swscale_internal.h"
|
34 | 36 | #include "graph.h"
|
35 | 37 |
|
@@ -463,18 +465,107 @@ static int add_legacy_sws_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
|
463 | 465 | return 0;
|
464 | 466 | }
|
465 | 467 |
|
| 468 | +/************************** |
| 469 | + * Gamut and tone mapping * |
| 470 | + **************************/ |
| 471 | + |
| 472 | +static void free_lut3d(void *priv) |
| 473 | +{ |
| 474 | + SwsLut3D *lut = priv; |
| 475 | + sws_lut3d_free(&lut); |
| 476 | +} |
| 477 | + |
| 478 | +static void run_lut3d(const SwsImg *out_base, const SwsImg *in_base, |
| 479 | + int y, int h, const SwsPass *pass) |
| 480 | +{ |
| 481 | + SwsLut3D *lut = pass->priv; |
| 482 | + const SwsImg in = shift_img(in_base, y); |
| 483 | + const SwsImg out = shift_img(out_base, y); |
| 484 | + |
| 485 | + sws_lut3d_apply(lut, in.data[0], in.linesize[0], out.data[0], |
| 486 | + out.linesize[0], pass->width, h); |
| 487 | +} |
| 488 | + |
| 489 | +static int adapt_colors(SwsGraph *graph, SwsFormat src, SwsFormat dst, |
| 490 | + SwsPass *input, SwsPass **output) |
| 491 | +{ |
| 492 | + enum AVPixelFormat fmt_in, fmt_out; |
| 493 | + SwsColorMap map = {0}; |
| 494 | + SwsLut3D *lut; |
| 495 | + SwsPass *pass; |
| 496 | + int ret; |
| 497 | + |
| 498 | + /** |
| 499 | + * Grayspace does not really have primaries, so just force the use of |
| 500 | + * the equivalent other primary set to avoid a conversion. Technically, |
| 501 | + * this does affect the weights used for the Grayscale conversion, but |
| 502 | + * in practise, that should give the expected results more often than not. |
| 503 | + */ |
| 504 | + if (isGray(dst.format)) { |
| 505 | + dst.color = src.color; |
| 506 | + } else if (isGray(src.format)) { |
| 507 | + src.color = dst.color; |
| 508 | + } |
| 509 | + |
| 510 | + /* Fully infer color spaces before color mapping logic */ |
| 511 | + graph->incomplete |= ff_infer_colors(&src.color, &dst.color); |
| 512 | + |
| 513 | + map.intent = graph->ctx->intent; |
| 514 | + map.src = src.color; |
| 515 | + map.dst = dst.color; |
| 516 | + |
| 517 | + if (sws_color_map_noop(&map)) |
| 518 | + return 0; |
| 519 | + |
| 520 | + lut = sws_lut3d_alloc(); |
| 521 | + if (!lut) |
| 522 | + return AVERROR(ENOMEM); |
| 523 | + |
| 524 | + fmt_in = sws_lut3d_pick_pixfmt(src, 0); |
| 525 | + fmt_out = sws_lut3d_pick_pixfmt(dst, 1); |
| 526 | + if (fmt_in != src.format) { |
| 527 | + SwsFormat tmp = src; |
| 528 | + tmp.format = fmt_in; |
| 529 | + ret = add_legacy_sws_pass(graph, src, tmp, input, &input); |
| 530 | + if (ret < 0) |
| 531 | + return ret; |
| 532 | + } |
| 533 | + |
| 534 | + ret = sws_lut3d_generate(lut, fmt_in, fmt_out, &map); |
| 535 | + if (ret < 0) { |
| 536 | + sws_lut3d_free(&lut); |
| 537 | + return ret; |
| 538 | + } |
| 539 | + |
| 540 | + pass = pass_add(graph, lut, fmt_out, src.width, src.height, |
| 541 | + input, 1, run_lut3d); |
| 542 | + if (!pass) { |
| 543 | + sws_lut3d_free(&lut); |
| 544 | + return AVERROR(ENOMEM); |
| 545 | + } |
| 546 | + pass->free = free_lut3d; |
| 547 | + |
| 548 | + *output = pass; |
| 549 | + return 0; |
| 550 | +} |
466 | 551 |
|
467 | 552 | /***************************************
|
468 | 553 | * Main filter graph construction code *
|
469 | 554 | ***************************************/
|
470 | 555 |
|
471 | 556 | static int init_passes(SwsGraph *graph)
|
472 | 557 | {
|
473 |
| - const SwsFormat src = graph->src; |
474 |
| - const SwsFormat dst = graph->dst; |
| 558 | + SwsFormat src = graph->src; |
| 559 | + SwsFormat dst = graph->dst; |
475 | 560 | SwsPass *pass = NULL; /* read from main input image */
|
476 | 561 | int ret;
|
477 | 562 |
|
| 563 | + ret = adapt_colors(graph, src, dst, pass, &pass); |
| 564 | + if (ret < 0) |
| 565 | + return ret; |
| 566 | + src.format = pass ? pass->format : src.format; |
| 567 | + src.color = dst.color; |
| 568 | + |
478 | 569 | if (!ff_fmt_equal(&src, &dst)) {
|
479 | 570 | ret = add_legacy_sws_pass(graph, src, dst, pass, &pass);
|
480 | 571 | if (ret < 0)
|
|
0 commit comments