diff mbox series

[FFmpeg-devel] avcodec/exr: add cineon lin2log trc

Message ID 20200305215039.79647-1-mindmark@gmail.com
State Superseded
Headers show
Series [FFmpeg-devel] avcodec/exr: add cineon lin2log trc | expand

Checks

Context Check Description
andriy/ffmpeg-patchwork fail Make fate failed

Commit Message

Mark Reid March 5, 2020, 9:50 p.m. UTC
From: Mark Reid <mindmark@gmail.com>

Hi,
The following patch adds a cineon lin2log color transfer characteristic to exr.
The purpose of this patch is to allow preserving of the dynamic range of an
exr file when converting to DPX or when using video filter such as 3d luts.
I wasn't sure if adding it to the AVColorTransferCharacteristic enum was the
correct approach as this might be a exr specific thing but I figured it was a good starting point.

---
 libavcodec/exr.c        |  2 ++
 libavutil/color_utils.c | 14 ++++++++++++++
 libavutil/pixfmt.h      |  1 +
 3 files changed, 17 insertions(+)

--
2.21.0

Comments

Paul B Mahol March 6, 2020, 9:40 a.m. UTC | #1
On 3/5/20, mindmark@gmail.com <mindmark@gmail.com> wrote:
> From: Mark Reid <mindmark@gmail.com>
>
> Hi,
> The following patch adds a cineon lin2log color transfer characteristic to
> exr.
> The purpose of this patch is to allow preserving of the dynamic range of an
> exr file when converting to DPX or when using video filter such as 3d luts.
> I wasn't sure if adding it to the AVColorTransferCharacteristic enum was the
> correct approach as this might be a exr specific thing but I figured it was
> a good starting point.
>
> ---
>  libavcodec/exr.c        |  2 ++
>  libavutil/color_utils.c | 14 ++++++++++++++
>  libavutil/pixfmt.h      |  1 +
>  3 files changed, 17 insertions(+)
>
> diff --git a/libavcodec/exr.c b/libavcodec/exr.c
> index 1db30a1ae0..f2900a7921 100644
> --- a/libavcodec/exr.c
> +++ b/libavcodec/exr.c
> @@ -1938,6 +1938,8 @@ static const AVOption options[] = {
>          AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTEST2084 },  INT_MIN,
> INT_MAX, VD, "apply_trc_type"},
>      { "smpte428_1",   "SMPTE ST 428-1",   0,
>          AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTEST428_1 }, INT_MIN,
> INT_MAX, VD, "apply_trc_type"},
> +    { "lin2log",      "Default Cineon/DPX log",   0,
> +        AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_CINE_LIN2LOG }, INT_MIN,
> INT_MAX, VD, "apply_trc_type"},
>
>      { NULL },
>  };
> diff --git a/libavutil/color_utils.c b/libavutil/color_utils.c
> index eb8bc7b5fc..e33c019d4a 100644
> --- a/libavutil/color_utils.c
> +++ b/libavutil/color_utils.c
> @@ -167,6 +167,16 @@ static double avpriv_trc_arib_std_b67(double Lc) {
>          (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c);
>  }
>
> +static double avpriv_trc_cine_lin2log(double Lc) {
> +    const double blackpoint =  95.0;
> +    const double whitepoint = 685.0;
> +    const double gamma      =   0.6;
> +    const double offset =  pow(10, (blackpoint - whitepoint) * 0.002 /
> gamma);
> +    const double gain   = 1.0 / (1.0 - offset);
> +
> +    return (log10((Lc + offset) / gain) / (0.002 / gamma) + whitepoint ) /
> 1023.0;
> +}
> +
>  avpriv_trc_function avpriv_get_trc_function_from_trc(enum
> AVColorTransferCharacteristic trc)
>  {
>      avpriv_trc_function func = NULL;
> @@ -225,6 +235,10 @@ avpriv_trc_function
> avpriv_get_trc_function_from_trc(enum AVColorTransferCharact
>              func = avpriv_trc_arib_std_b67;
>              break;
>
> +        case AVCOL_TRC_CINE_LIN2LOG:
> +            func = avpriv_trc_cine_lin2log;
> +            break;
> +
>          case AVCOL_TRC_RESERVED0:
>          case AVCOL_TRC_UNSPECIFIED:
>          case AVCOL_TRC_RESERVED:
> diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
> index 1c625cfc8a..1f3f9988d7 100644
> --- a/libavutil/pixfmt.h
> +++ b/libavutil/pixfmt.h
> @@ -499,6 +499,7 @@ enum AVColorTransferCharacteristic {
>      AVCOL_TRC_SMPTE428     = 17, ///< SMPTE ST 428-1
>      AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428,
>      AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid
> log-gamma"
> +    AVCOL_TRC_CINE_LIN2LOG = 19, ///< Default Cineon/DPX linear to log 1D
> curve

I do not think this one is correct.

>      AVCOL_TRC_NB                 ///< Not part of ABI
>  };
>
> --
> 2.21.0
> _______________________________________________
> 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".
Hendrik Leppkes March 6, 2020, 9:49 a.m. UTC | #2
On Fri, Mar 6, 2020 at 12:25 AM <mindmark@gmail.com> wrote:
>
> From: Mark Reid <mindmark@gmail.com>
>
> Hi,
> The following patch adds a cineon lin2log color transfer characteristic to exr.
> The purpose of this patch is to allow preserving of the dynamic range of an
> exr file when converting to DPX or when using video filter such as 3d luts.
> I wasn't sure if adding it to the AVColorTransferCharacteristic enum was the
> correct approach as this might be a exr specific thing but I figured it was a good starting point.
>
> ---
>  libavcodec/exr.c        |  2 ++
>  libavutil/color_utils.c | 14 ++++++++++++++
>  libavutil/pixfmt.h      |  1 +
>  3 files changed, 17 insertions(+)
>
> diff --git a/libavcodec/exr.c b/libavcodec/exr.c
> index 1db30a1ae0..f2900a7921 100644
> --- a/libavcodec/exr.c
> +++ b/libavcodec/exr.c
> @@ -1938,6 +1938,8 @@ static const AVOption options[] = {
>          AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTEST2084 },  INT_MIN, INT_MAX, VD, "apply_trc_type"},
>      { "smpte428_1",   "SMPTE ST 428-1",   0,
>          AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTEST428_1 }, INT_MIN, INT_MAX, VD, "apply_trc_type"},
> +    { "lin2log",      "Default Cineon/DPX log",   0,
> +        AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_CINE_LIN2LOG }, INT_MIN, INT_MAX, VD, "apply_trc_type"},
>
>      { NULL },
>  };
> diff --git a/libavutil/color_utils.c b/libavutil/color_utils.c
> index eb8bc7b5fc..e33c019d4a 100644
> --- a/libavutil/color_utils.c
> +++ b/libavutil/color_utils.c
> @@ -167,6 +167,16 @@ static double avpriv_trc_arib_std_b67(double Lc) {
>          (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c);
>  }
>
> +static double avpriv_trc_cine_lin2log(double Lc) {
> +    const double blackpoint =  95.0;
> +    const double whitepoint = 685.0;
> +    const double gamma      =   0.6;
> +    const double offset =  pow(10, (blackpoint - whitepoint) * 0.002 / gamma);
> +    const double gain   = 1.0 / (1.0 - offset);
> +
> +    return (log10((Lc + offset) / gain) / (0.002 / gamma) + whitepoint ) / 1023.0;
> +}
> +
>  avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc)
>  {
>      avpriv_trc_function func = NULL;
> @@ -225,6 +235,10 @@ avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharact
>              func = avpriv_trc_arib_std_b67;
>              break;
>
> +        case AVCOL_TRC_CINE_LIN2LOG:
> +            func = avpriv_trc_cine_lin2log;
> +            break;
> +
>          case AVCOL_TRC_RESERVED0:
>          case AVCOL_TRC_UNSPECIFIED:
>          case AVCOL_TRC_RESERVED:
> diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
> index 1c625cfc8a..1f3f9988d7 100644
> --- a/libavutil/pixfmt.h
> +++ b/libavutil/pixfmt.h
> @@ -499,6 +499,7 @@ enum AVColorTransferCharacteristic {
>      AVCOL_TRC_SMPTE428     = 17, ///< SMPTE ST 428-1
>      AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428,
>      AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma"
> +    AVCOL_TRC_CINE_LIN2LOG = 19, ///< Default Cineon/DPX linear to log 1D curve
>      AVCOL_TRC_NB                 ///< Not part of ABI

AVColorTransferCharacteristic should follow ISO/IEC 23001-8 and its
following standards (ISO/IEC 23091 I believe). Not sure we have a
solution for specialized variants, but adding one right there would
collide with the next addition to the standard...

- Hendrik
Kevin Wheatley March 6, 2020, 12:55 p.m. UTC | #3
On Fri, Mar 6, 2020 at 10:19 AM Hendrik Leppkes <h.leppkes@gmail.com> wrote:
> AVColorTransferCharacteristic should follow ISO/IEC 23001-8 and its
> following standards (ISO/IEC 23091 I believe). Not sure we have a
> solution for specialized variants, but adding one right there would
> collide with the next addition to the standard...

Agreed, A publicly "aligned twin text" version is available as ITU-T
H.273 https://www.itu.int/rec/T-REC-H.273-201612-I/en shows that value
is 'reserved'.

I would also suggest that there are a few implementations of the
Cineon log to lin conversion and as such I'd reject it as is.
You will need to pass in the parameters for the various variables
white, black etc. You will also need to add a parameter for the
density per code value constant (0.002 by default convention).
Not all implementations use a gain scaling, though strictly these are
no longer "Cineon" per se, but you will end up with needing various
camera vendor equivalents. This would result in a large proliferation
of equations, which I don't believe are core to the FFmpeg code.

You would perhaps be better creating a specialist filter and
implementing it using OCIO (as suggested
https://github.com/AcademySoftwareFoundation/tac/tree/master/gsoc), or
extending the current 3D LUT code to read Cinespace or other 3D LUT
formats that support a pre-shaper and handle the float->integer
conversion that way.

Kevin
Mark Reid March 6, 2020, 7:33 p.m. UTC | #4
On Fri, Mar 6, 2020 at 5:03 AM Kevin Wheatley <kevin.j.wheatley@gmail.com>
wrote:

> On Fri, Mar 6, 2020 at 10:19 AM Hendrik Leppkes <h.leppkes@gmail.com>
> wrote:
> > AVColorTransferCharacteristic should follow ISO/IEC 23001-8 and its
> > following standards (ISO/IEC 23091 I believe). Not sure we have a
> > solution for specialized variants, but adding one right there would
> > collide with the next addition to the standard...
>
> Agreed, A publicly "aligned twin text" version is available as ITU-T
> H.273 https://www.itu.int/rec/T-REC-H.273-201612-I/en shows that value
> is 'reserved'.
>
>
Agreed, it felt wrong about adding it where I did, but it was the quickest
way illustrate what I was trying
to do.

I would also suggest that there are a few implementations of the
> Cineon log to lin conversion and as such I'd reject it as is.
> You will need to pass in the parameters for the various variables
> white, black etc. You will also need to add a parameter for the
> density per code value constant (0.002 by default convention).
> Not all implementations use a gain scaling, though strictly these are
> no longer "Cineon" per se, but you will end up with needing various
> camera vendor equivalents. This would result in a large proliferation
> of equations, which I don't believe are core to the FFmpeg code.
>
>
Agreed and this all could also really be done with a 1dlut video filter but
the real issue I'm working around is that the
current float->int conversion happens in the exr codec. The currently
available apply_trc options clamp at 1.0f (unless I'm mistaken).
The full linear range is need to do any logarithmic conversion.

I was also thinking ACEScc or ACEScct might be more appropriate instead of
cineon.
http://j.mp/S-2014-003
http://j.mp/S-2016-001

I also thought of just adding a float pixel format output option to exr
sounded like a lot of work and I didn't know where to begin.


> You would perhaps be better creating a specialist filter and
> implementing it using OCIO (as suggested
> https://github.com/AcademySoftwareFoundation/tac/tree/master/gsoc), or
> extending the current 3D LUT code to read Cinespace or other 3D LUT
> formats that support a pre-shaper and handle the float->integer
> conversion that way.
>

I currently do have a workflow that does something similar to that, but it
slower and involves more steps :)


>
> Kevin
> _______________________________________________
> 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".
Gonzalo Garramuño March 6, 2020, 8:29 p.m. UTC | #5
El 06/03/20 a las 16:33, Mark Reid escribió:
>> You would perhaps be better creating a specialist filter and
>> implementing it using OCIO (as suggested
>> https://github.com/AcademySoftwareFoundation/tac/tree/master/gsoc), or
>> extending the current 3D LUT code to read Cinespace or other 3D LUT
>> formats that support a pre-shaper and handle the float->integer
>> conversion that way.
>>
> I currently do have a workflow that does something similar to that, but it
> slower and involves more steps :)
You are probably better off using oiiotool (part of Sony's OpenImageIO) 
for doing that sort of color corrections on EXRs.
Carl Eugen Hoyos March 6, 2020, 8:42 p.m. UTC | #6
Am Fr., 6. März 2020 um 00:25 Uhr schrieb <mindmark@gmail.com>:

> +    AVCOL_TRC_CINE_LIN2LOG = 19, ///< Default Cineon/DPX linear to log 1D curve

Isn't it possible to use a random large number here?

Carl Eugen
Paul B Mahol March 6, 2020, 8:44 p.m. UTC | #7
On 3/6/20, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> Am Fr., 6. März 2020 um 00:25 Uhr schrieb <mindmark@gmail.com>:
>
>> +    AVCOL_TRC_CINE_LIN2LOG = 19, ///< Default Cineon/DPX linear to log 1D
>> curve
>
> Isn't it possible to use a random large number here?


No, because that would be big hack on top of big pile of hacks that
exr in ffmpeg is already.

>
> Carl Eugen
> _______________________________________________
> 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".
Carl Eugen Hoyos March 6, 2020, 9:49 p.m. UTC | #8
Am Fr., 6. März 2020 um 22:11 Uhr schrieb Paul B Mahol <onemda@gmail.com>:
>
> On 3/6/20, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> > Am Fr., 6. März 2020 um 00:25 Uhr schrieb <mindmark@gmail.com>:
> >
> >> +    AVCOL_TRC_CINE_LIN2LOG = 19, ///< Default Cineon/DPX linear to log 1D
> >> curve
> >
> > Isn't it possible to use a random large number here?
>
> No, because that would be big hack on top of big pile of hacks that
> exr in ffmpeg is already.

The description sounds as if this isn't exr-only...

But any option is probably fine, Carl Eugen
diff mbox series

Patch

diff --git a/libavcodec/exr.c b/libavcodec/exr.c
index 1db30a1ae0..f2900a7921 100644
--- a/libavcodec/exr.c
+++ b/libavcodec/exr.c
@@ -1938,6 +1938,8 @@  static const AVOption options[] = {
         AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTEST2084 },  INT_MIN, INT_MAX, VD, "apply_trc_type"},
     { "smpte428_1",   "SMPTE ST 428-1",   0,
         AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTEST428_1 }, INT_MIN, INT_MAX, VD, "apply_trc_type"},
+    { "lin2log",      "Default Cineon/DPX log",   0,
+        AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_CINE_LIN2LOG }, INT_MIN, INT_MAX, VD, "apply_trc_type"},

     { NULL },
 };
diff --git a/libavutil/color_utils.c b/libavutil/color_utils.c
index eb8bc7b5fc..e33c019d4a 100644
--- a/libavutil/color_utils.c
+++ b/libavutil/color_utils.c
@@ -167,6 +167,16 @@  static double avpriv_trc_arib_std_b67(double Lc) {
         (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c);
 }

+static double avpriv_trc_cine_lin2log(double Lc) {
+    const double blackpoint =  95.0;
+    const double whitepoint = 685.0;
+    const double gamma      =   0.6;
+    const double offset =  pow(10, (blackpoint - whitepoint) * 0.002 / gamma);
+    const double gain   = 1.0 / (1.0 - offset);
+
+    return (log10((Lc + offset) / gain) / (0.002 / gamma) + whitepoint ) / 1023.0;
+}
+
 avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc)
 {
     avpriv_trc_function func = NULL;
@@ -225,6 +235,10 @@  avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharact
             func = avpriv_trc_arib_std_b67;
             break;

+        case AVCOL_TRC_CINE_LIN2LOG:
+            func = avpriv_trc_cine_lin2log;
+            break;
+
         case AVCOL_TRC_RESERVED0:
         case AVCOL_TRC_UNSPECIFIED:
         case AVCOL_TRC_RESERVED:
diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
index 1c625cfc8a..1f3f9988d7 100644
--- a/libavutil/pixfmt.h
+++ b/libavutil/pixfmt.h
@@ -499,6 +499,7 @@  enum AVColorTransferCharacteristic {
     AVCOL_TRC_SMPTE428     = 17, ///< SMPTE ST 428-1
     AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428,
     AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma"
+    AVCOL_TRC_CINE_LIN2LOG = 19, ///< Default Cineon/DPX linear to log 1D curve
     AVCOL_TRC_NB                 ///< Not part of ABI
 };