added sys/directdraw added sys/directsound added win32/vs6/gst_plugins_bad.dsw added...
authorSébastien Moutte <sebastien@moutte.net>
Thu, 5 Jan 2006 23:17:44 +0000 (23:17 +0000)
committerSébastien Moutte <sebastien@moutte.net>
Thu, 5 Jan 2006 23:17:44 +0000 (23:17 +0000)
Original commit message from CVS:
2006-01-05  Sebastien Moutte  <sebastien@moutte.net>
* added sys/directdraw
* added sys/directsound
* added win32/vs6/gst_plugins_bad.dsw
* added win32/vs6/libgstdirectsound.dsp
* added win32/vs6/libgstdirectdraw.dsp
* added win32/common/config.h

ChangeLog
sys/directdraw/gstdirectdrawplugin.c [new file with mode: 0644]
sys/directdraw/gstdirectdrawsink.c [new file with mode: 0644]
sys/directdraw/gstdirectdrawsink.h [new file with mode: 0644]
sys/directsound/gstdirectsoundplugin.c [new file with mode: 0644]
sys/directsound/gstdirectsoundsink.c [new file with mode: 0644]
sys/directsound/gstdirectsoundsink.h [new file with mode: 0644]
win32/common/config.h [new file with mode: 0644]
win32/vs6/gst_plugins_bad.dsw [new file with mode: 0644]
win32/vs6/libgstdirectdraw.dsp [new file with mode: 0644]
win32/vs6/libgstdirectsound.dsp [new file with mode: 0644]

index 3c55a45..fcf096a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2006-01-05  Sebastien Moutte  <sebastien@moutte.net>
+       * added sys/directdraw
+       * added sys/directsound
+       * added win32/vs6/gst_plugins_bad.dsw
+       * added win32/vs6/libgstdirectsound.dsp
+       * added win32/vs6/libgstdirectdraw.dsp
+       * added win32/common/config.h
+       
 2006-01-05  Stefan Kost  <ensonic@users.sf.net>
 
        * gst/games/gstpuzzle.c: (plugin_init):
diff --git a/sys/directdraw/gstdirectdrawplugin.c b/sys/directdraw/gstdirectdrawplugin.c
new file mode 100644 (file)
index 0000000..69d7950
--- /dev/null
@@ -0,0 +1,42 @@
+/* GStreamer
+* Copyright (C) 2005 Sebastien Moutte <sebastien@moutte.net>
+*
+* gstdirectdrawplugin.c:
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Library General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Library General Public License for more details.
+*
+* You should have received a copy of the GNU Library General Public
+* License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+* Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstdirectdrawsink.h"
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  if (!gst_element_register (plugin, "directdrawsink", GST_RANK_NONE,
+          GST_TYPE_DIRECTDRAW_SINK))
+    return FALSE;
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "directdraw",
+    "DIRECTDRAW plugin library",
+    plugin_init, VERSION, "LGPL", GST_PACKAGE, GST_ORIGIN)
diff --git a/sys/directdraw/gstdirectdrawsink.c b/sys/directdraw/gstdirectdrawsink.c
new file mode 100644 (file)
index 0000000..55a0d54
--- /dev/null
@@ -0,0 +1,1733 @@
+/* GStreamer
+* Copyright (C) 2005 Sebastien Moutte <sebastien@moutte.net>
+*      
+* Based on directfb video sink
+* gstdirectdrawsink.c:
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Library General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Library General Public License for more details.
+*
+* You should have received a copy of the GNU Library General Public
+* License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+* Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstdirectdrawsink.h"
+
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+GST_DEBUG_CATEGORY_STATIC (directdrawsink_debug);
+#define GST_CAT_DEFAULT directdrawsink_debug
+
+/* elementfactory information */
+static GstElementDetails gst_directdrawsink_details =
+GST_ELEMENT_DETAILS ("Video Sink (DIRECTDRAW)",
+    "Sink/Video",
+    "Output to a video card via DIRECTDRAW",
+    "Sebastien Moutte <sebastien@moutte.net>");
+
+static void
+_do_init (GType directdrawsink_type)
+{
+  GST_DEBUG_CATEGORY_INIT (directdrawsink_debug, "directdrawsink", 0,
+      "Direct draw sink");
+}
+
+GST_BOILERPLATE_FULL (GstDirectDrawSink, gst_directdrawsink, GstVideoSink,
+    GST_TYPE_VIDEO_SINK, _do_init);
+
+static void gst_directdrawsink_finalize (GObject * object);
+
+static void gst_directdrawsink_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_directdrawsink_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+
+static GstCaps *gst_directdrawsink_get_caps (GstBaseSink * bsink);
+static gboolean gst_directdrawsink_set_caps (GstBaseSink * bsink,
+    GstCaps * caps);
+
+static GstStateChangeReturn
+gst_directdrawsink_change_state (GstElement * element,
+    GstStateChange transition);
+
+static GstFlowReturn
+gst_directdrawsink_buffer_alloc (GstBaseSink * bsink, guint64 offset,
+    guint size, GstCaps * caps, GstBuffer ** buf);
+
+static void
+gst_directdrawsink_get_times (GstBaseSink * bsink, GstBuffer * buf,
+    GstClockTime * start, GstClockTime * end);
+
+static GstFlowReturn
+gst_directdrawsink_show_frame (GstBaseSink * bsink, GstBuffer * buf);
+
+static gboolean gst_directdrawsink_setup_ddraw (GstDirectDrawSink * ddrawsink);
+static gboolean gst_directdrawsink_create_default_window (GstDirectDrawSink *
+    ddrawsink);
+static gboolean gst_directdrawsink_create_ddraw_surfaces (GstDirectDrawSink *
+    ddrawsink);
+
+static GstCaps *gst_directdrawsink_get_ddrawcaps (GstDirectDrawSink *
+    ddrawsink);
+
+static void gst_directdrawsink_cleanup (GstDirectDrawSink * ddrawsink);
+static void gst_directdrawsink_bufferpool_clear (GstDirectDrawSink * ddrawsink);
+
+
+/*surfaces management functions*/
+static void
+gst_directdrawsink_surface_destroy (GstDirectDrawSink * ddrawsink,
+    GstDDrawSurface * surface);
+
+static GstDDrawSurface *gst_directdrawsink_surface_create (GstDirectDrawSink *
+    ddrawsink, GstCaps * caps, size_t size);
+
+static GstStaticPadTemplate directdrawsink_sink_factory =
+    GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("video/x-raw-rgb, "
+        "bpp = (int) { 8, 16, 24, 32 }, "
+        "depth = (int) { 0, 8, 16, 24, 32 }, "
+        "endianness = (int) LITTLE_ENDIAN, "
+        "framerate = (fraction) [ 0, MAX ], "
+        "width = (int) [ 1, MAX ], "
+        "height = (int) [ 1, MAX ]"
+        "; "
+        "video/x-raw-yuv, "
+        "framerate = (fraction) [ 0, MAX ], "
+        "width = (int) [ 1, MAX ], "
+        "height = (int) [ 1, MAX ], "
+        "format = (fourcc) { YUY2, UYVY, YVU9, YV12, AYUV }")
+    );
+
+enum
+{
+  PROP_0,
+  PROP_SURFACE,
+  PROP_WINDOW,
+  PROP_FULLSCREEN
+};
+
+/* Utility functions */
+static gboolean
+gst_ddrawvideosink_get_format_from_caps (GstCaps * caps,
+    DDPIXELFORMAT * pPixelFormat)
+{
+  GstStructure *structure = NULL;
+  gboolean ret = TRUE;
+
+  /*check params */
+  g_return_val_if_fail (pPixelFormat, FALSE);
+  g_return_val_if_fail (caps, FALSE);
+
+  /*init structure */
+  memset (pPixelFormat, 0, sizeof (DDPIXELFORMAT));
+  pPixelFormat->dwSize = sizeof (DDPIXELFORMAT);
+
+  if (!(structure = gst_caps_get_structure (caps, 0)))
+    return FALSE;
+
+  if (gst_structure_has_name (structure, "video/x-raw-rgb")) {
+    gint depth, bitcount, bitmask;
+
+    pPixelFormat->dwFlags = DDPF_RGB;
+    ret &= gst_structure_get_int (structure, "bpp", &bitcount);
+    pPixelFormat->dwRGBBitCount = bitcount;
+    ret &= gst_structure_get_int (structure, "depth", &depth);
+    ret &= gst_structure_get_int (structure, "red_mask", &bitmask);
+    pPixelFormat->dwRBitMask = bitmask;
+    ret &= gst_structure_get_int (structure, "green_mask", &bitmask);
+    pPixelFormat->dwGBitMask = bitmask;
+    ret &= gst_structure_get_int (structure, "blue_mask", &bitmask);
+    pPixelFormat->dwBBitMask = bitmask;
+  } else if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
+    gint fourcc;
+
+    pPixelFormat->dwFlags = DDPF_FOURCC;
+    ret &= gst_structure_get_fourcc (structure, "format", &fourcc);
+    pPixelFormat->dwFourCC = fourcc;
+  } else {
+    GST_WARNING ("unknown caps name received %" GST_PTR_FORMAT, caps);
+    ret = FALSE;
+  }
+
+  return ret;
+}
+
+static GstCaps *
+gst_ddrawvideosink_get_caps_from_format (DDPIXELFORMAT pixel_format)
+{
+  GstCaps *caps = NULL;
+  gint bpp, depth;
+  guint32 fourcc;
+
+  if ((pixel_format.dwFlags & DDPF_RGB) == DDPF_RGB) {
+    bpp = pixel_format.dwRGBBitCount;
+    if (bpp != 32)
+      depth = bpp;
+    else {
+      if ((pixel_format.dwFlags & DDPF_ALPHAPREMULT) == DDPF_ALPHAPREMULT)
+        depth = 32;
+      else
+        depth = 24;
+    }
+    caps = gst_caps_new_simple ("video/x-raw-rgb",
+        "bpp", G_TYPE_INT, bpp,
+        "depth", G_TYPE_INT, depth,
+        "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, NULL);
+  }
+
+  if ((pixel_format.dwFlags & DDPF_YUV) == DDPF_YUV) {
+    fourcc = pixel_format.dwFourCC;
+    caps = gst_caps_new_simple ("video/x-raw-yuv",
+        "format", GST_TYPE_FOURCC, fourcc, NULL);
+  }
+
+  g_assert (caps != NULL);
+
+  return caps;
+}
+
+static void
+gst_directdrawsink_center_rect (RECT src, RECT dst, RECT * result)
+{
+  gdouble src_ratio, dst_ratio;
+  long src_width = src.right;
+  long src_height = src.bottom;
+  long dst_width = dst.right - dst.left;
+  long dst_heigth = dst.bottom - dst.top;
+  long result_width = 0, result_height = 0;
+
+  g_return_if_fail (result != NULL);
+
+  src_ratio = (gdouble) src_width / src_height;
+  dst_ratio = (gdouble) dst_width / dst_heigth;
+
+  if (src_ratio > dst_ratio) {
+    /*new height */
+    result_height = (long) (dst_width / src_ratio);
+
+    result->left = dst.left;
+    result->right = dst.right;
+    result->top = dst.top + (dst_heigth - result_height) / 2;
+    result->bottom = result->top + result_height;
+
+  } else if (src_ratio < dst_ratio) {
+    /*new width */
+    result_width = (long) (dst_heigth * src_ratio);
+
+    result->top = dst.top;
+    result->bottom = dst.bottom;
+    result->left = dst.left + (dst_width - result_width) / 2;
+    result->right = result->left + result_width;
+
+  } else {
+    /*same ratio */
+    memcpy (result, &dst, sizeof (RECT));
+  }
+
+  GST_DEBUG ("source is %dx%d dest is %dx%d, result is %dx%d with x,y %dx%d",
+      src_width, src_height, dst_width, dst_heigth, result_width, result_height,
+      result->left, result->right);
+}
+
+/*subclass of GstBuffer which manages surfaces lifetime*/
+static void
+gst_ddrawsurface_finalize (GstDDrawSurface * surface)
+{
+  GstDirectDrawSink *ddrawsink = NULL;
+
+  g_return_if_fail (surface != NULL);
+
+  ddrawsink = surface->ddrawsink;
+  if (!ddrawsink)
+    goto no_sink;
+
+  /* If our geometry changed we can't reuse that image. */
+  if ((surface->width != ddrawsink->video_width) ||
+      (surface->height != ddrawsink->video_height) ||
+      (memcmp (&surface->dd_pixel_format, &ddrawsink->dd_pixel_format,
+              sizeof (DDPIXELFORMAT)) != 0)
+      ) {
+    GST_DEBUG ("destroy image as its size changed %dx%d vs current %dx%d",
+        surface->width, surface->height,
+        ddrawsink->video_width, ddrawsink->video_height);
+    gst_directdrawsink_surface_destroy (ddrawsink, surface);
+
+  } else {
+    /* In that case we can reuse the image and add it to our image pool. */
+    GST_DEBUG ("recycling image in pool");
+
+    /* need to increment the refcount again to recycle */
+    gst_buffer_ref (GST_BUFFER (surface));
+
+    g_mutex_lock (ddrawsink->pool_lock);
+    ddrawsink->buffer_pool = g_slist_prepend (ddrawsink->buffer_pool, surface);
+    g_mutex_unlock (ddrawsink->pool_lock);
+  }
+  return;
+
+no_sink:
+  GST_WARNING ("no sink found");
+  return;
+}
+
+static void
+gst_ddrawsurface_init (GstDDrawSurface * surface, gpointer g_class)
+{
+  surface->surface = NULL;
+  surface->width = 0;
+  surface->height = 0;
+  surface->ddrawsink = NULL;
+  memset (&surface->dd_pixel_format, 0, sizeof (DDPIXELFORMAT));
+}
+
+static void
+gst_ddrawsurface_class_init (gpointer g_class, gpointer class_data)
+{
+  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
+
+  mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
+      gst_ddrawsurface_finalize;
+}
+
+GType
+gst_ddrawsurface_get_type (void)
+{
+  static GType _gst_ddrawsurface_type;
+
+  if (G_UNLIKELY (_gst_ddrawsurface_type == 0)) {
+    static const GTypeInfo ddrawsurface_info = {
+      sizeof (GstBufferClass),
+      NULL,
+      NULL,
+      gst_ddrawsurface_class_init,
+      NULL,
+      NULL,
+      sizeof (GstDDrawSurface),
+      0,
+      (GInstanceInitFunc) gst_ddrawsurface_init,
+      NULL
+    };
+    _gst_ddrawsurface_type = g_type_register_static (GST_TYPE_BUFFER,
+        "GstDDrawSurface", &ddrawsurface_info, 0);
+  }
+  return _gst_ddrawsurface_type;
+}
+
+static GstDirectDrawSink *global_ddrawsink = NULL;
+
+/*GType
+gst_directdrawsink_get_type (void)
+{
+  static GType directdrawsink_type = 0;
+
+  if (!directdrawsink_type) {
+    static const GTypeInfo directdrawsink_info = {
+      sizeof (GstDirectDrawSinkClass),
+      gst_directdrawsink_base_init,
+      NULL,
+      (GClassInitFunc) gst_directdrawsink_class_init,
+      NULL,
+      NULL,
+      sizeof (GstDirectDrawSink),
+      0,
+      (GInstanceInitFunc) gst_directdrawsink_init,
+    };
+
+    directdrawsink_type =
+        g_type_register_static (GST_TYPE_VIDEO_SINK, "GstDirectDrawSink",
+        &directdrawsink_info, 0);
+  }
+
+  return directdrawsink_type;
+}
+*/
+static void
+gst_directdrawsink_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details (element_class, &gst_directdrawsink_details);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&directdrawsink_sink_factory));
+}
+
+static void
+gst_directdrawsink_class_init (GstDirectDrawSinkClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+  GstBaseSinkClass *gstbasesink_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstbasesink_class = (GstBaseSinkClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_directdrawsink_finalize);
+
+  gobject_class->get_property =
+      GST_DEBUG_FUNCPTR (gst_directdrawsink_get_property);
+  gobject_class->set_property =
+      GST_DEBUG_FUNCPTR (gst_directdrawsink_set_property);
+
+  gstelement_class->change_state =
+      GST_DEBUG_FUNCPTR (gst_directdrawsink_change_state);
+  gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_directdrawsink_get_caps);
+  gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_directdrawsink_set_caps);
+  gstbasesink_class->preroll =
+      GST_DEBUG_FUNCPTR (gst_directdrawsink_show_frame);
+  gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_directdrawsink_show_frame);
+
+  gstbasesink_class->get_times =
+      GST_DEBUG_FUNCPTR (gst_directdrawsink_get_times);
+  gstbasesink_class->buffer_alloc =
+      GST_DEBUG_FUNCPTR (gst_directdrawsink_buffer_alloc);
+
+  /*install properties */
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FULLSCREEN,
+      g_param_spec_boolean ("fullscreen", "fullscreen",
+          "boolean to activate fullscreen", FALSE, G_PARAM_READWRITE));
+
+  /*extern window where we will display the video */
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WINDOW,
+      g_param_spec_long ("window", "Window",
+          "The target window for video", G_MINLONG, G_MAXLONG, 0,
+          G_PARAM_WRITABLE));
+
+  /*extern surface where we will blit the video */
+  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SURFACE,
+      g_param_spec_pointer ("surface", "Surface",
+          "The target surface for video", G_PARAM_WRITABLE));
+
+  /*should add a color_key property to permit applications to define the color used for overlays */
+}
+
+static void
+gst_directdrawsink_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstDirectDrawSink *ddrawsink;
+
+  ddrawsink = GST_DIRECTDRAW_SINK (object);
+
+  switch (prop_id) {
+    case PROP_SURFACE:
+      ddrawsink->extern_surface = g_value_get_pointer (value);
+      break;
+    case PROP_WINDOW:
+      ddrawsink->video_window = (HWND) g_value_get_long (value);
+      ddrawsink->resize_window = FALSE;
+      break;
+    case PROP_FULLSCREEN:
+      if (g_value_get_boolean (value))
+        ddrawsink->bFullScreen = TRUE;
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_directdrawsink_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstDirectDrawSink *ddrawsink;
+
+  ddrawsink = GST_DIRECTDRAW_SINK (object);
+
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_directdrawsink_finalize (GObject * object)
+{
+  GstDirectDrawSink *ddrawsink;
+
+  ddrawsink = GST_DIRECTDRAW_SINK (object);
+
+  if (ddrawsink->pool_lock) {
+    g_mutex_free (ddrawsink->pool_lock);
+    ddrawsink->pool_lock = NULL;
+  }
+  if (ddrawsink->setup) {
+    gst_directdrawsink_cleanup (ddrawsink);
+  }
+}
+
+static void
+gst_directdrawsink_init (GstDirectDrawSink * ddrawsink,
+    GstDirectDrawSinkClass * g_class)
+{
+  /*init members variables */
+  ddrawsink->ddraw_object = NULL;
+  ddrawsink->primary_surface = NULL;
+  ddrawsink->overlays = NULL;
+  ddrawsink->clipper = NULL;
+  ddrawsink->extern_surface = NULL;
+
+  /*video default values */
+  ddrawsink->video_height = 0;
+  ddrawsink->video_width = 0;
+  ddrawsink->fps_n = 0;
+  ddrawsink->fps_d = 0;
+
+  memset (&ddrawsink->dd_pixel_format, 0, sizeof (DDPIXELFORMAT));
+
+  ddrawsink->caps = NULL;
+
+  ddrawsink->window_thread = NULL;
+
+  ddrawsink->bUseOverlay = TRUE;
+  ddrawsink->color_key = 0;     /*need to be a public property and may be we can enable overlays when this property is set ... */
+
+  ddrawsink->bFullScreen = FALSE;
+  ddrawsink->setup = FALSE;
+
+  ddrawsink->display_modes = NULL;
+  ddrawsink->buffer_pool = NULL;
+
+  ddrawsink->resize_window = TRUE;      /*resize only our internal window to the video size */
+  global_ddrawsink = ddrawsink;
+
+  ddrawsink->pool_lock = g_mutex_new ();
+}
+
+static GstCaps *
+gst_directdrawsink_get_caps (GstBaseSink * bsink)
+{
+  GstDirectDrawSink *ddrawsink;
+  GstCaps *caps = NULL;
+
+  ddrawsink = GST_DIRECTDRAW_SINK (bsink);
+
+  if (!ddrawsink->setup) {
+    caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD
+            (ddrawsink)));
+
+    GST_DEBUG ("getcaps called and we are not setup yet, "
+        "returning template %" GST_PTR_FORMAT, caps);
+  } else {
+    /*if (ddrawsink->extern_surface) {
+     * We are not rendering to our own surface, returning this surface's
+     *  pixel format *
+     GST_WARNING ("using extern surface");
+     caps = gst_ddrawvideosink_get_caps_from_format (ddrawsink->dd_pixel_format);
+     } else */
+
+    /* i think we can't really use the format of the extern surface as the application owning the surface doesn't know
+       the format we will render. But we need to use overlays to overlay any format on the extern surface */
+    caps = gst_caps_ref (ddrawsink->caps);
+  }
+
+  return caps;
+}
+
+static gboolean
+gst_directdrawsink_set_caps (GstBaseSink * bsink, GstCaps * caps)
+{
+  GstDirectDrawSink *ddrawsink;
+  GstStructure *structure = NULL;
+  gboolean ret;
+  const GValue *fps;
+
+  ddrawsink = GST_DIRECTDRAW_SINK (bsink);
+
+  structure = gst_caps_get_structure (caps, 0);
+  if (!structure)
+    return FALSE;
+
+  ret = gst_structure_get_int (structure, "width", &ddrawsink->video_width);
+  ret &= gst_structure_get_int (structure, "height", &ddrawsink->video_height);
+
+  fps = gst_structure_get_value (structure, "framerate");
+  ret &= (fps != NULL);
+
+  ret &=
+      gst_ddrawvideosink_get_format_from_caps (caps,
+      &ddrawsink->dd_pixel_format);
+
+  if (!ret)
+    return FALSE;
+
+  ddrawsink->fps_n = gst_value_get_fraction_numerator (fps);
+  ddrawsink->fps_d = gst_value_get_fraction_denominator (fps);
+
+  if (ddrawsink->video_window && ddrawsink->resize_window) {
+    SetWindowPos (ddrawsink->video_window, NULL,
+        0, 0, ddrawsink->video_width + (GetSystemMetrics (SM_CXSIZEFRAME) * 2),
+        ddrawsink->video_height + GetSystemMetrics (SM_CYCAPTION) +
+        (GetSystemMetrics (SM_CYSIZEFRAME) * 2), SWP_SHOWWINDOW | SWP_NOMOVE);
+  }
+
+  /*create overlays flipping chain and an offscreen surface */
+  gst_directdrawsink_create_ddraw_surfaces (ddrawsink);
+
+  return TRUE;
+}
+
+static GstStateChangeReturn
+gst_directdrawsink_change_state (GstElement * element,
+    GstStateChange transition)
+{
+  GstDirectDrawSink *ddrawsink;
+
+  ddrawsink = GST_DIRECTDRAW_SINK (element);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      GST_DEBUG ("GST_STATE_CHANGE_NULL_TO_READY\n");
+
+      if (ddrawsink->video_window == NULL && ddrawsink->extern_surface == NULL)
+        if (!gst_directdrawsink_create_default_window (ddrawsink))
+          return GST_STATE_CHANGE_FAILURE;
+
+      if (!gst_directdrawsink_setup_ddraw (ddrawsink))
+        return GST_STATE_CHANGE_FAILURE;
+
+      if (!(ddrawsink->caps = gst_directdrawsink_get_ddrawcaps (ddrawsink)))
+        return GST_STATE_CHANGE_FAILURE;
+
+      break;
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      GST_DEBUG ("GST_STATE_CHANGE_READY_TO_PAUSED\n");
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      GST_DEBUG ("GST_STATE_CHANGE_PAUSED_TO_PLAYING\n");
+      break;
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      GST_DEBUG ("GST_STATE_CHANGE_PLAYING_TO_PAUSED\n");
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      GST_DEBUG ("GST_STATE_CHANGE_PAUSED_TO_READY\n");
+
+      ddrawsink->fps_n = 0;
+      ddrawsink->fps_d = 1;
+      ddrawsink->video_width = 0;
+      ddrawsink->video_height = 0;
+
+      if (ddrawsink->buffer_pool)
+        gst_directdrawsink_bufferpool_clear (ddrawsink);
+
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      GST_DEBUG ("GST_STATE_CHANGE_READY_TO_NULL\n");
+
+      if (ddrawsink->setup)
+        gst_directdrawsink_cleanup (ddrawsink);
+
+      break;
+  }
+
+  return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+}
+
+/**
+ * Get DirectDraw error message.
+ * @hr: HRESULT code
+ * Returns: Text representation of the error.
+ */
+char *
+DDErrorString (HRESULT hr)
+{
+  switch (hr) {
+    case DDERR_ALREADYINITIALIZED:
+      return "DDERR_ALREADYINITIALIZED";
+    case DDERR_CANNOTATTACHSURFACE:
+      return "DDERR_CANNOTATTACHSURFACE";
+    case DDERR_CANNOTDETACHSURFACE:
+      return "DDERR_CANNOTDETACHSURFACE";
+    case DDERR_CURRENTLYNOTAVAIL:
+      return "DDERR_CURRENTLYNOTAVAIL";
+    case DDERR_EXCEPTION:
+      return "DDERR_EXCEPTION";
+    case DDERR_GENERIC:
+      return "DDERR_GENERIC";
+    case DDERR_HEIGHTALIGN:
+      return "DDERR_HEIGHTALIGN";
+    case DDERR_INCOMPATIBLEPRIMARY:
+      return "DDERR_INCOMPATIBLEPRIMARY";
+    case DDERR_INVALIDCAPS:
+      return "DDERR_INVALIDCAPS";
+    case DDERR_INVALIDCLIPLIST:
+      return "DDERR_INVALIDCLIPLIST";
+    case DDERR_INVALIDMODE:
+      return "DDERR_INVALIDMODE";
+    case DDERR_INVALIDOBJECT:
+      return "DDERR_INVALIDOBJECT";
+    case DDERR_INVALIDPARAMS:
+      return "DDERR_INVALIDPARAMS";
+    case DDERR_INVALIDPIXELFORMAT:
+      return "DDERR_INVALIDPIXELFORMAT";
+    case DDERR_INVALIDRECT:
+      return "DDERR_INVALIDRECT";
+    case DDERR_LOCKEDSURFACES:
+      return "DDERR_LOCKEDSURFACES";
+    case DDERR_NO3D:
+      return "DDERR_NO3D";
+    case DDERR_NOALPHAHW:
+      return "DDERR_NOALPHAHW";
+    case DDERR_NOCLIPLIST:
+      return "DDERR_NOCLIPLIST";
+    case DDERR_NOCOLORCONVHW:
+      return "DDERR_NOCOLORCONVHW";
+    case DDERR_NOCOOPERATIVELEVELSET:
+      return "DDERR_NOCOOPERATIVELEVELSET";
+    case DDERR_NOCOLORKEY:
+      return "DDERR_NOCOLORKEY";
+    case DDERR_NOCOLORKEYHW:
+      return "DDERR_NOCOLORKEYHW";
+    case DDERR_NODIRECTDRAWSUPPORT:
+      return "DDERR_NODIRECTDRAWSUPPORT";
+    case DDERR_NOEXCLUSIVEMODE:
+      return "DDERR_NOEXCLUSIVEMODE";
+    case DDERR_NOFLIPHW:
+      return "DDERR_NOFLIPHW";
+    case DDERR_NOGDI:
+      return "DDERR_NOGDI";
+    case DDERR_NOMIRRORHW:
+      return "DDERR_NOMIRRORHW";
+    case DDERR_NOTFOUND:
+      return "DDERR_NOTFOUND";
+    case DDERR_NOOVERLAYHW:
+      return "DDERR_NOOVERLAYHW";
+    case DDERR_NORASTEROPHW:
+      return "DDERR_NORASTEROPHW";
+    case DDERR_NOROTATIONHW:
+      return "DDERR_NOROTATIONHW";
+    case DDERR_NOSTRETCHHW:
+      return "DDERR_NOSTRETCHHW";
+    case DDERR_NOT4BITCOLOR:
+      return "DDERR_NOT4BITCOLOR";
+    case DDERR_NOT4BITCOLORINDEX:
+      return "DDERR_NOT4BITCOLORINDEX";
+    case DDERR_NOT8BITCOLOR:
+      return "DDERR_NOT8BITCOLOR";
+    case DDERR_NOTEXTUREHW:
+      return "DDERR_NOTEXTUREHW";
+    case DDERR_NOVSYNCHW:
+      return "DDERR_NOVSYNCHW";
+    case DDERR_NOZBUFFERHW:
+      return "DDERR_NOZBUFFERHW";
+    case DDERR_NOZOVERLAYHW:
+      return "DDERR_NOZOVERLAYHW";
+    case DDERR_OUTOFCAPS:
+      return "DDERR_OUTOFCAPS";
+    case DDERR_OUTOFMEMORY:
+      return "DDERR_OUTOFMEMORY";
+    case DDERR_OUTOFVIDEOMEMORY:
+      return "DDERR_OUTOFVIDEOMEMORY";
+    case DDERR_OVERLAYCANTCLIP:
+      return "DDERR_OVERLAYCANTCLIP";
+    case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
+      return "DDERR_OVERLAYCOLORKEYONLYONEACTIVE";
+    case DDERR_PALETTEBUSY:
+      return "DDERR_PALETTEBUSY";
+    case DDERR_COLORKEYNOTSET:
+      return "DDERR_COLORKEYNOTSET";
+    case DDERR_SURFACEALREADYATTACHED:
+      return "DDERR_SURFACEALREADYATTACHED";
+    case DDERR_SURFACEALREADYDEPENDENT:
+      return "DDERR_SURFACEALREADYDEPENDENT";
+    case DDERR_SURFACEBUSY:
+      return "DDERR_SURFACEBUSY";
+    case DDERR_CANTLOCKSURFACE:
+      return "DDERR_CANTLOCKSURFACE";
+    case DDERR_SURFACEISOBSCURED:
+      return "DDERR_SURFACEISOBSCURED";
+    case DDERR_SURFACELOST:
+      return "DDERR_SURFACELOST";
+    case DDERR_SURFACENOTATTACHED:
+      return "DDERR_SURFACENOTATTACHED";
+    case DDERR_TOOBIGHEIGHT:
+      return "DDERR_TOOBIGHEIGHT";
+    case DDERR_TOOBIGSIZE:
+      return "DDERR_TOOBIGSIZE";
+    case DDERR_TOOBIGWIDTH:
+      return "DDERR_TOOBIGWIDTH";
+    case DDERR_UNSUPPORTED:
+      return "DDERR_UNSUPPORTED";
+    case DDERR_UNSUPPORTEDFORMAT:
+      return "DDERR_UNSUPPORTEDFORMAT";
+    case DDERR_UNSUPPORTEDMASK:
+      return "DDERR_UNSUPPORTEDMASK";
+    case DDERR_VERTICALBLANKINPROGRESS:
+      return "DDERR_VERTICALBLANKINPROGRESS";
+    case DDERR_WASSTILLDRAWING:
+      return "DDERR_WASSTILLDRAWING";
+    case DDERR_XALIGN:
+      return "DDERR_XALIGN";
+    case DDERR_INVALIDDIRECTDRAWGUID:
+      return "DDERR_INVALIDDIRECTDRAWGUID";
+    case DDERR_DIRECTDRAWALREADYCREATED:
+      return "DDERR_DIRECTDRAWALREADYCREATED";
+    case DDERR_NODIRECTDRAWHW:
+      return "DDERR_NODIRECTDRAWHW";
+    case DDERR_PRIMARYSURFACEALREADYEXISTS:
+      return "DDERR_PRIMARYSURFACEALREADYEXISTS";
+    case DDERR_NOEMULATION:
+      return "DDERR_NOEMULATION";
+    case DDERR_REGIONTOOSMALL:
+      return "DDERR_REGIONTOOSMALL";
+    case DDERR_CLIPPERISUSINGHWND:
+      return "DDERR_CLIPPERISUSINGHWND";
+    case DDERR_NOCLIPPERATTACHED:
+      return "DDERR_NOCLIPPERATTACHED";
+    case DDERR_NOHWND:
+      return "DDERR_NOHWND";
+    case DDERR_HWNDSUBCLASSED:
+      return "DDERR_HWNDSUBCLASSED";
+    case DDERR_HWNDALREADYSET:
+      return "DDERR_HWNDALREADYSET";
+    case DDERR_NOPALETTEATTACHED:
+      return "DDERR_NOPALETTEATTACHED";
+    case DDERR_NOPALETTEHW:
+      return "DDERR_NOPALETTEHW";
+    case DDERR_BLTFASTCANTCLIP:
+      return "DDERR_BLTFASTCANTCLIP";
+    case DDERR_NOBLTHW:
+      return "DDERR_NOBLTHW";
+    case DDERR_NODDROPSHW:
+      return "DDERR_NODDROPSHW";
+    case DDERR_OVERLAYNOTVISIBLE:
+      return "DDERR_OVERLAYNOTVISIBLE";
+    case DDERR_NOOVERLAYDEST:
+      return "DDERR_NOOVERLAYDEST";
+    case DDERR_INVALIDPOSITION:
+      return "DDERR_INVALIDPOSITION";
+    case DDERR_NOTAOVERLAYSURFACE:
+      return "DDERR_NOTAOVERLAYSURFACE";
+    case DDERR_EXCLUSIVEMODEALREADYSET:
+      return "DDERR_EXCLUSIVEMODEALREADYSET";
+    case DDERR_NOTFLIPPABLE:
+      return "DDERR_NOTFLIPPABLE";
+    case DDERR_CANTDUPLICATE:
+      return "DDERR_CANTDUPLICATE";
+    case DDERR_NOTLOCKED:
+      return "DDERR_NOTLOCKED";
+    case DDERR_CANTCREATEDC:
+      return "DDERR_CANTCREATEDC";
+    case DDERR_NODC:
+      return "DDERR_NODC";
+    case DDERR_WRONGMODE:
+      return "DDERR_WRONGMODE";
+    case DDERR_IMPLICITLYCREATED:
+      return "DDERR_IMPLICITLYCREATED";
+    case DDERR_NOTPALETTIZED:
+      return "DDERR_NOTPALETTIZED";
+    case DDERR_UNSUPPORTEDMODE:
+      return "DDERR_UNSUPPORTEDMODE";
+    case DDERR_NOMIPMAPHW:
+      return "DDERR_NOMIPMAPHW";
+    case DDERR_INVALIDSURFACETYPE:
+      return "DDERR_INVALIDSURFACETYPE";
+    case DDERR_DCALREADYCREATED:
+      return "DDERR_DCALREADYCREATED";
+    case DDERR_CANTPAGELOCK:
+      return "DDERR_CANTPAGELOCK";
+    case DDERR_CANTPAGEUNLOCK:
+      return "DDERR_CANTPAGEUNLOCK";
+    case DDERR_NOTPAGELOCKED:
+      return "DDERR_NOTPAGELOCKED";
+    case DDERR_NOTINITIALIZED:
+      return "DDERR_NOTINITIALIZED";
+  }
+  return "Unknown Error";
+}
+
+
+static gint gtempcpt = 0;
+static GstFlowReturn
+gst_directdrawsink_buffer_alloc (GstBaseSink * bsink, guint64 offset,
+    guint size, GstCaps * caps, GstBuffer ** buf)
+{
+  GstDirectDrawSink *ddrawsink = NULL;
+  GstDDrawSurface *surface = NULL;
+  GstStructure *structure = NULL;
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  ddrawsink = GST_DIRECTDRAW_SINK (bsink);
+  GST_DEBUG ("a buffer of %d bytes was requested", size);
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  g_mutex_lock (ddrawsink->pool_lock);
+
+  /* Inspect our buffer pool */
+  while (ddrawsink->buffer_pool) {
+    surface = (GstDDrawSurface *) ddrawsink->buffer_pool->data;
+
+    if (surface) {
+      /* Removing from the pool */
+      ddrawsink->buffer_pool = g_slist_delete_link (ddrawsink->buffer_pool,
+          ddrawsink->buffer_pool);
+
+      /* If the surface is invalid for our need, destroy */
+      if ((surface->width != ddrawsink->video_width) ||
+          (surface->height != ddrawsink->video_height) ||
+          (memcmp (&surface->dd_pixel_format, &ddrawsink->dd_pixel_format,
+                  sizeof (DDPIXELFORMAT)))
+          ) {
+        gst_directdrawsink_surface_destroy (ddrawsink, surface);
+        surface = NULL;
+      } else {
+        /* We found a suitable surface */
+        break;
+      }
+    }
+  }
+
+  /* We haven't found anything, creating a new one */
+  if (!surface) {
+    surface = gst_directdrawsink_surface_create (ddrawsink, caps, size);
+    gtempcpt++;
+  }
+
+  /* Now we should have a surface, set appropriate caps on it */
+  if (surface) {
+    gst_buffer_set_caps (GST_BUFFER (surface), caps);
+  }
+
+  g_mutex_unlock (ddrawsink->pool_lock);
+
+  *buf = GST_BUFFER (surface);
+
+  return ret;
+}
+
+static gboolean
+gst_directdrawsink_fill_colorkey (LPDIRECTDRAWSURFACE surface, DWORD dwColorKey)
+{
+  DDBLTFX ddbfx;
+
+  if (!surface)
+    return FALSE;
+
+  ddbfx.dwSize = sizeof (DDBLTFX);
+  ddbfx.dwFillColor = dwColorKey;
+
+  if (IDirectDrawSurface_Blt (surface,
+          NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbfx) == DD_OK)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+
+static void
+gst_directdrawsink_show_overlay (GstDirectDrawSink * ddrawsink)
+{
+  HRESULT hRes;
+  RECT destsurf_rect, src_rect;
+  POINT dest_surf_point;
+  DDOVERLAYFX ddofx;
+  LPDIRECTDRAWSURFACE surface = NULL;
+
+  if (!ddrawsink || !ddrawsink->overlays)
+    return;
+
+  if (ddrawsink->extern_surface)
+    surface = ddrawsink->extern_surface;
+  else
+    surface = ddrawsink->primary_surface;
+
+  if (ddrawsink->extern_surface) {
+    destsurf_rect.left = 0;
+    destsurf_rect.top = 0;
+    destsurf_rect.right = ddrawsink->out_width;
+    destsurf_rect.bottom = ddrawsink->out_height;
+  } else {
+    dest_surf_point.x = 0;
+    dest_surf_point.y = 0;
+    ClientToScreen (ddrawsink->video_window, &dest_surf_point);
+    GetClientRect (ddrawsink->video_window, &destsurf_rect);
+    OffsetRect (&destsurf_rect, dest_surf_point.x, dest_surf_point.y);
+  }
+
+  src_rect.top = 0;
+  src_rect.left = 0;
+  src_rect.bottom = ddrawsink->video_height;
+  src_rect.right = ddrawsink->video_width;
+  gst_directdrawsink_center_rect (src_rect, destsurf_rect, &destsurf_rect);
+
+  gst_directdrawsink_fill_colorkey (surface, ddrawsink->color_key);
+
+  ddofx.dwSize = sizeof (DDOVERLAYFX);
+  ddofx.dckDestColorkey.dwColorSpaceLowValue = ddrawsink->color_key;
+  ddofx.dckDestColorkey.dwColorSpaceHighValue = ddrawsink->color_key;
+
+  hRes = IDirectDrawSurface_UpdateOverlay (ddrawsink->overlays,
+      NULL, surface, &destsurf_rect, DDOVER_KEYDESTOVERRIDE | DDOVER_SHOW,
+      &ddofx);
+}
+
+static GstFlowReturn
+gst_directdrawsink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
+{
+  GstDirectDrawSink *ddrawsink;
+  HRESULT hRes;
+
+  DDSURFACEDESC surf_desc;
+  RECT destsurf_rect, src_rect;
+  POINT dest_surf_point;
+  LPDIRECTDRAWSURFACE lpSurface = NULL;
+
+  ddrawsink = GST_DIRECTDRAW_SINK (bsink);
+
+  if (ddrawsink->extern_surface) {
+    destsurf_rect.left = 0;
+    destsurf_rect.top = 0;
+    destsurf_rect.right = ddrawsink->out_width;
+    destsurf_rect.bottom = ddrawsink->out_height;
+  } else {
+    dest_surf_point.x = 0;
+    dest_surf_point.y = 0;
+    ClientToScreen (ddrawsink->video_window, &dest_surf_point);
+    GetClientRect (ddrawsink->video_window, &destsurf_rect);
+    OffsetRect (&destsurf_rect, dest_surf_point.x, dest_surf_point.y);
+  }
+
+  src_rect.top = 0;
+  src_rect.left = 0;
+  src_rect.bottom = ddrawsink->video_height;
+  src_rect.right = ddrawsink->video_width;
+  gst_directdrawsink_center_rect (src_rect, destsurf_rect, &destsurf_rect);
+
+  if (ddrawsink->bUseOverlay) {
+    /*get the back buffer of the overlays flipping chain */
+    DDSCAPS ddbackcaps;
+
+    ddbackcaps.dwCaps = DDSCAPS_BACKBUFFER;
+    IDirectDrawSurface_GetAttachedSurface (ddrawsink->overlays, &ddbackcaps,
+        &lpSurface);
+  } else {
+    /*use our offscreen surface */
+    lpSurface = ddrawsink->offscreen_surface;
+  }
+
+  if (lpSurface == NULL)
+    return GST_FLOW_ERROR;
+
+  if (!GST_IS_DDRAWSURFACE (buf) ||
+      ((GST_IS_DDRAWSURFACE (buf)) && (GST_BUFFER (buf)->malloc_data))) {
+
+    LPBYTE data = NULL;
+    guint src_pitch, line;
+
+    /* Check for lost surface */
+    if (IDirectDrawSurface_IsLost (lpSurface) == DDERR_SURFACELOST) {
+      IDirectDrawSurface_Restore (lpSurface);
+    }
+
+    ZeroMemory (&surf_desc, sizeof (surf_desc));
+    surf_desc.dwSize = sizeof (surf_desc);
+
+    /* Lock the surface */
+    hRes =
+        IDirectDrawSurface_Lock (lpSurface, NULL, &surf_desc, DDLOCK_WAIT,
+        NULL);
+    if (hRes != DD_OK) {
+      GST_DEBUG ("gst_directdrawsink_show_frame failed locking surface %s",
+          DDErrorString (hRes));
+      return GST_FLOW_ERROR;
+    }
+
+    /* Write data */
+    data = surf_desc.lpSurface;
+
+    /* Source video rowbytes */
+    src_pitch = GST_BUFFER_SIZE (buf) / ddrawsink->video_height;
+
+    /* Write each line respecting dest surface pitch */
+    for (line = 0; line < surf_desc.dwHeight; line++) {
+      memcpy (data, GST_BUFFER_DATA (buf) + (line * src_pitch), src_pitch);
+      data += surf_desc.lPitch;
+    }
+
+    /* Unlock the surface */
+    hRes = IDirectDrawSurface_Unlock (lpSurface, NULL);
+    if (hRes != DD_OK) {
+      GST_DEBUG ("gst_directdrawsink_show_frame failed unlocking surface %s",
+          DDErrorString (hRes));
+      return GST_FLOW_ERROR;
+    }
+
+    if (ddrawsink->bUseOverlay) {
+      /*Flip to front overlay */
+      hRes =
+          IDirectDrawSurface_Flip (ddrawsink->overlays, lpSurface, DDFLIP_WAIT);
+      IDirectDrawSurface_Release (lpSurface);
+      lpSurface = NULL;
+    } else {
+      if (ddrawsink->extern_surface) {
+        if (ddrawsink->out_height == ddrawsink->video_height &&
+            ddrawsink->out_width == ddrawsink->video_width) {
+          /*Fast blit to extern surface */
+          hRes = IDirectDrawSurface_BltFast (ddrawsink->extern_surface, 0, 0,
+              lpSurface, NULL, DDBLTFAST_WAIT);
+
+        } else {
+          /*blit to extern surface (Blt will scale the video the dest rect surface if needed) */
+          hRes =
+              IDirectDrawSurface_Blt (ddrawsink->extern_surface, &destsurf_rect,
+              lpSurface, NULL, DDBLT_WAIT, NULL);
+        }
+      } else {
+        /*blit to primary surface ( Blt will scale the video the dest rect surface if needed */
+        hRes =
+            IDirectDrawSurface_Blt (ddrawsink->primary_surface, &destsurf_rect,
+            lpSurface, NULL, DDBLT_WAIT, NULL);
+      }
+    }
+  } else {
+
+    GstDDrawSurface *surface = NULL;
+
+    surface = GST_DDRAWSURFACE (buf);
+
+    /* Unlocking surface before blit */
+    IDirectDrawSurface_Unlock (surface->surface, NULL);
+    surface->locked = FALSE;
+
+    /* Check for lost surfaces */
+    if (IDirectDrawSurface_IsLost (surface->surface) == DDERR_SURFACELOST) {
+      IDirectDrawSurface_Restore (surface->surface);
+    }
+
+    if (ddrawsink->bUseOverlay) {
+      /* blit to the overlays back buffer */
+      hRes = IDirectDrawSurface_Blt (lpSurface, NULL,
+          surface->surface, NULL, DDBLT_WAIT, NULL);
+
+      hRes = IDirectDrawSurface_Flip (ddrawsink->overlays, NULL, DDFLIP_WAIT);
+      if (hRes != DD_OK)
+        GST_WARNING ("error flipping");
+
+    } else {
+      if (ddrawsink->extern_surface) {
+        /*blit to the extern surface */
+        if (ddrawsink->out_height == ddrawsink->video_height &&
+            ddrawsink->out_width == ddrawsink->video_width) {
+          /*Fast blit to extern surface */
+          hRes = IDirectDrawSurface_BltFast (ddrawsink->extern_surface, 0, 0,
+              surface->surface, NULL, DDBLTFAST_WAIT);
+
+        } else {
+          /*blit to extern surface (Blt will scale the video the dest rect surface if needed) */
+          hRes =
+              IDirectDrawSurface_Blt (ddrawsink->extern_surface, &destsurf_rect,
+              surface->surface, NULL, DDBLT_WAIT, NULL);
+        }
+      } else {
+        /*blit to our primary surface */
+        hRes =
+            IDirectDrawSurface_Blt (ddrawsink->primary_surface, &destsurf_rect,
+            surface->surface, NULL, DDBLT_WAIT, NULL);
+        if (hRes != DD_OK)
+          GST_WARNING ("IDirectDrawSurface_Blt returned %s",
+              DDErrorString (hRes));
+      }
+    }
+  }
+
+  if (ddrawsink->bUseOverlay)
+    gst_directdrawsink_show_overlay (ddrawsink);
+
+  return GST_FLOW_OK;
+}
+
+static gboolean
+gst_directdrawsink_setup_ddraw (GstDirectDrawSink * ddrawsink)
+{
+  gboolean bRet = TRUE;
+  HRESULT hRes;
+  DWORD dwCooperativeLevel;
+  DDSURFACEDESC dd_surface_desc;
+
+  /*create an instance of the ddraw object */
+  hRes = DirectDrawCreate (NULL, &ddrawsink->ddraw_object, NULL);
+  if (hRes != DD_OK || ddrawsink->ddraw_object == NULL)
+    return FALSE;
+
+  /*set cooperative level */
+  if (ddrawsink->bFullScreen)
+    dwCooperativeLevel = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
+  else
+    dwCooperativeLevel = DDSCL_NORMAL;
+
+  hRes = IDirectDraw_SetCooperativeLevel (ddrawsink->ddraw_object,
+      ddrawsink->video_window, dwCooperativeLevel);
+  if (hRes != DD_OK)
+    bRet = FALSE;
+
+  /*for fullscreen mode, setup display mode */
+  if (ddrawsink->bFullScreen) {
+    hRes = IDirectDraw_SetDisplayMode (ddrawsink->ddraw_object, 640, 480, 32);
+  }
+
+  if (!ddrawsink->extern_surface) {
+    /*create our primary surface */
+    memset (&dd_surface_desc, 0, sizeof (dd_surface_desc));
+    dd_surface_desc.dwSize = sizeof (dd_surface_desc);
+    dd_surface_desc.dwFlags = DDSD_CAPS;
+    dd_surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+    hRes = IDirectDraw_CreateSurface (ddrawsink->ddraw_object, &dd_surface_desc,
+        &ddrawsink->primary_surface, NULL);
+    if (hRes != DD_OK)
+      bRet = FALSE;
+
+    if (bRet == FALSE) {
+      if (ddrawsink->ddraw_object) {
+        IDirectDraw_Release (ddrawsink->ddraw_object);
+        GST_DEBUG ("CreateSurface failed with: %s", DDErrorString (hRes));
+        return FALSE;
+      }
+    }
+
+    hRes = IDirectDraw_CreateClipper (ddrawsink->ddraw_object, 0,
+        &ddrawsink->clipper, NULL);
+    if (hRes == DD_OK) {
+      hRes = IDirectDrawClipper_SetHWnd (ddrawsink->clipper, 0,
+          ddrawsink->video_window);
+      hRes = IDirectDrawSurface_SetClipper (ddrawsink->primary_surface,
+          ddrawsink->clipper);
+    }
+  } else {
+    DDSURFACEDESC desc_surface;
+
+    desc_surface.dwSize = sizeof (DDSURFACEDESC);
+
+    /*get extern surface size */
+    hRes = IDirectDrawSurface_GetSurfaceDesc (ddrawsink->extern_surface,
+        &desc_surface);
+    if (hRes != DD_OK) {
+      /*error while retrieving ext surface description */
+      return FALSE;
+    }
+
+    ddrawsink->out_width = desc_surface.dwWidth;
+    ddrawsink->out_height = desc_surface.dwHeight;
+
+    /*get extern surface pixel format (FIXME not needed if we are using overlays) */
+    ddrawsink->dd_pixel_format.dwSize = sizeof (DDPIXELFORMAT);
+    hRes = IDirectDrawSurface_GetPixelFormat (ddrawsink->extern_surface,
+        &ddrawsink->dd_pixel_format);
+    if (hRes != DD_OK) {
+      /*error while retrieving ext surface pixel format */
+      return FALSE;
+    }
+
+    /*get specific caps if needed ... */
+  }
+
+  ddrawsink->setup = TRUE;
+
+  return bRet;
+}
+
+long FAR PASCAL
+WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message) {
+    case WM_ERASEBKGND:
+      return TRUE;
+/*    case WM_WINDOWPOSCHANGED:
+    case WM_MOVE:
+    case WM_SIZE:
+               if(global_ddrawsink && global_ddrawsink->bUseOverlay)
+                       gst_directdrawsink_show_overlay(global_ddrawsink);
+               break;
+ case WM_PAINT:
+               if(global_ddrawsink && global_ddrawsink->bUseOverlay)
+    {
+      if(global_ddrawsink->extern_surface)
+        gst_directdrawsink_fill_colorkey(global_ddrawsink->extern_surface, 
+            global_ddrawsink->color_key);
+      else
+        gst_directdrawsink_fill_colorkey(global_ddrawsink->primary_surface, 
+            global_ddrawsink->color_key);
+    }
+       break;
+*/
+    case WM_DESTROY:
+      PostQuitMessage (0);
+      break;
+    case WM_CLOSE:
+      DestroyWindow (hWnd);
+      return 0;
+  }
+  return DefWindowProc (hWnd, message, wParam, lParam);
+}
+
+static gpointer
+gst_directdrawsink_window_thread (GstDirectDrawSink * ddrawsink)
+{
+  WNDCLASS WndClass;
+
+  memset (&WndClass, 0, sizeof (WNDCLASS));
+
+  WndClass.style = CS_HREDRAW | CS_VREDRAW;
+  WndClass.hInstance = GetModuleHandle (NULL);
+  WndClass.lpszClassName = "GStreamer-DirectDraw";
+  WndClass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
+  WndClass.cbClsExtra = 0;
+  WndClass.cbWndExtra = 0;
+  WndClass.lpfnWndProc = WndProc;
+  WndClass.hCursor = LoadCursor (NULL, IDC_ARROW);
+
+  RegisterClass (&WndClass);
+
+  ddrawsink->video_window = CreateWindowEx (0, "GStreamer-DirectDraw",
+      "GStreamer-DirectDraw sink default window",
+      WS_OVERLAPPEDWINDOW | WS_SIZEBOX, 0, 0, 640, 480, NULL, NULL,
+      WndClass.hInstance, NULL);
+
+  if (ddrawsink->video_window == NULL)
+    return FALSE;
+
+  ShowWindow (ddrawsink->video_window, SW_SHOW);
+
+  /*start message loop processing our default window messages */
+  while (1) {
+    MSG msg;
+
+    if (!GetMessage (&msg, ddrawsink->video_window, 0, 0))
+      break;
+    DispatchMessage (&msg);
+  }
+
+  return NULL;
+}
+
+static gboolean
+gst_directdrawsink_create_default_window (GstDirectDrawSink * ddrawsink)
+{
+  ddrawsink->window_thread = g_thread_create (
+      (GThreadFunc) gst_directdrawsink_window_thread, ddrawsink, TRUE, NULL);
+
+  if (ddrawsink->window_thread == NULL)
+    return FALSE;
+
+  /*TODO:wait for the window to be created with timeout */
+
+  return TRUE;
+}
+
+static gboolean
+gst_directdrawsink_create_ddraw_surfaces (GstDirectDrawSink * ddrawsink)
+{
+  DDSURFACEDESC dd_surface_desc;
+  HRESULT hRes;
+
+  memset (&dd_surface_desc, 0, sizeof (dd_surface_desc));
+  dd_surface_desc.dwSize = sizeof (dd_surface_desc);
+
+  dd_surface_desc.dwFlags =
+      DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
+  dd_surface_desc.dwHeight = ddrawsink->video_height;
+  dd_surface_desc.dwWidth = ddrawsink->video_width;
+  memcpy (&(dd_surface_desc.ddpfPixelFormat), &ddrawsink->dd_pixel_format,
+      sizeof (DDPIXELFORMAT));
+
+  if (ddrawsink->bUseOverlay) {
+    /*create overlays flipping chain */
+    dd_surface_desc.ddsCaps.dwCaps =
+        DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
+    dd_surface_desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
+    dd_surface_desc.dwBackBufferCount = 1;
+
+    hRes = IDirectDraw_CreateSurface (ddrawsink->ddraw_object, &dd_surface_desc,
+        &ddrawsink->overlays, NULL);
+
+    if (hRes != DD_OK) {
+      GST_DEBUG ("create_ddraw_surfaces:CreateSurface(overlays) failed %s",
+          DDErrorString (hRes));
+      return FALSE;
+    }
+  } else {
+    dd_surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+
+    hRes = IDirectDraw_CreateSurface (ddrawsink->ddraw_object, &dd_surface_desc,
+        &ddrawsink->offscreen_surface, NULL);
+
+    if (hRes != DD_OK) {
+      GST_DEBUG ("create_ddraw_surfaces:CreateSurface(offscreen) failed %s",
+          DDErrorString (hRes));
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+static void
+gst_directdrawsink_get_times (GstBaseSink * bsink, GstBuffer * buf,
+    GstClockTime * start, GstClockTime * end)
+{
+  GstDirectDrawSink *ddrawsink;
+
+  ddrawsink = GST_DIRECTDRAW_SINK (bsink);
+
+  if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+    *start = GST_BUFFER_TIMESTAMP (buf);
+    if (GST_BUFFER_DURATION_IS_VALID (buf)) {
+      *end = *start + GST_BUFFER_DURATION (buf);
+    } else {
+      if (ddrawsink->fps_n > 0) {
+        *end = *start + (GST_SECOND * ddrawsink->fps_d) / ddrawsink->fps_n;
+      }
+    }
+  }
+}
+
+static int
+gst_directdrawsink_get_depth (LPDDPIXELFORMAT lpddpfPixelFormat)
+{
+  gint order = 0, binary;
+
+  binary =
+      lpddpfPixelFormat->dwRBitMask | lpddpfPixelFormat->
+      dwGBitMask | lpddpfPixelFormat->dwBBitMask | lpddpfPixelFormat->
+      dwRGBAlphaBitMask;
+  while (binary != 0) {
+    if ((binary % 2) == 1)
+      order++;
+    binary = binary >> 1;
+  }
+  return order;
+}
+
+HRESULT WINAPI
+EnumModesCallback2 (LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID lpContext)
+{
+  GstDirectDrawSink *ddrawsink = (GstDirectDrawSink *) lpContext;
+  GstCaps *format_caps = NULL;
+
+  if (!ddrawsink || !lpDDSurfaceDesc)
+    return DDENUMRET_CANCEL;
+
+  if ((lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT) != DDSD_PIXELFORMAT) {
+    GST_DEBUG ("Display mode found with DDSD_PIXELFORMAT not set");
+    return DDENUMRET_OK;
+  }
+
+  if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) != DDPF_RGB)
+    return DDENUMRET_OK;
+
+  format_caps = gst_caps_new_simple ("video/x-raw-rgb",
+      "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
+      "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
+      "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,
+      "bpp", G_TYPE_INT, lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount,
+      "depth", G_TYPE_INT,
+      gst_directdrawsink_get_depth (&lpDDSurfaceDesc->ddpfPixelFormat),
+      "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, "red_mask", G_TYPE_INT,
+      lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask, "green_mask", G_TYPE_INT,
+      lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask, "blue_mask", G_TYPE_INT,
+      lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask, NULL);
+
+  if (format_caps) {
+    gst_caps_append (ddrawsink->caps, format_caps);
+  }
+
+  return DDENUMRET_OK;
+}
+
+static GstCaps *
+gst_directdrawsink_get_ddrawcaps (GstDirectDrawSink * ddrawsink)
+{
+  HRESULT hRes = S_OK;
+  DWORD dwFourccCodeIndex = 0;
+  LPDWORD pdwFourccCodes = NULL;
+  DWORD dwNbFourccCodes = 0;
+  GstCaps *format_caps = NULL;
+
+  ddrawsink->caps = gst_caps_new_empty ();
+  if (!ddrawsink->caps)
+    return FALSE;
+
+  /*enumerate display modes exposed by directdraw object */
+  hRes =
+      IDirectDraw_EnumDisplayModes (ddrawsink->ddraw_object, DDEDM_REFRESHRATES,
+      NULL, ddrawsink, EnumModesCallback2);
+  if (hRes != DD_OK) {
+    GST_DEBUG ("EnumDisplayModes returns: %s", DDErrorString (hRes));
+    return FALSE;
+  }
+
+  /* enumerate non-rgb modes exposed by directdraw object */
+  IDirectDraw_GetFourCCCodes (ddrawsink->ddraw_object, &dwNbFourccCodes, NULL);
+  if (dwNbFourccCodes != 0) {
+    pdwFourccCodes = g_new0 (DWORD, dwNbFourccCodes);
+    if (!pdwFourccCodes)
+      return FALSE;
+
+    if (FAILED (IDirectDraw_GetFourCCCodes (ddrawsink->ddraw_object,
+                &dwNbFourccCodes, pdwFourccCodes))) {
+      g_free (pdwFourccCodes);
+      return FALSE;
+    }
+
+    for (dwFourccCodeIndex = 0; dwFourccCodeIndex < dwNbFourccCodes;
+        dwFourccCodeIndex++) {
+      /*support only yuv formats YUY2, UYVY, YVU9, YV12, AYUV */
+      if (pdwFourccCodes[dwFourccCodeIndex] == mmioFOURCC ('Y', 'U', 'Y', '2')
+          || pdwFourccCodes[dwFourccCodeIndex] == mmioFOURCC ('U', 'Y', 'V',
+              'Y')
+          || pdwFourccCodes[dwFourccCodeIndex] == mmioFOURCC ('Y', 'V', 'U',
+              '9')
+          || pdwFourccCodes[dwFourccCodeIndex] == mmioFOURCC ('Y', 'V', '1',
+              '2')
+          || pdwFourccCodes[dwFourccCodeIndex] == mmioFOURCC ('A', 'Y', 'U',
+              'V')
+          ) {
+        format_caps = gst_caps_new_simple ("video/x-raw-yuv",
+            "format", GST_TYPE_FOURCC, pdwFourccCodes[dwFourccCodeIndex],
+            "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
+            "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
+            "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
+
+        if (format_caps)
+          gst_caps_append (ddrawsink->caps, format_caps);
+      }
+    }
+
+    g_free (pdwFourccCodes);
+  }
+
+  if (gst_caps_is_empty (ddrawsink->caps)) {
+    gst_caps_unref (ddrawsink->caps);
+
+    GST_ELEMENT_ERROR (ddrawsink, STREAM, WRONG_TYPE, (NULL),
+        ("No supported format found"));
+    return NULL;
+  }
+
+  return ddrawsink->caps;
+}
+
+/* Creates miniobject and our internal surface */
+static GstDDrawSurface *
+gst_directdrawsink_surface_create (GstDirectDrawSink * ddrawsink,
+    GstCaps * caps, size_t size)
+{
+  GstDDrawSurface *surface = NULL;
+  GstStructure *structure = NULL;
+
+  HRESULT hRes;
+  DDSURFACEDESC surf_desc, surf_lock_desc;
+
+  g_return_val_if_fail (GST_IS_DIRECTDRAW_SINK (ddrawsink), NULL);
+
+  /*init structures */
+  memset (&surf_desc, 0, sizeof (surf_desc));
+  memset (&surf_lock_desc, 0, sizeof (surf_desc));
+  surf_desc.dwSize = sizeof (surf_desc);
+  surf_lock_desc.dwSize = sizeof (surf_lock_desc);
+
+  /*create miniobject and initialize it */
+  surface = (GstDDrawSurface *) gst_mini_object_new (GST_TYPE_DDRAWSURFACE);
+  surface->locked = FALSE;
+
+  structure = gst_caps_get_structure (caps, 0);
+  if (!gst_structure_get_int (structure, "width", &surface->width) ||
+      !gst_structure_get_int (structure, "height", &surface->height)) {
+    GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
+  }
+
+  if (!gst_ddrawvideosink_get_format_from_caps (caps,
+          &surface->dd_pixel_format)) {
+    GST_WARNING ("failed getting pixel format from caps %" GST_PTR_FORMAT,
+        caps);
+  }
+
+  if (ddrawsink->ddraw_object) {
+    /* Creating an internal surface which will be used as GstBuffer, we used
+       the detected pixel format and video dimensions */
+    gint pitch = GST_ROUND_UP_8 (size / surface->height);
+
+    surf_desc.lPitch = pitch;
+
+    surf_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+    surf_desc.dwFlags =
+        DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH;
+    surf_desc.dwHeight = surface->height;
+    surf_desc.dwWidth = surface->width;
+
+    memcpy (&(surf_desc.ddpfPixelFormat), &surface->dd_pixel_format,
+        sizeof (DDPIXELFORMAT));
+
+    hRes = IDirectDraw_CreateSurface (ddrawsink->ddraw_object, &surf_desc,
+        &surface->surface, NULL);
+    if (hRes != DD_OK) {
+      gst_object_unref (surface);
+      surface = NULL;
+      goto beach;
+    }
+
+    /* Locking the surface to acquire the memory pointer.
+       Use DDLOCK_NOSYSLOCK to disable syslock which can cause a deadlock 
+       if directdraw api is used while a buffer is lock */
+    hRes = IDirectDrawSurface_Lock (surface->surface, NULL, &surf_lock_desc,
+        DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL);
+    surface->locked = TRUE;
+
+    if (surf_lock_desc.lPitch != pitch) {
+      GST_DEBUG
+          ("DDraw stride/pitch %d isn't as expected value %d, let's continue allocating buffer.",
+          surf_lock_desc.lPitch, pitch);
+      IDirectDrawSurface_Release (surface->surface);
+      goto surface_pitch_bad;
+    }
+
+    GST_DEBUG ("allocating a surface of %d bytes (stride=%d)\n", size,
+        surf_lock_desc.lPitch);
+    GST_BUFFER_DATA (surface) = surf_lock_desc.lpSurface;
+    GST_BUFFER_SIZE (surface) = surf_lock_desc.lPitch * surface->height;
+  } else {
+
+  surface_pitch_bad:
+    GST_BUFFER (surface)->malloc_data = g_malloc (size);
+    GST_BUFFER_DATA (surface) = GST_BUFFER (surface)->malloc_data;
+    GST_BUFFER_SIZE (surface) = size;
+    surface->surface = NULL;
+    printf ("allocating a buffer of %d bytes\n", size);
+  }
+
+  /* Keep a ref to our sink */
+  surface->ddrawsink = gst_object_ref (ddrawsink);
+
+beach:
+  return surface;
+}
+
+/* We are called from the finalize method of miniobject, the object will be
+ * destroyed so we just have to clean our internal stuff */
+static void
+gst_directdrawsink_surface_destroy (GstDirectDrawSink * ddrawsink,
+    GstDDrawSurface * surface)
+{
+  g_return_if_fail (GST_IS_DIRECTDRAW_SINK (ddrawsink));
+
+  /* Release our internal surface */
+  if (surface->surface) {
+    if (surface->locked) {
+      IDirectDrawSurface_Unlock (surface->surface, NULL);
+      surface->locked = FALSE;
+    }
+    IDirectDrawSurface_Release (surface->surface);
+    surface->surface = NULL;
+  }
+
+  if (GST_BUFFER (surface)->malloc_data) {
+    g_free (GST_BUFFER (surface)->malloc_data);
+    GST_BUFFER (surface)->malloc_data = NULL;
+  }
+
+  if (!surface->ddrawsink) {
+    goto no_sink;
+  }
+
+  /* Release the ref to our sink */
+  surface->ddrawsink = NULL;
+  gst_object_unref (ddrawsink);
+
+  return;
+
+no_sink:
+  GST_WARNING ("no sink found in surface");
+  return;
+}
+
+static void
+gst_directdrawsink_bufferpool_clear (GstDirectDrawSink * ddrawsink)
+{
+  g_mutex_lock (ddrawsink->pool_lock);
+  while (ddrawsink->buffer_pool) {
+    GstDDrawSurface *surface = ddrawsink->buffer_pool->data;
+
+    ddrawsink->buffer_pool = g_slist_delete_link (ddrawsink->buffer_pool,
+        ddrawsink->buffer_pool);
+    gst_directdrawsink_surface_destroy (ddrawsink, surface);
+  }
+  g_mutex_unlock (ddrawsink->pool_lock);
+}
+
+static void
+gst_directdrawsink_cleanup (GstDirectDrawSink * ddrawsink)
+{
+  /* Post quit message and wait for our event window thread */
+  if (ddrawsink->video_window)
+    PostMessage (ddrawsink->video_window, WM_QUIT, 0, 0);
+  if (ddrawsink->window_thread) {
+    g_thread_join (ddrawsink->window_thread);
+    ddrawsink->window_thread = NULL;
+  }
+
+  if (ddrawsink->buffer_pool) {
+    gst_directdrawsink_bufferpool_clear (ddrawsink);
+    ddrawsink->buffer_pool = NULL;
+  }
+
+  if (ddrawsink->display_modes) {
+    GSList *walk = ddrawsink->display_modes;
+
+    while (walk) {
+      g_free (walk->data);
+      walk = g_slist_next (walk);
+    }
+    g_slist_free (ddrawsink->display_modes);
+    ddrawsink->display_modes = NULL;
+  }
+
+  if (ddrawsink->overlays) {
+    IDirectDrawSurface_Release (ddrawsink->overlays);
+    ddrawsink->overlays = NULL;
+  }
+
+  if (ddrawsink->offscreen_surface) {
+    IDirectDrawSurface_Release (ddrawsink->offscreen_surface);
+    ddrawsink->offscreen_surface = NULL;
+  }
+
+  if (ddrawsink->clipper) {
+    IDirectDrawClipper_Release (ddrawsink->clipper);
+    ddrawsink->clipper = NULL;
+  }
+
+  if (ddrawsink->primary_surface) {
+    IDirectDrawSurface_Release (ddrawsink->primary_surface);
+    ddrawsink->primary_surface = NULL;
+  }
+
+  if (ddrawsink->ddraw_object) {
+    IDirectDraw_Release (ddrawsink->ddraw_object);
+    ddrawsink->ddraw_object = NULL;
+  }
+
+  ddrawsink->setup = FALSE;
+}
diff --git a/sys/directdraw/gstdirectdrawsink.h b/sys/directdraw/gstdirectdrawsink.h
new file mode 100644 (file)
index 0000000..7476eaa
--- /dev/null
@@ -0,0 +1,132 @@
+/* GStreamer
+ * Copyright (C)  2005 Sebastien Moutte <sebastien@moutte.net>
+ *
+ * gstdirectdrawsink.h: 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_DIRECTDRAWSINK_H__
+#define __GST_DIRECTDRAWSINK_H__
+
+#define DIRECTDRAW_VERSION 0x0700
+
+#include <gst/gst.h>
+#include <gst/video/gstvideosink.h>
+#include <windows.h>
+
+#include <ddraw.h>
+
+G_BEGIN_DECLS
+#define GST_TYPE_DIRECTDRAW_SINK          (gst_directdrawsink_get_type())
+#define GST_DIRECTDRAW_SINK(obj)          (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DIRECTDRAW_SINK,GstDirectDrawSink))
+#define GST_DIRECTDRAW_SINK_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DIRECTDRAW_SINK,GstDirectDrawSinkClass))
+#define GST_IS_DIRECTDRAW_SINK(obj)       (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DIRECTDRAW_SINK))
+#define GST_IS_DIRECTDRAW_SINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DIRECTDRAW_SINK))
+typedef struct _GstDirectDrawSink GstDirectDrawSink;
+typedef struct _GstDirectDrawSinkClass GstDirectDrawSinkClass;
+
+#define GST_TYPE_DDRAWSURFACE (gst_ddrawsurface_get_type())
+#define GST_IS_DDRAWSURFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DDRAWSURFACE))
+#define GST_DDRAWSURFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DDRAWSURFACE, GstDDrawSurface))
+
+typedef struct _GstDDrawSurface GstDDrawSurface;
+
+struct _GstDDrawSurface
+{
+  /* Extension of GstBuffer to store directdraw surfaces */
+  GstBuffer buffer;
+
+  /*directdraw surface */
+  LPDIRECTDRAWSURFACE surface;
+
+  gint width;
+  gint height;
+  gboolean locked;
+
+  DDPIXELFORMAT dd_pixel_format;
+
+  GstDirectDrawSink *ddrawsink;
+};
+
+
+typedef struct _GstDDDDisplayMode GstDDDisplayMode;
+
+struct _GstDDDDisplayMode
+{
+  gint width;
+  gint height;
+  gint bpp;
+};
+
+struct _GstDirectDrawSink
+{
+  GstVideoSink videosink;
+
+  /*directdraw offscreen surfaces pool */
+  GSList *buffer_pool;
+
+  GSList *display_modes;
+  //GstDDDisplayMode display_mode;
+
+  /*directdraw objects */
+  LPDIRECTDRAW ddraw_object;
+  LPDIRECTDRAWSURFACE primary_surface;
+  LPDIRECTDRAWSURFACE offscreen_surface;
+  LPDIRECTDRAWSURFACE overlays;
+  LPDIRECTDRAWCLIPPER clipper;
+  LPDIRECTDRAWSURFACE extern_surface;
+
+  /*Directdraw caps */
+  GstCaps *caps;
+
+  /*handle of the video window */
+  HWND video_window;
+  gboolean resize_window;
+
+  /*video properties */
+  gint video_width, video_height;
+  gint out_width, out_height;
+  //gdouble framerate;
+  gint fps_n;
+  gint fps_d;
+
+  /*pixel format */
+  DDPIXELFORMAT dd_pixel_format;
+
+  GThread *window_thread;
+
+  gboolean bUseOverlay;
+  gboolean bIsOverlayVisible;
+  gboolean bFullScreen;
+  gboolean setup;
+
+  GMutex *pool_lock;
+
+  guint color_key;
+  /*LPDIRECTDRAWSURFACE extern_surface; */
+};
+
+struct _GstDirectDrawSinkClass
+{
+  GstVideoSinkClass parent_class;
+};
+
+GType gst_directdrawsink_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_DIRECTDRAWSINK_H__ */
diff --git a/sys/directsound/gstdirectsoundplugin.c b/sys/directsound/gstdirectsoundplugin.c
new file mode 100644 (file)
index 0000000..c789b2b
--- /dev/null
@@ -0,0 +1,43 @@
+/* GStreamer
+* Copyright (C) 2005 Sebastien Moutte <sebastien@moutte.net>
+*
+* gstdirectsoundplugin.c:
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Library General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Library General Public License for more details.
+*
+* You should have received a copy of the GNU Library General Public
+* License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+* Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstdirectsoundsink.h"
+
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  if (!gst_element_register (plugin, "directsoundsink", GST_RANK_NONE,
+          GST_TYPE_DIRECTSOUND_SINK))
+    return FALSE;
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    "directsound",
+    "DIRECTSOUND plugin library",
+    plugin_init, VERSION, "LGPL", GST_PACKAGE, GST_ORIGIN)
diff --git a/sys/directsound/gstdirectsoundsink.c b/sys/directsound/gstdirectsoundsink.c
new file mode 100644 (file)
index 0000000..3d7ab99
--- /dev/null
@@ -0,0 +1,421 @@
+/* GStreamer
+* Copyright (C) 2005 Sebastien Moutte <sebastien@moutte.net>
+*
+* gstdirectsoundsink.c:
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Library General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Library General Public License for more details.
+*
+* You should have received a copy of the GNU Library General Public
+* License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+* Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstdirectsoundsink.h"
+
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+GST_DEBUG_CATEGORY_STATIC (directsoundsink_debug);
+#define GST_CAT_DEFAULT directsoundsink_debug
+
+/* elementfactory information */
+static GstElementDetails gst_directsoundsink_details =
+GST_ELEMENT_DETAILS ("Audio Sink (DIRECTSOUND)",
+    "Sink/Audio",
+    "Output to a sound card via DIRECTSOUND",
+    "Sebastien Moutte <sebastien@moutte.net>");
+
+static void gst_directsoundsink_base_init (gpointer g_class);
+static void gst_directsoundsink_class_init (GstDirectSoundSinkClass * klass);
+static void gst_directsoundsink_init (GstDirectSoundSink * alsasink);
+static void gst_directsoundsink_dispose (GObject * object);
+static void gst_directsoundsink_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_directsoundsink_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+
+static GstCaps *gst_directsoundsink_getcaps (GstBaseSink * bsink);
+
+static gboolean gst_directsoundsink_prepare (GstAudioSink * asink,
+    GstRingBufferSpec * spec);
+static gboolean gst_directsoundsink_unprepare (GstAudioSink * asink);
+
+static gboolean gst_directsoundsink_open (GstAudioSink * asink);
+static gboolean gst_directsoundsink_close (GstAudioSink * asink);
+static guint gst_directsoundsink_write (GstAudioSink * asink, gpointer data,
+    guint length);
+static guint gst_directsoundsink_delay (GstAudioSink * asink);
+static void gst_directsoundsink_reset (GstAudioSink * asink);
+
+
+static GstStaticPadTemplate directsoundsink_sink_factory =
+    GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-int, "
+        "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
+        "signed = (boolean) { TRUE, FALSE }, "
+        "width = (int) 16, "
+        "depth = (int) 16, "
+        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
+        "audio/x-raw-int, "
+        "signed = (boolean) { TRUE, FALSE }, "
+        "width = (int) 8, "
+        "depth = (int) 8, "
+        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]"));
+
+static void
+_do_init (GType directsoundsink_type)
+{
+  GST_DEBUG_CATEGORY_INIT (directsoundsink_debug, "directsoundsink", 0,
+      "DirectSound sink");
+}
+
+GST_BOILERPLATE_FULL (GstDirectSoundSink, gst_directsoundsink, GstAudioSink,
+    GST_TYPE_AUDIO_SINK, _do_init);
+
+static void
+gst_directsoundsink_dispose (GObject * object)
+{
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_directsoundsink_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details (element_class, &gst_directsoundsink_details);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&directsoundsink_sink_factory));
+}
+
+static void
+gst_directsoundsink_class_init (GstDirectSoundSinkClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+  GstBaseSinkClass *gstbasesink_class;
+  GstBaseAudioSinkClass *gstbaseaudiosink_class;
+  GstAudioSinkClass *gstaudiosink_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+  gstbasesink_class = (GstBaseSinkClass *) klass;
+  gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
+  gstaudiosink_class = (GstAudioSinkClass *) klass;
+
+  parent_class = g_type_class_ref (GST_TYPE_DIRECTSOUND_SINK);
+
+  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_directsoundsink_dispose);
+  gobject_class->get_property =
+      GST_DEBUG_FUNCPTR (gst_directsoundsink_get_property);
+  gobject_class->set_property =
+      GST_DEBUG_FUNCPTR (gst_directsoundsink_set_property);
+
+  gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_directsoundsink_getcaps);
+
+  gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_directsoundsink_prepare);
+  gstaudiosink_class->unprepare =
+      GST_DEBUG_FUNCPTR (gst_directsoundsink_unprepare);
+  gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_directsoundsink_open);
+  gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_directsoundsink_close);
+  gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_directsoundsink_write);
+
+  gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_directsoundsink_delay);
+  gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_directsoundsink_reset);
+}
+
+static void
+gst_directsoundsink_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstDirectSoundSink *dsoundsink;
+
+  dsoundsink = GST_DIRECTSOUND_SINK (object);
+
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_directsoundsink_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstDirectSoundSink *dsoundsink;
+
+  dsoundsink = GST_DIRECTSOUND_SINK (object);
+
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_directsoundsink_init (GstDirectSoundSink * dsoundsink,
+    GstDirectSoundSinkClass g_class)
+{
+  GST_DEBUG ("initializing directsoundsink");
+
+  dsoundsink->pDS = NULL;
+  dsoundsink->pDSBSecondary = NULL;
+  dsoundsink->current_circular_offset = 0;
+  dsoundsink->buffer_size = DSBSIZE_MIN;
+}
+
+static GstCaps *
+gst_directsoundsink_getcaps (GstBaseSink * bsink)
+{
+  GstDirectSoundSink *dsoundsink;
+
+  dsoundsink = GST_DIRECTSOUND_SINK (bsink);
+
+  return
+      gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD
+          (dsoundsink)));
+}
+
+static gboolean
+gst_directsoundsink_open (GstAudioSink * asink)
+{
+  GstDirectSoundSink *dsoundsink;
+  HRESULT hRes;
+
+  dsoundsink = GST_DIRECTSOUND_SINK (asink);
+
+  /* create and initialize a DirecSound object */
+  if (FAILED (hRes = DirectSoundCreate (NULL, &dsoundsink->pDS, NULL))) {
+    GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ,
+        ("gst_directsoundsink_open: DirectSoundCreate: %s",
+            DXGetErrorString9 (hRes)), (NULL));
+    return FALSE;
+  }
+
+  if (FAILED (hRes =
+          IDirectSound_SetCooperativeLevel (dsoundsink->pDS,
+              GetDesktopWindow (), DSSCL_PRIORITY))) {
+    GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ,
+        ("gst_directsoundsink_open: IDirectSound_SetCooperativeLevel: %s",
+            DXGetErrorString9 (hRes)), (NULL));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_directsoundsink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
+{
+  GstDirectSoundSink *dsoundsink;
+  HRESULT hRes;
+  DSBUFFERDESC descSecondary;
+  WAVEFORMATEX wfx;
+
+  dsoundsink = GST_DIRECTSOUND_SINK (asink);
+
+  /*save number of bytes per sample */
+  dsoundsink->bytes_per_sample = spec->bytes_per_sample;
+
+  /* fill the WAVEFORMATEX struture with spec params */
+  memset (&wfx, 0, sizeof (wfx));
+  wfx.cbSize = sizeof (wfx);
+  wfx.wFormatTag = WAVE_FORMAT_PCM;
+  wfx.nChannels = spec->channels;
+  wfx.nSamplesPerSec = spec->rate;
+  wfx.wBitsPerSample = (spec->bytes_per_sample * 8) / wfx.nChannels;
+  wfx.nBlockAlign = spec->bytes_per_sample;
+  wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+
+
+  GST_DEBUG
+      ("GstRingBufferSpec->channels: %d, GstRingBufferSpec->rate: %d, GstRingBufferSpec->bytes_per_sample: %d\n"
+      "WAVEFORMATEX.nSamplesPerSec: %ld, WAVEFORMATEX.wBitsPerSample: %d, WAVEFORMATEX.nBlockAlign: %d, WAVEFORMATEX.nAvgBytesPerSec: %ld\n",
+      spec->channels, spec->rate, spec->bytes_per_sample, wfx.nSamplesPerSec,
+      wfx.wBitsPerSample, wfx.nBlockAlign, wfx.nAvgBytesPerSec);
+
+  /* directsound buffer size can handle 2 secs of the stream */
+  dsoundsink->buffer_size = wfx.nAvgBytesPerSec / 2;
+
+  /* create a secondary directsound buffer */
+  memset (&descSecondary, 0, sizeof (DSBUFFERDESC));
+  descSecondary.dwSize = sizeof (DSBUFFERDESC);
+  descSecondary.dwFlags = DSBCAPS_GETCURRENTPOSITION2 |
+      DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLVOLUME;
+
+  descSecondary.dwBufferBytes = dsoundsink->buffer_size;
+  descSecondary.lpwfxFormat = (WAVEFORMATEX *) & wfx;
+
+  hRes = IDirectSound_CreateSoundBuffer (dsoundsink->pDS, &descSecondary,
+      &dsoundsink->pDSBSecondary, NULL);
+  if (FAILED (hRes)) {
+    GST_ELEMENT_ERROR (dsoundsink, RESOURCE, OPEN_READ,
+        ("gst_directsoundsink_prepare: IDirectSound_CreateSoundBuffer: %s",
+            DXGetErrorString9 (hRes)), (NULL));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_directsoundsink_unprepare (GstAudioSink * asink)
+{
+  GstDirectSoundSink *dsoundsink;
+
+  dsoundsink = GST_DIRECTSOUND_SINK (asink);
+
+  /* release secondary DirectSound buffer */
+  if (dsoundsink->pDSBSecondary)
+    IDirectSoundBuffer_Release (dsoundsink->pDSBSecondary);
+
+  return TRUE;
+}
+
+static gboolean
+gst_directsoundsink_close (GstAudioSink * asink)
+{
+  GstDirectSoundSink *dsoundsink = NULL;
+
+  dsoundsink = GST_DIRECTSOUND_SINK (asink);
+
+  /* release DirectSound object */
+  g_return_val_if_fail (dsoundsink->pDS != NULL, FALSE);
+  IDirectSound_Release (dsoundsink->pDS);
+
+  return TRUE;
+}
+
+
+static guint
+gst_directsoundsink_write (GstAudioSink * asink, gpointer data, guint length)
+{
+  GstDirectSoundSink *dsoundsink;
+  DWORD dwStatus;
+  HRESULT hRes;
+  LPVOID pLockedBuffer1 = NULL, pLockedBuffer2 = NULL;
+  DWORD dwSizeBuffer1, dwSizeBuffer2;
+  DWORD dwCurrentPlayCursor;
+
+  dsoundsink = GST_DIRECTSOUND_SINK (asink);
+
+  /* get current buffer status */
+  hRes = IDirectSoundBuffer_GetStatus (dsoundsink->pDSBSecondary, &dwStatus);
+
+  /* get current play cursor position */
+  hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary,
+      &dwCurrentPlayCursor, NULL);
+  if (SUCCEEDED (hRes) && (dwStatus & DSBSTATUS_PLAYING)) {
+    DWORD dwFreeBufferSize;
+
+  calculate_freesize:
+    /* calculate the free size of the circular buffer */
+    if (dwCurrentPlayCursor < dsoundsink->current_circular_offset)
+      dwFreeBufferSize =
+          dsoundsink->buffer_size - (dsoundsink->current_circular_offset -
+          dwCurrentPlayCursor);
+    else
+      dwFreeBufferSize =
+          dwCurrentPlayCursor - dsoundsink->current_circular_offset;
+
+    if (length >= dwFreeBufferSize) {
+      Sleep (100);
+      hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary,
+          &dwCurrentPlayCursor, NULL);
+      goto calculate_freesize;
+    }
+  }
+
+  if (dwStatus & DSBSTATUS_BUFFERLOST) {
+    hRes = IDirectSoundBuffer_Restore (dsoundsink->pDSBSecondary);      /*need a loop waiting the buffer is restored?? */
+
+    dsoundsink->current_circular_offset = 0;
+  }
+
+  hRes = IDirectSoundBuffer_Lock (dsoundsink->pDSBSecondary,
+      dsoundsink->current_circular_offset, length, &pLockedBuffer1,
+      &dwSizeBuffer1, &pLockedBuffer2, &dwSizeBuffer2, 0L);
+
+  if (SUCCEEDED (hRes)) {
+    // Write to pointers without reordering.
+    memcpy (pLockedBuffer1, data, dwSizeBuffer1);
+    if (pLockedBuffer2 != NULL)
+      memcpy (pLockedBuffer2, (LPBYTE) data + dwSizeBuffer1, dwSizeBuffer2);
+
+    // Update where the buffer will lock (for next time)
+    dsoundsink->current_circular_offset += dwSizeBuffer1 + dwSizeBuffer2;
+    dsoundsink->current_circular_offset %= dsoundsink->buffer_size;     /* Circular buffer */
+
+    hRes = IDirectSoundBuffer_Unlock (dsoundsink->pDSBSecondary, pLockedBuffer1,
+        dwSizeBuffer1, pLockedBuffer2, dwSizeBuffer2);
+  }
+
+  /* if the buffer was not in playing state yet, call play on the buffer */
+  if (!(dwStatus & DSBSTATUS_PLAYING)) {
+    hRes = IDirectSoundBuffer_Play (dsoundsink->pDSBSecondary, 0, 0,
+        DSBPLAY_LOOPING);
+  }
+
+  return length;
+}
+
+static guint
+gst_directsoundsink_delay (GstAudioSink * asink)
+{
+  GstDirectSoundSink *dsoundsink;
+  HRESULT hRes;
+  DWORD dwCurrentPlayCursor;
+  DWORD dwBytesInQueue = 0;
+  gint nNbSamplesInQueue = 0;
+
+  dsoundsink = GST_DIRECTSOUND_SINK (asink);
+
+  /*evaluate the number of samples in queue in the circular buffer */
+  hRes = IDirectSoundBuffer_GetCurrentPosition (dsoundsink->pDSBSecondary,
+      &dwCurrentPlayCursor, NULL);
+
+  if (hRes == S_OK) {
+    if (dwCurrentPlayCursor < dsoundsink->current_circular_offset)
+      dwBytesInQueue =
+          dsoundsink->current_circular_offset - dwCurrentPlayCursor;
+    else
+      dwBytesInQueue =
+          dsoundsink->current_circular_offset + (dsoundsink->buffer_size -
+          dwCurrentPlayCursor);
+
+    nNbSamplesInQueue = dwBytesInQueue / dsoundsink->bytes_per_sample;
+  }
+
+  return nNbSamplesInQueue;
+}
+
+static void
+gst_directsoundsink_reset (GstAudioSink * asink)
+{
+  /*not tested for seeking */
+  GstDirectSoundSink *dsoundsink;
+
+  dsoundsink = GST_DIRECTSOUND_SINK (asink);
+
+  IDirectSoundBuffer_Stop (dsoundsink->pDSBSecondary);
+}
diff --git a/sys/directsound/gstdirectsoundsink.h b/sys/directsound/gstdirectsoundsink.h
new file mode 100644 (file)
index 0000000..54f7148
--- /dev/null
@@ -0,0 +1,68 @@
+/* GStreamer
+ * Copyright (C)  2005 Sebastien Moutte <sebastien@moutte.net>
+ *
+ * gstdirectsoundsink.h: 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_DIRECTSOUNDSINK_H__
+#define __GST_DIRECTSOUNDSINK_H__
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosink.h>
+
+#include <windows.h>
+#include <dxerr9.h>
+#include <dsound.h>
+
+
+G_BEGIN_DECLS
+#define GST_TYPE_DIRECTSOUND_SINK          (gst_directsoundsink_get_type())
+#define GST_DIRECTSOUND_SINK(obj)          (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DIRECTSOUND_SINK,GstDirectSoundSink))
+#define GST_DIRECTSOUND_SINK_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DIRECTSOUND_SINK,GstDirectSoundSinkClass))
+#define GST_IS_DIRECTSOUND_SINK(obj)       (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DIRECTSOUND_SINK))
+#define GST_IS_DIRECTSOUND_SINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DIRECTSOUND_SINK))
+typedef struct _GstDirectSoundSink GstDirectSoundSink;
+typedef struct _GstDirectSoundSinkClass GstDirectSoundSinkClass;
+
+struct _GstDirectSoundSink
+{
+  GstAudioSink sink;
+
+  LPDIRECTSOUND pDS;
+
+  LPDIRECTSOUNDBUFFER pDSBSecondary;
+
+  /*DirectSound buffer size */
+  guint buffer_size;
+
+  /*Offset of the circular buffer where we must write next */
+  guint current_circular_offset;
+
+  guint bytes_per_sample;
+};
+
+struct _GstDirectSoundSinkClass
+{
+  GstAudioSinkClass parent_class;
+};
+
+GType gst_directsoundsink_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_DIRECTSOUNDSINK_H__ */
diff --git a/win32/common/config.h b/win32/common/config.h
new file mode 100644 (file)
index 0000000..4588c24
--- /dev/null
@@ -0,0 +1,229 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+/* This copy of config.h.in is specifically for win32 Visual Studio builds */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+#undef ENABLE_NLS
+
+/* gettext package name */
+#define GETTEXT_PACKAGE "gstreamer-0.10"
+
+/* PREFIX - specifically added for Windows for easier moving */
+#define PREFIX "C:\\gstreamer"
+
+/* Location of registry */
+#define GST_CACHE_DIR PREFIX "\\var\\cache"
+
+/* macro to use to show function name */
+#undef GST_FUNCTION
+
+/* Defined if gcov is enabled to force a rebuild due to config.h changing */
+#undef GST_GCOV_ENABLED
+
+/* Default errorlevel to use */
+#define GST_LEVEL_DEFAULT GST_LEVEL_ERROR
+
+/* GStreamer license */
+#define GST_LICENSE "LGPL"
+
+/* package origin */
+#define GST_PACKAGE_ORIGIN "Unknown package origin"
+
+/* package name in plugins */
+#define GST_PACKAGE_NAME "GStreamer CVS/prerelease"
+
+/* Define the version */
+#define GST_VERSION "0.10.0"
+
+/* Define if the host CPU is an Alpha */
+#undef HAVE_CPU_ALPHA
+
+/* Define if the host CPU is an ARM */
+#undef HAVE_CPU_ARM
+
+/* Define if the host CPU is a HPPA */
+#undef HAVE_CPU_HPPA
+
+/* Define if the host CPU is an x86 */
+#undef HAVE_CPU_I386
+
+/* Define if the host CPU is a IA64 */
+#undef HAVE_CPU_IA64
+
+/* Define if the host CPU is a M68K */
+#undef HAVE_CPU_M68K
+
+/* Define if the host CPU is a MIPS */
+#undef HAVE_CPU_MIPS
+
+/* Define if the host CPU is a PowerPC */
+#undef HAVE_CPU_PPC
+
+/* Define if the host CPU is a S390 */
+#undef HAVE_CPU_S390
+
+/* Define if the host CPU is a SPARC */
+#undef HAVE_CPU_SPARC
+
+/* Define if the host CPU is a x86_64 */
+#undef HAVE_CPU_X86_64
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+#undef HAVE_DCGETTEXT
+
+/* Defined if we have dladdr () */
+#undef HAVE_DLADDR
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the `fgetpos' function. */
+#define HAVE_FGETPOS 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#undef HAVE_FSEEKO
+
+/* Define to 1 if you have the `fsetpos' function. */
+#define HAVE_FSETPOS 1
+
+/* Define to 1 if you have the `ftello' function. */
+#undef HAVE_FTELLO
+
+/* defined if the compiler implements __func__ */
+#undef HAVE_FUNC
+
+/* defined if the compiler implements __FUNCTION__ */
+#undef HAVE_FUNCTION
+
+/* Define to 1 if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+#undef HAVE_GETTEXT
+
+/* Define if you have the iconv() function. */
+#undef HAVE_ICONV
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if libxml2 is available */
+#define HAVE_LIBXML2 1
+
+/* defined if we have makecontext () */
+#undef HAVE_MAKECONTEXT
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* defined if the compiler implements __PRETTY_FUNCTION__ */
+#undef HAVE_PRETTY_FUNCTION
+
+/* Defined if we have register_printf_function () */
+#undef HAVE_PRINTF_EXTENSION
+
+/* Define to 1 if you have the <process.h> header file. */
+#define HAVE_PROCESS_H 1
+
+/* Define if RDTSC is available */
+#undef HAVE_RDTSC
+
+/* Define to 1 if you have the `sigaction' function. */
+#undef HAVE_SIGACTION
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <ucontext.h> header file. */
+#undef HAVE_UCONTEXT_H
+
+/* defined if unaligned memory access works correctly */
+#undef HAVE_UNALIGNED_ACCESS
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if valgrind should be used */
+#undef HAVE_VALGRIND
+
+/* Defined if compiling for Windows */
+#define HAVE_WIN32 1
+
+/* library dir */
+#define LIBDIR PREFIX "\\lib"
+
+/* gettext locale dir */
+#define LOCALEDIR PREFIX "\\share\\locale"
+
+/* Name of package */
+#define PACKAGE "gstreamer"
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define the plugin directory */
+#define PLUGINDIR PREFIX "\\lib\\gstreamer-0.10"
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if we should poison deallocated memory */
+#undef USE_POISONING
+
+/* Version number of package */
+#define VERSION "0.10.0"
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#undef _LARGEFILE_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+/* #undef inline */
+
+#define GST_PACKAGE "Gstreamer"
+#define PACKAGE "gstreamer"
+#define GST_ORIGIN "gstreamer.freedesktop.org"
diff --git a/win32/vs6/gst_plugins_bad.dsw b/win32/vs6/gst_plugins_bad.dsw
new file mode 100644 (file)
index 0000000..b84125b
--- /dev/null
@@ -0,0 +1,41 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "libgstdirectdraw"=".\libgstdirectdraw.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libgstdirectsound"=".\libgstdirectsound.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/win32/vs6/libgstdirectdraw.dsp b/win32/vs6/libgstdirectdraw.dsp
new file mode 100644 (file)
index 0000000..37432a9
--- /dev/null
@@ -0,0 +1,125 @@
+# Microsoft Developer Studio Project File - Name="libgstdirectdraw" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libgstdirectdraw - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "libgstdirectdraw.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "libgstdirectdraw.mak" CFG="libgstdirectdraw - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "libgstdirectdraw - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libgstdirectdraw - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "libgstdirectdraw - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDIRECTDRAW_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../../gst-plugins-base/gst-libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDIRECTDRAW_EXPORTS" /D "HAVE_CONFIG_H" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x40c /d "NDEBUG"
+# ADD RSC /l 0x40c /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib libgstvideo-0.10.lib glib-2.0.lib gobject-2.0.lib user32.lib gdi32.lib ddraw.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"../../../gst-plugins-base/win32/vs6/release" /libpath:"./release"
+# Begin Special Build Tool
+TargetPath=.\Release\libgstdirectdraw.dll
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10
+# End Special Build Tool
+
+!ELSEIF  "$(CFG)" == "libgstdirectdraw - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDIRECTDRAW_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../../gst-plugins-base/gst-libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDIRECTDRAW_EXPORTS" /D "HAVE_CONFIG_H" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x40c /d "_DEBUG"
+# ADD RSC /l 0x40c /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib libgstvideo-0.10.lib glib-2.0D.lib gobject-2.0D.lib ddraw.lib user32.lib gdi32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"../../../gst-plugins-base/win32/vs6/debug" /libpath:"./debug"
+# Begin Special Build Tool
+TargetPath=.\Debug\libgstdirectdraw.dll
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10
+# End Special Build Tool
+
+!ENDIF 
+
+# Begin Target
+
+# Name "libgstdirectdraw - Win32 Release"
+# Name "libgstdirectdraw - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\sys\directdraw\gstdirectdrawplugin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\sys\directdraw\gstdirectdrawsink.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\sys\directdraw\gstdirectdrawsink.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/win32/vs6/libgstdirectsound.dsp b/win32/vs6/libgstdirectsound.dsp
new file mode 100644 (file)
index 0000000..859dd7d
--- /dev/null
@@ -0,0 +1,125 @@
+# Microsoft Developer Studio Project File - Name="libgstdirectsound" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libgstdirectsound - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "libgstdirectsound.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "libgstdirectsound.mak" CFG="libgstdirectsound - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "libgstdirectsound - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libgstdirectsound - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "libgstdirectsound - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDIRECTSOUND_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /I "../.." /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../../gst-plugins-base/gst-libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDIRECTSOUND_EXPORTS" /D "HAVE_CONFIG_H" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x40c /d "NDEBUG"
+# ADD RSC /l 0x40c /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib libgstaudio-0.10.lib glib-2.0.lib gobject-2.0.lib dsound.lib dxerr9.lib  user32.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"../../../gst-plugins-base/win32/vs6/release" /libpath:"./release"
+# Begin Special Build Tool
+TargetPath=.\Release\libgstdirectsound.dll
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10
+# End Special Build Tool
+
+!ELSEIF  "$(CFG)" == "libgstdirectsound - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDIRECTSOUND_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../../gst-plugins-base/gst-libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDIRECTSOUND_EXPORTS" /D "HAVE_CONFIG_H" /FR /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x40c /d "_DEBUG"
+# ADD RSC /l 0x40c /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib libgstaudio-0.10.lib glib-2.0D.lib gobject-2.0D.lib dsound.lib dxerr9.lib user32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"../../../gst-plugins-base/win32/vs6/debug" /libpath:"./debug"
+# Begin Special Build Tool
+TargetPath=.\Debug\libgstdirectsound.dll
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10
+# End Special Build Tool
+
+!ENDIF 
+
+# Begin Target
+
+# Name "libgstdirectsound - Win32 Release"
+# Name "libgstdirectsound - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\sys\directsound\gstdirectsoundplugin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\sys\directsound\gstdirectsoundsink.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\sys\directsound\gstdirectsoundsink.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project