[vlc-devel] [PATCH 2/2] XYZ to RGB filter conversion

Nicolas BERTRAND nicoinattendu at gmail.com
Thu Feb 14 15:27:34 CET 2013


Modification in modules/codec/avcodec to handle JPEG2000 codec and
set chroma format to XYZ

Creation of module xyz_rgb in modules/video_chroma. This module filter
from XYZ to RGB. Actually it converts from XYZ12 to RGB32. As XYZ is
12 bits depth and RGB 8 bit depth, a lack of precision is introduced
in colors precision.

RGB color space display mist be used with opengl output (-Vgl)

WARNING: This modification needs a libav supporting XYZ format,
i.e PIX_FMT_XYZ12
---
 modules/codec/avcodec/chroma.c  |    3 +
 modules/codec/avcodec/video.c   |    1 +
 modules/video_chroma/Modules.am |    5 +
 modules/video_chroma/xyz_rgb.c  |  267 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 276 insertions(+)
 create mode 100644 modules/video_chroma/xyz_rgb.c

diff --git a/modules/codec/avcodec/chroma.c b/modules/codec/avcodec/chroma.c
index f482cf5..39f3a6d 100644
--- a/modules/codec/avcodec/chroma.c
+++ b/modules/codec/avcodec/chroma.c
@@ -118,6 +118,9 @@ static const struct
      /* Paletized RGB */
     {VLC_CODEC_RGBP, PIX_FMT_PAL8, 0, 0, 0},
 
+    /* XYZ */
+    {VLC_CODEC_XYZ12, PIX_FMT_XYZ12, 0xfff0, 0xfff0, 0xfff0},
+
 
     { 0, 0, 0, 0, 0 }
 };
diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index 062068f..41f602b 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -369,6 +369,7 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
         p_dec->i_extra_picture_buffers = 2 * p_sys->p_context->thread_count;
 #endif
 
+    if (i_codec_id == CODEC_ID_JPEG2000)  p_context->pix_fmt = PIX_FMT_XYZ12;
 
     /* ***** misc init ***** */
     p_sys->i_pts = VLC_TS_INVALID;
diff --git a/modules/video_chroma/Modules.am b/modules/video_chroma/Modules.am
index f7195f9..9966393 100644
--- a/modules/video_chroma/Modules.am
+++ b/modules/video_chroma/Modules.am
@@ -34,6 +34,10 @@ SOURCES_yuy2_i420 = \
 
 SOURCES_rv32 = rv32.c
 
+SOURCES_xyz_rgb = \
+	xyz_rgb.c \
+	$(NULL)
+
 libvlc_LTLIBRARIES += \
 	libi420_rgb_plugin.la \
 	libi420_yuy2_plugin.la \
@@ -43,6 +47,7 @@ libvlc_LTLIBRARIES += \
 	libyuy2_i420_plugin.la \
 	libyuy2_i422_plugin.la \
 	librv32_plugin.la \
+	libxyz_rgb_plugin.la \
 	$(NULL)
 
 libchroma_omx_plugin_la_SOURCES = omxdl.c
diff --git a/modules/video_chroma/xyz_rgb.c b/modules/video_chroma/xyz_rgb.c
new file mode 100644
index 0000000..6d53d4a
--- /dev/null
+++ b/modules/video_chroma/xyz_rgb.c
@@ -0,0 +1,267 @@
+/*****************************************************************************
+ * xyz_rgb.c : XYZ to RGB conversion module for VLC
+ *****************************************************************************
+ * Copyright (C) 2013 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Nicolas Bertrand <nico at isf.cc>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include "math.h"
+#include <stdlib.h>
+/* VLC core API headers */
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_filter.h>
+
+
+#define SRC_FOURCC  "XY12,XYZ"
+#define DEST_FOURCC  "RGB32"
+
+#define XYZGAMMA (2.6f)
+#define RGBGAMMA (1.0/2.2f)
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int OpenFilter(vlc_object_t *);
+static void CloseFilter(vlc_object_t *);
+static picture_t *Filter( filter_t *, picture_t * );
+
+static void InitFilter( filter_sys_t *p_sys);
+static void CalcXyz2Rgb(filter_t *p_filter, uint8_t *p_src, uint8_t *p_dst);
+
+//static picture_t *XYZ_RGB_Filter  ( filter_t *, picture_t * );
+
+/*****************************************************************************
+ * Module descriptor.
+ *****************************************************************************/
+vlc_module_begin()
+    set_shortname(N_("XYZ to RGB"))
+    set_description(N_("Conversions from " SRC_FOURCC " to " DEST_FOURCC) )
+    set_capability("video filter2", 200)
+    set_callbacks(OpenFilter, CloseFilter)
+vlc_module_end ()
+
+/*****************************************************************************
+ * Internal strucuture
+ * --------------------
+ *  store LUTs for XYZ and RGB gamma correction
+ *  store values for transformation matrix
+ *****************************************************************************/
+struct filter_sys_t
+{
+    int xyzgamma[4096];
+    int rgbgamma[4096];
+    int matrix[3][3];
+
+   double v_xyzgamma ;
+   double v_rgbgamma ;
+};
+
+/*****************************************************************************
+ * OpenFilter
+ *****************************************************************************
+ * This function alocates and initializes the chroma function
+ *****************************************************************************/
+static int OpenFilter( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t *)p_this;
+    filter_sys_t *p_sys;
+
+    msg_Info(p_this, "Entering XYZ to RGB chroma filter module  , input chroma %4.4s, out format %4.4s",
+            (char *)&p_filter->fmt_in.video.i_chroma, (char *)&p_filter->fmt_out.video.i_chroma);
+
+    if( p_filter->fmt_in.video.i_chroma != VLC_CODEC_XYZ12 ||
+           p_filter->fmt_out.video.i_chroma != VLC_CODEC_RGB32)
+       return VLC_EGENERIC;
+
+    if( p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width
+        || p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height )
+       return VLC_EGENERIC;
+
+    /* Allocate structure */
+    p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
+    if( p_filter->p_sys == NULL )
+        return VLC_ENOMEM;
+    p_sys = p_filter->p_sys;
+
+    p_filter->pf_video_filter = Filter;
+    InitFilter(p_sys);
+
+   msg_Info(p_this, "filter configured and selected");
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * CloseFilter
+ *****************************************************************************
+ * This function frees the previously allocated chroma function
+ *****************************************************************************/
+static void CloseFilter( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t *)p_this;
+
+
+    free( p_filter->p_sys );
+    return;
+}
+
+
+/*****************************************************************************
+ * InitFilter
+ *****************************************************************************
+ * This function initializes XYZ-->RGB filter (LUTs and matrix)
+ *****************************************************************************/
+static void InitFilter( filter_sys_t *p_sys)
+{
+    int i;
+    p_sys->v_xyzgamma = XYZGAMMA;
+    p_sys->v_rgbgamma = RGBGAMMA;
+
+    for (i = 0; i < 4096; i++)
+        {
+        p_sys->xyzgamma[i] = (int)(pow(i/4095.0,p_sys->v_xyzgamma)*4095.0+0.5);
+        p_sys->rgbgamma[i] = (int)(pow(i/4095.0,p_sys->v_rgbgamma)*4095.0+0.5);
+        }
+
+    p_sys->matrix[0][0] = (int)(3.2404542 * 4095.0 + 0.5);
+    p_sys->matrix[0][1] = (int)(- 1.5371385 * 4095.0 - 0.5);
+    p_sys->matrix[0][2] = (int)(- 0.4985314 * 4095.0 - 0.5);
+    p_sys->matrix[1][0] = (int)(- 0.9692660 * 4095.0 - 0.5);
+    p_sys->matrix[1][1] = (int)(1.8760108 * 4095.0 + 0.5);
+    p_sys->matrix[1][2] = (int)(0.0415560 * 4095.0 + 0.5);
+    p_sys->matrix[2][0] = (int)(0.0556434 * 4095.0 + 0.5);
+    p_sys->matrix[2][1] = (int)(- 0.2040259 * 4095.0 - 0.5);
+    p_sys->matrix[2][2] = (int)(1.0572252  * 4095.0 + 0.5);
+}
+
+
+
+/*****************************************************************************
+ * Filter
+ *****************************************************************************
+ * This function is the callback for filtering
+ *****************************************************************************/
+static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+{
+    picture_t *p_pic_dst;
+    filter_sys_t *p_sys=p_filter->p_sys;
+    unsigned int temp;
+
+    int i_plane, i;
+    unsigned int j;
+    int r,g,b,x,y,z;
+
+    /* Request output picture */
+    p_pic_dst = filter_NewPicture( p_filter );
+    if( !p_pic_dst )
+    {
+        picture_Release( p_pic );
+        return NULL;
+    }
+    /* Convert XYZ to RGB32 */
+    for( i_plane = 0; i_plane < p_pic_dst->i_planes; i_plane++ )
+    {
+        uint8_t *p_src = p_pic->p[i_plane].p_pixels;
+        uint8_t *p_dst = p_pic_dst->p[i_plane].p_pixels;
+        unsigned int i_width = p_filter->fmt_out.video.i_width;
+
+        for( i = 0; i < p_pic_dst->p[i_plane].i_lines; i++ )
+        {
+            for( j = 0; j < i_width; j++ )
+            {
+
+                CalcXyz2Rgb(p_filter, p_src, p_dst);
+
+                // XYZ source is stored in 6 bytes
+                p_src += 6;
+                //RGB32 dest is stored in 4 bytes
+                p_dst += 4 ;
+
+
+            }
+            p_src += p_pic->p[i_plane].i_pitch - 6 * i_width;
+            p_dst += p_pic_dst->p[i_plane].i_pitch - 4 * i_width;
+        }
+    }
+
+    picture_CopyProperties( p_pic_dst, p_pic );
+    picture_Release( p_pic );
+
+    return p_pic_dst;
+}
+
+/*****************************************************************************
+ * CalcXyz2Rgb
+ *****************************************************************************
+ * This function convert a pixel from XYZ to RGB
+ *****************************************************************************/
+static void CalcXyz2Rgb(filter_t *p_filter, uint8_t *p_src, uint8_t *p_dst){
+    filter_sys_t *p_sys = p_filter->p_sys;
+    unsigned int temp;
+
+    int r,g,b,x,y,z;
+
+    // read low endian and scale from 16bit to 12bit
+    x = (int) ( (p_src[0] + (p_src[1]<<8) ) >> 4);
+    y = (int) ( (p_src[2] + (p_src[3]<<8) ) >> 4);
+    z = (int) ( (p_src[4] + (p_src[5]<<8) ) >> 4);
+
+    // convert from X'Y'Z' to XYZ (i.e. gamma correction)
+    x = p_sys->xyzgamma[x];
+    y = p_sys->xyzgamma[y];
+    z = p_sys->xyzgamma[z];
+
+    // convert from XYZ to sRGBlinear
+    r = p_sys->matrix[0][0] * x + p_sys->matrix[0][1] * y + p_sys->matrix[0][2] * z >> 12;
+    g = p_sys->matrix[1][0] * x + p_sys->matrix[1][1] * y + p_sys->matrix[1][2] * z >> 12;
+    b = p_sys->matrix[2][0] * x + p_sys->matrix[1][2] * y + p_sys->matrix[2][2] * z >> 12;
+
+    // limit values to 12bit legal values [0..0495]
+    if (r > 4095) r = 4095; if (r < 0) r = 0;
+    if (g > 4095) g = 4095; if (g < 0) g = 0;
+    if (b > 4095) b = 4095; if (b < 0) b = 0;
+
+    // convert from sRGBlinear to sRGB
+    r = p_sys->rgbgamma[r] ;
+    g = p_sys->rgbgamma[g] ;
+    b = p_sys->rgbgamma[b] ;
+
+
+    // Scale to 8 bits value and store
+    p_dst[0] =  (uint8_t) (r >> 4);
+    p_dst[1] =  (uint8_t) (g >> 4);
+    p_dst[2] =  (uint8_t) (b >> 4);
+
+    // As we convert to RGB32 set alpha to 1
+    p_dst[3] = 0xff;  /* Alpha */
+
+
+
+
+}
+
-- 
1.7.9.5




More information about the vlc-devel mailing list