Reworked the colorspace converter and the scaler API.
authorWim Taymans <wim.taymans@gmail.com>
Mon, 12 Jun 2000 21:27:19 +0000 (21:27 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Mon, 12 Jun 2000 21:27:19 +0000 (21:27 +0000)
Original commit message from CVS:
Reworked the colorspace converter and the scaler API.
Fixed some MMX bugs in the mpeg encoder.

libs/colorspace/gstcolorspace.c
libs/colorspace/gstcolorspace.h
libs/colorspace/rgb2rgb.c
libs/colorspace/yuv2rgb.c
libs/colorspace/yuv2rgb.h
libs/videoscale/Makefile.am
libs/videoscale/gstvideoscale.c
libs/videoscale/gstvideoscale.h
test/mp1parse.c
test/mp2tomp1.c

index aa9e2ac..058bc13 100644 (file)
 
 #include <gstcolorspace.h>
 
-extern GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace srcspace, 
-                                                                     GstColorSpace destspace);
-extern GstColorSpaceConverter gst_colorspace_yuv2rgb_get_converter(GstColorSpace srcspace, 
-                                                                     GstColorSpace destspace);
-extern GstColorSpaceConverter gst_colorspace_rgb2yuv_get_converter(GstColorSpace srcspace, 
-                                                                     GstColorSpace destspace);
-extern GstColorSpaceConverter gst_colorspace_yuv2yuv_get_converter(GstColorSpace srcspace, 
-                                                                     GstColorSpace destspace);
-
-GstBuffer *gst_colorspace_convert(GstBuffer *src, GstColorSpace dest) {
-  switch (dest) {
-    default:
-      break;
-  }
 
-  return src;
-}
+extern GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace *space, GstColorSpaceType srcspace, 
+                                                                     GstColorSpaceType destspace);
+extern GstColorSpaceConverter gst_colorspace_yuv2rgb_get_converter(GstColorSpace *space, GstColorSpaceType srcspace, 
+                                                                     GstColorSpaceType destspace);
+extern GstColorSpaceConverter gst_colorspace_rgb2yuv_get_converter(GstColorSpace *space, GstColorSpaceType srcspace, 
+                                                                     GstColorSpaceType destspace);
+extern GstColorSpaceConverter gst_colorspace_yuv2yuv_get_converter(GstColorSpace *space, GstColorSpaceType srcspace, 
+                                                                     GstColorSpaceType destspace);
+
+GstColorSpace *gst_colorspace_new(int width, int height, GstColorSpaceType srcspace, GstColorSpaceType destspace, GdkVisual *destvisual) 
+{
+
+  GstColorSpace *new = g_malloc(sizeof(GstColorSpace));
 
-GstColorSpaceConverter gst_colorspace_get_converter(GstColorSpace srcspace, GstColorSpace destspace) {
-  DEBUG("gst_colorspace: get converter\n");
+  new->width = width;
+  new->height = height;
+  new->srcspace = srcspace;
+  new->destspace = destspace;
+  new->visual = destvisual;
+  new->convert = NULL;
+
+  DEBUG("gst_colorspace: new\n");
   if (GST_COLORSPACE_IS_RGB_TYPE(srcspace)) {
     if (GST_COLORSPACE_IS_RGB_TYPE(destspace)) {
-      return gst_colorspace_rgb2rgb_get_converter(srcspace, destspace);
+      new->convert =  gst_colorspace_rgb2rgb_get_converter(new, srcspace, destspace);
     }
     else {
       //return gst_colorspace_rgb2yuv_get_converter(srcspace, destspace);
@@ -52,12 +55,20 @@ GstColorSpaceConverter gst_colorspace_get_converter(GstColorSpace srcspace, GstC
   }
   else if (GST_COLORSPACE_IS_YUV_TYPE(srcspace)) {
     if (GST_COLORSPACE_IS_RGB_TYPE(destspace)) {
-      return gst_colorspace_yuv2rgb_get_converter(srcspace, destspace);
+      new->convert =  gst_colorspace_yuv2rgb_get_converter(new, srcspace, destspace);
     }
     else {
       //return gst_colorspace_yuv2yuv_get_converter(srcspace, destspace);
     }
   }
-  g_print("gst_colorspace: conversion not implemented\n");
-  return NULL;
+  if (new->convert == NULL) {
+    g_print("gst_colorspace: conversion not implemented\n");
+  }
+  return new;
+}
+
+void gst_colorspace_destroy(GstColorSpace *space) 
+{
+  if (space->color_tables) g_free(space->color_tables);
+  g_free(space);
 }
index 5002433..01ee2fe 100644 (file)
@@ -25,8 +25,9 @@
 #include <gst/gstbuffer.h>
 #include <gst/gstplugin.h>
 
-typedef enum {
+#include "yuv2rgb.h"
 
+typedef enum {
 #define GST_COLORSPACE_RGB_FIRST GST_COLORSPACE_RGB555
   GST_COLORSPACE_RGB555,
   GST_COLORSPACE_BGR555,
@@ -45,15 +46,22 @@ typedef enum {
   GST_COLORSPACE_YUV422P,
 #define GST_COLORSPACE_YUV_LAST GST_COLORSPACE_YUV422P
 
-} GstColorSpace;
+} GstColorSpaceType;
 
-typedef struct _GstColorSpaceParameters GstColorSpaceParameters;
+typedef struct _GstColorSpace GstColorSpace;
+typedef void (*GstColorSpaceConverter) (GstColorSpace *space, unsigned char *src, unsigned char *dest);
 
-struct _GstColorSpaceParameters {
+struct _GstColorSpace {
   guint width;
   guint height;
-  gchar *outbuf;
+  GstColorSpaceType srcspace;
+  GstColorSpaceType destspace;
   GdkVisual *visual;
+  guint insize;
+  guint outsize;
+  /* private */
+  GstColorSpaceYUVTables *color_tables;
+  GstColorSpaceConverter convert;
 };
 
 
@@ -62,11 +70,7 @@ struct _GstColorSpaceParameters {
 #define GST_COLORSPACE_IS_YUV_TYPE(type) ((type)>=GST_COLORSPACE_YUV_FIRST && \
                                          (type)<=GST_COLORSPACE_YUV_LAST)
 
-typedef GstBuffer * (*GstColorSpaceConverter) (GstBuffer *src, GstColorSpaceParameters *params);
-
-GstColorSpaceConverter gst_colorspace_get_converter(GstColorSpace srcspace, GstColorSpace destspace);
-
-/* convert a buffer to a new buffer in the given colorspace */
-GstBuffer *gst_colorspace_convert(GstBuffer *buf, GstColorSpace destspace);
+GstColorSpace *gst_colorspace_new(int width, int height, GstColorSpaceType srcspace, GstColorSpaceType destspace, GdkVisual *destvisual);
+void gst_colorspace_destroy(GstColorSpace *space);
 
 #endif /* __GST_COLORSPACE_H__ */
index b9c605f..892e30a 100644 (file)
 #include <gst/gst.h>
 #include <gstcolorspace.h>
 
-static GstBuffer *gst_colorspace_rgb24_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_rgb_to_rgb_identity(GstBuffer *src, GstColorSpaceParameters *params);
+static void gst_colorspace_rgb_to_rgb_identity(GstColorSpace *space, unsigned char *src, unsigned char *dest); 
+static void gst_colorspace_rgb24_to_bgr24(GstColorSpace *space, unsigned char *src, unsigned char *dest);
 
-GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace src, GstColorSpace dest) {
+GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace *space, GstColorSpaceType src, GstColorSpaceType dest) {
   switch(src) {
     case GST_COLORSPACE_RGB24:
+      space->insize = space->width*space->height*3;
       switch(dest) {
         case GST_COLORSPACE_RGB24:
+         space->outsize = space->width*space->height*3;
           return gst_colorspace_rgb_to_rgb_identity;
         case GST_COLORSPACE_BGR24:
+         space->outsize = space->width*space->height*3;
           return gst_colorspace_rgb24_to_bgr24;
        default:
          break;
       }
       break;
     case GST_COLORSPACE_BGR24:
+      space->insize = space->width*space->height*3;
       switch(dest) {
         case GST_COLORSPACE_RGB24:
+         space->outsize = space->width*space->height*3;
           return gst_colorspace_rgb24_to_bgr24;
         case GST_COLORSPACE_BGR24:
+         space->outsize = space->width*space->height*3;
           return gst_colorspace_rgb_to_rgb_identity;
        default:
          break;
@@ -54,35 +60,36 @@ GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace src, G
   return NULL;
 }
 
-static GstBuffer *gst_colorspace_rgb_to_rgb_identity(GstBuffer *src, GstColorSpaceParameters *params) {
-  return src;
+static void gst_colorspace_rgb_to_rgb_identity(GstColorSpace *space, unsigned char *src, unsigned char *dest) 
+{
+  memcpy(dest, src, space->outsize);
 }
 
-static GstBuffer *gst_colorspace_rgb24_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params) {
+static void gst_colorspace_rgb24_to_bgr24(GstColorSpace *space, unsigned char *src, unsigned char *dest) 
+{
   gint size;
   gchar temp;
-  gchar *data;
 
-  DEBUG("gst_colorspace_rgb24_to_bgr24 %d\n", GST_BUFFER_SIZE(src));
+  DEBUG("gst_colorspace_rgb24_to_bgr24\n");
 
-  size = GST_BUFFER_SIZE(src)/3;
+  size = space->outsize;
 
-  if (params != NULL && params->outbuf != NULL) {
-    data = params->outbuf;
-    DEBUG("gst_colorspace: to buffer %p\n", data);
+  if (src == dest) {
+    while (size--) {
+      temp = src[0];
+      src[0] = src[2];
+      src[2] = temp;
+      src+=3;
+    }
   }
   else {
-    data = GST_BUFFER_DATA(src);
+    while (size--) {
+      *dest++ = src[2];
+      *dest++ = src[1];
+      *dest++ = src[0];
+      src+=3;
+    }
   }
-
-  while (size--) {
-    temp = data[0];
-    data[0] = data[2];
-    data[2] = temp;
-    data+=3;
-  }
-  DEBUG("gst_colorspace_rgb24_to_bgr24 end %d\n", GST_BUFFER_SIZE(src));
-
-  return src;
+  DEBUG("gst_colorspace_rgb24_to_bgr24 end\n");
 }
 
index 5d584f5..b65bbd4 100644 (file)
 
 #include "yuv2rgb.h"
 
-static GstBuffer *gst_colorspace_yuv420P_to_rgb32(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_yuv420P_to_bgr32(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_yuv420P_to_bgr32_mmx(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_yuv420P_to_rgb24(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_yuv420P_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_yuv420P_to_rgb16(GstBuffer *src, GstColorSpaceParameters *params);
-static GstBuffer *gst_colorspace_yuv420P_to_bgr16_mmx(GstBuffer *src, GstColorSpaceParameters *params);
+static void gst_colorspace_yuv420P_to_rgb32(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_yuv420P_to_bgr32(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_yuv420P_to_bgr32_mmx(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_yuv420P_to_rgb24(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_yuv420P_to_bgr24(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_yuv420P_to_rgb16(GstColorSpace *space, unsigned char *src, unsigned char *dest);
+static void gst_colorspace_yuv420P_to_bgr16_mmx(GstColorSpace *space, unsigned char *src, unsigned char *dest);
 
 static void gst_colorspace_yuv_to_rgb16(GstColorSpaceYUVTables *tables,
                                        unsigned char *lum,
@@ -76,25 +76,38 @@ static void gst_colorspace_yuv_to_bgr16_mmx(GstColorSpaceYUVTables *tables,
 static GstColorSpaceYUVTables * gst_colorspace_init_yuv(long depth, 
                                                long red_mask, long green_mask, long blue_mask);
 
-GstColorSpaceConverter gst_colorspace_yuv2rgb_get_converter(GstColorSpace src, GstColorSpace dest) {
-  DEBUG("gst_colorspace_yuv2rgb_get_converter %d\n", dest);
+GstColorSpaceConverter gst_colorspace_yuv2rgb_get_converter(GstColorSpace *space, GstColorSpaceType src, GstColorSpaceType dest) {
+  DEBUG("gst_colorspace_yuv2rgb_get_converter %d %d\n", src, dest);
   switch(src) {
     case GST_COLORSPACE_YUV420P:
+      space->insize = space->width*space->height+space->width*space->height/2;
       switch(dest) {
         case GST_COLORSPACE_BGR32:
+          space->color_tables = gst_colorspace_init_yuv(32, 0xFF0000, 0x00FF00, 0x0000FF);
+          space->outsize = space->width*space->height*4;
           //return gst_colorspace_yuv420P_to_bgr32;
           return gst_colorspace_yuv420P_to_bgr32_mmx;
         case GST_COLORSPACE_RGB32:
+          space->color_tables = gst_colorspace_init_yuv(32, 0x0000FF, 0x00FF00, 0xFF0000);
+          space->outsize = space->width*space->height*4;
           return gst_colorspace_yuv420P_to_rgb32;
         case GST_COLORSPACE_RGB24:
+          space->color_tables = gst_colorspace_init_yuv(24, 0x0000FF, 0x00FF00, 0xFF0000);
+          space->outsize = space->width*space->height*3;
           return gst_colorspace_yuv420P_to_rgb24;
         case GST_COLORSPACE_BGR24:
+          space->color_tables = gst_colorspace_init_yuv(24, 0xFF0000, 0x00FF00, 0x0000FF);
+          space->outsize = space->width*space->height*3;
           return gst_colorspace_yuv420P_to_bgr24;
         case GST_COLORSPACE_RGB555:
         case GST_COLORSPACE_RGB565:
         case GST_COLORSPACE_BGR555:
+          g_return_val_if_fail(space->visual != NULL, NULL);
+          space->color_tables = gst_colorspace_init_yuv(16, space->visual->red_mask, space->visual->green_mask, space->visual->blue_mask);
+          space->outsize = space->width*space->height*2;
           return gst_colorspace_yuv420P_to_rgb16;
         case GST_COLORSPACE_BGR565:
+          space->outsize = space->width*space->height*2;
           return gst_colorspace_yuv420P_to_bgr16_mmx;
        default:
          break;
@@ -107,221 +120,122 @@ GstColorSpaceConverter gst_colorspace_yuv2rgb_get_converter(GstColorSpace src, G
   return NULL;
 }
 
-static GstBuffer *gst_colorspace_yuv420P_to_bgr32(GstBuffer *src, GstColorSpaceParameters *params) {
-  static GstColorSpaceYUVTables *color_tables = NULL;
+static void gst_colorspace_yuv420P_to_bgr32(GstColorSpace *space, unsigned char *src, unsigned char *dest) 
+{
   int size;
-  GstBuffer *buf = NULL;
-  guchar *out;
   DEBUG("gst_colorspace_yuv420P_to_bgr32\n");
 
-  g_return_val_if_fail(params != NULL, NULL);
+  size = space->width * space->height;
+
+  gst_colorspace_yuv_to_rgb32(space->color_tables,
+                       src,                                    // Y component
+                        src+size,                              // cr component
+                       src+size+(size>>2),                     // cb component
+                        dest,
+                       space->height,
+                       space->width);
 
-  if (color_tables == NULL) {
-    color_tables = gst_colorspace_init_yuv(32, 0xFF0000, 0x00FF00, 0x0000FF);
-  }
-  size = params->width * params->height;
-  if (params->outbuf == NULL) {
-    buf = gst_buffer_new();
-    out = GST_BUFFER_DATA(buf) = g_malloc(size * 4);
-    GST_BUFFER_SIZE(buf) = size * 4;
-  }
-  else out = params->outbuf;
-
-  gst_colorspace_yuv_to_rgb32(color_tables,
-                       GST_BUFFER_DATA(src),                                   // Y component
-                        GST_BUFFER_DATA(src)+size,                                     // cr component
-                       GST_BUFFER_DATA(src)+size+(size>>2),                    // cb component
-                        out,
-                       params->height,
-                       params->width);
-
-  if (buf) {
-    gst_buffer_unref(src);
-    return buf;
-  }
-  else return src;
 }
 
-static GstBuffer *gst_colorspace_yuv420P_to_rgb32(GstBuffer *src, GstColorSpaceParameters *params) {
-  static GstColorSpaceYUVTables *color_tables = NULL;
+static void gst_colorspace_yuv420P_to_rgb32(GstColorSpace *space, unsigned char *src, unsigned char *dest) 
+{
   int size;
-  GstBuffer *buf = NULL;
-  guchar *out;
   DEBUG("gst_colorspace_yuv420P_to_rgb32\n");
 
-  g_return_val_if_fail(params != NULL, NULL);
 
-  if (color_tables == NULL) {
-    color_tables = gst_colorspace_init_yuv(32, 0x0000FF, 0x00FF00, 0xFF0000);
-  }
-  size = params->width * params->height;
-  if (params->outbuf == NULL) {
-    buf = gst_buffer_new();
-    out = GST_BUFFER_DATA(buf) = g_malloc(size * 4);
-    GST_BUFFER_SIZE(buf) = size * 4;
-  }
-  else out = params->outbuf;
-
-  gst_colorspace_yuv_to_rgb32(color_tables,
-                       GST_BUFFER_DATA(src),                                   // Y component
-                        GST_BUFFER_DATA(src)+size,                                     // cr component
-                       GST_BUFFER_DATA(src)+size+(size>>2),                    // cb component
-                        out,
-                       params->height,
-                       params->width);
-
-  if (buf) {
-    gst_buffer_unref(src);
-    return buf;
-  }
-  else return src;
+  size = space->width * space->height;
+
+  gst_colorspace_yuv_to_rgb32(space->color_tables,
+                       src,                                    // Y component
+                        src+size,                              // cr component
+                       src+size+(size>>2),                     // cb component
+                        dest,
+                       space->height,
+                       space->width);
+
 }
 
-static GstBuffer *gst_colorspace_yuv420P_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params) {
-  static GstColorSpaceYUVTables *color_tables = NULL;
+static void gst_colorspace_yuv420P_to_bgr24(GstColorSpace *space, unsigned char *src, unsigned char *dest) {
   int size;
-  GstBuffer *buf = NULL;
-  guchar *out;
   DEBUG("gst_colorspace_yuv420P_to_bgr24\n");
 
-  g_return_val_if_fail(params != NULL, NULL);
+  size = space->width * space->height;
 
-  if (color_tables == NULL) {
-    color_tables = gst_colorspace_init_yuv(24, 0xFF0000, 0x00FF00, 0x0000FF);
-  }
-  size = params->width * params->height;
-  if (params->outbuf == NULL) {
-    buf = gst_buffer_new();
-    out = GST_BUFFER_DATA(buf) = g_malloc(size * 3);
-    GST_BUFFER_SIZE(buf) = size * 3;
-  }
-  else out = params->outbuf;
-
-  gst_colorspace_yuv_to_rgb24(color_tables,
-                       GST_BUFFER_DATA(src),                                   // Y component
-                        GST_BUFFER_DATA(src)+size,                                     // cr component
-                       GST_BUFFER_DATA(src)+size+(size>>2),                    // cb component
-                        out,
-                       params->height,
-                       params->width);
-  if (buf) {
-    gst_buffer_unref(src);
-    return buf;
-  }
-  else return src;
+  gst_colorspace_yuv_to_rgb24(space->color_tables,
+                       src,                                    // Y component
+                        src+size,                              // cr component
+                       src+size+(size>>2),                     // cb component
+                        dest,
+                       space->height,
+                       space->width);
 }
 
-static GstBuffer *gst_colorspace_yuv420P_to_rgb24(GstBuffer *src, GstColorSpaceParameters *params) {
-  static GstColorSpaceYUVTables *color_tables = NULL;
+static void gst_colorspace_yuv420P_to_rgb24(GstColorSpace *space, unsigned char *src, unsigned char *dest) {
   int size;
-  GstBuffer *buf = NULL;
-  guchar *out;
   DEBUG("gst_colorspace_yuv420P_to_rgb24\n");
 
-  g_return_val_if_fail(params != NULL, NULL);
+  size = space->width * space->height;
+
+  gst_colorspace_yuv_to_rgb24(space->color_tables,
+                       src,                                    // Y component
+                        src+size,                              // cr component
+                       src+size+(size>>2),                     // cb component
+                        dest,
+                       space->height,
+                       space->width);
 
-  if (color_tables == NULL) {
-    color_tables = gst_colorspace_init_yuv(24, 0x0000FF, 0x00FF00, 0xFF0000);
-  }
-  size = params->width * params->height;
-  if (params->outbuf == NULL) {
-    buf = gst_buffer_new();
-    out = GST_BUFFER_DATA(buf) = g_malloc(size * 3);
-    GST_BUFFER_SIZE(buf) = size * 3;
-  }
-  else out = params->outbuf;
-
-  gst_colorspace_yuv_to_rgb24(color_tables,
-                       GST_BUFFER_DATA(src),                                   // Y component
-                        GST_BUFFER_DATA(src)+size,                                     // cr component
-                       GST_BUFFER_DATA(src)+size+(size>>2),                    // cb component
-                        out,
-                       params->height,
-                       params->width);
-
-  if (buf) {
-    gst_buffer_unref(src);
-    return buf;
-  }
-  else return src;
 }
 
-static GstBuffer *gst_colorspace_yuv420P_to_rgb16(GstBuffer *src, GstColorSpaceParameters *params) {
-  static GstColorSpaceYUVTables *color_tables = NULL;
+static void gst_colorspace_yuv420P_to_rgb16(GstColorSpace *space, unsigned char *src, unsigned char *dest) {
   int size;
   DEBUG("gst_colorspace_yuv420P_to_rgb16\n");
 
-  g_return_val_if_fail(params != NULL, NULL);
-  g_return_val_if_fail(params->visual != NULL, NULL);
-
-  if (color_tables == NULL) {
-    color_tables = gst_colorspace_init_yuv(16, params->visual->red_mask, params->visual->green_mask, params->visual->blue_mask);
-  }
-  size = params->width * params->height;
+  size = space->width * space->height;
 
-  gst_colorspace_yuv_to_rgb16(color_tables,
-                       GST_BUFFER_DATA(src),                                   // Y component
-                        GST_BUFFER_DATA(src)+size,                                     // cr component
-                       GST_BUFFER_DATA(src)+size+(size>>2),                    // cb component
-                        params->outbuf,
-                       params->height,
-                       params->width);
+  gst_colorspace_yuv_to_rgb16(space->color_tables,
+                       src,                                    // Y component
+                        src+size,                              // cr component
+                       src+size+(size>>2),                     // cb component
+                        dest,
+                       space->height,
+                       space->width);
 
-  return src;
 }
 
 #ifdef HAVE_LIBMMX
 static mmx_t MMX16_redmask   = (mmx_t)(long long)0xf800f800f800f800LL;             //dd    07c00 7c00h, 07c007c00h
 static mmx_t MMX16_grnmask   = (mmx_t)(long long)0x07e007e007e007e0LL;                 //dd    003e0 03e0h, 003e003e0h
 
-static GstBuffer *gst_colorspace_yuv420P_to_bgr32_mmx(GstBuffer *src, GstColorSpaceParameters *params) {
+static void gst_colorspace_yuv420P_to_bgr32_mmx(GstColorSpace *space, unsigned char *src, unsigned char *dest) {
   int size;
-  GstBuffer *buf = NULL;
-  guchar *out;
   DEBUG("gst_colorspace_yuv420P_to_rgb32_mmx\n");
 
-  g_return_val_if_fail(params != NULL, NULL);
-
-  size = params->width * params->height;
-  if (params->outbuf == NULL) {
-    buf = gst_buffer_new();
-    out = GST_BUFFER_DATA(buf) = g_malloc(size * 4);
-    GST_BUFFER_SIZE(buf) = size * 4;
-  }
-  else out = params->outbuf;
+  size = space->width * space->height;
 
   gst_colorspace_yuv_to_bgr32_mmx(NULL,
-                       GST_BUFFER_DATA(src),                                   // Y component
-                        GST_BUFFER_DATA(src)+size,                                     // cr component
-                       GST_BUFFER_DATA(src)+size+(size>>2),                    // cb component
-                        out,
-                       params->height,
-                       params->width);
-
-  if (buf) {
-    gst_buffer_unref(src);
-    return buf;
-  }
-  else return src;
+                       src,                                    // Y component
+                        src+size,                              // cr component
+                       src+size+(size>>2),                     // cb component
+                        dest,
+                       space->height,
+                       space->width);
+
 }
-static GstBuffer *gst_colorspace_yuv420P_to_bgr16_mmx(GstBuffer *src, GstColorSpaceParameters *params) {
+static void gst_colorspace_yuv420P_to_bgr16_mmx(GstColorSpace *space, unsigned char *src, unsigned char *dest) {
   int size;
   DEBUG("gst_colorspace_yuv420P_to_bgr16_mmx \n");
 
-  g_return_val_if_fail(params != NULL, NULL);
-
-  size = params->width * params->height;
+  size = space->width * space->height;
 
   gst_colorspace_yuv_to_bgr16_mmx(NULL,
-                       GST_BUFFER_DATA(src),                                   // Y component
-                        GST_BUFFER_DATA(src)+size,                                     // cr component
-                       GST_BUFFER_DATA(src)+size+(size>>2),                    // cb component
-                        params->outbuf,
-                       params->height,
-                       params->width);
+                       src,                                    // Y component
+                        src+size,                              // cr component
+                       src+size+(size>>2),                     // cb component
+                        dest,
+                       space->height,
+                       space->width);
   DEBUG("gst_colorspace_yuv420P_to_bgr16_mmx done\n");
 
-  return src;
 }
 #endif
 
index 59e6fc2..e0e8772 100644 (file)
@@ -19,6 +19,9 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  */
 
+#ifndef __YUV2RGB_H__
+#define __YUV2RGB_H__
+
 typedef struct _GstColorSpaceYUVTables GstColorSpaceYUVTables;
 
 struct _GstColorSpaceYUVTables {
@@ -61,4 +64,5 @@ struct _GstColorSpaceYUVTables {
                         ? Min(127.0,  ((x) * chromaCorrect)) \
                         : Max(-128.0, ((x) * chromaCorrect)))
 
+#endif
 
index c82bc4d..19b0920 100644 (file)
@@ -9,7 +9,7 @@ libgstvideoscaleinclude_HEADERS = gstvideoscale.h
 
 noinst_HEADERS = yuv2rgb.h
 
-CFLAGS += -Wall -O2  -fomit-frame-pointer -funroll-all-loops -finline-functions -ffast-math
+CFLAGS += -Wall -O2 -fomit-frame-pointer -funroll-all-loops -finline-functions -ffast-math
 
 INCLUDES = $(GLIB_CFLAGS) $(GTK_CFLAGS) -I$(top_srcdir) -I$(top_srcdir)/include
 LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(top_srcdir)/gst/libgst.la
index a3dd08c..cca2eac 100644 (file)
 #include <gstvideoscale.h>
 #include <gst/meta/videoraw.h>
 
-static void gst_videoscale_scale_plane(unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh);
-static void gst_videoscale_scale_plane_slow(unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh);
-
-GstBuffer *gst_videoscale_scale(GstBuffer *src, int sw, int sh, int dw, int dh, int format) {
-  GstBuffer *outbuf;
-  char *source;
-  char *dest;
-  GstMeta *meta;
-  
-  DEBUG("videoscale: scaling %dx%d to %dx%d\n", sw, sh, dw, dh);
-
-  source = GST_BUFFER_DATA(src);
+static void gst_videoscale_scale_yuv(GstVideoScale *scale, unsigned char *src, unsigned char *dest); 
+
+/* scalers */
+static void generate_rowbytes(unsigned char *copy_row, int src_w, int dst_w, int bpp);
+static void gst_videoscale_scale_nearest(GstVideoScale *scale, unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh); 
+static void gst_videoscale_scale_plane_slow(GstVideoScale *scale, unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh); 
+
+/* filters */
+static unsigned char gst_videoscale_bilinear(unsigned char *src, double x, double y, int sw, int sh);
+static unsigned char gst_videoscale_bicubic(unsigned char *src, double x, double y, int sw, int sh);
+
+GstVideoScale *gst_videoscale_new(int sw, int sh, int dw, int dh, int format, GstVideoScaleMethod method) 
+{
+  GstVideoScale *new = g_malloc(sizeof(GstVideoScale));
+
+  new->source_width = sw;
+  new->source_height = sh;
+  new->dest_width = dw;
+  new->dest_height = dh;
+  new->format = format;
+  new->method = method;
+
+
+  new->scale = gst_videoscale_scale_yuv;
+
+  switch (method) {
+    case GST_VIDEOSCALE_NEAREST:
+      generate_rowbytes(new->copy_row, sw, dw, 1);
+      new->scaler = gst_videoscale_scale_nearest;
+      DEBUG("videoscale: scaling method NEAREST\n");
+      break;
+    case GST_VIDEOSCALE_BILINEAR:
+      new->scaler = gst_videoscale_scale_plane_slow;
+      new->filter = gst_videoscale_bilinear;
+      break;
+    case GST_VIDEOSCALE_BICUBIC:
+      new->scaler = gst_videoscale_scale_plane_slow;
+      new->filter = gst_videoscale_bicubic;
+      break;
+    default:
+      g_print("videoscale: unsupported scaling method %d\n", method);
+      break;
+  }
 
-  outbuf = gst_buffer_new();
-  dest = GST_BUFFER_DATA(outbuf) = g_malloc((dw*dh*12)/8);
-  GST_BUFFER_SIZE(outbuf) = (dw*dh*12)/8;
+  return new;
+}
 
-  meta = gst_buffer_get_first_meta(src);
-  if (meta) {
-    ((MetaVideoRaw *)meta)->width = dw;
-    ((MetaVideoRaw *)meta)->height = dh;
+void gst_videoscale_destroy(GstVideoScale *scale) 
+{
+  g_free(scale);
+}
 
-   gst_buffer_add_meta(outbuf, meta);
-  }
+static void gst_videoscale_scale_yuv(GstVideoScale *scale, unsigned char *src, unsigned char *dest) 
+{
+  int sw = scale->source_width;
+  int sh = scale->source_height;
+  int dw = scale->dest_width;
+  int dh = scale->dest_height;
+  
+  DEBUG("videoscale: scaling YUV420 %dx%d to %dx%d\n", sw, sh, dw, dh);
 
-  gst_videoscale_scale_plane_slow(source, dest, sw, sh, dw, dh);
+  scale->scaler(scale, src, dest, sw, sh, dw, dh);
 
-  source += sw*sh;
+  src += sw*sh;
   dest += dw*dh;
 
   dh = dh>>1;
@@ -60,21 +96,17 @@ GstBuffer *gst_videoscale_scale(GstBuffer *src, int sw, int sh, int dw, int dh,
   sh = sh>>1;
   sw = sw>>1;
 
-  gst_videoscale_scale_plane_slow(source, dest, sw, sh, dw, dh);
+  scale->scaler(scale, src, dest, sw, sh, dw, dh);
 
-  source += sw*sh;
+  src += sw*sh;
   dest += dw*dh;
 
-  gst_videoscale_scale_plane_slow(source, dest, sw, sh, dw, dh);
-
-  gst_buffer_unref(src);
-
-  return outbuf;
+  scale->scaler(scale, src, dest, sw, sh, dw, dh);
 }
 
 #define RC(x,y) *(src+(int)(x)+(int)((y)*sw))
 
-static unsigned char gst_videoscale_bilinear(unsigned char *src, double x, double y, int sw) {
+static unsigned char gst_videoscale_bilinear(unsigned char *src, double x, double y, int sw, int sh) {
   int j=floor(x);
   int k=floor(y);
   double a=x-j;
@@ -83,8 +115,10 @@ static unsigned char gst_videoscale_bilinear(unsigned char *src, double x, doubl
   int color;
 
   dest=(1-a)*(1-b)*RC(j,k)+
-       a*(1-b)*RC(j+1,k)+
-       b*(1-a)*RC(j,k+1)+
+       a*(1-b)*RC(j+1,k);
+
+  k = MIN(sh-1, k);
+  dest+= b*(1-a)*RC(j,k+1)+
        a*b*RC(j+1,k+1);
 
   color=rint(dest);
@@ -127,7 +161,8 @@ static unsigned char gst_videoscale_bicubic(unsigned char *src, double x, double
   return (unsigned char) color;
 }
 
-static void gst_videoscale_scale_plane_slow(unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh) {
+static void gst_videoscale_scale_plane_slow(GstVideoScale *scale, unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh)
+{
   double zoomx = ((double)dw)/(double)sw;
   double zoomy = ((double)dh)/(double)sh;
   double xr, yr;
@@ -142,62 +177,93 @@ static void gst_videoscale_scale_plane_slow(unsigned char *src, unsigned char *d
        *dest++ = RC(xr, yr);
       }
       else {
-       //*dest++ = gst_videoscale_bilinear(src, xr, yr, sw);
-       *dest++ = gst_videoscale_bicubic(src, xr, yr, sw, sh);
+       *dest++ = scale->filter(src, xr, yr, sw, sh);
+       //*dest++ = gst_videoscale_bicubic(src, xr, yr, sw, sh);
       }
     }
   }
   
 }
 
-static void gst_videoscale_scale_plane(unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh) {
-
-  int yinc = sh / dh;
-  int srcys = sh % dh;
-  int destys = dh;
-  int dy = 2 * (srcys - destys);
-  int incyE = 2 * srcys;
-  int incyNE = 2 * (srcys - destys);
-  int x, y;
-
-  int xinc = sw / dw;
-  int srcxs = sw % dw;
-  int destxs = dw;
-  int incxE = 2 * srcxs;
-  int incxNE = 2 * (srcxs - destxs);
-  int dx;
-  unsigned char *sourcep;
-  int srcinc = 0;
-  int xskip, yskip =0;
-
-  for (y = 0; y<dh; y++) {
-
-    dx = 2 * (srcxs - destxs);
-    sourcep = src + (srcinc*sw);
-
-    for (x = dw; x; x--) {
-      if (dx <= 0) {
-       dx += incxE;
-       xskip = 0;
-      }
-      else {
-        dx += incxNE;
-       xskip = 1;
-       sourcep++;
+#define PREFIX16        0x66
+#define STORE_BYTE      0xAA
+#define STORE_WORD      0xAB
+#define LOAD_BYTE       0xAC
+#define LOAD_WORD       0xAD
+#define RETURN          0xC3
+
+static void generate_rowbytes(unsigned char *copy_row, int src_w, int dst_w, int bpp)
+{
+  int i;
+  int pos, inc;
+  unsigned char *eip;
+  unsigned char load, store;
+
+  DEBUG("videoscale: setup scaling %p\n", copy_row);
+
+  switch (bpp) {
+    case 1:
+      load = LOAD_BYTE;
+      store = STORE_BYTE;
+      break;
+    case 2:
+    case 4:
+      load = LOAD_WORD;
+      store = STORE_WORD;
+      break;
+    default:
+      return;
+  }
+  pos = 0x10000;
+  inc = (src_w << 16) / dst_w;
+  eip = copy_row;
+  for ( i=0; i<dst_w; ++i ) {
+    while ( pos >= 0x10000L ) {
+      if ( bpp == 2 ) {
+        *eip++ = PREFIX16;
       }
-      sourcep += xinc;
-
-      *dest++ = *sourcep;
+      *eip++ = load;
+      pos -= 0x10000L;
     }
-    if (dy <= 0) {
-      dy += incyE;
-      yskip = 0;
+    if ( bpp == 2 ) {
+      *eip++ = PREFIX16;
     }
-    else {
-      dy += incyNE;
-      srcinc++;
-      yskip = 1;
+    *eip++ = store;
+    pos += inc;
+  }
+  *eip++ = RETURN;
+}
+
+
+static void gst_videoscale_scale_nearest(GstVideoScale *scale, unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh) 
+{
+  int pos, inc, y;
+  int u1, u2;
+  
+  scale->temp = scale->copy_row;
+  
+  DEBUG("videoscale: scaling nearest %p\n", scale->copy_row);
+
+  pos = 0x10000;
+  inc = (sh<<16)/dh;
+
+  for (y = dh; y; y--) {
+
+    while (pos >0x10000) {
+      src += sw;
+      pos-=0x10000;
     }
-    srcinc += yinc;
+    __asm__ __volatile__ ("
+          movl %2, %%eax\n
+           call *%%eax
+           "
+           : "=&D" (u1), "=&S" (u2)
+           : "g" (scale->temp), "0" (dest), "1" (src)
+           : "memory" );
+
+    dest+= dw;
+
+    pos += inc;
   }
+  DEBUG("videoscale: scaling nearest done %p\n", scale->copy_row);
 }
index 064c575..a96d67b 100644 (file)
 #ifndef __GST_VIDEOSCALE_H__
 #define __GST_VIDEOSCALE_H__
 
-#include <gdk/gdk.h>
-#include <gst/gstbuffer.h>
-#include <gst/gstplugin.h>
+#include <gst/gst.h>
 
-GstBuffer *gst_videoscale_scale(GstBuffer *src, int sw, int sh, int dw, int dh, int format);
+typedef enum {
+  GST_VIDEOSCALE_NEAREST,
+  GST_VIDEOSCALE_BILINEAR,
+  GST_VIDEOSCALE_BICUBIC
+} GstVideoScaleMethod;
+
+typedef struct _GstVideoScale GstVideoScale;
+
+struct _GstVideoScale {
+  guint source_width;
+  guint source_height;
+  guint dest_width;
+  guint dest_height;
+  guint format;
+  GstVideoScaleMethod method;
+  /* private */
+  guchar copy_row[4096];
+  guchar *temp;
+  void (*scale) (GstVideoScale *scale, unsigned char *src, unsigned char *dest);
+  void (*scaler) (GstVideoScale *scale, unsigned char *src, unsigned char *dest, int sw, int sh, int dw, int dh);
+  unsigned char (*filter) (unsigned char *src, double x, double y, int sw, int sh);
+};
+
+GstVideoScale *gst_videoscale_new(int sw, int sh, int dw, int dh, int format, GstVideoScaleMethod method);
+void gst_videoscale_destroy(GstVideoScale *scale);
 
 #endif /* __GST_VIDEOSCALE_H__ */
index 06f5743..5670b38 100644 (file)
@@ -14,7 +14,7 @@ void eof(GstSrc *src) {
 }
 
 void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
-  GstElement *parse_audio, *parse_video, *decode, *decode_video, *play, *show;
+  GstElement *parse_audio, *parse_video, *decode, *decode_video, *play, *videoscale, *show;
   GstElement *audio_queue, *video_queue;
   GstElement *audio_thread, *video_thread;
 
@@ -71,12 +71,18 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
 
     gst_plugin_load("mp1videoparse");
     gst_plugin_load(VIDEO_DECODER);
+    gst_plugin_load("videoscale");
     gst_plugin_load("videosink");
     // construct internal pipeline elements
     parse_video = gst_elementfactory_make("mp1videoparse","parse_video");
     g_return_if_fail(parse_video != NULL);
     decode_video = gst_elementfactory_make(VIDEO_DECODER,"decode_video");
     g_return_if_fail(decode_video != NULL);
+    videoscale = gst_elementfactory_make("videoscale","videoscale");
+    g_return_if_fail(videoscale != NULL);
+    gtk_object_set(GTK_OBJECT(videoscale),"width",704, "height", 576,NULL);
+
+
     show = gst_elementfactory_make("videosink","show");
     g_return_if_fail(show != NULL);
     //gtk_object_set(GTK_OBJECT(show),"width",640, "height", 480,NULL);
@@ -91,6 +97,7 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
     g_return_if_fail(video_thread != NULL);
     gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(parse_video));
     gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(decode_video));
+    gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(videoscale));
     gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(show));
 
     // set up pad connections
@@ -99,6 +106,8 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
     gst_pad_connect(gst_element_get_pad(parse_video,"src"),
                     gst_element_get_pad(decode_video,"sink"));
     gst_pad_connect(gst_element_get_pad(decode_video,"src"),
+    //                gst_element_get_pad(videoscale,"sink"));
+    //gst_pad_connect(gst_element_get_pad(videoscale,"src"),
                     gst_element_get_pad(show,"sink"));
 
     // construct queue and connect everything in the main pipeline
index dce2398..70e4bb7 100644 (file)
@@ -139,18 +139,17 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) {
     g_return_if_fail(decode_video != NULL);
     videoscale = gst_elementfactory_make("videoscale","videoscale");
     g_return_if_fail(videoscale != NULL);
-    g_return_if_fail(median != NULL);
+    gtk_object_set(GTK_OBJECT(videoscale),"width",352, "height", 240,NULL);
     median = gst_elementfactory_make("median","median");
-    gtk_object_set(GTK_OBJECT(median),"filtersize",5,NULL);
+    g_return_if_fail(median != NULL);
+    gtk_object_set(GTK_OBJECT(median),"filtersize",9,NULL);
     smooth = gst_elementfactory_make("smooth","smooth");
     g_return_if_fail(smooth != NULL);
     gtk_object_set(GTK_OBJECT(smooth),"filtersize",5,NULL);
     gtk_object_set(GTK_OBJECT(smooth),"tolerance",9,NULL);
-
-    gtk_object_set(GTK_OBJECT(videoscale),"width",352, "height", 240,NULL);
     encode = gst_elementfactory_make("mpeg2enc","encode");
-    gtk_object_set(GTK_OBJECT(encode),"frames_per_second",29.97,NULL);
     g_return_if_fail(encode != NULL);
+    gtk_object_set(GTK_OBJECT(encode),"frames_per_second",29.97,NULL);
     //encode = gst_elementfactory_make("mpeg1encoder","encode");
     //gtk_object_set(GTK_OBJECT(show),"width",640, "height", 480,NULL);
 
@@ -172,10 +171,10 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) {
     gst_pad_connect(gst_element_get_pad(parse_video,"src"),
                     gst_element_get_pad(decode_video,"sink"));
     gst_pad_connect(gst_element_get_pad(decode_video,"src"),
-                    gst_element_get_pad(videoscale,"sink"));
-    gst_pad_connect(gst_element_get_pad(videoscale,"src"),
                     gst_element_get_pad(median,"sink"));
     gst_pad_connect(gst_element_get_pad(median,"src"),
+                    gst_element_get_pad(videoscale,"sink"));
+    gst_pad_connect(gst_element_get_pad(videoscale,"src"),
     //                gst_element_get_pad(smooth,"sink"));
     //gst_pad_connect(gst_element_get_pad(smooth,"src"),
                     gst_element_get_pad(encode,"sink"));