[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