From 50fa9610b1e59e1db7c9b0cdd037ff19bcb31f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 2 Nov 2010 16:05:37 +0100 Subject: [PATCH] colorspace: Add support for 8 bit paletted RGB This needs the 8 bit paletted support from -base which will be committed after release. Without this the 8 bit parts are disabled. --- gst/colorspace/colorspace.c | 72 +++++++++++++++++++++++++++++++++- gst/colorspace/colorspace.h | 3 +- gst/colorspace/gstcolorspace.c | 61 +++++++++++++++++++++------- gst/colorspace/gstcolorspace.h | 1 - 4 files changed, 120 insertions(+), 17 deletions(-) diff --git a/gst/colorspace/colorspace.c b/gst/colorspace/colorspace.c index a20f5e26df..8541767314 100644 --- a/gst/colorspace/colorspace.c +++ b/gst/colorspace/colorspace.c @@ -61,6 +61,7 @@ colorspace_convert_new (GstVideoFormat to_format, ColorSpaceColorSpec to_spec, || gst_video_format_is_yuv (from_format) || (gst_video_format_is_gray (from_format) && from_spec == COLOR_SPEC_GRAY), NULL); + g_return_val_if_fail (to_format != from_format, NULL); convert = g_malloc (sizeof (ColorspaceConvert)); memset (convert, 0, sizeof (ColorspaceConvert)); @@ -98,6 +99,30 @@ colorspace_convert_new (GstVideoFormat to_format, ColorSpaceColorSpec to_spec, convert->tmpline = g_malloc (sizeof (guint32) * width * 2); +#ifdef GST_VIDEO_CAPS_RGB8_PALETTED + if (to_format == GST_VIDEO_FORMAT_RGB8_PALETTED) { + /* build poor man's palette, taken from ffmpegcolorspace */ + static const guint8 pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff }; + guint32 *palette; + gint r, g, b; + + convert->palette = palette = g_new (guint32, 256); + i = 0; + for (r = 0; r < 6; r++) { + for (g = 0; g < 6; g++) { + for (b = 0; b < 6; b++) { + palette[i++] = + (0xffU << 24) | (pal_value[r] << 16) | (pal_value[g] << 8) | + pal_value[b]; + } + } + } + palette[i++] = 0; /* 100% transparent, i == 6*6*6 */ + while (i < 256) + palette[i++] = 0xff000000; + } +#endif + return convert; } @@ -120,7 +145,8 @@ colorspace_convert_set_interlaced (ColorspaceConvert * convert, } void -colorspace_convert_set_palette (ColorspaceConvert * convert, guint32 * palette) +colorspace_convert_set_palette (ColorspaceConvert * convert, + const guint32 * palette) { if (convert->palette == NULL) { convert->palette = g_malloc (sizeof (guint32) * 256); @@ -128,6 +154,12 @@ colorspace_convert_set_palette (ColorspaceConvert * convert, guint32 * palette) memcpy (convert->palette, palette, sizeof (guint32) * 256); } +const guint32 * +colorspace_convert_get_palette (ColorspaceConvert * convert) +{ + return convert->palette; +} + void colorspace_convert_convert (ColorspaceConvert * convert, guint8 * dest, const guint8 * src) @@ -850,6 +882,41 @@ putline_A420 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, FRAME_GET_LINE (dest, 3, j), src, convert->width / 2); } +#ifdef GST_VIDEO_CAPS_RGB8_PALETTED +static void +getline_RGB8P (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, + int j) +{ + int i; + const guint8 *srcline = FRAME_GET_LINE (src, 0, j); + for (i = 0; i < convert->width; i++) { + guint32 v = convert->palette[srcline[i]]; + dest[i * 4 + 0] = (v >> 24) & 0xff; + dest[i * 4 + 1] = (v >> 16) & 0xff; + dest[i * 4 + 2] = (v >> 8) & 0xff; + dest[i * 4 + 3] = (v) & 0xff; + } +} + +static void +putline_RGB8P (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, + int j) +{ + int i; + guint8 *destline = FRAME_GET_LINE (dest, 0, j); + /* Use our poor man's palette, taken from ffmpegcolorspace too */ + for (i = 0; i < convert->width; i++) { + /* crude approximation for alpha ! */ + if (src[i * 4 + 0] < 0x80) + destline[i] = 6 * 6 * 6; + else + destline[i] = + ((((src[i * 4 + 1]) / 47) % 6) * 6 * 6 + (((src[i * 4 + + 2]) / 47) % 6) * 6 + (((src[i * 4 + 3]) / 47) % 6)); + } +} +#endif + typedef struct { GstVideoFormat format; @@ -894,6 +961,9 @@ static const ColorspaceLine lines[] = { {GST_VIDEO_FORMAT_BGR15, getline_BGR15, putline_BGR15}, {GST_VIDEO_FORMAT_UYVP, getline_UYVP, putline_UYVP}, {GST_VIDEO_FORMAT_A420, getline_A420, putline_A420} +#ifdef GST_VIDEO_CAPS_RGB8_PALETTED + , {GST_VIDEO_FORMAT_RGB8_PALETTED, getline_RGB8P, putline_RGB8P} +#endif }; static void diff --git a/gst/colorspace/colorspace.h b/gst/colorspace/colorspace.h index ee2f548fbe..b12b032df9 100644 --- a/gst/colorspace/colorspace.h +++ b/gst/colorspace/colorspace.h @@ -69,7 +69,8 @@ ColorspaceConvert * colorspace_convert_new (GstVideoFormat to_format, void colorspace_convert_set_interlaced (ColorspaceConvert *convert, gboolean interlaced); void colorspace_convert_set_palette (ColorspaceConvert *convert, - guint32 *palette); + const guint32 *palette); +const guint32 * colorspace_convert_get_palette (ColorspaceConvert *convert); void colorspace_convert_free (ColorspaceConvert * convert); void colorspace_convert_convert (ColorspaceConvert * convert, guint8 *dest, const guint8 *src); diff --git a/gst/colorspace/gstcolorspace.c b/gst/colorspace/gstcolorspace.c index dd2e03da0f..e39814a0a9 100644 --- a/gst/colorspace/gstcolorspace.c +++ b/gst/colorspace/gstcolorspace.c @@ -40,10 +40,20 @@ #include "gstcolorspace.h" #include +#include + GST_DEBUG_CATEGORY (colorspace_debug); #define GST_CAT_DEFAULT colorspace_debug GST_DEBUG_CATEGORY (colorspace_performance); +#ifndef GST_VIDEO_CAPS_RGB8_PALETTED +#define GST_VIDEO_CAPS_RGB8_PALETTED \ + "video/x-raw-rgb, bpp = (int)8, depth = (int)8, " \ + "width = "GST_VIDEO_SIZE_RANGE" , " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = "GST_VIDEO_FPS_RANGE +#endif + #define CSP_VIDEO_CAPS \ "video/x-raw-yuv, width = "GST_VIDEO_SIZE_RANGE" , " \ "height="GST_VIDEO_SIZE_RANGE",framerate="GST_VIDEO_FPS_RANGE"," \ @@ -62,10 +72,7 @@ GST_DEBUG_CATEGORY (colorspace_performance); GST_VIDEO_CAPS_BGR_16";" \ GST_VIDEO_CAPS_RGB_15";" \ GST_VIDEO_CAPS_BGR_15";" \ - "video/x-raw-rgb, bpp = (int)8, depth = (int)8, " \ - "width = "GST_VIDEO_SIZE_RANGE" , " \ - "height = " GST_VIDEO_SIZE_RANGE ", " \ - "framerate = "GST_VIDEO_FPS_RANGE ";" \ + GST_VIDEO_CAPS_RGB8_PALETTED";" \ GST_VIDEO_CAPS_GRAY8";" \ GST_VIDEO_CAPS_GRAY16("BIG_ENDIAN")";" \ GST_VIDEO_CAPS_GRAY16("LITTLE_ENDIAN")";" @@ -306,11 +313,34 @@ gst_csp_set_caps (GstBaseTransform * btrans, GstCaps * incaps, if (space->convert) { colorspace_convert_set_interlaced (space->convert, in_interlaced); } - +#ifdef GST_VIDEO_CAPS_RGB8_PALETTED /* palette, only for from data */ - /* FIXME add palette handling */ -#if 0 - colorspace_convert_set_palette (convert, palette); + if (space->from_format == GST_VIDEO_FORMAT_RGB8_PALETTED && + space->to_format == GST_VIDEO_FORMAT_RGB8_PALETTED) { + goto format_mismatch; + } else if (space->from_format == GST_VIDEO_FORMAT_RGB8_PALETTED) { + GstBuffer *palette; + + palette = gst_video_parse_caps_palette (incaps); + + if (!palette || GST_BUFFER_SIZE (palette) < 256 * 4) { + if (palette) + gst_buffer_unref (palette); + goto invalid_palette; + } + colorspace_convert_set_palette (space->convert, + (const guint32 *) GST_BUFFER_DATA (palette)); + gst_buffer_unref (palette); + } else if (space->to_format == GST_VIDEO_FORMAT_RGB8_PALETTED) { + const guint32 *palette; + GstBuffer *p_buf; + + palette = colorspace_convert_get_palette (space->convert); + p_buf = gst_buffer_new_and_alloc (256 * 4); + memcpy (GST_BUFFER_DATA (p_buf), palette, 256 * 4); + gst_caps_set_simple (outcaps, "palette_data", GST_TYPE_BUFFER, p_buf, NULL); + gst_buffer_unref (p_buf); + } #endif GST_DEBUG ("reconfigured %d %d", space->from_format, space->to_format); @@ -339,6 +369,15 @@ format_mismatch: space->to_format = GST_VIDEO_FORMAT_UNKNOWN; return FALSE; } +#ifdef GST_VIDEO_CAPS_RGB8_PALETTED +invalid_palette: + { + GST_ERROR_OBJECT (space, "invalid palette"); + space->from_format = GST_VIDEO_FORMAT_UNKNOWN; + space->to_format = GST_VIDEO_FORMAT_UNKNOWN; + return FALSE; + } +#endif } GST_BOILERPLATE (GstCsp, gst_csp, GstVideoFilter, GST_TYPE_VIDEO_FILTER); @@ -366,11 +405,6 @@ gst_csp_base_init (gpointer klass) static void gst_csp_finalize (GObject * obj) { - GstCsp *space = GST_CSP (obj); - - if (space->palette) - g_free (space->palette); - G_OBJECT_CLASS (parent_class)->finalize (obj); } @@ -398,7 +432,6 @@ gst_csp_init (GstCsp * space, GstCspClass * klass) { space->from_format = GST_VIDEO_FORMAT_UNKNOWN; space->to_format = GST_VIDEO_FORMAT_UNKNOWN; - space->palette = NULL; } static gboolean diff --git a/gst/colorspace/gstcolorspace.h b/gst/colorspace/gstcolorspace.h index 9dcdb5e25f..c97705ceac 100644 --- a/gst/colorspace/gstcolorspace.h +++ b/gst/colorspace/gstcolorspace.h @@ -54,7 +54,6 @@ struct _GstCsp { ColorSpaceColorSpec from_spec; GstVideoFormat to_format; ColorSpaceColorSpec to_spec; - guint32 *palette; ColorspaceConvert *convert; };