Added MMX optimized yuv2rgb (AlienSong now plays back at only 6% CPU)
authorWim Taymans <wim.taymans@gmail.com>
Sun, 9 Apr 2000 21:36:56 +0000 (21:36 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Sun, 9 Apr 2000 21:36:56 +0000 (21:36 +0000)
Original commit message from CVS:
Added MMX optimized yuv2rgb (AlienSong now plays back at only 6% CPU)
Added mpeg1 picture skipping and fixed a buffer overflow.
Added a system clock. The audiosink can now adjust the clock.
Fixed incorrect behaviour on 8, 15, 16, 24 and 32 bits displays.
Cleanup of the videosink, it now uses the color conversion library when
needed.

16 files changed:
gst/Makefile.am
gst/elements/gstasyncdisksrc.c
gst/elements/gstaudiosink.c
gst/elements/gstaudiosink.h
gst/elements/gstqueue.c
gst/gstelement.c
libs/colorspace/Makefile.am
libs/colorspace/gstcolorspace.c
libs/colorspace/gstcolorspace.h
libs/colorspace/rgb2rgb.c
libs/colorspace/yuv2rgb.c
plugins/elements/gstasyncdisksrc.c
plugins/elements/gstaudiosink.c
plugins/elements/gstaudiosink.h
plugins/elements/gstqueue.c
test/mp1parse.c

index 6ed71cb..6e48bf1 100644 (file)
@@ -13,6 +13,7 @@ libgst_la_SOURCES =   \
        $(GSTOBJECT_SRCS)       \
        gstpad.c        \
        gstbuffer.c     \
+       gstclock.c      \
        gstelement.c    \
        gstelementfactory.c     \
        gstbin.c        \
@@ -38,6 +39,7 @@ libgstinclude_HEADERS =       \
        $(GSTOBJECT_INCLUDES)   \
        gstpad.h        \
        gstbuffer.h     \
+       gstclock.h      \
        gstelement.h    \
        gstbin.h        \
        gstpipeline.h   \
index 94c23a0..1d534a4 100644 (file)
@@ -142,7 +142,7 @@ static void gst_asyncdisksrc_set_arg(GtkObject *object,GtkArg *arg,guint id) {
   switch(id) {
     case ARG_LOCATION:
       /* the element must be stopped in order to do this */
-      g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING));
+      g_return_if_fail(!GST_FLAG_IS_SET(src,GST_ASYNCDISKSRC_OPEN));
 
       if (src->filename) g_free(src->filename);
       /* clear the filename if we get a NULL (is that possible?) */
@@ -215,12 +215,13 @@ void gst_asyncdisksrc_push(GstSrc *src) {
 
   /* create the buffer */
   // FIXME: should eventually use a bufferpool for this
-  buf = GST_BUFFER(gst_buffer_new());
+  buf = gst_buffer_new();
   g_return_if_fail(buf != NULL);
 
   /* simply set the buffer to point to the correct region of the file */
   GST_BUFFER_DATA(buf) = asyncdisksrc->map + asyncdisksrc->curoffset;
   GST_BUFFER_OFFSET(buf) = asyncdisksrc->curoffset;
+  GST_BUFFER_FLAG_SET(buf, GST_BUFFER_DONTFREE);
 
   if ((asyncdisksrc->curoffset + asyncdisksrc->bytes_per_read) >
       asyncdisksrc->size) {
@@ -230,6 +231,8 @@ void gst_asyncdisksrc_push(GstSrc *src) {
     GST_BUFFER_SIZE(buf) = asyncdisksrc->bytes_per_read;
   asyncdisksrc->curoffset += GST_BUFFER_SIZE(buf);
 
+  //gst_buffer_ref(buf);
+
   /* we're done, push the buffer off now */
   gst_pad_push(asyncdisksrc->srcpad,buf);
 }
@@ -265,6 +268,7 @@ void gst_asyncdisksrc_push_region(GstSrc *src,gulong offset,gulong size) {
   /* simply set the buffer to point to the correct region of the file */
   GST_BUFFER_DATA(buf) = asyncdisksrc->map + offset;
   GST_BUFFER_OFFSET(buf) = asyncdisksrc->curoffset;
+  GST_BUFFER_FLAG_SET(buf, GST_BUFFER_DONTFREE);
 
   if ((offset + size) > asyncdisksrc->size) {
     GST_BUFFER_SIZE(buf) = asyncdisksrc->size - offset;
@@ -293,6 +297,7 @@ static gboolean gst_asyncdisksrc_open_file(GstAsyncDiskSrc *src) {
     lseek(src->fd,0,SEEK_SET);
     /* map the file into memory */
     src->map = mmap(NULL,src->size,PROT_READ,MAP_SHARED,src->fd,0);
+    madvise(src->map,src->size,2);
     /* collapse state if that failed */
     if (src->map == NULL) {
       close(src->fd);
index 491847f..eafacde 100644 (file)
@@ -126,12 +126,16 @@ static void gst_audiosink_init(GstAudioSink *audiosink) {
   gst_pad_set_chain_function(audiosink->sinkpad,gst_audiosink_chain);
 
   audiosink->fd = -1;
+  audiosink->clock = gst_clock_get_system();
+  gst_clock_register(audiosink->clock, GST_OBJECT(audiosink));
+  audiosink->clocktime = 0LL;
 
   gst_element_set_state(GST_ELEMENT(audiosink),GST_STATE_COMPLETE);
 }
 
 void gst_audiosink_sync_parms(GstAudioSink *audiosink) {
   audio_buf_info ospace;
+  int frag;
 
   g_return_if_fail(audiosink != NULL);
   g_return_if_fail(GST_IS_AUDIOSINK(audiosink));
@@ -142,12 +146,15 @@ void gst_audiosink_sync_parms(GstAudioSink *audiosink) {
   ioctl(audiosink->fd,SNDCTL_DSP_SETFMT,&audiosink->format);
   ioctl(audiosink->fd,SNDCTL_DSP_CHANNELS,&audiosink->channels);
   ioctl(audiosink->fd,SNDCTL_DSP_SPEED,&audiosink->frequency);
+  ioctl(audiosink->fd,SNDCTL_DSP_GETBLKSIZE, &frag);
 
   ioctl(audiosink->fd,SNDCTL_DSP_GETOSPACE,&ospace);
 
-  g_print("setting sound card to %dKHz %d bit %s (%d bytes buffer)\n",
+  g_print("audiosink: setting sound card to %dKHz %d bit %s (%d bytes buffer, %d fragment)\n",
           audiosink->frequency,audiosink->format,
-          (audiosink->channels == 2) ? "stereo" : "mono",ospace.bytes);
+          (audiosink->channels == 2) ? "stereo" : "mono",ospace.bytes, frag);
+
+
 }
 
 GstElement *gst_audiosink_new(gchar *name) {
@@ -159,6 +166,7 @@ GstElement *gst_audiosink_new(gchar *name) {
 void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
   GstAudioSink *audiosink;
   MetaAudioRaw *meta;
+  count_info info;
 
   g_return_if_fail(pad != NULL);
   g_return_if_fail(GST_IS_PAD(pad));
@@ -179,7 +187,7 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
       audiosink->channels = meta->channels;
       audiosink->frequency = meta->frequency;
       gst_audiosink_sync_parms(audiosink);
-      g_print("sound device set to format %d, %d channels, %dHz\n",
+      g_print("audiosink: sound device set to format %d, %d channels, %dHz\n",
               audiosink->format,audiosink->channels,audiosink->frequency);
     }
   }
@@ -189,9 +197,18 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
   if (GST_BUFFER_DATA(buf) != NULL) {
     gst_trace_add_entry(NULL,0,buf,"audiosink: writing to soundcard");
     //g_print("audiosink: writing to soundcard\n");
-    if (audiosink->fd > 2)
+    if (audiosink->fd > 2) {
+      if (audiosink->clocktime == 0LL) 
+             gst_clock_wait(audiosink->clock, audiosink->clocktime, GST_OBJECT(audiosink));
+      ioctl(audiosink->fd,SNDCTL_DSP_GETOPTR,&info);
+      audiosink->clocktime = (info.bytes*1000000LL)/(audiosink->frequency*audiosink->channels);
+      //g_print("audiosink: bytes sent %d time %llu\n", info.bytes, audiosink->clocktime);
+      gst_clock_set(audiosink->clock, audiosink->clocktime);
       write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf));
+      //audiosink->clocktime +=  (1000000LL*GST_BUFFER_SIZE(buf)/(audiosink->channels*
+//                           (audiosink->format/8)*(audiosink->frequency)));
     //g_print("audiosink: writing to soundcard ok\n");
+    }
   }
 
   //g_print("a unref\n");
@@ -229,7 +246,7 @@ void gst_audiosink_set_frequency(GstAudioSink *audiosink,gint frequency) {
 static gboolean gst_audiosink_open_audio(GstAudioSink *sink) {
   g_return_val_if_fail(sink->fd == -1, FALSE);
 
-  g_print("attempting to open sound device\n");
+  g_print("audiosink: attempting to open sound device\n");
 
   /* first try to open the sound card */
   sink->fd = open("/dev/dsp",O_RDWR);
@@ -241,7 +258,16 @@ static gboolean gst_audiosink_open_audio(GstAudioSink *sink) {
     sink->channels = 2; /* stereo */
     sink->frequency = 44100;
     gst_audiosink_sync_parms(sink);
-    g_print("opened audio\n");
+    ioctl(sink->fd,SNDCTL_DSP_GETCAPS,&sink->caps);
+
+    g_print("audiosink: Capabilities\n");
+    if (sink->caps & DSP_CAP_DUPLEX)   g_print("audiosink:   Full duplex\n");
+    if (sink->caps & DSP_CAP_REALTIME) g_print("audiosink:   Realtime\n");
+    if (sink->caps & DSP_CAP_BATCH)    g_print("audiosink:   Batch\n");
+    if (sink->caps & DSP_CAP_COPROC)   g_print("audiosink:   Has coprocessor\n");
+    if (sink->caps & DSP_CAP_TRIGGER)  g_print("audiosink:   Trigger\n");
+    if (sink->caps & DSP_CAP_MMAP)     g_print("audiosink:   Direct access\n");
+    g_print("audiosink: opened audio\n");
     return TRUE;
   }
 
@@ -253,7 +279,7 @@ static void gst_audiosink_close_audio(GstAudioSink *sink) {
 
   close(sink->fd);
   sink->fd = -1;
-  g_print("closed sound device\n");
+  g_print("audiosink: closed sound device\n");
 }
 
 static gboolean gst_audiosink_start(GstElement *element,
index fc50a0b..9bdb53f 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <config.h>
 #include <gst/gst.h>
+#include <gst/gstclock.h>
 
 
 #ifdef __cplusplus
@@ -53,8 +54,11 @@ struct _GstAudioSink {
 
   GstPad *sinkpad;
 
+  GstClockTime clocktime;
+  GstClock *clock;
   /* soundcard state */
   int fd;
+  int caps; /* the capabilities */
   gint format;
   gint channels;
   gint frequency;
index 7d463e6..45867c6 100644 (file)
@@ -87,7 +87,7 @@ static void gst_queue_class_init(GstQueueClass *klass) {
   gtk_object_add_arg_type("GstQueue::level", GTK_TYPE_INT,
                           GTK_ARG_READABLE, ARG_LEVEL);
   gtk_object_add_arg_type("GstQueue::max_level", GTK_TYPE_INT,
-                          GTK_ARG_READWRITE, ARG_LEVEL);
+                          GTK_ARG_READWRITE, ARG_MAX_LEVEL);
 
   gstconnection_class->push = gst_queue_push;
 
@@ -136,7 +136,7 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) {
   /* we have to lock the queue since we span threads */
   
   GST_LOCK(queue);
-       //g_print("queue: chain %d\n", queue->level_buffers);
+  //g_print("queue: chain %d\n", queue->level_buffers);
 
   if (queue->level_buffers >= queue->max_buffers) {
          //g_print("queue: waiting %d\n", queue->level_buffers);
index b5bf819..ea6a45c 100644 (file)
@@ -339,7 +339,7 @@ gboolean gst_element_change_state(GstElement *element,
 //  g_print(", is now %08lx\n",GST_STATE(element));
   gtk_signal_emit(GTK_OBJECT(element),gst_element_signals[STATE_CHANGE],
                   state);
-       return TRUE;
+  return TRUE;
 }
 
 /**
index 9ad989d..634b143 100644 (file)
@@ -11,5 +11,5 @@ noinst_HEADERS = yuv2rgb.h
 
 CFLAGS += -Wall -O2  -fomit-frame-pointer -funroll-all-loops -finline-functions -ffast-math
 
-INCLUDES = $(GLIB_CFLAGS) $(GTK_CFLAGS) -I$(top_srcdir)
+INCLUDES = $(GLIB_CFLAGS) $(GTK_CFLAGS) -I$(top_srcdir) -I$(top_srcdir)/include
 LDADD = $(GLIB_LIBS) $(GTK_LIBS) $(top_srcdir)/gst/libgst.la
index f0cdd44..aa9e2ac 100644 (file)
@@ -58,8 +58,6 @@ GstColorSpaceConverter gst_colorspace_get_converter(GstColorSpace srcspace, GstC
       //return gst_colorspace_yuv2yuv_get_converter(srcspace, destspace);
     }
   }
-  else {
-    return NULL;
-  }
+  g_print("gst_colorspace: conversion not implemented\n");
   return NULL;
 }
index 90832fb..5002433 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef __GST_COLORSPACE_H__
 #define __GST_COLORSPACE_H__
 
-
+#include <gdk/gdk.h>
 #include <gst/gstbuffer.h>
 #include <gst/gstplugin.h>
 
@@ -35,7 +35,8 @@ typedef enum {
   GST_COLORSPACE_RGB24,                   // RGB
   GST_COLORSPACE_BGR24,                   // RGB
   GST_COLORSPACE_RGB32,
-#define GST_COLORSPACE_RGB_LAST GST_COLORSPACE_RGB32
+  GST_COLORSPACE_BGR32,
+#define GST_COLORSPACE_RGB_LAST GST_COLORSPACE_BGR32
 
 #define GST_COLORSPACE_YUV_FIRST GST_COLORSPACE_YUV420
   GST_COLORSPACE_YUV420,                  // YUV 
@@ -52,6 +53,7 @@ struct _GstColorSpaceParameters {
   guint width;
   guint height;
   gchar *outbuf;
+  GdkVisual *visual;
 };
 
 
index f13a8b9..b9c605f 100644 (file)
 #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);
 
 GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace src, GstColorSpace dest) {
   switch(src) {
     case GST_COLORSPACE_RGB24:
       switch(dest) {
+        case GST_COLORSPACE_RGB24:
+          return gst_colorspace_rgb_to_rgb_identity;
         case GST_COLORSPACE_BGR24:
           return gst_colorspace_rgb24_to_bgr24;
        default:
@@ -38,6 +41,8 @@ GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace src, G
       switch(dest) {
         case GST_COLORSPACE_RGB24:
           return gst_colorspace_rgb24_to_bgr24;
+        case GST_COLORSPACE_BGR24:
+          return gst_colorspace_rgb_to_rgb_identity;
        default:
          break;
       }
@@ -45,9 +50,14 @@ GstColorSpaceConverter gst_colorspace_rgb2rgb_get_converter(GstColorSpace src, G
     default:
       break;
   }
+  g_print("gst_colorspace: conversion not supported\n");
   return NULL;
 }
 
+static GstBuffer *gst_colorspace_rgb_to_rgb_identity(GstBuffer *src, GstColorSpaceParameters *params) {
+  return src;
+}
+
 static GstBuffer *gst_colorspace_rgb24_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params) {
   gint size;
   gchar temp;
@@ -55,9 +65,16 @@ static GstBuffer *gst_colorspace_rgb24_to_bgr24(GstBuffer *src, GstColorSpacePar
 
   DEBUG("gst_colorspace_rgb24_to_bgr24 %d\n", GST_BUFFER_SIZE(src));
 
-  data = GST_BUFFER_DATA(src);
   size = GST_BUFFER_SIZE(src)/3;
 
+  if (params != NULL && params->outbuf != NULL) {
+    data = params->outbuf;
+    DEBUG("gst_colorspace: to buffer %p\n", data);
+  }
+  else {
+    data = GST_BUFFER_DATA(src);
+  }
+
   while (size--) {
     temp = data[0];
     data[0] = data[2];
index 87bc38f..0faab31 100644 (file)
@@ -17,6 +17,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include "config.h"
 
 #include <math.h>
 #include <stdlib.h>
 #include <gst/gst.h>
 #include <gstcolorspace.h>
 
+#ifdef HAVE_LIBMMX
+#include "mmx.h"
+#endif
+
 #include "yuv2rgb.h"
 
+static GstBuffer *gst_colorspace_yuv422P_to_rgb32(GstBuffer *src, GstColorSpaceParameters *params);
+static GstBuffer *gst_colorspace_yuv422P_to_bgr32(GstBuffer *src, GstColorSpaceParameters *params);
+static GstBuffer *gst_colorspace_yuv422P_to_bgr32_mmx(GstBuffer *src, GstColorSpaceParameters *params);
 static GstBuffer *gst_colorspace_yuv422P_to_rgb24(GstBuffer *src, GstColorSpaceParameters *params);
+static GstBuffer *gst_colorspace_yuv422P_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params);
 static GstBuffer *gst_colorspace_yuv422P_to_rgb16(GstBuffer *src, GstColorSpaceParameters *params);
+static GstBuffer *gst_colorspace_yuv422P_to_bgr16_mmx(GstBuffer *src, GstColorSpaceParameters *params);
 
 static void gst_colorspace_yuv_to_rgb16(GstColorSpaceYUVTables *tables,
                                        unsigned char *lum,
@@ -36,20 +46,56 @@ static void gst_colorspace_yuv_to_rgb16(GstColorSpaceYUVTables *tables,
                                        unsigned char *cb,
                                        unsigned char *out,
                                        int cols, int rows);
+static void gst_colorspace_yuv_to_rgb24(GstColorSpaceYUVTables *tables,
+                                       unsigned char *lum,
+                                       unsigned char *cr,
+                                       unsigned char *cb,
+                                       unsigned char *out,
+                                       int cols, int rows);
+static void gst_colorspace_yuv_to_rgb32(GstColorSpaceYUVTables *tables,
+                                       unsigned char *lum,
+                                       unsigned char *cr,
+                                       unsigned char *cb,
+                                       unsigned char *out,
+                                       int cols, int rows);
+#ifdef HAVE_LIBMMX
+static void gst_colorspace_yuv_to_bgr32_mmx(GstColorSpaceYUVTables *tables,
+                                       unsigned char *lum,
+                                       unsigned char *cr,
+                                       unsigned char *cb,
+                                       unsigned char *out,
+                                       int cols, int rows);
+static void gst_colorspace_yuv_to_bgr16_mmx(GstColorSpaceYUVTables *tables,
+                                       unsigned char *lum,
+                                       unsigned char *cr,
+                                       unsigned char *cb,
+                                       unsigned char *out,
+                                       int cols, int rows);
+#endif
 
 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\n");
+  DEBUG("gst_colorspace_yuv2rgb_get_converter %d\n", dest);
   switch(src) {
     case GST_COLORSPACE_YUV422P:
       switch(dest) {
+        case GST_COLORSPACE_BGR32:
+          //return gst_colorspace_yuv422P_to_bgr32;
+          return gst_colorspace_yuv422P_to_bgr32_mmx;
+        case GST_COLORSPACE_RGB32:
+          return gst_colorspace_yuv422P_to_rgb32;
         case GST_COLORSPACE_RGB24:
           return gst_colorspace_yuv422P_to_rgb24;
+        case GST_COLORSPACE_BGR24:
+          return gst_colorspace_yuv422P_to_bgr24;
         case GST_COLORSPACE_RGB555:
         case GST_COLORSPACE_RGB565:
+        case GST_COLORSPACE_BGR555:
           return gst_colorspace_yuv422P_to_rgb16;
+        case GST_COLORSPACE_BGR565:
+          return gst_colorspace_yuv422P_to_bgr16_mmx;
        default:
          break;
       }
@@ -57,30 +103,166 @@ GstColorSpaceConverter gst_colorspace_yuv2rgb_get_converter(GstColorSpace src, G
     default:
       break;
   }
+  g_print("gst_colorspace_yuv2rgb not implemented\n");
   return NULL;
 }
 
+static GstBuffer *gst_colorspace_yuv422P_to_bgr32(GstBuffer *src, GstColorSpaceParameters *params) {
+  static GstColorSpaceYUVTables *color_tables = NULL;
+  int size;
+  GstBuffer *buf = NULL;
+  guchar *out;
+  DEBUG("gst_colorspace_yuv422P_to_bgr32\n");
+
+  g_return_val_if_fail(params != NULL, NULL);
+
+  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_yuv422P_to_rgb32(GstBuffer *src, GstColorSpaceParameters *params) {
+  static GstColorSpaceYUVTables *color_tables = NULL;
+  int size;
+  GstBuffer *buf = NULL;
+  guchar *out;
+  DEBUG("gst_colorspace_yuv422P_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;
+}
+
+static GstBuffer *gst_colorspace_yuv422P_to_bgr24(GstBuffer *src, GstColorSpaceParameters *params) {
+  static GstColorSpaceYUVTables *color_tables = NULL;
+  int size;
+  GstBuffer *buf = NULL;
+  guchar *out;
+  DEBUG("gst_colorspace_yuv422P_to_bgr24\n");
+
+  g_return_val_if_fail(params != NULL, NULL);
+
+  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;
+}
+
 static GstBuffer *gst_colorspace_yuv422P_to_rgb24(GstBuffer *src, GstColorSpaceParameters *params) {
+  static GstColorSpaceYUVTables *color_tables = NULL;
+  int size;
+  GstBuffer *buf = NULL;
+  guchar *out;
   DEBUG("gst_colorspace_yuv422P_to_rgb24\n");
 
-  return src;
+  g_return_val_if_fail(params != NULL, NULL);
+
+  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_yuv422P_to_rgb16(GstBuffer *src, GstColorSpaceParameters *params) {
   static GstColorSpaceYUVTables *color_tables = NULL;
+  int size;
   DEBUG("gst_colorspace_yuv422P_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, 0xF800, 0x07E0, 0x001F);
+    color_tables = gst_colorspace_init_yuv(16, params->visual->red_mask, params->visual->green_mask, params->visual->blue_mask);
   }
+  size = params->width * params->height;
 
   gst_colorspace_yuv_to_rgb16(color_tables,
-                       GST_BUFFER_DATA(src),                                  // Y component
-                        GST_BUFFER_DATA(src)+params->width*params->height,     // cr component
-                       GST_BUFFER_DATA(src)+params->width*params->height+
-                                     (params->width*params->height)/4,   // cb component
+                       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);
@@ -88,6 +270,59 @@ static GstBuffer *gst_colorspace_yuv422P_to_rgb16(GstBuffer *src, GstColorSpaceP
   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_yuv422P_to_bgr32_mmx(GstBuffer *src, GstColorSpaceParameters *params) {
+  int size;
+  GstBuffer *buf = NULL;
+  guchar *out;
+  DEBUG("gst_colorspace_yuv422P_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;
+
+  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;
+}
+static GstBuffer *gst_colorspace_yuv422P_to_bgr16_mmx(GstBuffer *src, GstColorSpaceParameters *params) {
+  int size;
+  DEBUG("gst_colorspace_yuv422P_to_bgr16_mmx \n");
+
+  g_return_val_if_fail(params != NULL, NULL);
+
+  size = params->width * params->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);
+
+  return src;
+}
+#endif
 
 /*
  * How many 1 bits are there in the longword.
@@ -241,7 +476,7 @@ gst_colorspace_init_yuv(long depth, long red_mask, long green_mask, long blue_ma
        * A similar optimisation for Alpha for 64 bit has been
        * prepared for, but is not yet implemented.
        */
-      if(!(depth == 32)) {
+      if(!(depth == 32) && !(depth == 24)) {
 
        r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16;
        g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16;
@@ -311,90 +546,115 @@ gst_colorspace_yuv_to_rgb16(tables, lum, cr, cb, out, rows, cols)
     unsigned char *lum2;
     int x, y;
     int cr_r;
-    int cr_g;
-    int cb_g;
+    int crb_g;
     int cb_b;
-    int cols_2 = cols/2;
+    int cols_2 = cols>>1;
 
     row1 = (unsigned short *)out;
-    row2 = row1 + cols_2 + cols_2;
-    lum2 = lum + cols_2 + cols_2;
+    row2 = row1 + cols;
+    lum2 = lum + cols;
 
-    for (y=0; y<rows; y+=2) {
-       for (x=0; x<cols_2; x++) {
-           int R, G, B;
+    for (y=rows>>1; y; y--) {
+       for (x=cols_2; x; x--) {
 
            CR = *cr++;
            CB = *cb++;
            cr_r = tables->Cr_r_tab[CR];
-           cr_g = tables->Cr_g_tab[CR];
-           cb_g = tables->Cb_g_tab[CB];
+           crb_g = tables->Cr_g_tab[CR] + tables->Cb_g_tab[CB];
            cb_b = tables->Cb_b_tab[CB];
 
             L = tables->L_tab[(int) *lum++];
 
-           R = L + cr_r;
-           G = L + cr_g + cb_g;
-           B = L + cb_b;
-
-           *row1++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
-
-#ifdef INTERPOLATE
-            if(x != cols_2 - 1) {
-             CR = (CR + *cr) >> 1;
-             CB = (CB + *cb) >> 1;
-             cr_r = tables->Cr_r_tab[CR];
-             cr_g = tables->Cr_g_tab[CR];
-             cb_g = tables->Cb_g_tab[CB];
-             cb_b = tables->Cb_b_tab[CB];
-            }
-#endif
+           *row1++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
 
             L = tables->L_tab[(int) *lum++];
 
-           R = L + cr_r;
-           G = L + cr_g + cb_g;
-           B = L + cb_b;
-
-           *row1++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
+           *row1++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
 
            /*
             * Now, do second row.
             */
-#ifdef INTERPOLATE
-            if(y != rows - 2) {
-             CR = (CR + *(cr + cols_2 - 1)) >> 1;
-             CB = (CB + *(cb + cols_2 - 1)) >> 1;
-             cr_r = tables->Cr_r_tab[CR];
-             cr_g = tables->Cr_g_tab[CR];
-             cb_g = tables->Cb_g_tab[CB];
-             cb_b = tables->Cb_b_tab[CB];
-            }
-#endif
-
            L = tables->L_tab[(int) *lum2++];
-           R = L + cr_r;
-           G = L + cr_g + cb_g;
-           B = L + cb_b;
 
-           *row2++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
+           *row2++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
 
            L = tables->L_tab[(int) *lum2++];
-           R = L + cr_r;
-           G = L + cr_g + cb_g;
-           B = L + cb_b;
 
-           *row2++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
+           *row2++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
        }
         /*
          * These values are at the start of the next line, (due
          * to the ++'s above),but they need to be at the start
          * of the line after that.
          */
-       lum += cols_2 + cols_2;
-       lum2 += cols_2 + cols_2;
-       row1 += cols_2 + cols_2;
-       row2 += cols_2 + cols_2;
+       lum = lum2;
+       row1 = row2;
+       lum2 += cols;
+       row2 += cols;
+    }
+}
+
+static void
+gst_colorspace_yuv_to_rgb24(tables, lum, cr, cb, out, rows, cols)
+  GstColorSpaceYUVTables *tables;
+  unsigned char *lum;
+  unsigned char *cr;
+  unsigned char *cb;
+  unsigned char *out;
+  int cols, rows;
+
+{
+    int L, CR, CB;
+    unsigned char *row1, *row2;
+    unsigned char *lum2;
+    int x, y;
+    int cr_r;
+    int crb_g;
+    int cb_b;
+    int cols_2 = cols>>1;
+    int cols_3 = cols*3;
+    unsigned char pixels[4];
+
+    row1 = out;
+    row2 = row1 + cols_3;
+    lum2 = lum + cols;
+    for (y=rows>>1; y; y--) {
+       for (x=cols_2; x; x--) {
+
+           CR = *cr++;
+           CB = *cb++;
+           cr_r = tables->Cr_r_tab[CR];
+           crb_g = tables->Cr_g_tab[CR] + tables->Cb_g_tab[CB];
+           cb_b = tables->Cb_b_tab[CB];
+
+            L = tables->L_tab[(int) *lum++];
+
+           ((int *)pixels)[0] = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
+           *row1++ = pixels[0]; *row1++ = pixels[1]; *row1++ = pixels[2];
+
+            L = tables->L_tab[(int) *lum++];
+
+           ((int *)pixels)[0] = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
+           *row1++ = pixels[0]; *row1++ = pixels[1]; *row1++ = pixels[2];
+
+           /*
+            * Now, do second row.
+            */
+
+           L = tables->L_tab [(int) *lum2++];
+
+           ((int *)pixels)[0] = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
+           *row2++ = pixels[0]; *row2++ = pixels[1]; *row2++ = pixels[2];
+
+           L = tables->L_tab [(int) *lum2++];
+
+           ((int *)pixels)[0] = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
+           *row2++ = pixels[0]; *row2++ = pixels[1]; *row2++ = pixels[2];
+       }
+       lum = lum2;
+       row1 = row2;
+       lum2 += cols;
+       row2 += cols_3;
     }
 }
 
@@ -434,85 +694,365 @@ gst_colorspace_yuv_to_rgb32(tables, lum, cr, cb, out, rows, cols)
     unsigned char *lum2;
     int x, y;
     int cr_r;
-    int cr_g;
-    int cb_g;
+    int crb_g;
     int cb_b;
-    int cols_2 = cols / 2;
+    int cols_2 = cols>>1;
 
-    row1 = (unsigned int *)out;
-    row2 = row1 + cols_2 + cols_2;
-    lum2 = lum + cols_2 + cols_2;
-    for (y=0; y<rows; y+=2) {
-       for (x=0; x<cols_2; x++) {
-           int R, G, B;
+    row1 = (guint32  *)out;
+    row2 = row1 + cols;
+    lum2 = lum + cols;
+    for (y=rows>>1; y; y--) {
+       for (x=cols_2; x; x--) {
 
            CR = *cr++;
            CB = *cb++;
            cr_r = tables->Cr_r_tab[CR];
-           cr_g = tables->Cr_g_tab[CR];
-           cb_g = tables->Cb_g_tab[CB];
+           crb_g = tables->Cr_g_tab[CR] + tables->Cb_g_tab[CB];
            cb_b = tables->Cb_b_tab[CB];
 
             L = tables->L_tab[(int) *lum++];
 
-           R = L + cr_r;
-           G = L + cr_g + cb_g;
-           B = L + cb_b;
-
-           *row1++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
-
-#ifdef INTERPOLATE
-            if(x != cols_2 - 1) {
-             CR = (CR + *cr) >> 1;
-             CB = (CB + *cb) >> 1;
-             cr_r = tables->Cr_r_tab[CR];
-             cr_g = tables->Cr_g_tab[CR];
-             cb_g = tables->Cb_g_tab[CB];
-             cb_b = tables->Cb_b_tab[CB];
-            }
-#endif
+           *row1++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
 
             L = tables->L_tab[(int) *lum++];
 
-           R = L + cr_r;
-           G = L + cr_g + cb_g;
-           B = L + cb_b;
-
-           *row1++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
+           *row1++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
 
            /*
             * Now, do second row.
             */
 
-#ifdef INTERPOLATE
-            if(y != rows - 2) {
-             CR = (CR + *(cr + cols_2 - 1)) >> 1;
-             CB = (CB + *(cb + cols_2 - 1)) >> 1;
-             cr_r = tables->Cr_r_tab[CR];
-             cr_g = tables->Cr_g_tab[CR];
-             cb_g = tables->Cb_g_tab[CB];
-             cb_b = tables->Cb_b_tab[CB];
-            }
-#endif
-
            L = tables->L_tab [(int) *lum2++];
-           R = L + cr_r;
-           G = L + cr_g + cb_g;
-           B = L + cb_b;
 
-           *row2++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
+           *row2++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
 
            L = tables->L_tab [(int) *lum2++];
-           R = L + cr_r;
-           G = L + cr_g + cb_g;
-           B = L + cb_b;
 
-           *row2++ = (tables->r_2_pix[R] | tables->g_2_pix[G] | tables->b_2_pix[B]);
+           *row2++ = (tables->r_2_pix[L+cr_r] | tables->g_2_pix[L+crb_g] | tables->b_2_pix[L+cb_b]);
        }
-       lum += cols_2 + cols_2;
-       lum2 += cols_2 + cols_2;
-       row1 += cols_2 + cols_2;
-       row2 += cols_2 + cols_2;
+       lum = lum2;
+       row1 = row2;
+       lum2 += cols;
+       row2 += cols;
     }
 }
 
+#ifdef HAVE_LIBMMX
+
+static mmx_t MMX_80w           = (mmx_t)(long long)0x0080008000800080LL;                     //dd    00080 0080h, 000800080h
+
+static mmx_t MMX_00FFw         = (mmx_t)(long long)0x00ff00ff00ff00ffLL;                     //dd    000FF 00FFh, 000FF00FFh
+static mmx_t MMX_FF00w         = (mmx_t)(long long)0xff00ff00ff00ff00LL;                     //dd    000FF 00FFh, 000FF00FFh
+
+static mmx_t MMX16_Vredcoeff   = (mmx_t)(long long)0x0066006600660066LL;                     //dd    00066 0066h, 000660066h
+static mmx_t MMX16_Ublucoeff   = (mmx_t)(long long)0x0081008100810081LL;                     //dd    00081 0081h, 000810081h
+static mmx_t MMX16_Ugrncoeff   = (mmx_t)(long long)0xffe8ffe8ffe8ffe8LL;             //dd    0FFE7 FFE7h, 0FFE7FFE7h
+static mmx_t MMX16_Vgrncoeff   = (mmx_t)(long long)0xffcdffcdffcdffcdLL;             //dd    0FFCC FFCCh, 0FFCCFFCCh
+
+static mmx_t MMX16_Ycoeff      = (mmx_t)(long long)0x004a004a004a004aLL;                     //dd    0004A 004Ah, 0004A004Ah
+
+
+static mmx_t MMX32_Vredcoeff     = (mmx_t)(long long)0x0059005900590059LL;  
+static mmx_t MMX32_Ubluecoeff    = (mmx_t)(long long)0x0072007200720072LL;    
+static mmx_t MMX32_Ugrncoeff     = (mmx_t)(long long)0xffeaffeaffeaffeaLL; 
+static mmx_t MMX32_Vgrncoeff     = (mmx_t)(long long)0xffd2ffd2ffd2ffd2LL;  
+
+static void
+gst_colorspace_yuv_to_bgr16_mmx(tables, lum, cr, cb, out, rows, cols)
+  GstColorSpaceYUVTables *tables;
+  unsigned char *lum;
+  unsigned char *cr;
+  unsigned char *cb;
+  unsigned char *out;
+  int cols, rows;
+
+{
+    unsigned short *row1 = (unsigned short* )out;         // 32 bit target
+    int cols8 = cols>>3;
+
+    int y, x; 
+
+    for (y=rows>>1; y; y--) {
+      for (x=cols8; x; x--) {
+
+        movd_m2r(*(mmx_t *)cb, mm0);           // 4 Cb     0  0  0  0 u3 u2 u1 u0
+        pxor_r2r(mm7, mm7);
+        movd_m2r(*(mmx_t *)cr, mm1);           // 4 Cr     0  0  0  0 v3 v2 v1 v0
+        punpcklbw_r2r(mm7, mm0);               // 4 W cb   0 u3  0 u2  0 u1  0 u0
+        punpcklbw_r2r(mm7, mm1);               // 4 W cr   0 v3  0 v2  0 v1  0 v0
+        psubw_m2r(MMX_80w, mm0);
+        psubw_m2r(MMX_80w, mm1);
+        movq_r2r(mm0, mm2);                    // Cb       0 u3  0 u2  0 u1  0 u0
+        movq_r2r(mm1, mm3);                    // Cr
+        pmullw_m2r(MMX16_Ugrncoeff, mm2);      // Cb2green 0 R3  0 R2  0 R1  0 R0
+        movq_m2r(*(mmx_t *)lum, mm6);          // L1      l7 L6 L5 L4 L3 L2 L1 L0
+        pmullw_m2r(MMX16_Ublucoeff, mm0);      // Cb2blue
+        pand_m2r(MMX_00FFw, mm6);              // L1      00 L6 00 L4 00 L2 00 L0
+        pmullw_m2r(MMX16_Vgrncoeff, mm3);      // Cr2green
+        movq_m2r(*(mmx_t *)lum, mm7);          // L2
+        pmullw_m2r(MMX16_Vredcoeff, mm1);      // Cr2red
+        // "psubw          MMX_10w,                %%mm6\n"
+        psrlw_i2r(8, mm7);                     // L2           00 L7 00 L5 00 L3 00 L1
+        pmullw_m2r(MMX16_Ycoeff, mm6);         // lum1
+        // "psubw          MMX_10w,                %%mm7\n" // L2
+        paddw_r2r(mm3, mm2);                   // Cb2green + Cr2green == green
+        pmullw_m2r(MMX16_Ycoeff, mm7);         // lum2
+
+        movq_r2r(mm6, mm4);                    // lum1
+        paddw_r2r(mm0, mm6);                   // lum1 +blue 00 B6 00 B4 00 B2 00 B0
+        movq_r2r(mm4, mm5);                    // lum1
+        paddw_r2r(mm1, mm4);                   // lum1 +red  00 R6 00 R4 00 R2 00 R0
+        paddw_r2r(mm2, mm5);                   // lum1 +green 00 G6 00 G4 00 G2 00 G0
+        psraw_i2r(6, mm4);                     // R1 0 .. 64
+        movq_r2r(mm7, mm3);                    // lum2                       00 L7 00 L5 00 L3 00 L1
+        psraw_i2r(6, mm5);                     // G1  - .. +
+        paddw_r2r(mm0, mm7);                   // Lum2 +blue 00 B7 00 B5 00 B3 00 B1
+        psraw_i2r(6, mm6);                     // B1         0 .. 64
+        packuswb_r2r(mm4, mm4);                // R1 R1
+        packuswb_r2r(mm5, mm5);                // G1 G1
+        packuswb_r2r(mm6, mm6);                // B1 B1
+        punpcklbw_r2r(mm4, mm4);
+        punpcklbw_r2r(mm5, mm5);
+
+        pand_m2r(MMX16_redmask, mm4);
+        psllw_i2r(3, mm5);                     // GREEN       1
+        punpcklbw_r2r(mm6, mm6);
+        pand_m2r(MMX16_grnmask, mm5);
+        pand_m2r(MMX16_redmask, mm6);
+        por_r2r(mm5, mm4);                     //
+        psrlw_i2r(11, mm6);                    // BLUE        1
+        movq_r2r(mm3, mm5);                    // lum2
+        paddw_r2r(mm1, mm3);                   // lum2 +red      00 R7 00 R5 00 R3 00 R1
+        paddw_r2r(mm2, mm5);                   // lum2 +green 00 G7 00 G5 00 G3 00 G1
+        psraw_i2r(6, mm3);                     // R2
+        por_r2r(mm6, mm4);                     // MM4
+        psraw_i2r(6, mm5);                     // G2
+        movq_m2r(*(mmx_t *)(lum+cols), mm6);   // L3 load lum2
+        psraw_i2r(6, mm7);
+        packuswb_r2r(mm3, mm3);
+        packuswb_r2r(mm5, mm5);
+        packuswb_r2r(mm7, mm7);
+        pand_m2r(MMX_00FFw, mm6);              // L3
+        punpcklbw_r2r(mm3, mm3);
+         //                              "psubw          MMX_10w,                        %%mm6\n"  // L3
+        punpcklbw_r2r(mm5, mm5);
+        pmullw_m2r(MMX16_Ycoeff, mm6);         // lum3
+        punpcklbw_r2r(mm7, mm7);
+        psllw_i2r(3, mm5);                     // GREEN 2
+        pand_m2r(MMX16_redmask, mm7);
+        pand_m2r(MMX16_redmask, mm3);
+        psrlw_i2r(11, mm7);                    // BLUE  2
+        pand_m2r(MMX16_grnmask, mm5);
+        por_r2r(mm7, mm3);
+        movq_m2r(*(mmx_t *)(lum+cols), mm7);   // L4 load lum2
+        por_r2r(mm5, mm3);                             //
+        psrlw_i2r(8, mm7);                     // L4
+        movq_r2r(mm4, mm5);
+         //                              "psubw          MMX_10w,                        %%mm7\n"                // L4
+        punpcklwd_r2r(mm3, mm4);
+        pmullw_m2r(MMX16_Ycoeff, mm7);         // lum4
+        punpckhwd_r2r(mm3, mm5);
+
+        movq_r2m(mm4, *(row1));                // write row1
+        movq_r2m(mm5, *(row1+4));              // write row1
+
+        movq_r2r(mm6, mm4);                    // Lum3
+        paddw_r2r(mm0, mm6);                   // Lum3 +blue
+
+        movq_r2r(mm4, mm5);                     // Lum3
+        paddw_r2r(mm1, mm4);                   // Lum3 +red
+        paddw_r2r(mm2, mm5);                    // Lum3 +green
+        psraw_i2r(6, mm4);
+        movq_r2r(mm7, mm3);                     // Lum4
+        psraw_i2r(6, mm5);
+        paddw_r2r(mm0, mm7);                           // Lum4 +blue
+        psraw_i2r(6, mm6);                             // Lum3 +blue
+        movq_r2r(mm3, mm0);                    // Lum4
+        packuswb_r2r(mm4, mm4);
+        paddw_r2r(mm1, mm3);                   // Lum4 +red
+        packuswb_r2r(mm5, mm5);
+        paddw_r2r(mm2, mm0);                   // Lum4 +green
+        packuswb_r2r(mm6, mm6);
+        punpcklbw_r2r(mm4, mm4);
+        punpcklbw_r2r(mm5, mm5);
+        punpcklbw_r2r(mm6, mm6);
+        psllw_i2r(3, mm5);                     // GREEN 3
+        pand_m2r(MMX16_redmask, mm4);
+        psraw_i2r(6, mm3);                     // psr 6
+        psraw_i2r(6, mm0);
+        pand_m2r(MMX16_redmask, mm6);          // BLUE
+        pand_m2r(MMX16_grnmask, mm5);
+        psrlw_i2r(11, mm6);                    // BLUE  3
+        por_r2r(mm5, mm4);
+        psraw_i2r(6, mm7);
+        por_r2r(mm6, mm4);
+        packuswb_r2r(mm3, mm3);
+        packuswb_r2r(mm0, mm0);
+        packuswb_r2r(mm7, mm7);
+        punpcklbw_r2r(mm3, mm3);
+        punpcklbw_r2r(mm0, mm0);
+        punpcklbw_r2r(mm7, mm7);
+        pand_m2r(MMX16_redmask, mm3);
+        pand_m2r(MMX16_redmask, mm7);          // BLUE
+        psllw_i2r(3, mm0);                     // GREEN 4
+        psrlw_i2r(11, mm7);
+        pand_m2r(MMX16_grnmask, mm0);
+        por_r2r(mm7, mm3);
+        por_r2r(mm0, mm3);
+
+        movq_r2r(mm4, mm5);
+
+        punpcklwd_r2r(mm3, mm4);
+        punpckhwd_r2r(mm3, mm5);
+
+        movq_r2m(mm4, *(row1+cols));
+        movq_r2m(mm5, *(row1+cols+4));
+
+        lum+=8;
+        cr+=4;
+        cb+=4;
+        row1 +=8;
+      }
+      lum += cols;
+      row1 += cols;
+    }
+
+    emms();
+
+}
+static void
+gst_colorspace_yuv_to_bgr32_mmx(tables, lum, cr, cb, out, rows, cols)
+  GstColorSpaceYUVTables *tables;
+  unsigned char *lum;
+  unsigned char *cr;
+  unsigned char *cb;
+  unsigned char *out;
+  int cols, rows;
+
+{
+    guint32 *row1 = (guint32 *)out;         // 32 bit target
+    int cols4 = cols>>2;
+
+    int y, x; 
+    
+    for (y=rows>>1; y; y--) {
+      for (x=cols4; x; x--) {
+
+        // create Cr (result in mm1)
+        movd_m2r(*(mmx_t *)cr, mm1);           //         0  0  0  0  v3 v2 v1 v0
+        pxor_r2r(mm7, mm7);                    //         00 00 00 00 00 00 00 00
+        movd_m2r(*(mmx_t *)lum, mm2);           //          0  0  0  0 l3 l2 l1 l0
+        punpcklbw_r2r(mm7, mm1);               //         0  v3 0  v2 00 v1 00 v0
+        punpckldq_r2r(mm1, mm1);               //         00 v1 00 v0 00 v1 00 v0
+        psubw_m2r(MMX_80w, mm1);               // mm1-128:r1 r1 r0 r0 r1 r1 r0 r0 
+
+        // create Cr_g (result in mm0)
+        movq_r2r(mm1, mm0);                    // r1 r1 r0 r0 r1 r1 r0 r0
+        pmullw_m2r(MMX32_Vgrncoeff, mm0);      // red*-46dec=0.7136*64
+        pmullw_m2r(MMX32_Vredcoeff, mm1);      // red*89dec=1.4013*64
+        psraw_i2r(6, mm0);                     // red=red/64
+        psraw_i2r(6, mm1);                     // red=red/64
+                
+        // create L1 L2 (result in mm2,mm4)
+        // L2=lum+cols
+        movq_m2r(*(mmx_t *)(lum+cols),mm3);     //    0  0  0  0 L3 L2 L1 L0
+        punpckldq_r2r(mm3, mm2);               //   L3 L2 L1 L0 l3 l2 l1 l0
+        movq_r2r(mm2, mm4);                    //   L3 L2 L1 L0 l3 l2 l1 l0
+        pand_m2r(MMX_FF00w, mm2);                      //   L3 0  L1  0 l3  0 l1  0
+        pand_m2r(MMX_00FFw, mm4);                      //   0  L2  0 L0  0 l2  0 l0
+        psrlw_i2r(8, mm2);                             //   0  L3  0 L1  0 l3  0 l1
+
+        // create R (result in mm6)
+        movq_r2r(mm2, mm5);                    //   0 L3  0 L1  0 l3  0 l1
+        movq_r2r(mm4, mm6);                    //   0 L2  0 L0  0 l2  0 l0
+        paddsw_r2r(mm1, mm5);                  // lum1+red:x R3 x R1 x r3 x r1
+        paddsw_r2r(mm1, mm6);                  // lum1+red:x R2 x R0 x r2 x r0
+        packuswb_r2r(mm5, mm5);                //  R3 R1 r3 r1 R3 R1 r3 r1
+        packuswb_r2r(mm6, mm6);                //  R2 R0 r2 r0 R2 R0 r2 r0
+        pxor_r2r(mm7, mm7);                    //  00 00 00 00 00 00 00 00
+        punpcklbw_r2r(mm5, mm6);               //  R3 R2 R1 R0 r3 r2 r1 r0
+
+        // create Cb (result in mm1)
+        movd_m2r(*(mmx_t *)cb, mm1);           //         0  0  0  0  u3 u2 u1 u0
+        punpcklbw_r2r(mm7, mm1);               //         0  u3 0  u2 00 u1 00 u0
+        punpckldq_r2r(mm1, mm1);               //         00 u1 00 u0 00 u1 00 u0
+        psubw_m2r(MMX_80w, mm1);               // mm1-128:u1 u1 u0 u0 u1 u1 u0 u0 
+        // create Cb_g (result in mm5)
+        movq_r2r(mm1, mm5);                            // u1 u1 u0 u0 u1 u1 u0 u0
+        pmullw_m2r(MMX32_Ugrncoeff, mm5);      // blue*-109dec=1.7129*64
+        pmullw_m2r(MMX32_Ubluecoeff, mm1);     // blue*114dec=1.78125*64
+        psraw_i2r(6, mm5);                     // blue=red/64
+        psraw_i2r(6, mm1);                     // blue=blue/64
+
+        // create G (result in mm7)
+        movq_r2r(mm2, mm3);                    //   0  L3  0 L1  0 l3  0 l1
+        movq_r2r(mm4, mm7);                    //   0  L2  0 L0  0 l2  0 l1
+        paddsw_r2r(mm5, mm3);                          // lum1+Cb_g:x G3t x G1t x g3t x g1t
+        paddsw_r2r(mm5, mm7);                          // lum1+Cb_g:x G2t x G0t x g2t x g0t
+        paddsw_r2r(mm0, mm3);                          // lum1+Cr_g:x G3  x G1  x g3  x g1
+        paddsw_r2r(mm0, mm7);                          // lum1+blue:x G2  x G0  x g2  x g0
+        packuswb_r2r(mm3, mm3);                // G3 G1 g3 g1 G3 G1 g3 g1
+        packuswb_r2r(mm7, mm7);                // G2 G0 g2 g0 G2 G0 g2 g0
+        punpcklbw_r2r(mm3, mm7);               // G3 G2 G1 G0 g3 g2 g1 g0
+
+        // create B (result in mm5)
+        movq_r2r(mm2, mm3);                    //   0  L3  0 L1  0 l3  0 l1
+        movq_r2r(mm4, mm5);                    //   0  L2  0 L0  0 l2  0 l1
+        paddsw_r2r(mm1, mm3);                  // lum1+blue:x B3 x B1 x b3 x b1
+        paddsw_r2r(mm1, mm5);                  // lum1+blue:x B2 x B0 x b2 x b0
+        packuswb_r2r(mm3, mm3);                // B3 B1 b3 b1 B3 B1 b3 b1
+        packuswb_r2r(mm5, mm5);                // B2 B0 b2 b0 B2 B0 b2 b0
+        punpcklbw_r2r(mm3, mm5);               // B3 B2 B1 B0 b3 b2 b1 b0
+
+        // fill destination row1 (needed are mm6=Rr,mm7=Gg,mm5=Bb)
+
+        pxor_r2r(mm2, mm2);                    //  0  0  0  0  0  0  0  0
+        pxor_r2r(mm4, mm4);                    //  0  0  0  0  0  0  0  0
+        movq_r2r(mm6, mm1);                    // R3 R2 R1 R0 r3 r2 r1 r0
+        movq_r2r(mm5, mm3);                    // B3 B2 B1 B0 b3 b2 b1 b0
+        // process lower lum
+        punpcklbw_r2r(mm4, mm1);               //  0 r3  0 r2  0 r1  0 r0
+        punpcklbw_r2r(mm4, mm3);               //  0 b3  0 b2  0 b1  0 b0
+        movq_r2r(mm1, mm2);                    //  0 r3  0 r2  0 r1  0 r0
+        movq_r2r(mm3, mm0);                    //  0 b3  0 b2  0 b1  0 b0
+        punpcklwd_r2r(mm1, mm3);               //  0 r1  0 b1  0 r0  0 b0
+        punpckhwd_r2r(mm2, mm0);               //  0 r3  0 b3  0 r2  0 b2
+
+        pxor_r2r(mm2, mm2);                    //  0  0  0  0  0  0  0  0
+        movq_r2r(mm7, mm1);                    // G3 G2 G1 G0 g3 g2 g1 g0
+        punpcklbw_r2r(mm1, mm2);               // g3  0 g2  0 g1  0 g0  0
+        punpcklwd_r2r(mm4, mm2);               //  0  0 g1  0  0  0 g0  0 
+        por_r2r(mm3, mm2);                     //  0 r1 g1 b1  0 r0 g0 b0
+        movq_r2m(mm2, *(mmx_t *)row1);         // wrote out ! row1
+
+        pxor_r2r(mm2, mm2);                    //  0  0  0  0  0  0  0  0
+        punpcklbw_r2r(mm1, mm4);               // g3  0 g2  0 g1  0 g0  0
+        punpckhwd_r2r(mm2, mm4);               //  0  0 g3  0  0  0 g2  0 
+        por_r2r(mm0, mm4);                     //  0 r3 g3 b3  0 r2 g2 b2
+        movq_r2m(mm4, *(mmx_t *)(row1+2));     // wrote out ! row1
+                
+        // fill destination row2 (needed are mm6=Rr,mm7=Gg,mm5=Bb)
+        // this can be done "destructive"
+        pxor_r2r(mm2, mm2);                    //  0  0  0  0  0  0  0  0
+        punpckhbw_r2r(mm2, mm6);               //  0 R3  0 R2  0 R1  0 R0
+        punpckhbw_r2r(mm1, mm5);               // G3 B3 G2 B2 G1 B1 G0 B0
+        movq_r2r(mm5, mm1);                    // G3 B3 G2 B2 G1 B1 G0 B0
+        punpcklwd_r2r(mm6, mm1);               //  0 R1 G1 B1  0 R0 G0 B0
+        movq_r2m(mm1, *(mmx_t *)(row1+cols));  // wrote out ! row2
+        punpckhwd_r2r(mm6, mm5);               //  0 R3 G3 B3  0 R2 G2 B2
+        movq_r2m(mm5, *(mmx_t *)(row1+cols+2)); // wrote out ! row2
+                
+        lum+=4;
+        cr+=2;
+        cb+=2;
+        row1 +=4;
+      }
+      lum += cols;
+      row1 += cols;
+    }
+
+    emms();
+
+}
+#endif
+
index 94c23a0..1d534a4 100644 (file)
@@ -142,7 +142,7 @@ static void gst_asyncdisksrc_set_arg(GtkObject *object,GtkArg *arg,guint id) {
   switch(id) {
     case ARG_LOCATION:
       /* the element must be stopped in order to do this */
-      g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING));
+      g_return_if_fail(!GST_FLAG_IS_SET(src,GST_ASYNCDISKSRC_OPEN));
 
       if (src->filename) g_free(src->filename);
       /* clear the filename if we get a NULL (is that possible?) */
@@ -215,12 +215,13 @@ void gst_asyncdisksrc_push(GstSrc *src) {
 
   /* create the buffer */
   // FIXME: should eventually use a bufferpool for this
-  buf = GST_BUFFER(gst_buffer_new());
+  buf = gst_buffer_new();
   g_return_if_fail(buf != NULL);
 
   /* simply set the buffer to point to the correct region of the file */
   GST_BUFFER_DATA(buf) = asyncdisksrc->map + asyncdisksrc->curoffset;
   GST_BUFFER_OFFSET(buf) = asyncdisksrc->curoffset;
+  GST_BUFFER_FLAG_SET(buf, GST_BUFFER_DONTFREE);
 
   if ((asyncdisksrc->curoffset + asyncdisksrc->bytes_per_read) >
       asyncdisksrc->size) {
@@ -230,6 +231,8 @@ void gst_asyncdisksrc_push(GstSrc *src) {
     GST_BUFFER_SIZE(buf) = asyncdisksrc->bytes_per_read;
   asyncdisksrc->curoffset += GST_BUFFER_SIZE(buf);
 
+  //gst_buffer_ref(buf);
+
   /* we're done, push the buffer off now */
   gst_pad_push(asyncdisksrc->srcpad,buf);
 }
@@ -265,6 +268,7 @@ void gst_asyncdisksrc_push_region(GstSrc *src,gulong offset,gulong size) {
   /* simply set the buffer to point to the correct region of the file */
   GST_BUFFER_DATA(buf) = asyncdisksrc->map + offset;
   GST_BUFFER_OFFSET(buf) = asyncdisksrc->curoffset;
+  GST_BUFFER_FLAG_SET(buf, GST_BUFFER_DONTFREE);
 
   if ((offset + size) > asyncdisksrc->size) {
     GST_BUFFER_SIZE(buf) = asyncdisksrc->size - offset;
@@ -293,6 +297,7 @@ static gboolean gst_asyncdisksrc_open_file(GstAsyncDiskSrc *src) {
     lseek(src->fd,0,SEEK_SET);
     /* map the file into memory */
     src->map = mmap(NULL,src->size,PROT_READ,MAP_SHARED,src->fd,0);
+    madvise(src->map,src->size,2);
     /* collapse state if that failed */
     if (src->map == NULL) {
       close(src->fd);
index 491847f..eafacde 100644 (file)
@@ -126,12 +126,16 @@ static void gst_audiosink_init(GstAudioSink *audiosink) {
   gst_pad_set_chain_function(audiosink->sinkpad,gst_audiosink_chain);
 
   audiosink->fd = -1;
+  audiosink->clock = gst_clock_get_system();
+  gst_clock_register(audiosink->clock, GST_OBJECT(audiosink));
+  audiosink->clocktime = 0LL;
 
   gst_element_set_state(GST_ELEMENT(audiosink),GST_STATE_COMPLETE);
 }
 
 void gst_audiosink_sync_parms(GstAudioSink *audiosink) {
   audio_buf_info ospace;
+  int frag;
 
   g_return_if_fail(audiosink != NULL);
   g_return_if_fail(GST_IS_AUDIOSINK(audiosink));
@@ -142,12 +146,15 @@ void gst_audiosink_sync_parms(GstAudioSink *audiosink) {
   ioctl(audiosink->fd,SNDCTL_DSP_SETFMT,&audiosink->format);
   ioctl(audiosink->fd,SNDCTL_DSP_CHANNELS,&audiosink->channels);
   ioctl(audiosink->fd,SNDCTL_DSP_SPEED,&audiosink->frequency);
+  ioctl(audiosink->fd,SNDCTL_DSP_GETBLKSIZE, &frag);
 
   ioctl(audiosink->fd,SNDCTL_DSP_GETOSPACE,&ospace);
 
-  g_print("setting sound card to %dKHz %d bit %s (%d bytes buffer)\n",
+  g_print("audiosink: setting sound card to %dKHz %d bit %s (%d bytes buffer, %d fragment)\n",
           audiosink->frequency,audiosink->format,
-          (audiosink->channels == 2) ? "stereo" : "mono",ospace.bytes);
+          (audiosink->channels == 2) ? "stereo" : "mono",ospace.bytes, frag);
+
+
 }
 
 GstElement *gst_audiosink_new(gchar *name) {
@@ -159,6 +166,7 @@ GstElement *gst_audiosink_new(gchar *name) {
 void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
   GstAudioSink *audiosink;
   MetaAudioRaw *meta;
+  count_info info;
 
   g_return_if_fail(pad != NULL);
   g_return_if_fail(GST_IS_PAD(pad));
@@ -179,7 +187,7 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
       audiosink->channels = meta->channels;
       audiosink->frequency = meta->frequency;
       gst_audiosink_sync_parms(audiosink);
-      g_print("sound device set to format %d, %d channels, %dHz\n",
+      g_print("audiosink: sound device set to format %d, %d channels, %dHz\n",
               audiosink->format,audiosink->channels,audiosink->frequency);
     }
   }
@@ -189,9 +197,18 @@ void gst_audiosink_chain(GstPad *pad,GstBuffer *buf) {
   if (GST_BUFFER_DATA(buf) != NULL) {
     gst_trace_add_entry(NULL,0,buf,"audiosink: writing to soundcard");
     //g_print("audiosink: writing to soundcard\n");
-    if (audiosink->fd > 2)
+    if (audiosink->fd > 2) {
+      if (audiosink->clocktime == 0LL) 
+             gst_clock_wait(audiosink->clock, audiosink->clocktime, GST_OBJECT(audiosink));
+      ioctl(audiosink->fd,SNDCTL_DSP_GETOPTR,&info);
+      audiosink->clocktime = (info.bytes*1000000LL)/(audiosink->frequency*audiosink->channels);
+      //g_print("audiosink: bytes sent %d time %llu\n", info.bytes, audiosink->clocktime);
+      gst_clock_set(audiosink->clock, audiosink->clocktime);
       write(audiosink->fd,GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf));
+      //audiosink->clocktime +=  (1000000LL*GST_BUFFER_SIZE(buf)/(audiosink->channels*
+//                           (audiosink->format/8)*(audiosink->frequency)));
     //g_print("audiosink: writing to soundcard ok\n");
+    }
   }
 
   //g_print("a unref\n");
@@ -229,7 +246,7 @@ void gst_audiosink_set_frequency(GstAudioSink *audiosink,gint frequency) {
 static gboolean gst_audiosink_open_audio(GstAudioSink *sink) {
   g_return_val_if_fail(sink->fd == -1, FALSE);
 
-  g_print("attempting to open sound device\n");
+  g_print("audiosink: attempting to open sound device\n");
 
   /* first try to open the sound card */
   sink->fd = open("/dev/dsp",O_RDWR);
@@ -241,7 +258,16 @@ static gboolean gst_audiosink_open_audio(GstAudioSink *sink) {
     sink->channels = 2; /* stereo */
     sink->frequency = 44100;
     gst_audiosink_sync_parms(sink);
-    g_print("opened audio\n");
+    ioctl(sink->fd,SNDCTL_DSP_GETCAPS,&sink->caps);
+
+    g_print("audiosink: Capabilities\n");
+    if (sink->caps & DSP_CAP_DUPLEX)   g_print("audiosink:   Full duplex\n");
+    if (sink->caps & DSP_CAP_REALTIME) g_print("audiosink:   Realtime\n");
+    if (sink->caps & DSP_CAP_BATCH)    g_print("audiosink:   Batch\n");
+    if (sink->caps & DSP_CAP_COPROC)   g_print("audiosink:   Has coprocessor\n");
+    if (sink->caps & DSP_CAP_TRIGGER)  g_print("audiosink:   Trigger\n");
+    if (sink->caps & DSP_CAP_MMAP)     g_print("audiosink:   Direct access\n");
+    g_print("audiosink: opened audio\n");
     return TRUE;
   }
 
@@ -253,7 +279,7 @@ static void gst_audiosink_close_audio(GstAudioSink *sink) {
 
   close(sink->fd);
   sink->fd = -1;
-  g_print("closed sound device\n");
+  g_print("audiosink: closed sound device\n");
 }
 
 static gboolean gst_audiosink_start(GstElement *element,
index fc50a0b..9bdb53f 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <config.h>
 #include <gst/gst.h>
+#include <gst/gstclock.h>
 
 
 #ifdef __cplusplus
@@ -53,8 +54,11 @@ struct _GstAudioSink {
 
   GstPad *sinkpad;
 
+  GstClockTime clocktime;
+  GstClock *clock;
   /* soundcard state */
   int fd;
+  int caps; /* the capabilities */
   gint format;
   gint channels;
   gint frequency;
index 7d463e6..45867c6 100644 (file)
@@ -87,7 +87,7 @@ static void gst_queue_class_init(GstQueueClass *klass) {
   gtk_object_add_arg_type("GstQueue::level", GTK_TYPE_INT,
                           GTK_ARG_READABLE, ARG_LEVEL);
   gtk_object_add_arg_type("GstQueue::max_level", GTK_TYPE_INT,
-                          GTK_ARG_READWRITE, ARG_LEVEL);
+                          GTK_ARG_READWRITE, ARG_MAX_LEVEL);
 
   gstconnection_class->push = gst_queue_push;
 
@@ -136,7 +136,7 @@ void gst_queue_chain(GstPad *pad,GstBuffer *buf) {
   /* we have to lock the queue since we span threads */
   
   GST_LOCK(queue);
-       //g_print("queue: chain %d\n", queue->level_buffers);
+  //g_print("queue: chain %d\n", queue->level_buffers);
 
   if (queue->level_buffers >= queue->max_buffers) {
          //g_print("queue: waiting %d\n", queue->level_buffers);
index 1483be8..c08f809 100644 (file)
@@ -15,7 +15,7 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
   GstElement *audio_queue, *video_queue;
   GstElement *audio_thread, *video_thread;
 
-       GtkWidget *appwindow;
+  GtkWidget *appwindow;
 
   g_print("***** a new pad %s was created\n", gst_pad_get_name(pad));
 
@@ -49,6 +49,7 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
 
     // construct queue and connect everything in the main pipelie
     audio_queue = gst_elementfactory_make("queue","audio_queue");
+    gtk_object_set(GTK_OBJECT(audio_queue),"max_level",30,NULL);
     gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(audio_queue));
     gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(audio_thread));
     gst_pad_connect(pad,
@@ -63,7 +64,7 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
     g_print("setting to PLAYING state\n");
     gst_element_set_state(GST_ELEMENT(audio_thread),GST_STATE_PLAYING);
   } else if (strncmp(gst_pad_get_name(pad), "video_", 6) == 0) {
-       //} else if (0) {
+  //} else if (0) {
 
     gst_plugin_load("mp1videoparse");
     gst_plugin_load("mpeg_play");
@@ -71,34 +72,35 @@ void new_pad_created(GstElement *parse,GstPad *pad,GstElement *pipeline) {
     // construct internal pipeline elements
     parse_video = gst_elementfactory_make("mp1videoparse","parse_video");
     g_return_if_fail(parse_video != NULL);
-    decode = gst_elementfactory_make("mpeg_play","decode_video");
+    decode_video = gst_elementfactory_make("mpeg_play","decode_video");
     g_return_if_fail(decode_video != NULL);
     show = gst_elementfactory_make("videosink","show");
     g_return_if_fail(show != NULL);
     //gtk_object_set(GTK_OBJECT(show),"width",640, "height", 480,NULL);
 
-               appwindow = gnome_app_new("MPEG1 player","MPEG1 player");
-               gnome_app_set_contents(GNOME_APP(appwindow),
-                                                                               gst_util_get_widget_arg(GTK_OBJECT(show),"widget"));
+    appwindow = gnome_app_new("MPEG1 player","MPEG1 player");
+    gnome_app_set_contents(GNOME_APP(appwindow),
+               gst_util_get_widget_arg(GTK_OBJECT(show),"widget"));
                gtk_widget_show_all(appwindow);
 
     // create the thread and pack stuff into it
     video_thread = gst_thread_new("video_thread");
     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));
+    gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(decode_video));
     gst_bin_add(GST_BIN(video_thread),GST_ELEMENT(show));
 
     // set up pad connections
     gst_element_add_ghost_pad(GST_ELEMENT(video_thread),
                               gst_element_get_pad(parse_video,"sink"));
     gst_pad_connect(gst_element_get_pad(parse_video,"src"),
-                    gst_element_get_pad(decode,"sink"));
-    gst_pad_connect(gst_element_get_pad(decode,"src"),
+                    gst_element_get_pad(decode_video,"sink"));
+    gst_pad_connect(gst_element_get_pad(decode_video,"src"),
                     gst_element_get_pad(show,"sink"));
 
     // construct queue and connect everything in the main pipeline
     video_queue = gst_elementfactory_make("queue","video_queue");
+    gtk_object_set(GTK_OBJECT(video_queue),"max_level",30,NULL);
     gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(video_queue));
     gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(video_thread));
     gst_pad_connect(pad,
@@ -130,6 +132,7 @@ int main(int argc,char *argv[]) {
   pipeline = gst_pipeline_new("pipeline");
   g_return_if_fail(pipeline != NULL);
 
+  //src = gst_elementfactory_make("asyncdisksrc","src");
   src = gst_elementfactory_make("disksrc","src");
   g_return_if_fail(src != NULL);
   gtk_object_set(GTK_OBJECT(src),"location",argv[1],NULL);
@@ -157,18 +160,18 @@ int main(int argc,char *argv[]) {
 
   g_print("about to enter loop\n");
 
-       while (1) {
-         gst_src_push(GST_SRC(src));
-       }
-       // this does not work due to multithreading
-       /*
-       g_idle_add(idle_func,src);
+  while (1) {
+    gst_src_push(GST_SRC(src));
+  }
+  // this does not work due to multithreading
+  /*
+  g_idle_add(idle_func,src);
 
-       gtk_main();
-       */
+  gtk_main();
+  */
 }
 
 gboolean idle_func(gpointer data) {
-       gst_src_push(GST_SRC(data));
-       return TRUE;
+  gst_src_push(GST_SRC(data));
+  return TRUE;
 }