[MOVED FROM BAD 47/68] colorspace: Add support for 8 bit paletted RGB
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 2 Nov 2010 15:05:37 +0000 (16:05 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Wed, 15 Jun 2011 14:12:55 +0000 (16:12 +0200)
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
gst/colorspace/colorspace.h
gst/colorspace/gstcolorspace.c
gst/colorspace/gstcolorspace.h

index a20f5e2..8541767 100644 (file)
@@ -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
index ee2f548..b12b032 100644 (file)
@@ -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);
index dd2e03d..e39814a 100644 (file)
 #include "gstcolorspace.h"
 #include <gst/video/video.h>
 
+#include <string.h>
+
 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
index 9dcdb5e..c97705c 100644 (file)
@@ -54,7 +54,6 @@ struct _GstCsp {
   ColorSpaceColorSpec from_spec;
   GstVideoFormat to_format;
   ColorSpaceColorSpec to_spec;
-  guint32 *palette;
 
   ColorspaceConvert *convert;
 };