diff mbox series

[FFmpeg-devel,2/2] lavfi/vf_colorspace: Add SMPTE ST 2084 support

Message ID 22244352f670c17aee4d2ba0f97cc894dfa4199b.camel@haerdin.se
State New
Headers show
Series [FFmpeg-devel,1/2] lavfi/vf_colorspace: Add support for 14- and 16-bit YUV | expand

Checks

Context Check Description
andriy/configure_x86 warning Failed to apply patch
yinshiyou/configure_loongarch64 warning Failed to apply patch

Commit Message

Tomas Härdin Feb. 3, 2023, 3:54 p.m. UTC
We need something better for proper tonemap support, but this is at
least useful for getting the HDR discussion going.

/Tomas

Comments

Pierre-Anthony Lemieux Feb. 3, 2023, 4:29 p.m. UTC | #1
On Fri, Feb 3, 2023 at 7:54 AM Tomas Härdin <git@haerdin.se> wrote:
>
> We need something better for proper tonemap support, but this is at
> least useful for getting the HDR discussion going.

Below is a demonstration of two tonemap methods:

https://www.sandflow.com/public/tone-mapping/index.html

>
> /Tomas
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Tomas Härdin Feb. 6, 2023, 9:35 a.m. UTC | #2
fre 2023-02-03 klockan 08:29 -0800 skrev Pierre-Anthony Lemieux:
> On Fri, Feb 3, 2023 at 7:54 AM Tomas Härdin <git@haerdin.se> wrote:
> > 
> > We need something better for proper tonemap support, but this is at
> > least useful for getting the HDR discussion going.
> 
> Below is a demonstration of two tonemap methods:
> 
> https://www.sandflow.com/public/tone-mapping/index.html

Does not work in Firefox. But it does work in Chromium. Looks like it
could be static images only.

Anyway what I feel bears discussion is whether we should add a field to
AVCodecContext like "nits" that says how many nits the max values of
integer pixel formats correspond to, and similarly for float formats
what 1.0 corresponds to. The latter is usually 203 cd/m² but is it
always? The link you posted appears to use 100 cd/m²:

> l_sdr = 100;

/Tomas
Tomas Härdin Feb. 6, 2023, 9:51 a.m. UTC | #3
mån 2023-02-06 klockan 10:35 +0100 skrev Tomas Härdin:
> fre 2023-02-03 klockan 08:29 -0800 skrev Pierre-Anthony Lemieux:
> > On Fri, Feb 3, 2023 at 7:54 AM Tomas Härdin <git@haerdin.se> wrote:
> > > 
> > > We need something better for proper tonemap support, but this is
> > > at
> > > least useful for getting the HDR discussion going.
> > 
> > Below is a demonstration of two tonemap methods:
> > 
> > https://www.sandflow.com/public/tone-mapping/index.html
> 
> Does not work in Firefox. But it does work in Chromium. Looks like it
> could be static images only.
> 
> Anyway what I feel bears discussion is whether we should add a field
> to
> AVCodecContext like "nits" that says how many nits the max values of
> integer pixel formats correspond to, and similarly for float formats
> what 1.0 corresponds to. The latter is usually 203 cd/m² but is it
> always? The link you posted appears to use 100 cd/m²:
> 
> > l_sdr = 100;

Another thing: we probably need a float YUV format

/Tomas
diff mbox series

Patch

From fd7a789fbffdd0f7e41b77a9d70ae0696142c6db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= <git@haerdin.se>
Date: Fri, 3 Feb 2023 14:00:38 +0100
Subject: [PATCH 2/2] lavfi/vf_colorspace: Add SMPTE ST 2084 support

This makes 10000 nits == 65535 in 16-bit,
meaning SDR white is 65535*203/10000 = 1330.
---
 libavfilter/vf_colorspace.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/libavfilter/vf_colorspace.c b/libavfilter/vf_colorspace.c
index 1e1ab5fb34..081c1c9d0e 100644
--- a/libavfilter/vf_colorspace.c
+++ b/libavfilter/vf_colorspace.c
@@ -173,6 +173,7 @@  static const struct TransferCharacteristics transfer_characteristics[AVCOL_TRC_N
     [AVCOL_TRC_IEC61966_2_4] = { 1.099, 0.018, 0.45, 4.5 },
     [AVCOL_TRC_BT2020_10] = { 1.099,  0.018,  0.45, 4.5 },
     [AVCOL_TRC_BT2020_12] = { 1.0993, 0.0181, 0.45, 4.5 },
+    [AVCOL_TRC_SMPTE2084] = { 1.0,    0,      0,    0 }, // fake entry, actual TRC uses entirely separate formula
 };
 
 static const struct TransferCharacteristics *
@@ -197,6 +198,8 @@  static int fill_gamma_table(ColorSpaceContext *s)
     double in_ialpha = 1.0 / in_alpha, in_igamma = 1.0 / in_gamma, in_idelta = 1.0 / in_delta;
     double out_alpha = s->out_txchr->alpha, out_beta = s->out_txchr->beta;
     double out_gamma = s->out_txchr->gamma, out_delta = s->out_txchr->delta;
+    double m1 = 1305.0/8192, m2 = 2523.0/32, c2 = 2413.0/128, c3 = 2392.0/128, c1 = c3 - c2 + 1;
+    double im1 = 1.0 / m1, im2 = 1.0 / m2;
 
     s->lin_lut = av_malloc(sizeof(*s->lin_lut) * 32768 * 2);
     if (!s->lin_lut)
@@ -206,7 +209,15 @@  static int fill_gamma_table(ColorSpaceContext *s)
         double v = (n - 2048.0) / 28672.0, d, l;
 
         // delinearize
-        if (v <= -out_beta) {
+        if (s->out_trc == AVCOL_TRC_SMPTE2084) {
+            // see BT.2100-2
+            if (v >= 0) {
+                double vm1 = pow(v, m1);
+                d = pow((c1 + c2 * vm1)/(1 + c3 * vm1), m2);
+            } else {
+                d = 0;
+            }
+        } else if (v <= -out_beta) {
             d = -out_alpha * pow(-v, out_gamma) + (out_alpha - 1.0);
         } else if (v < out_beta) {
             d = out_delta * v;
@@ -216,7 +227,16 @@  static int fill_gamma_table(ColorSpaceContext *s)
         s->delin_lut[n] = av_clip_int16(lrint(d * 28672.0));
 
         // linearize
-        if (v <= -in_beta * in_delta) {
+        if (s->in_trc == AVCOL_TRC_SMPTE2084) {
+            // see BT.2100-2
+            if (v >= 0) {
+                double vim2 = pow(v, im2);
+                // note that [0,1] here corresponds to [0,100] in SDR
+                l = pow((vim2 - c1 > 0 ? vim2 - c1 : 0) / (c2 - c3 * vim2), im1);
+            } else {
+                l = 0;
+            }
+        } else if (v <= -in_beta * in_delta) {
             l = -pow((1.0 - in_alpha - v) * in_ialpha, in_igamma);
         } else if (v < in_beta * in_delta) {
             l = v * in_idelta;
@@ -956,6 +976,7 @@  static const AVOption colorspace_options[] = {
     ENUM("iec61966-2-4", AVCOL_TRC_IEC61966_2_4, "trc"),
     ENUM("bt2020-10",    AVCOL_TRC_BT2020_10,    "trc"),
     ENUM("bt2020-12",    AVCOL_TRC_BT2020_12,    "trc"),
+    ENUM("smpte2084",    AVCOL_TRC_SMPTE2084,    "trc"),
 
     { "format",   "Output pixel format",
       OFFSET(user_format), AV_OPT_TYPE_INT,  { .i64 = AV_PIX_FMT_NONE },
-- 
2.30.2