[MOVED FROM GOOD] added sys/directdraw added sys/directsound added win32/vs6/gst_plug...
authorSébastien Moutte <sebastien@moutte.net>
Thu, 5 Jan 2006 23:17:44 +0000 (23:17 +0000)
committerJan Schmidt <thaytan@noraisin.net>
Sat, 16 May 2009 00:29:14 +0000 (01:29 +0100)
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

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]

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__ */