[vlc-devel] [PATCH] Enable display color correction from ICC profile provided by user (opengl output only) - Add file search menu to opengl menu - File reading and RGB correction table creation with Lcms - Correction is applied by GPU via OpenGL 3D-LUT interpolation (GLSL >= 3.3) - Inserted within liplacebo processings as libplacebo already requires Lcms

Sean McGovern gseanmcg at gmail.com
Fri May 5 15:49:30 UTC 2023


Hi Fabien,

2 things:

1. Please submit patches via the Gitlab instance at
https://code.videolan.org
2. Commit title is waaaaay too long, please write something concise for the
title and add details on the lines below it.

Thanks,
Sean McGovern

On Fri, May 5, 2023, 10:48 Fabien <fabi_motta at hotmail.fr> wrote:

> ---
>  modules/video_output/Makefile.am              |   2 +-
>  modules/video_output/opengl/converter.h       |   9 +
>  modules/video_output/opengl/display.c         |  22 ++
>  .../video_output/opengl/fragment_shaders.c    |  44 +++
>  modules/video_output/opengl/vout_helper.c     | 333 ++++++++++++++++++
>  modules/video_output/opengl/vout_helper.h     |  30 ++
>  6 files changed, 439 insertions(+), 1 deletion(-)
>
> diff --git a/modules/video_output/Makefile.am
> b/modules/video_output/Makefile.am
> index da559cf329..74e147c77c 100644
> --- a/modules/video_output/Makefile.am
> +++ b/modules/video_output/Makefile.am
> @@ -8,7 +8,7 @@ OPENGL_COMMONSOURCES = video_output/opengl/vout_helper.c \
>         video_output/opengl/internal.h
> video_output/opengl/fragment_shaders.c \
>         video_output/opengl/converter_sw.c
>
> -OPENGL_COMMONCLFAGS = $(LIBPLACEBO_CFLAGS)
> +OPENGL_COMMONCLFAGS = $(LIBPLACEBO_CFLAGS) -llcms2
>  OPENGL_COMMONLIBS = $(LIBPLACEBO_LIBS)
>
>  if HAVE_DECKLINK
> diff --git a/modules/video_output/opengl/converter.h
> b/modules/video_output/opengl/converter.h
> index 7000e1f38e..dc0b14c589 100644
> --- a/modules/video_output/opengl/converter.h
> +++ b/modules/video_output/opengl/converter.h
> @@ -170,6 +170,9 @@ typedef struct {
>      PFNGLGETSTRINGPROC      GetString;
>      PFNGLPIXELSTOREIPROC    PixelStorei;
>      PFNGLTEXIMAGE2DPROC     TexImage2D;
> +    /* <color_correction> */
> +    PFNGLTEXIMAGE3DPROC     TexImage3D;
> +    /* </color_correction> */
>      PFNGLTEXPARAMETERFPROC  TexParameterf;
>      PFNGLTEXPARAMETERIPROC  TexParameteri;
>      PFNGLTEXSUBIMAGE2DPROC  TexSubImage2D;
> @@ -339,6 +342,12 @@ struct opengl_tex_converter_t
>
>      struct pl_shader *pl_sh;
>      const struct pl_shader_res *pl_sh_res;
> +    /* <color_correction>
> +    Data needed to the icc color correction LUT (Texture3D) */
> +    GLint clutId;
> +    GLuint clut_tex;
> +    GLfloat *g_3dlut;
> +    /*</color_correction> */
>
>      /* Private context */
>      void *priv;
> diff --git a/modules/video_output/opengl/display.c
> b/modules/video_output/opengl/display.c
> index ec671109bc..f0c0393b97 100644
> --- a/modules/video_output/opengl/display.c
> +++ b/modules/video_output/opengl/display.c
> @@ -69,6 +69,28 @@ vlc_module_begin ()
>                  GL_TEXT, PROVIDER_LONGTEXT, true)
>  #endif
>      add_glopts ()
> +
> +/* <color_correction> */
> +#ifdef HAVE_LIBPLACEBO
> +    set_section("ICC profile color correction", NULL) \
> +    add_loadfile("icc_profile", "", "File path to display icc profile",\
> +                 "File path to an icc profile (.icc, .icm) for color \
> +                 correction by a 3DLut generated at video beginning \
> +                 (can take a few seconds, depending on your machine).",
> true )
> +    add_integer("icc_bp_offset_mode", ICC_BP_MODE_DEFAULT, "Black point
> offset mode",\
> +    "Black point offset evaluation mode, change this if image constrast\
> +    is not satisfactory.", true) \
> +    change_integer_list( icc_bp_mode_list, icc_bp_mode_text) \
> +    add_float("icc_bp_offset", 0.05, "Black point offset [0.0;1.0]",
> "Modify this \
> +    if image is too dark (increase it), or too light (decrease it). As a\
> +    starting point, select VLC estimation mode, launch VLC in debugging
> mode\
> +    (-vv) and look for black point offset estimation values in the
> messages.",\
> +     true ) \
> +     add_bool("force_bt709", false, "Force BT709 colorspace (HDTV)", "Try
> this \
> +          with webcam or usb sources if colors seem wrong.", true)
> +#endif
> +/* </color_correction> */
> +
>  vlc_module_end ()
>
>  struct vout_display_sys_t
> diff --git a/modules/video_output/opengl/fragment_shaders.c
> b/modules/video_output/opengl/fragment_shaders.c
> index 2246e33afd..89a10059af 100644
> --- a/modules/video_output/opengl/fragment_shaders.c
> +++ b/modules/video_output/opengl/fragment_shaders.c
> @@ -363,6 +363,14 @@ tc_base_fetch_locations(opengl_tex_converter_t *tc,
> GLuint program)
>          struct pl_shader_var sv = res->variables[i];
>          tc->uloc.pl_vars[i] = tc->vt->GetUniformLocation(program,
> sv.var.name);
>      }
> +
> +    /* <color_correction> */
> +    if ( tc->g_3dlut != NULL ) {
> +        tc->clutId = tc->vt->GetUniformLocation(program, "clut3d");
> +        if (tc->clutId == -1)
> +            return VLC_EGENERIC;
> +    }
> +    /* </color_correction> */
>  #endif
>
>      return VLC_SUCCESS;
> @@ -429,6 +437,11 @@ tc_base_prepare_shader(const opengl_tex_converter_t
> *tc,
>              break;
>          }
>      }
> +
> +    /* <color_correction> */
> +    if ( tc->g_3dlut != NULL )
> +        tc->vt->Uniform1i(tc->clutId, tc->tex_count );
> +    /* </color_correction> */
>  #endif
>  }
>
> @@ -600,6 +613,25 @@
> opengl_fragment_shader_init_impl(opengl_tex_converter_t *tc, GLenum
> tex_target,
>      if (vlc_memstream_open(&ms) != 0)
>          return 0;
>
> +/* <color_correction>
> + * Forcing GLSL 3.3 to be able to use TexImage3D */
> +#ifdef HAVE_LIBPLACEBO
> +    if ( tc->g_3dlut != NULL ) {
> +        if ( tc->glsl_version < 300 ) {
> +            msg_Warn(tc->gl,"GLSL version used by VLC is %u",
> tc->glsl_version);
> +            tc->glsl_version = 330;
> +            msg_Warn(tc->gl,"Forcing the use of %u glsl version", \
> +            tc->glsl_version);
> +        }
> +
> +        else {
> +           msg_Dbg(tc->gl,"Using %u glsl version, \n%s",
> tc->glsl_version, \
> +            tc->glsl_precision_header);
> +        }
> +    }
> +#endif
> +/* </color_correction> */
> +
>  #define ADD(x) vlc_memstream_puts(&ms, x)
>  #define ADDF(x, ...) vlc_memstream_printf(&ms, x, ##__VA_ARGS__)
>
> @@ -703,6 +735,13 @@
> opengl_fragment_shader_init_impl(opengl_tex_converter_t *tc, GLenum
> tex_target,
>      if (is_yuv)
>          ADD("uniform vec4 Coefficients[4];\n");
>
> +/* <color_correction> */
> +#ifdef HAVE_LIBPLACEBO
> +    if ( tc->g_3dlut != NULL )
> +        ADD("uniform sampler3D clut3d ;\n");
> +#endif
> +/* </color_correction> */
> +
>      ADD("uniform vec4 FillColor;\n"
>          "void main(void) {\n"
>          " float val;vec4 colors;\n");
> @@ -770,7 +809,12 @@
> opengl_fragment_shader_init_impl(opengl_tex_converter_t *tc, GLenum
> tex_target,
>          assert(res->input  == PL_SHADER_SIG_COLOR);
>          assert(res->output == PL_SHADER_SIG_COLOR);
>          ADDF(" result = %s(result);\n", res->name);
> +
>      }
> +    /* <color_correction> */
> +    if ( tc->g_3dlut != NULL )
> +        ADD(" result.rgb = texture( clut3d, result.rgb ).rgb;\n" );
> +    /* </color_correction> */
>  #endif
>
>      ADD(" gl_FragColor = result * FillColor;\n"
> diff --git a/modules/video_output/opengl/vout_helper.c
> b/modules/video_output/opengl/vout_helper.c
> index 13d65e04c8..74de9309e9 100644
> --- a/modules/video_output/opengl/vout_helper.c
> +++ b/modules/video_output/opengl/vout_helper.c
> @@ -43,6 +43,11 @@
>
>  #include "vout_helper.h"
>  #include "internal.h"
> +/* <color_correction> */
> +#ifdef HAVE_LIBPLACEBO
> +#include <lcms2.h>
> +#endif
> +/* </color_correction> */
>
>  #ifndef GL_CLAMP_TO_EDGE
>  # define GL_CLAMP_TO_EDGE 0x812F
> @@ -572,6 +577,11 @@ opengl_deinit_program(vout_display_opengl_t *vgl,
> struct prgm *prgm)
>      FREENULL(tc->uloc.pl_vars);
>      if (tc->pl_ctx)
>          pl_context_destroy(&tc->pl_ctx);
> +
> +    /* <color_correction> */
> +    if ( tc->g_3dlut != NULL )
> +        free( tc->g_3dlut );
> +    /* </color_correction> */
>  #endif
>
>      vlc_object_release(tc);
> @@ -640,6 +650,47 @@ opengl_init_program(vout_display_opengl_t *vgl,
> struct prgm *prgm,
>  #   endif
>          }
>      }
> +
> +    /* <color_correction> */
> +    /* Icc file reading, GLSL version check, 3D LUT allocation */
> +    if (!subpics) {
> +        tc->g_3dlut = NULL;
> +
> +        char *filename = var_InheritString( tc->gl, "icc_profile" );
> +        if ( filename != NULL ) {
> +
> +            char *glsl_version;
> +            glsl_version = (char*)
> tc->vt->GetString(GL_SHADING_LANGUAGE_VERSION );
> +            msg_Dbg( tc->gl, "Available GLSL version %s", glsl_version );
> +            if ( atof( glsl_version ) < 2.99 ) {
> +              msg_Dbg( tc->gl, "Max available GLSL version %s too old for
> color\
> +               correction (needs version > 3.3 )",\
> +                     glsl_version );
> +            }
> +            else {
> +
> +                tc->g_3dlut = ( GLfloat* ) malloc( sizeof(GLfloat) * \
> +                            g_3d_lut_size * g_3d_lut_size * g_3d_lut_size
> * 3 );
> +                if ( tc->g_3dlut == NULL ) {
> +                    msg_Dbg( tc->gl, "Could not allocate color correction
> table");
> +                }
> +                else {
> +                    int err = CreateCorrectionLUT( tc->g_3dlut, tc->gl,
> fmt, filename );
> +                    if ( err != VLC_SUCCESS ) {
> +                        msg_Dbg( tc->gl, "Could not create Color
> Correction LUT, \
> +                        disabling color correction" );
> +                        free( tc->g_3dlut );
> +                        tc->g_3dlut = NULL;
> +                    }
> +                }
> +            }
> +        }
> +        else {
> +            msg_Dbg( tc->gl, "Absent or invalid path to icc correction
> profile, \
> +            disabling color correction" );
> +        }
> +    }
> +    /* </color_correction> */
>  #endif
>
>      int ret;
> @@ -736,6 +787,255 @@ ResizeFormatToGLMaxTexSize(video_format_t *fmt,
> unsigned int max_tex_size)
>      }
>  }
>
> +/* <color_correction>
> + * Creates the 3D-LUT from image/video reported colorspace, icc profile
> file
> + * and lcms2 functions
> + */
> +#ifdef HAVE_LIBPLACEBO
> +int CreateCorrectionLUT( GLfloat *lut, vlc_gl_t *gl, \
> +                         const video_format_t *fmt, char *filename )
> +{
> +    /* Some colorimetric data for BT601/709/2020 and sRGB standards which
> are
> +     * the only provided by VLC video format
> +     * D65 whitepoint is common to all these standards
> +     * The primaries and tone response curve (TRC) differ between BT and
> sRGB
> +     * We use LittleCMS to compute the correction 3DLUT
> +     * Video profile is built with LCMS routines
> +     * Display profile is read from the path given by the user in the
> advanced
> +     * configuration parameters. */
> +
> +    struct trc_param {
> +        uint8_t          type_nb;
> +        cmsFloat64Number param[10];
> +    };
> +
> +    static cmsCIExyY d65_wp = { 0.3127, 0.3290, 1.0 };
> +
> +    static cmsCIExyYTRIPLE bt709_prim = { { 0.640, 0.330, 1.00 }, \
> +                                          { 0.300, 0.600, 1.00 }, \
> +                                          { 0.150, 0.060, 1.00 } };
> +
> +    static cmsCIExyYTRIPLE bt601_525_prim = { { 0.630, 0.340, 1.00 }, \
> +                                              { 0.310, 0.595, 1.00 }, \
> +                                              { 0.155, 0.070, 1.00 } };
> +
> +    static cmsCIExyYTRIPLE bt601_625_prim = { { 0.640, 0.330, 1.00 }, \
> +                                              { 0.290, 0.600, 1.00 }, \
> +                                              { 0.150, 0.060, 1.00 } };
> +
> +    static cmsCIExyYTRIPLE bt2020_prim = { { 0.708, 0.292, 1.0 }, \
> +                                           { 0.170, 0.797, 1.0 }, \
> +                                           { 0.131, 0.046, 1.0 } };
> +
> +    static struct trc_param srgb_trc_params = { \
> +        4, { 2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045 } };
> +
> +    /* The Tone Response Curve (or Gamma curve) values are the same for
> BT709,
> +     * BT601 and BT2020.
> +     * They depend on the display black point luminance, according to
> BT1886,
> +     * one per color component. Below are default values, but they will be
> +     * computed at correction initialisation */
> +    static struct trc_param bt_trc_params = { 6, { 2.4, 0.94, 0.06, 0. }
> };
> +
> +
> +
> +    // Icc profile correction cLUT computation
> +    // First, creatign a profile from video format colorspace data
> +    msg_Dbg(gl, "Create source colorspace profile from video format");
> +    cmsToneCurve *trc[3];
> +
> +    cmsContext cms_ctx = cmsCreateContext(NULL, NULL);
> +
> +    if ( cms_ctx == NULL) {
> +        msg_Dbg( gl,"Could not create cms context\n" );
> +        return VLC_ENOMEM;
> +    }
> +
> +    msg_Dbg( gl, "User icc profile path %s", filename );
> +    cmsHPROFILE  hOutProfile = cmsOpenProfileFromFile( filename, "r");
> +    if ( hOutProfile == NULL ) {
> +        msg_Dbg( gl, "Could not read user display icc profile" );
> +        return VLC_ENOMEM;
> +    }
> +
> +    /* Building TRC curve for BT standards according to BT 1886
> recommendations
> +    *  It requires the black point of the display to build a modified
> +    *  gamma 2.4 curve.
> +    *  This type of curve corresponds to type number 6 for lcms
> +    *  Determination of black point offset is skipped if a user value is
> provi-
> +    *  ded. */
> +    float bp_offset[3];
> +    int icc_bp_offset_mode = var_InheritInteger(gl, "icc_bp_offset_mode");
> +    msg_Dbg( gl, "Black point offset mode = %s",\
> +                  icc_bp_mode_text[ icc_bp_offset_mode ]  );
> +
> +    switch ( icc_bp_offset_mode )
> +    {
> +        case ICC_BP_MODE_USER:
> +            bp_offset[0] = var_InheritFloat(gl, "icc_bp_offset");
> +            bp_offset[0] = fminf( fmaxf( 0.0, bp_offset[0] ), 1.0 );
> +            msg_Dbg( gl, "Black point offset provided by user = %f",
> bp_offset[0] );
> +            bp_offset[1] = bp_offset[0];
> +            bp_offset[2] = bp_offset[0];
> +            break;
> +
> +        case ICC_BP_MODE_VLC:
> +            float bp_XYZ[3], bp_rgb[3];
> +            cmsCIEXYZ cms_bp_XYZ;
> +            cmsDetectBlackPoint( &cms_bp_XYZ, hOutProfile,\
> +                                 INTENT_RELATIVE_COLORIMETRIC, 0);
> +            bp_XYZ[0] = cms_bp_XYZ.X;
> +            bp_XYZ[1] = cms_bp_XYZ.Y;
> +            bp_XYZ[2] = cms_bp_XYZ.Z;
> +
> +            msg_Dbg( gl, "Detected black point in CIE XYZ = %f %f %f", \
> +                     bp_XYZ[0], bp_XYZ[1], bp_XYZ[2] );
> +
> +            // Compute black point in BT709 components from XYZ
> +
> +            cmsHPROFILE XYZProfile = cmsCreateXYZProfile();
> +            cmsToneCurve *lin_trc = cmsBuildGamma( cms_ctx, 1.0);
> +
> +            cmsHPROFILE hInProfile_lin = cmsCreateRGBProfile( &d65_wp, \
> +                &bt709_prim, \
> +                ( cmsToneCurve*[3] ) { lin_trc, lin_trc, lin_trc } );
> +
> +            cmsHTRANSFORM hTransform = cmsCreateTransform( \
> +                XYZProfile,  TYPE_XYZ_FLT, \
> +                hInProfile_lin, TYPE_RGB_FLT, \
> +                INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_HIGHRESPRECALC | \
> +                                   cmsFLAGS_BLACKPOINTCOMPENSATION );
> +
> +            cmsDoTransform( hTransform, &bp_XYZ, &bp_rgb, 1 );
> +
> +            msg_Dbg( gl, "Detected black point in BT709 RGB lin = %f %f
> %f", \
> +                 bp_rgb[0], bp_rgb[1], bp_rgb[2] );
> +
> +            bp_offset[0] = powf( bp_rgb[0], 1.0 / 2.4 );
> +            bp_offset[1] = powf( bp_rgb[1], 1.0 / 2.4 );
> +            bp_offset[2] = powf( bp_rgb[2], 1.0 / 2.4 );
> +
> +            cmsDeleteTransform( hTransform );
> +            cmsCloseProfile( hInProfile_lin );
> +            cmsCloseProfile( XYZProfile );
> +            cmsFreeToneCurve( lin_trc );
> +
> +            break;
> +
> +            default:
> +                bp_offset[0] = 0.05;
> +                bp_offset[1] = 0.05;
> +                bp_offset[2] = 0.05;
> +
> +    }
> +
> +    // Compute BT 1886 curve
> +    bt_trc_params.param[0] = 2.4;
> +    bt_trc_params.param[3] = 0.0;
> +    for (int i = 0; i < 3 ; i++ ) {
> +        bt_trc_params.param[2] = bp_offset[i];
> +        msg_Dbg( gl, "Black point offset = %f", bt_trc_params.param[2] );
> +        bt_trc_params.param[1] = 1.0 - bt_trc_params.param[2];
> +        trc[i] = cmsBuildParametricToneCurve( cms_ctx, \
> +            bt_trc_params.type_nb, bt_trc_params.param );
> +        }
> +
> +    cmsCIExyYTRIPLE *m_prim;
> +    int colorspace = fmt->space;
> +    if ( var_InheritBool(gl, "force_bt709") ) {
> +        colorspace = COLOR_SPACE_BT709;
> +    }
> +
> +    switch ( colorspace ) {
> +
> +        case COLOR_SPACE_UNDEF:
> +            msg_Dbg( gl, "Image colorspace is undefined, taking sRGB\n" );
> +            trc[0] = cmsBuildParametricToneCurve( cms_ctx,\
> +
> srgb_trc_params.type_nb, \
> +                                                  srgb_trc_params.param );
> +            trc[1] = cmsBuildParametricToneCurve( cms_ctx,\
> +
> srgb_trc_params.type_nb, \
> +                                                  srgb_trc_params.param );
> +            trc[2] = cmsBuildParametricToneCurve( cms_ctx,\
> +
> srgb_trc_params.type_nb, \
> +                                                  srgb_trc_params.param );
> +            // BT709 and sRGB have the same primaries
> +            m_prim = &bt709_prim;
> +            break;
> +
> +        case COLOR_SPACE_BT601:
> +            msg_Dbg( gl, "Image colorspace is BT 601" );
> +
> +            if ( fmt->i_height > 500 ) {
> +                msg_Dbg( gl, "Detected PAL, adjusting RGB primaries" );
> +                m_prim = &bt601_625_prim;
> +            }
> +            else {
> +                msg_Dbg( gl, "Detected NTSC, adjusting RGB primaries" );
> +                m_prim = &bt601_525_prim;
> +            }
> +            break;
> +
> +        case COLOR_SPACE_BT2020:
> +            msg_Dbg( gl, "Image colorspace is BT 2020" );
> +            m_prim = &bt2020_prim;
> +            break;
> +
> +        case COLOR_SPACE_BT709:
> +            msg_Dbg( gl, "Image colorspace is BT 709" );
> +            m_prim = &bt709_prim;
> +            break;
> +
> +        default:
> +            msg_Dbg( gl, "Image colorspace is unknown, taking BT 709" );
> +            m_prim = &bt709_prim;
> +
> +    }
> +
> +    cmsHPROFILE hInProfile = cmsCreateRGBProfile( &d65_wp, m_prim, trc );
> +    if ( hInProfile == NULL ) {
> +        msg_Dbg( gl, "Could not create image colorspace profile" );
> +        return VLC_EGENERIC;
> +    }
> +
> +    msg_Dbg(gl, "Creating lcms Transform");
> +    cmsHTRANSFORM hTransform = cmsCreateTransform( \
> +        hInProfile,  TYPE_RGB_16, \
> +        hOutProfile, TYPE_RGB_16, \
> +        INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_HIGHRESPRECALC | \
> +                           cmsFLAGS_BLACKPOINTCOMPENSATION );
> +
> +    msg_Dbg(gl, "Creating lut table");
> +    uint16_t rgb[3], icc_rgb[3];
> +    int index;
> +    int ratio = ( 1 << (sizeof(uint16_t) * 8 ) ) / g_3d_lut_size;
> +    for (int b = 0 ; b < g_3d_lut_size ; b++ ) {
> +        for (int g = 0 ; g < g_3d_lut_size ; g++ ) {
> +            for (int r = 0 ; r < g_3d_lut_size ; r++ ) {
> +                rgb[0] = r * ratio;
> +                rgb[1] = g * ratio;
> +                rgb[2] = b * ratio;
> +                cmsDoTransform( hTransform, &rgb, &icc_rgb, 1 );
> +                index = ( ( b*g_3d_lut_size + g )*g_3d_lut_size + r )*3;
> +                lut[ index ]    = (float) icc_rgb[0] /\
> +                                  (float) ( g_3d_lut_size * ratio - 1 );
> +                lut[ index + 1] = (float) icc_rgb[1] /\
> +                                  (float) ( g_3d_lut_size * ratio - 1 );
> +                lut[ index + 2] = (float) icc_rgb[2] /\
> +                                  (float) ( g_3d_lut_size * ratio - 1 );
> +            }
> +        }
> +    }
> +    msg_Dbg(gl, "Lut table created");
> +    cmsDeleteTransform( hTransform );
> +    cmsCloseProfile(hInProfile);
> +    cmsCloseProfile(hOutProfile);
> +    cmsFreeToneCurveTriple(trc);
> +    return VLC_SUCCESS;
> +}
> +#endif
> +/* </color_correction> */
> +
>  vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
>                                                 const vlc_fourcc_t
> **subpicture_chromas,
>                                                 vlc_gl_t *gl,
> @@ -792,6 +1092,11 @@ vout_display_opengl_t
> *vout_display_opengl_New(video_format_t *fmt,
>      GET_PROC_ADDR_CORE(GetString);
>      GET_PROC_ADDR_CORE(PixelStorei);
>      GET_PROC_ADDR_CORE(TexImage2D);
> +    /* <color_correction> */
> +    #ifdef HAVE_LIBPLACEBO
> +    GET_PROC_ADDR_CORE(TexImage3D);
> +    #endif
> +    /* </color_correction> */
>      GET_PROC_ADDR_CORE(TexParameterf);
>      GET_PROC_ADDR_CORE(TexParameteri);
>      GET_PROC_ADDR_CORE(TexSubImage2D);
> @@ -956,6 +1261,25 @@ vout_display_opengl_t
> *vout_display_opengl_New(video_format_t *fmt,
>          }
>      }
>
> +    /* <color_correction> */
> +#ifdef HAVE_LIBPLACEBO
> +    if ( vgl->prgm->tc->g_3dlut != NULL ) {
> +        vgl->vt.GenTextures(1, &vgl->prgm->tc->clut_tex);
> +        vgl->vt.BindTexture(GL_TEXTURE_3D, vgl->prgm->tc->clut_tex);
> +        vgl->vt.TexImage3D( GL_TEXTURE_3D, 0, GL_RGB,\
> +                            g_3d_lut_size, g_3d_lut_size, g_3d_lut_size,
> 0,\
> +                            GL_RGB, GL_FLOAT, vgl->prgm->tc->g_3dlut );
> +        // Set sampling parameters, clamp to edge, weird colors otherwise
> +        vgl->vt.TexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,
> GL_LINEAR);
> +        vgl->vt.TexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER,
> GL_LINEAR);
> +        vgl->vt.TexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,
> GL_CLAMP_TO_EDGE);
> +        vgl->vt.TexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,
> GL_CLAMP_TO_EDGE);
> +        vgl->vt.TexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,
> GL_CLAMP_TO_EDGE);
> +        msg_Dbg(gl, "Icc correction texture allocated");
> +    }
> +#endif
> +/* </color_correction> */
> +
>      /* */
>      vgl->vt.Disable(GL_BLEND);
>      vgl->vt.Disable(GL_DEPTH_TEST);
> @@ -1602,6 +1926,15 @@ static void DrawWithShaders(vout_display_opengl_t
> *vgl, struct prgm *prgm)
>                                       0, 0, 0);
>      }
>
> +/* <color_correction> */
> + #ifdef HAVE_LIBPLACEBO
> +    if ( vgl->prgm->tc->g_3dlut != NULL ) {
> +        vgl->vt.ActiveTexture(GL_TEXTURE0  + vgl->prgm->tc->tex_count );
> +        vgl->vt.BindTexture(GL_TEXTURE_3D, vgl->prgm->tc->clut_tex );
> +    }
> +#endif
> +/* </color_correction> */
> +
>      vgl->vt.BindBuffer(GL_ARRAY_BUFFER, vgl->vertex_buffer_object);
>      vgl->vt.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, vgl->index_buffer_object);
>      vgl->vt.EnableVertexAttribArray(prgm->aloc.VertexPosition);
> diff --git a/modules/video_output/opengl/vout_helper.h
> b/modules/video_output/opengl/vout_helper.h
> index 48014b454c..dc20e347eb 100644
> --- a/modules/video_output/opengl/vout_helper.h
> +++ b/modules/video_output/opengl/vout_helper.h
> @@ -33,6 +33,13 @@
>
>  #ifdef HAVE_LIBPLACEBO
>  #include <libplacebo/shaders/colorspace.h>
> +/* <color correction
> + * A 3D LUT size of 256 bytes per channel is chosen to have a full
> correction of
> + * 8-bit images, and interpolation above
> + */
> +#include <lcms2.h>
> +static int g_3d_lut_size = 256;
> +/* </color_correction> */
>
>  # if PL_MAJOR_VER >= 5
>  # define pl_context_create pl_log_create
> @@ -226,6 +233,29 @@ static const char * const dither_text[] = {
>              change_integer_list(dither_values, dither_text) \
>      add_integer_with_range("dither-depth", 0, 0, 16, DEPTH_TEXT,
> DEPTH_LONGTEXT, false) \
>      add_desat_params()
> +
> +    /* <color_correction> */
> +    enum icc_bp_mode {
> +        ICC_BP_MODE_DEFAULT = 0,
> +        ICC_BP_MODE_VLC,
> +        ICC_BP_MODE_USER
> +    };
> +
> +    static const int icc_bp_mode_list[] = {
> +        ICC_BP_MODE_DEFAULT,\
> +        ICC_BP_MODE_VLC,
> +        ICC_BP_MODE_USER
> +    };
> +
> +    static const char * const icc_bp_mode_text[] = {
> +        "Default value (0.05)",\
> +        "VLC estimation from profile",\
> +        "User defined value"
> +    };
> +
> +    int CreateCorrectionLUT( GLfloat *g_3dlut, vlc_gl_t *gl, \
> +                         const video_format_t *fmt, char *filename );
> +    /* </color_correction> */
>  #else
>  #define add_glopts_placebo()
>  #endif
> --
> 2.39.2
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20230505/3ad0282e/attachment.htm>


More information about the vlc-devel mailing list