[018/906] * configure.ac: * sys/Makefile.am: * sys/glsink/Makefile.am: * sys/glsink...
authorDavid Schleef <ds@schleef.org>
Sat, 28 Jan 2006 04:39:18 +0000 (04:39 +0000)
committerMatthew Waters <ystreet00@gmail.com>
Sat, 15 Mar 2014 17:36:16 +0000 (18:36 +0100)
gst/gl/Makefile.am
gst/gl/glimagesink.c
gst/gl/glimagesink.h [deleted file]

index 68c4515..e442f30 100644 (file)
@@ -2,9 +2,9 @@
 plugin_LTLIBRARIES = libgstglimagesink.la
 
 libgstglimagesink_la_SOURCES =  glimagesink.c 
-libgstglimagesink_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS)
-libgstglimagesink_la_LIBADD = $(X_LIBS) $(XSHM_LIBS) -lGL -lGLU\
-       $(top_builddir)/gst-libs/gst/libgstinterfaces-$(GST_MAJORMINOR).la
+libgstglimagesink_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS) $(GST_BASE_CFLAGS)
+libgstglimagesink_la_LIBADD = $(X_LIBS) $(XSHM_LIBS) -lGL -lGLU \
+       $(GST_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) -lgstinterfaces-$(GST_MAJORMINOR)
 libgstglimagesink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
 noinst_HEADERS = glimagesink.h 
index efef625..348fc33 100644 (file)
@@ -1,5 +1,6 @@
 /* GStreamer
- * Copyright (C) <2003> Julien Moutte <julien@moutte.net>
+ * Copyright (C) 2003 Julien Moutte <julien@moutte.net>
+ * Copyright (C) 2005,2006 David A. Schleef <ds@schleef.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #include "config.h"
 #endif
 
-/* Our interfaces */
-#include <gst/navigation/navigation.h>
-#include <gst/xoverlay/xoverlay.h>
 
-/* Object header */
-#include "glimagesink.h"
+#include <gst/gst.h>
+#include <gst/interfaces/xoverlay.h>
+#include <gst/video/gstvideosink.h>
+#include <gst/video/video.h>
 
-/* Debugging category */
-#include <gst/gstinfo.h>
-GST_DEBUG_CATEGORY_STATIC (gst_debug_glimagesink);
-#define GST_CAT_DEFAULT gst_debug_glimagesink
+#include <string.h>
 
-static void gst_glimagesink_buffer_free (GstBuffer * buffer);
+#include <GL/glx.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
 
-/* ElementFactory information */
-static GstElementDetails gst_glimagesink_details =
-GST_ELEMENT_DETAILS ("Video sink",
-    "Sink/Video",
-    "An OpenGL 1.2 based videosink",
-    "Gernot Ziegler <gz@lysator.liu.se>, Julien Moutte <julien@moutte.net>");
+GST_DEBUG_CATEGORY (gst_debug_glimage_sink);
+#define GST_CAT_DEFAULT gst_debug_glimage_sink
 
-/* Default template - initiated with class struct to allow gst-register to work
-   without X running */
-static GstStaticPadTemplate gst_glimagesink_sink_template_factory =
-    GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw-rgb, "
-        "framerate = (double) [ 1.0, 100.0 ], "
-        "width = (int) [ 1, MAX ], "
-        "height = (int) [ 1, MAX ]; "
-        "video/x-raw-yuv, "
-        "framerate = (double) [ 1.0, 100.0 ], "
-        "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
-    );
+#define GST_TYPE_GLIMAGE_SINK \
+    (gst_glimage_sink_get_type())
+#define GST_GLIMAGE_SINK(obj) \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GLIMAGE_SINK,GstGLImageSink))
+#define GST_GLIMAGE_SINK_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GLIMAGE_SINK,GstGLImageSinkClass))
+#define GST_IS_GLIMAGE_SINK(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GLIMAGE_SINK))
+#define GST_IS_GLIMAGE_SINK_CLASS(obj) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GLIMAGE_SINK))
 
-/* GLImageSink signals and args */
-enum
-{
-  SIGNAL_HANDOFF,
-  SIGNAL_BUFALLOC,
-  LAST_SIGNAL
-      /* FILL ME */
-};
+typedef struct _GstGLImageSink GstGLImageSink;
+typedef struct _GstGLImageSinkClass GstGLImageSinkClass;
 
-static guint gst_glimagesink_signals[LAST_SIGNAL] = { 0 };
-
-enum
+struct _GstGLImageSink
 {
-  ARG_0,
-  ARG_DISPLAY,
-  ARG_SYNCHRONOUS,
-  ARG_SIGNAL_HANDOFFS
-      /* FILL ME */
-};
+  GstVideoSink video_sink;
 
-static GstVideoSinkClass *parent_class = NULL;
+  /* properties */
+  char *display_name;
 
-/* ============================================================= */
-/*                                                               */
-/*                       Private Methods                         */
-/*                                                               */
-/* ============================================================= */
+  /* caps */
+  GstCaps *caps;
+  int fps_n, fps_d;
+  int par_n, par_d;
+  int height, width;
 
-/* X11 and GLX stuff */
-
-#define TEX_XSIZE 1024
-#define TEX_YSIZE 1024
-
-/* This function handles GstGLImage creation 
-   it creates data buffers and corresponding texture IDs */
-static GstGLImage *
-gst_glimagesink_ximage_new (GstGLImageSink * glimagesink, gint width,
-    gint height)
-{
-  GstGLImage *ximage = NULL;
+  Window window;
+  Window parent_window;
+  XVisualInfo *visinfo;
 
-  g_return_val_if_fail (GST_IS_GLIMAGESINK (glimagesink), NULL);
+  Display *display;
+  GLXContext context;
 
-  ximage = g_new0 (GstGLImage, 1);
+  int max_texture_size;
+  gboolean have_yuv;
 
-  ximage->width = width;
-  ximage->height = height;
-  ximage->data = NULL;
-  ximage->glimagesink = glimagesink;
-
-  g_mutex_lock (glimagesink->x_lock);
-
-  ximage->size =
-      (glimagesink->xcontext->bpp / 8) * ximage->width * ximage->height;
+  gboolean use_rgb;
+  gboolean use_rgbx;
+  gboolean use_yuy2;
+};
 
-  printf ("No ximage_new yet !\n");
+struct _GstGLImageSinkClass
+{
+  GstVideoSinkClass video_sink_class;
 
-  {
-    ximage->data = g_malloc (ximage->size);
+};
 
-    ximage->texid = 1000;
-  }
+static void gst_glimage_sink_finalize (GObject * object);
+static void gst_glimage_sink_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * param_spec);
+static void gst_glimage_sink_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * param_spec);
 
-  if (0)                        // can't fail ! 
-  {
-    if (ximage->data)
-      g_free (ximage->data);
+static GstStateChangeReturn
+gst_glimage_sink_change_state (GstElement * element, GstStateChange transition);
+
+static void gst_glimage_sink_get_times (GstBaseSink * bsink, GstBuffer * buf,
+    GstClockTime * start, GstClockTime * end);
+static GstCaps *gst_glimage_sink_get_caps (GstBaseSink * bsink);
+static gboolean gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps);
+static GstFlowReturn gst_glimage_sink_render (GstBaseSink * bsink,
+    GstBuffer * buf);
+
+static void gst_glimage_sink_create_window (GstGLImageSink * glimage_sink);
+static gboolean gst_glimage_sink_init_display (GstGLImageSink * glimage_sink);
+static void gst_glimage_sink_update_caps (GstGLImageSink * glimage_sink);
+static void gst_glimage_sink_push_image (GstGLImageSink * glimage_sink,
+    GstBuffer * buf);
+
+static GstElementDetails gst_glimage_sink_details =
+GST_ELEMENT_DETAILS ("OpenGL video sink",
+    "Sink/Video",
+    "A videosink based on OpenGL",
+    "David Schleef <ds@schleef.org>");
 
-    g_free (ximage);
-    //ximage = NULL;
-  }
+#ifdef GL_YCBCR_MESA
+#define YUV_CAPS ";" GST_VIDEO_CAPS_YUV ("{ UYVY, YUY2 }")
+#else
+#define YUV_CAPS
+#endif
+static GstStaticPadTemplate gst_glimage_sink_template =
+    GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx YUV_CAPS)
+    );
 
-  g_mutex_unlock (glimagesink->x_lock);
+enum
+{
+  ARG_0,
+  ARG_DISPLAY
+};
 
-  return ximage;
-}
+GST_BOILERPLATE (GstGLImageSink, gst_glimage_sink, GstVideoSink,
+    GST_TYPE_VIDEO_SINK);
 
-/* This function destroys a GstGLImage handling XShm availability */
 static void
-gst_glimagesink_ximage_destroy (GstGLImageSink * glimagesink,
-    GstGLImage * ximage)
+gst_glimage_sink_base_init (gpointer g_class)
 {
-  g_return_if_fail (ximage != NULL);
-  g_return_if_fail (GST_IS_GLIMAGESINK (glimagesink));
-
-  /* If the destroyed image is the current one we destroy our reference too */
-  if (glimagesink->cur_image == ximage)
-    glimagesink->cur_image = NULL;
-
-  printf ("No ximage_destroy implemented yet !\n");
-
-  g_mutex_lock (glimagesink->x_lock);
-
-  {
-    //if (ximage->ximage) // FIXME: doesnt exist - dealloc textures
-    //  XDestroyImage (ximage->ximage);
-  }
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 
-  g_mutex_unlock (glimagesink->x_lock);
+  gst_element_class_set_details (element_class, &gst_glimage_sink_details);
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_glimage_sink_template));
 
-  g_free (ximage);
 }
 
-/* This function puts a GstGLImage on a GstGLImagesink's window */
 static void
-gst_glimagesink_ximage_put (GstGLImageSink * glimagesink, GstGLImage * ximage)
+gst_glimage_sink_class_init (GstGLImageSinkClass * klass)
 {
-  float xmax;
-  float ymax;
-  float px;
-  float py;
-
-  g_return_if_fail (ximage != NULL);
-  g_return_if_fail (GST_IS_GLIMAGESINK (glimagesink));
-
-  if (glimagesink->signal_handoffs) {
-    g_warning ("Not drawing anything due to signal_handoffs !\n");
-    return;
-  }
-
-  /* Store a reference to the last image we put */
-  if (glimagesink->cur_image != ximage)
-    glimagesink->cur_image = ximage;
-
-  g_mutex_lock (glimagesink->x_lock);
-
-  // both upload the video, and redraw the screen
-
-  //printf("No ximage_put yet !\n");
-
-  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-  glMatrixMode (GL_PROJECTION);
-  glLoadIdentity ();
-
-  glMatrixMode (GL_MODELVIEW);
-  glLoadIdentity ();
-  //glTranslatef(0.0, 0.0, -5.0);
-
-  glEnable (GL_TEXTURE_2D);
-
-  glBindTexture (GL_TEXTURE_2D, ximage->texid);
-  glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, ximage->width, ximage->height,
-      GL_RGB, GL_UNSIGNED_BYTE, ximage->data);
-
-  xmax = (float) ximage->width / TEX_XSIZE;
-  ymax = (float) ximage->height / TEX_YSIZE;
-
-  //float aspect = ximage->width/(float)ximage->height;
-
-  // don't know what to do with pixel aspect yet.
-  //float pixel_aspect = glimagesink->pixel_width/(float)glimagesink->pixel_height;
-
-  //if (aspect != pixel_aspect)
-  //  g_warning("screen aspect %f differs from pixel_aspect %f !", aspect, pixel_aspect);
-
-  glColor4f (1, 1, 1, 1);
-  glBegin (GL_QUADS);
-
-  glNormal3f (0, -1, 0);
-
-  glTexCoord2f (xmax, 0);
-  glVertex3f (1, 1, 0);
-
-  glTexCoord2f (0, 0);
-  glVertex3f (-1, 1, 0);
-
-  glTexCoord2f (0, ymax);
-  glVertex3f (-1, -1, 0);
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+  GstBaseSinkClass *gstbasesink_class;
 
-  glTexCoord2f (xmax, ymax);
-  glVertex3f (1, -1, 0);
-  glEnd ();
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+  gstbasesink_class = (GstBaseSinkClass *) klass;
 
-#if 1                           // for pointer feedback, later
-  glDisable (GL_TEXTURE_2D);
-  if (glimagesink->pointer_moved)
-    glColor3f (1, 1, 1);
-  else
-    glColor3f (1, 0, 1);
+  gobject_class->set_property = gst_glimage_sink_set_property;
+  gobject_class->get_property = gst_glimage_sink_get_property;
 
-  if (glimagesink->pointer_button[0])
-    glColor3f (1, 0, 0);
+  g_object_class_install_property (gobject_class, ARG_DISPLAY,
+      g_param_spec_string ("display", "Display", "X Display name",
+          NULL, G_PARAM_READWRITE));
 
-  px = 2 * glimagesink->pointer_x / (float) ximage->width - 1.0;
-  py = 2 * glimagesink->pointer_y / (float) ximage->height - 1.0;
-  glPointSize (10);
-  glBegin (GL_POINTS);
-  glVertex2f (px, -py);
-  glEnd ();
-#endif
+  gobject_class->finalize = gst_glimage_sink_finalize;
 
-  glXSwapBuffers (glimagesink->xcontext->disp, glimagesink->window->win);
+  gstelement_class->change_state = gst_glimage_sink_change_state;
 
-  g_mutex_unlock (glimagesink->x_lock);
+  gstbasesink_class->get_caps = gst_glimage_sink_get_caps;
+  gstbasesink_class->set_caps = gst_glimage_sink_set_caps;
+  gstbasesink_class->get_times = gst_glimage_sink_get_times;
+  gstbasesink_class->preroll = gst_glimage_sink_render;
+  gstbasesink_class->render = gst_glimage_sink_render;
 }
 
-/* This function handles a GstXWindow creation */
-static GstGLWindow *
-gst_glimagesink_xwindow_new (GstGLImageSink * glimagesink, gint width,
-    gint height)
+static void
+gst_glimage_sink_init (GstGLImageSink * glimage_sink,
+    GstGLImageSinkClass * glimage_sink_class)
 {
-  GstGLWindow *xwindow = NULL;
-  GstXContext *xcontext = glimagesink->xcontext;
-  Colormap cmap;
-  Atom wmDelete;
-
-  if (glimagesink->signal_handoffs) {
-    g_warning ("NOT CREATING any window due to signal_handoffs !\n");
-    return NULL;
-  }
-
-  g_return_val_if_fail (GST_IS_GLIMAGESINK (glimagesink), NULL);
-
-  xwindow = g_new0 (GstGLWindow, 1);
+  int screen;
 
-  xwindow->width = width;
-  xwindow->height = height;
-  xwindow->internal = TRUE;
+  //glimage_sink->display = XOpenDisplay (NULL);
 
-  g_mutex_lock (glimagesink->x_lock);
+  screen = DefaultScreen (glimage_sink->display);
 
-  /* create a color map */
-  cmap =
-      XCreateColormap (xcontext->disp, RootWindow (xcontext->disp,
-          xcontext->visualinfo->screen), xcontext->visualinfo->visual,
-      AllocNone);
-  xwindow->attr.colormap = cmap;
-  xwindow->attr.border_pixel = 0;
-
-#if 0
-  /* set sizes */
-  xwindow->x = 0;
-  xwindow->y = 0;
-  xwindow->width = 10;
-  xwindow->height = 10;
-
-  xwindow->rotX = 0;
-  xwindow->rotY = 0;
-  xwindow->zoom = 1;
-  xwindow->zoomdir = 0.01;
-#endif
-
-  xwindow->attr.event_mask =
-      ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
-
-  /* create a window in window mode */
-  xwindow->win = XCreateWindow (xcontext->disp, /*xcontext->root, */
-      RootWindow (xcontext->disp, xcontext->visualinfo->screen),
-      0, 0, xwindow->width, xwindow->height, 0, xcontext->visualinfo->depth,
-      InputOutput, xcontext->visualinfo->visual,
-      CWBorderPixel | CWColormap | CWEventMask, &xwindow->attr);
-
-  /* only set window title and handle wm_delete_events if in windowed mode */
-  wmDelete = XInternAtom (xcontext->disp, "WM_DELETE_WINDOW", True);
-  XSetWMProtocols (xcontext->disp, xwindow->win, &wmDelete, 1);
-  XSetStandardProperties (xcontext->disp, xwindow->win, "glsink",
-      "glsink", None, NULL, 0, NULL);
-
-#if 0
-  XSelectInput (xcontext->disp, xwindow->win,
-      ExposureMask | StructureNotifyMask);
-#else // we want more than that
-  XSelectInput (glimagesink->xcontext->disp, xwindow->win, ExposureMask |
-      StructureNotifyMask | PointerMotionMask | KeyPressMask |
-      KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
-#endif
-
-  //xwindow->win = XCreateSimpleWindow (glimagesink->xcontext->disp,
-  //    glimagesink->xcontext->root,
-  //    0, 0, xwindow->width, xwindow->height, 0, 0, glimagesink->xcontext->black);
-
-  XMapRaised (glimagesink->xcontext->disp, xwindow->win);
-
-  /* connect the glx-context to the window */
-  glXMakeCurrent (xcontext->disp, xwindow->win, xcontext->glx);
-
-  printf ("Initializing OpenGL parameters\n");
-  /* initialize OpenGL drawing */
-  glDisable (GL_DEPTH_TEST);
-  //glShadeModel(GL_SMOOTH);
-
-  glDisable (GL_TEXTURE_2D);
-  glDisable (GL_CULL_FACE);
-  glClearDepth (1.0f);
-  glClearColor (0, 0.5, 0, 1);
-
-  // both upload the video, and redraw the screen
-  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-
-  //glEnable(GL_LIGHT0);                                        // Quick And Dirty Lighting (Assumes Light0 Is Set Up)
-  //glEnable(GL_LIGHTING);                                      // Enable Lighting
-  glDisable (GL_COLOR_MATERIAL);        // Enable Material Coloring
-  glEnable (GL_AUTO_NORMAL);    // let OpenGL generate the Normals
-
-  glDisable (GL_BLEND);
-
-  glPolygonMode (GL_FRONT, GL_FILL);
-  glPolygonMode (GL_BACK, GL_FILL);
-
-  glShadeModel (GL_SMOOTH);
-  glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
-
-  glBindTexture (GL_TEXTURE_2D, 1000);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-  glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, TEX_XSIZE, TEX_YSIZE, 0, GL_RGBA,
-      GL_UNSIGNED_BYTE, NULL);
+  //XSynchronize(glimage_sink->display, True);
+  //XSetErrorHandler (error_handler);
+  glimage_sink->width = 400;
+  glimage_sink->height = 400;
 
-  glXSwapBuffers (xcontext->disp, xwindow->win);
-
-  g_mutex_unlock (glimagesink->x_lock);
-
-  gst_x_overlay_got_xwindow_id (GST_X_OVERLAY (glimagesink), xwindow->win);
-
-  return xwindow;
+  gst_glimage_sink_update_caps (glimage_sink);
+  glimage_sink->display_name = g_strdup ("");
 }
 
-/* This function destroys a GstGLWindow */
 static void
-gst_glimagesink_xwindow_destroy (GstGLImageSink * glimagesink,
-    GstGLWindow * xwindow)
+gst_glimage_sink_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
 {
-  GstXContext *xcontext = glimagesink->xcontext;
+  GstGLImageSink *glimage_sink;
 
-  g_return_if_fail (xwindow != NULL);
-  g_return_if_fail (GST_IS_GLIMAGESINK (glimagesink));
+  g_return_if_fail (GST_IS_GLIMAGE_SINK (object));
 
-  g_mutex_lock (glimagesink->x_lock);
+  glimage_sink = GST_GLIMAGE_SINK (object);
 
-  if (glimagesink->signal_handoffs) {
-    g_warning ("NOT DESTROYING any window due to signal_handoff !\n");
-    return;
-  }
-
-  if (xcontext->glx) {
-    if (!glXMakeCurrent (xcontext->disp, None, NULL)) {
-      printf ("Could not release drawing context.\n");
-    }
-    glXDestroyContext (xcontext->disp, xcontext->glx);
-    xcontext->glx = NULL;
-  }
-#if 0                           // not used: prepared for fs mode
-  /* switch back to original desktop resolution if we were in fs */
-  if (GLWin.fs) {
-    XF86VidModeSwitchToMode (GLWin.dpy, GLWin.screen, &GLWin.deskMode);
-    XF86VidModeSetViewPort (GLWin.dpy, GLWin.screen, 0, 0);
+  switch (prop_id) {
+    case ARG_DISPLAY:
+      if (glimage_sink->display_name) {
+        g_free (glimage_sink->display_name);
+      }
+      glimage_sink->display_name = g_strdup (g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
   }
-#endif
-
-  /* If we did not create that window we just free the GC and let it live */
-  if (xwindow->internal)
-    XDestroyWindow (glimagesink->xcontext->disp, xwindow->win);
-  else
-    XSelectInput (glimagesink->xcontext->disp, xwindow->win, 0);
-
-  printf ("Check Xwindow destroy !\n");
-
-  g_mutex_unlock (glimagesink->x_lock);
-
-  g_free (xwindow);
 }
 
-/* This function resizes a GstGLWindow */
 static void
-gst_glimagesink_xwindow_resize (GstGLImageSink * glimagesink,
-    GstGLWindow * xwindow, guint width, guint height)
+gst_glimage_sink_finalize (GObject * object)
 {
-  g_return_if_fail (xwindow != NULL);
-  g_return_if_fail (GST_IS_GLIMAGESINK (glimagesink));
-
-  g_mutex_lock (glimagesink->x_lock);
+  GstGLImageSink *glimage_sink;
 
-  xwindow->width = width;
-  xwindow->height = height;
+  g_return_if_fail (GST_IS_GLIMAGE_SINK (object));
 
-  XResizeWindow (glimagesink->xcontext->disp, xwindow->win,
-      xwindow->width, xwindow->height);
+  glimage_sink = GST_GLIMAGE_SINK (object);
 
-  printf ("No xwindow resize implemented yet !\n");
+  gst_caps_unref (glimage_sink->caps);
+  g_free (glimage_sink->display_name);
 
-  g_mutex_unlock (glimagesink->x_lock);
 }
 
 static void
-gst_glimagesink_xwindow_update_geometry (GstGLImageSink * glimagesink,
-    GstGLWindow * xwindow)
+gst_glimage_sink_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
 {
-  XWindowAttributes attr;
+  GstGLImageSink *glimage_sink;
 
-  g_return_if_fail (xwindow != NULL);
-  g_return_if_fail (GST_IS_GLIMAGESINK (glimagesink));
+  g_return_if_fail (GST_IS_GLIMAGE_SINK (object));
 
-  /* Update the window geometry */
-  g_mutex_lock (glimagesink->x_lock);
-  XGetWindowAttributes (glimagesink->xcontext->disp,
-      glimagesink->window->win, &attr);
-  g_mutex_unlock (glimagesink->x_lock);
+  glimage_sink = GST_GLIMAGE_SINK (object);
 
-  // FIXME: Need to introduce OpenGL setup here if PROJECTION_MATRIX depends on width/height
-  //printf("No update geometry implemented yet !\n");
-
-  glimagesink->window->width = attr.width;
-  glimagesink->window->height = attr.height;
+  switch (prop_id) {
+    case ARG_DISPLAY:
+      g_value_set_string (value, g_strdup (glimage_sink->display_name));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
 }
 
-#if 0
-static void
-gst_glimagesink_renegotiate_size (GstGLImageSink * glimagesink)
-{
-  g_return_if_fail (GST_IS_GLIMAGESINK (glimagesink));
-
-  if (!glimagesink->window)
-    return;
+/*
+ * GstElement methods
+ */
 
-  gst_glimagesink_xwindow_update_geometry (glimagesink, glimagesink->window);
+static GstStateChangeReturn
+gst_glimage_sink_change_state (GstElement * element, GstStateChange transition)
+{
+  GstGLImageSink *glimage_sink;
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
 
-  if (glimagesink->window->width <= 1 || glimagesink->window->height <= 1)
-    return;
+  GST_DEBUG ("change state");
 
-  if (GST_PAD_IS_NEGOTIATING (GST_VIDEOSINK_PAD (glimagesink)) ||
-      !gst_pad_is_negotiated (GST_VIDEOSINK_PAD (glimagesink)))
-    return;
+  glimage_sink = GST_GLIMAGE_SINK (element);
 
-  /* Window got resized or moved. We do caps negotiation again to get video
-     scaler to fit that new size only if size of the window differs from our
-     size. */
-
-  if (GST_VIDEOSINK_WIDTH (glimagesink) != glimagesink->window->width ||
-      GST_VIDEOSINK_HEIGHT (glimagesink) != glimagesink->window->height) {
-    GstPadLinkReturn r;
-
-    r = gst_pad_try_set_caps (GST_VIDEOSINK_PAD (glimagesink),
-        gst_caps_new_simple ("video/x-raw-rgb",
-            "bpp", G_TYPE_INT, glimagesink->xcontext->bpp,
-            "depth", G_TYPE_INT, glimagesink->xcontext->depth,
-            "endianness", G_TYPE_INT, glimagesink->xcontext->endianness,
-            "red_mask", G_TYPE_INT, glimagesink->xcontext->visual->red_mask,
-            "green_mask", G_TYPE_INT, glimagesink->xcontext->visual->green_mask,
-            "blue_mask", G_TYPE_INT, glimagesink->xcontext->visual->blue_mask,
-            "width", G_TYPE_INT, glimagesink->window->width,
-            "height", G_TYPE_INT, glimagesink->window->height,
-            "framerate", G_TYPE_DOUBLE, glimagesink->framerate, NULL));
-
-    if ((r == GST_PAD_LINK_OK) || (r == GST_PAD_LINK_DONE)) {
-      /* Renegotiation succeeded, we update our size and image */
-      GST_VIDEOSINK_WIDTH (glimagesink) = glimagesink->window->width;
-      GST_VIDEOSINK_HEIGHT (glimagesink) = glimagesink->window->height;
-
-      if ((glimagesink->glimage) &&
-          ((GST_VIDEOSINK_WIDTH (glimagesink) != glimagesink->glimage->width) ||
-              (GST_VIDEOSINK_HEIGHT (glimagesink) !=
-                  glimagesink->glimage->height))) {
-        /* We renew our ximage only if size changed */
-        gst_glimagesink_ximage_destroy (glimagesink, glimagesink->glimage);
-
-        glimagesink->glimage = gst_glimagesink_ximage_new (glimagesink,
-            GST_VIDEOSINK_WIDTH (glimagesink),
-            GST_VIDEOSINK_HEIGHT (glimagesink));
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      if (!gst_glimage_sink_init_display (glimage_sink)) {
+        GST_ELEMENT_ERROR (glimage_sink, RESOURCE, WRITE, (NULL),
+            ("Could not initialize OpenGL"));
+        return GST_STATE_CHANGE_FAILURE;
       }
-    }
+      break;
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+      break;
+    default:
+      break;
   }
-}
-#endif
-
-/* This function handles XEvents that might be in the queue. It generates
-   GstEvent that will be sent upstream in the pipeline to handle interactivity
-   and navigation. It will also listen for configure events on the window to
-   trigger caps renegotiation so on the fly software scaling can work. */
-static void
-gst_glimagesink_handle_xevents (GstGLImageSink * glimagesink, GstPad * pad)
-{
-  XEvent e;
 
-  glimagesink->pointer_moved = FALSE;
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE)
+    return ret;
 
-  g_return_if_fail (GST_IS_GLIMAGESINK (glimagesink));
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      /* FIXME clear window */
+      glimage_sink->fps_n = 0;
+      glimage_sink->fps_d = 1;
+      GST_VIDEO_SINK_WIDTH (glimage_sink) = 0;
+      GST_VIDEO_SINK_HEIGHT (glimage_sink) = 0;
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      /* FIXME dispose of window */
+      break;
+    default:
+      break;
+  }
 
-  //printf("handling xevents\n");
+  return ret;
+}
 
-  //gst_glimagesink_renegotiate_size (glimagesink);
+/*
+ * GstBaseSink methods
+ */
 
-  /* Then we get all pointer motion events, only the last position is
-     interesting. */
-  g_mutex_lock (glimagesink->x_lock);
-  while (XCheckWindowEvent (glimagesink->xcontext->disp,
-          glimagesink->window->win, PointerMotionMask, &e)) {
-    g_mutex_unlock (glimagesink->x_lock);
+static void
+gst_glimage_sink_get_times (GstBaseSink * bsink, GstBuffer * buf,
+    GstClockTime * start, GstClockTime * end)
+{
 
-    switch (e.type) {
-      case MotionNotify:
-        glimagesink->pointer_x = e.xmotion.x;
-        glimagesink->pointer_y = e.xmotion.y;
-        glimagesink->pointer_moved = TRUE;
-        break;
-      default:
-        break;
-    }
+}
 
-    g_mutex_lock (glimagesink->x_lock);
-  }
-  g_mutex_unlock (glimagesink->x_lock);
+static GstCaps *
+gst_glimage_sink_get_caps (GstBaseSink * bsink)
+{
+  GstGLImageSink *glimage_sink;
 
-  if (glimagesink->pointer_moved) {
-    GST_DEBUG ("glimagesink pointer moved over window at %d,%d",
-        glimagesink->pointer_x, glimagesink->pointer_y);
-    gst_navigation_send_mouse_event (GST_NAVIGATION (glimagesink),
-        "mouse-move", 0, glimagesink->pointer_x, glimagesink->pointer_y);
-  }
+  glimage_sink = GST_GLIMAGE_SINK (bsink);
 
-  /* We get all remaining events on our window to throw them upstream */
-  g_mutex_lock (glimagesink->x_lock);
-  while (XCheckWindowEvent (glimagesink->xcontext->disp,
-          glimagesink->window->win,
-          KeyPressMask | KeyReleaseMask |
-          ButtonPressMask | ButtonReleaseMask, &e)) {
-    KeySym keysym;
-
-    /* We lock only for the X function call */
-    g_mutex_unlock (glimagesink->x_lock);
-
-    switch (e.type) {
-      case ButtonPress:
-        /* Mouse button pressed/released over our window. We send upstream
-           events for interactivity/navigation */
-        GST_DEBUG ("glimagesink button %d pressed over window at %d,%d",
-            e.xbutton.button, e.xbutton.x, e.xbutton.x);
-        glimagesink->pointer_button[e.xbutton.button - Button1] = TRUE;
-        gst_navigation_send_mouse_event (GST_NAVIGATION (glimagesink),
-            "mouse-button-press", e.xbutton.button, e.xbutton.x, e.xbutton.y);
-        break;
-      case ButtonRelease:
-        GST_DEBUG ("glimagesink button %d release over window at %d,%d",
-            e.xbutton.button, e.xbutton.x, e.xbutton.x);
-        glimagesink->pointer_button[e.xbutton.button - Button1] = FALSE;
-        gst_navigation_send_mouse_event (GST_NAVIGATION (glimagesink),
-            "mouse-button-release", e.xbutton.button, e.xbutton.x, e.xbutton.y);
-        break;
-      case KeyPress:
-      case KeyRelease:
-        /* Key pressed/released over our window. We send upstream
-           events for interactivity/navigation */
-        GST_DEBUG ("glimagesink key %d released over window at %d,%d",
-            e.xkey.keycode, e.xkey.x, e.xkey.x);
-        keysym = XKeycodeToKeysym (glimagesink->xcontext->disp,
-            e.xkey.keycode, 0);
-        if (keysym != NoSymbol) {
-          gst_navigation_send_key_event (GST_NAVIGATION (glimagesink),
-              e.type == KeyPress ?
-              "key-press" : "key-release", XKeysymToString (keysym));
-        } else {
-          gst_navigation_send_key_event (GST_NAVIGATION (glimagesink),
-              e.type == KeyPress ? "key-press" : "key-release", "unknown");
-        }
-        break;
-      default:
-        GST_DEBUG ("glimagesink unhandled X event (%d)", e.type);
-    }
+  GST_DEBUG ("get caps returning %" GST_PTR_FORMAT, glimage_sink->caps);
 
-    g_mutex_lock (glimagesink->x_lock);
-  }
-  g_mutex_unlock (glimagesink->x_lock);
+  return gst_caps_ref (glimage_sink->caps);
 }
 
-/* attributes for a single buffered visual in RGBA format with at least
- * 4 bits per color and a 16 bit depth buffer */
-static int attrListSingle[] = {
-  GLX_RGBA,
-  GLX_RED_SIZE, 4,
-  GLX_GREEN_SIZE, 4,
-  GLX_BLUE_SIZE, 4,
-  GLX_DEPTH_SIZE, 16,
-  None
-};
-
-/* attributes for a double buffered visual in RGBA format with at least
- * 4 bits per color and a 16 bit depth buffer */
-static int attrListDouble[] = {
-  GLX_RGBA, GLX_DOUBLEBUFFER,
-  GLX_RED_SIZE, 4,
-  GLX_GREEN_SIZE, 4,
-  GLX_BLUE_SIZE, 4,
-  GLX_DEPTH_SIZE, 16,
-  None
-};
-
-/* This function get the X Display and global infos about it. Everything is
-   stored in our object and will be cleaned when the object is finalized. Note
-   here that caps for supported format are generated without any window or 
-   image creation */
-static GstXContext *
-gst_glimagesink_xcontext_get (GstGLImageSink * glimagesink)
+static gboolean
+gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
 {
-  GstXContext *xcontext = NULL;
-  int glxMajorVersion, glxMinorVersion;
-  XPixmapFormatValues *px_formats = NULL;
-  gint nb_formats = 0, i;
-
-  printf ("Acquiring X context\n");
-
-  g_return_val_if_fail (GST_IS_GLIMAGESINK (glimagesink), NULL);
+  GstGLImageSink *glimage_sink;
+  GstCaps *intersection;
+  GstStructure *structure;
+  int width;
+  int height;
+  gboolean ret;
+  const GValue *fps;
+  const GValue *par;
 
-  xcontext = g_new0 (GstXContext, 1);
+  GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);
 
-  g_mutex_lock (glimagesink->x_lock);
+  glimage_sink = GST_GLIMAGE_SINK (bsink);
 
-  xcontext->disp = XOpenDisplay (glimagesink->display_name);
+  intersection = gst_caps_intersect (glimage_sink->caps, caps);
 
-  if (!xcontext->disp) {
-    g_mutex_unlock (glimagesink->x_lock);
-    g_free (xcontext);
-    GST_ELEMENT_ERROR (glimagesink, RESOURCE, TOO_LAZY, (NULL),
-        ("Could not open display"));
-    return NULL;
+  if (gst_caps_is_empty (intersection)) {
+    return FALSE;
   }
 
-  xcontext->screen_num = DefaultScreen (xcontext->disp);
-  xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
+  gst_caps_unref (intersection);
 
-  /* get an appropriate visual */
-  xcontext->visualinfo =
-      glXChooseVisual (xcontext->disp, xcontext->screen_num, attrListDouble);
-  if (xcontext->visualinfo == NULL) {
-    xcontext->visualinfo =
-        glXChooseVisual (xcontext->disp, xcontext->screen_num, attrListSingle);
-    GST_DEBUG ("Only Singlebuffered Visual!\n");
+  structure = gst_caps_get_structure (caps, 0);
+  ret = gst_structure_get_int (structure, "width", &width);
+  ret &= gst_structure_get_int (structure, "height", &height);
+  fps = gst_structure_get_value (structure, "framerate");
+  ret &= (fps != NULL);
+  par = gst_structure_get_value (structure, "pixel-aspect-ratio");
+
+  if (!ret)
+    return FALSE;
 
-    if (xcontext->visualinfo == NULL)
-      GST_ELEMENT_ERROR (glimagesink, RESOURCE, TOO_LAZY, (NULL),
-          ("Could not open GLX connection"));
+  glimage_sink->width = width;
+  glimage_sink->height = height;
+  glimage_sink->fps_n = gst_value_get_fraction_numerator (fps);
+  glimage_sink->fps_d = gst_value_get_fraction_denominator (fps);
+  if (par) {
+    glimage_sink->par_n = gst_value_get_fraction_numerator (par);
+    glimage_sink->par_d = gst_value_get_fraction_denominator (par);
   } else {
-    GST_DEBUG ("Got Doublebuffered Visual!\n");
+    glimage_sink->par_n = 1;
+    glimage_sink->par_d = 1;
   }
-  glXQueryVersion (xcontext->disp, &glxMajorVersion, &glxMinorVersion);
-  GST_DEBUG ("glX-Version %d.%d\n", glxMajorVersion, glxMinorVersion);
-
-  printf ("Creating GLX context\n");
-
-  /* create a GLX context */
-  xcontext->glx =
-      glXCreateContext (xcontext->disp, xcontext->visualinfo, 0, GL_TRUE);
-
-  if (glXIsDirect (xcontext->disp, xcontext->glx))
-    printf ("Congrats, you have Direct Rendering!\n");
-  else
-    printf ("Sorry, no Direct Rendering possible!\n");
 
-  xcontext->endianness =
-      (ImageByteOrder (xcontext->disp) ==
-      LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
+  GST_VIDEO_SINK_WIDTH (glimage_sink) = width;
+  GST_VIDEO_SINK_HEIGHT (glimage_sink) = height;
 
-  xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
-  xcontext->root = DefaultRootWindow (xcontext->disp);
+  if (strcmp (gst_structure_get_name (structure), "video/x-raw-rgb") == 0) {
+    int red_mask;
 
-#if 1
+    GST_DEBUG ("using RGB");
+    glimage_sink->use_rgb = TRUE;
+    gst_structure_get_int (structure, "red_mask", &red_mask);
 
-  xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num);
-  xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num);
-  xcontext->depth = DefaultDepthOfScreen (xcontext->screen);
+    if (red_mask == 0xff000000) {
+      glimage_sink->use_rgbx = TRUE;
+    } else {
+      glimage_sink->use_rgbx = FALSE;
+    }
+  } else {
+    unsigned int fourcc;
 
-  /* We get supported pixmap formats at supported depth */
-  px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
+    GST_DEBUG ("using YUV");
+    glimage_sink->use_rgb = FALSE;
 
-  if (!px_formats) {
-    XCloseDisplay (xcontext->disp);
-    g_mutex_unlock (glimagesink->x_lock);
-    g_free (xcontext);
-    return NULL;
+    gst_structure_get_fourcc (structure, "format", &fourcc);
+    if (fourcc == GST_MAKE_FOURCC ('Y', 'U', 'Y', '2')) {
+      glimage_sink->use_yuy2 = TRUE;
+    } else {
+      glimage_sink->use_yuy2 = FALSE;
+    }
   }
 
-  /* We get bpp value corresponding to our running depth */
-  for (i = 0; i < nb_formats; i++) {
-    if (px_formats[i].depth == xcontext->depth)
-      xcontext->bpp = px_formats[i].bits_per_pixel;
+#if 0
+  if (!glimage_sink->window) {
+    gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (glimage_sink));
   }
-
-  XFree (px_formats);
 #endif
 
-  /* our caps system handles 24/32bpp RGB as big-endian. */
-  if ((xcontext->bpp == 24 || xcontext->bpp == 32) &&
-      xcontext->endianness == G_LITTLE_ENDIAN) {
-    xcontext->endianness = G_BIG_ENDIAN;
-    xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask);
-    xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask);
-    xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask);
-    if (xcontext->bpp == 24) {
-      xcontext->visual->red_mask >>= 8;
-      xcontext->visual->green_mask >>= 8;
-      xcontext->visual->blue_mask >>= 8;
-    }
+  if (!glimage_sink->window) {
+    gst_glimage_sink_create_window (glimage_sink);
   }
 
-  xcontext->endianness = G_BIG_ENDIAN;
-  xcontext->visual->red_mask = 0xff0000;
-  xcontext->visual->green_mask = 0xff00;
-  xcontext->visual->blue_mask = 0xff;
-  xcontext->bpp = 24;
-  xcontext->depth = 24;
-
-  //char yuvformat[4] = {'Y', 'V', '1', '2'};
-
-  if (!glimagesink->signal_handoffs)
-    xcontext->caps = gst_caps_new_simple ("video/x-raw-rgb",
-        "bpp", G_TYPE_INT, xcontext->bpp,
-        "depth", G_TYPE_INT, xcontext->depth,
-        "endianness", G_TYPE_INT, xcontext->endianness,
-        "red_mask", G_TYPE_INT, xcontext->visual->red_mask,
-        "green_mask", G_TYPE_INT, xcontext->visual->green_mask,
-        "blue_mask", G_TYPE_INT, xcontext->visual->blue_mask,
-        "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
-        "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
-        "framerate", GST_TYPE_DOUBLE_RANGE, 1.0, 100.0, NULL);
-  else
-    xcontext->caps = gst_caps_new_simple ("video/x-raw-yuv",
-        //                                      "format", GST_TYPE_FOURCC, GST_PROPS_FOURCC (GST_STR_FOURCC ("YV12")),
-        "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
-        "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
-        "framerate", GST_TYPE_DOUBLE_RANGE, 1.0, 100.0, NULL);
-
-  g_mutex_unlock (glimagesink->x_lock);
-
-  return xcontext;
+  return TRUE;
 }
 
-/* This function cleans the X context. Closing the Display and unrefing the
-   caps for supported formats. */
-static void
-gst_glimagesink_xcontext_clear (GstGLImageSink * glimagesink)
+static GstFlowReturn
+gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf)
 {
-  g_return_if_fail (GST_IS_GLIMAGESINK (glimagesink));
-
-  gst_caps_free (glimagesink->xcontext->caps);
-
-  g_mutex_lock (glimagesink->x_lock);
+  GstGLImageSink *glimage_sink;
 
-  XCloseDisplay (glimagesink->xcontext->disp);
+  glimage_sink = GST_GLIMAGE_SINK (bsink);
 
-  g_mutex_unlock (glimagesink->x_lock);
+  gst_glimage_sink_push_image (glimage_sink, buf);
 
-  glimagesink->xcontext = NULL;
+  return GST_FLOW_OK;
 }
 
-static void
-gst_glimagesink_imagepool_clear (GstGLImageSink * glimagesink)
-{
-  g_mutex_lock (glimagesink->pool_lock);
-
-  while (glimagesink->image_pool) {
-    GstGLImage *ximage = glimagesink->image_pool->data;
-
-    glimagesink->image_pool = g_slist_delete_link (glimagesink->image_pool,
-        glimagesink->image_pool);
-    gst_glimagesink_ximage_destroy (glimagesink, ximage);
-  }
-
-  g_mutex_unlock (glimagesink->pool_lock);
-}
 
-/* 
-=================
-Element stuff 
-=================
-*/
+/*
+ * helper functions
+ */
 
-static GstCaps *
-gst_glimagesink_fixate (GstPad * pad, const GstCaps * caps)
+static void
+gst_caps_set_all (GstCaps * caps, char *field, ...)
 {
   GstStructure *structure;
-  GstCaps *newcaps;
-
-  printf ("Linking the sink\n");
+  va_list var_args;
+  int i;
 
-  if (gst_caps_get_size (caps) > 1)
-    return NULL;
+  for (i = 0; i < gst_caps_get_size (caps); i++) {
+    structure = gst_caps_get_structure (caps, i);
 
-  newcaps = gst_caps_copy (caps);
-  structure = gst_caps_get_structure (newcaps, 0);
-
-  if (gst_structure_fixate_field_nearest_int (structure, "width", 320)) {
-    return newcaps;
-  }
-  if (gst_structure_fixate_field_nearest_int (structure, "height", 240)) {
-    return newcaps;
+    va_start (var_args, field);
+    gst_structure_set_valist (structure, field, var_args);
+    va_end (var_args);
   }
-  if (gst_structure_fixate_field_nearest_double (structure, "framerate", 30.0)) {
-    return newcaps;
-  }
-
-  gst_caps_free (newcaps);
-  return NULL;
 }
 
-static GstCaps *
-gst_glimagesink_getcaps (GstPad * pad)
+static void
+gst_glimage_sink_update_caps (GstGLImageSink * glimage_sink)
 {
-  GstGLImageSink *glimagesink;
+  GstCaps *caps;
+  int max_size;
 
-  glimagesink = GST_GLIMAGESINK (gst_pad_get_parent (pad));
-
-  if (glimagesink->xcontext)
-    return gst_caps_copy (glimagesink->xcontext->caps);
+  if (glimage_sink->display == NULL) {
+    gst_caps_unref (glimage_sink->caps);
+    glimage_sink->caps =
+        gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD
+            (glimage_sink)));
+    return;
+  }
 
-#if 0
-  if (!glimagesink->signal_handoffs)
-    return gst_caps_from_string ("video/x-raw-rgb, "
-        "framerate = (double) [ 1, 100 ], "
-        "width = (int) [ 0, MAX ], " "height = (int) [ 0, MAX ]");
-  else
+  caps = gst_caps_from_string (GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx);
+#ifdef GL_YCBCR_MESA
+  if (glimage_sink->have_yuv) {
+    GstCaps *ycaps =
+        gst_caps_from_string (GST_VIDEO_CAPS_YUV ("{ UYVY, YUY2 }"));
+    gst_caps_append (ycaps, caps);
+    caps = ycaps;
+  }
 #endif
-    return gst_caps_from_string ("video/x-raw-yuv, "
-        "framerate = (double) [ 1, 100 ], "
-        "width = (int) [ 0, MAX ], " "height = (int) [ 0, MAX ]");
-}
-
-static GstPadLinkReturn
-gst_glimagesink_sink_link (GstPad * pad, const GstCaps * caps)
-{
-  GstGLImageSink *glimagesink;
-  gboolean ret;
-  GstStructure *structure;
-
-  glimagesink = GST_GLIMAGESINK (gst_pad_get_parent (pad));
-
-  if (!glimagesink->xcontext)
-    return GST_PAD_LINK_DELAYED;
 
-  GST_DEBUG_OBJECT (glimagesink,
-      "sinkconnect possible caps %" GST_PTR_FORMAT " with given caps %"
-      GST_PTR_FORMAT, glimagesink->xcontext->caps, caps);
-
-  structure = gst_caps_get_structure (caps, 0);
-  ret = gst_structure_get_int (structure, "width",
-      &(GST_VIDEOSINK_WIDTH (glimagesink)));
-  ret &= gst_structure_get_int (structure, "height",
-      &(GST_VIDEOSINK_HEIGHT (glimagesink)));
-  ret &= gst_structure_get_double (structure,
-      "framerate", &glimagesink->framerate);
-  if (!ret)
-    return GST_PAD_LINK_REFUSED;
-
-  glimagesink->pixel_width = 1;
-  gst_structure_get_int (structure, "pixel_width", &glimagesink->pixel_width);
-
-  glimagesink->pixel_height = 1;
-  gst_structure_get_int (structure, "pixel_height", &glimagesink->pixel_height);
-
-  /* Creating our window and our image */
-  if (!glimagesink->window)
-    glimagesink->window = gst_glimagesink_xwindow_new (glimagesink,
-        GST_VIDEOSINK_WIDTH (glimagesink), GST_VIDEOSINK_HEIGHT (glimagesink));
-  else {
-    if (glimagesink->window->internal)
-      gst_glimagesink_xwindow_resize (glimagesink, glimagesink->window,
-          GST_VIDEOSINK_WIDTH (glimagesink),
-          GST_VIDEOSINK_HEIGHT (glimagesink));
+  max_size = glimage_sink->max_texture_size;
+  if (max_size == 0) {
+    max_size = 1024;
   }
 
-  if ((glimagesink->glimage) && ((GST_VIDEOSINK_WIDTH (glimagesink) != glimagesink->glimage->width) || (GST_VIDEOSINK_HEIGHT (glimagesink) != glimagesink->glimage->height))) { /* We renew our ximage only if size changed */
-    gst_glimagesink_ximage_destroy (glimagesink, glimagesink->glimage);
-
-    glimagesink->glimage = gst_glimagesink_ximage_new (glimagesink,
-        GST_VIDEOSINK_WIDTH (glimagesink), GST_VIDEOSINK_HEIGHT (glimagesink));
-  } else if (!glimagesink->glimage)     /* If no ximage, creating one */
-    glimagesink->glimage = gst_glimagesink_ximage_new (glimagesink,
-        GST_VIDEOSINK_WIDTH (glimagesink), GST_VIDEOSINK_HEIGHT (glimagesink));
-
-  gst_x_overlay_got_desired_size (GST_X_OVERLAY (glimagesink),
-      GST_VIDEOSINK_WIDTH (glimagesink), GST_VIDEOSINK_HEIGHT (glimagesink));
-
-  return GST_PAD_LINK_OK;
-}
+  gst_caps_set_all (caps,
+      "width", GST_TYPE_INT_RANGE, 16, max_size,
+      "height", GST_TYPE_INT_RANGE, 16, max_size, NULL);
 
-static GstStateChangeReturn
-gst_glimagesink_change_state (GstElement * element, GstStateChange transition)
-{
-  GstGLImageSink *glimagesink;
-
-  printf ("change state\n");
-
-  glimagesink = GST_GLIMAGESINK (element);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      /* Initializing the XContext */
-      if (!glimagesink->xcontext) {
-        glimagesink->xcontext = gst_glimagesink_xcontext_get (glimagesink);
-        if (!glimagesink->xcontext)
-          return GST_STATE_CHANGE_FAILURE;
-      }
-      printf ("null to ready done\n");
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      printf ("ready to paused\n");
-      //if (glimagesink->window) // not needed with OpenGL
-      //  gst_glimagesink_xwindow_clear (glimagesink, glimagesink->window);
-      glimagesink->time = 0;
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      break;
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      glimagesink->framerate = 0;
-      GST_VIDEOSINK_WIDTH (glimagesink) = 0;
-      GST_VIDEOSINK_HEIGHT (glimagesink) = 0;
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      if (glimagesink->glimage) {
-        gst_glimagesink_ximage_destroy (glimagesink, glimagesink->glimage);
-        glimagesink->glimage = NULL;
-      }
-
-      if (glimagesink->image_pool)
-        gst_glimagesink_imagepool_clear (glimagesink);
-
-      if (glimagesink->window) {
-        gst_glimagesink_xwindow_destroy (glimagesink, glimagesink->window);
-        glimagesink->window = NULL;
-      }
-
-      if (glimagesink->xcontext) {
-        gst_glimagesink_xcontext_clear (glimagesink);
-        glimagesink->xcontext = NULL;
-      }
-      break;
+  if (glimage_sink->caps) {
+    gst_caps_unref (glimage_sink->caps);
   }
-
-  if (GST_ELEMENT_CLASS (parent_class)->change_state)
-    return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  return GST_STATE_CHANGE_SUCCESS;
+  glimage_sink->caps = caps;
 }
 
 static void
-gst_glimagesink_chain (GstPad * pad, GstData * data)
+gst_glimage_sink_create_window (GstGLImageSink * glimage_sink)
 {
-  GstBuffer *buf = GST_BUFFER (data);
-  GstGLImageSink *glimagesink;
-
-  //printf("CHAIN CALL\n");
-
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (buf != NULL);
-
-  glimagesink = GST_GLIMAGESINK (gst_pad_get_parent (pad));
-
-  if (GST_IS_EVENT (data)) {
-    gst_pad_event_default (pad, GST_EVENT (data));
-    return;
-  }
-
-  buf = GST_BUFFER (data);
-  /* update time */
-  if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
-    glimagesink->time = GST_BUFFER_TIMESTAMP (buf);
+  gboolean ret;
+  Window root;
+  XSetWindowAttributes attr;
+  Screen *screen;
+  int scrnum;
+  int mask;
+  int width, height;
+
+  screen = XDefaultScreenOfDisplay (glimage_sink->display);
+  scrnum = XScreenNumberOfScreen (screen);
+  root = XRootWindow (glimage_sink->display, scrnum);
+
+  if (glimage_sink->parent_window) {
+    XWindowAttributes pattr;
+
+    XGetWindowAttributes (glimage_sink->display, glimage_sink->parent_window,
+        &pattr);
+    width = pattr.width;
+    height = pattr.height;
+  } else {
+    width = GST_VIDEO_SINK (glimage_sink)->width;
+    height = GST_VIDEO_SINK (glimage_sink)->height;
+  }
+  attr.background_pixel = 0;
+  attr.border_pixel = 0;
+  attr.colormap = XCreateColormap (glimage_sink->display, root,
+      glimage_sink->visinfo->visual, AllocNone);
+  if (glimage_sink->parent_window) {
+    attr.override_redirect = True;
+  } else {
+    attr.override_redirect = False;
   }
 
-  if (glimagesink->signal_handoffs)
-    g_signal_emit (G_OBJECT (glimagesink),
-        gst_glimagesink_signals[SIGNAL_HANDOFF], 0, buf, pad);
-  else {
-    /* If this buffer has been allocated using our buffer management we simply
-       put the ximage which is in the PRIVATE pointer */
-    if (GST_BUFFER_FREE_DATA_FUNC (buf) == gst_glimagesink_buffer_free)
-      gst_glimagesink_ximage_put (glimagesink, GST_BUFFER_PRIVATE (buf));
-    else {                      /* Else we have to copy the data into our private image, */
-      /* if we have one... */
-      printf ("Non-locally allocated: Sub-optimal buffer transfer!\n");
-      if (glimagesink->glimage) {
-#if 0
-        memcpy (glimagesink->glimage->ximage->data,
-            GST_BUFFER_DATA (buf),
-            MIN (GST_BUFFER_SIZE (buf), glimagesink->glimage->size));
-#endif
-        gst_glimagesink_ximage_put (glimagesink, glimagesink->glimage);
-      } else {                  /* No image available. Something went wrong during capsnego ! */
+  mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect;
 
-        gst_buffer_unref (buf);
-        GST_ELEMENT_ERROR (glimagesink, CORE, NEGOTIATION, (NULL),
-            ("no format defined before chain function"));
-        return;
-      }
-    }
-  }
+  GST_DEBUG ("creating window with size %d x %d", width, height);
 
-  GST_DEBUG ("clock wait: %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (glimagesink->time));
+  glimage_sink->window = XCreateWindow (glimage_sink->display, root, 0, 0,
+      width, height,
+      0, glimage_sink->visinfo->depth, InputOutput,
+      glimage_sink->visinfo->visual, mask, &attr);
 
-  /// ah, BTW, I think the gst_element_wait should happen _before_ the ximage is shown
-  if (GST_VIDEOSINK_CLOCK (glimagesink))
-    gst_element_wait (GST_ELEMENT (glimagesink), glimagesink->time);
-
-  /* set correct time for next buffer */
-  if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf) && glimagesink->framerate > 0)
-    glimagesink->time += GST_SECOND / glimagesink->framerate;
+  if (glimage_sink->parent_window) {
+    ret = XReparentWindow (glimage_sink->display, glimage_sink->window,
+        glimage_sink->parent_window, 0, 0);
+    XMapWindow (glimage_sink->display, glimage_sink->window);
+  } else {
+    XMapWindow (glimage_sink->display, glimage_sink->window);
+  }
 
-  gst_buffer_unref (buf);
+  glXMakeCurrent (glimage_sink->display, glimage_sink->window,
+      glimage_sink->context);
 
-  if (!glimagesink->signal_handoffs)
-    gst_glimagesink_handle_xevents (glimagesink, pad);
+  glDepthFunc (GL_LESS);
+  glEnable (GL_DEPTH_TEST);
+  glClearColor (0.2, 0.2, 0.2, 1.0);
+  glViewport (0, 0, width, height);
 }
 
-/* Buffer management */
 
-static void
-gst_glimagesink_buffer_free (GstBuffer * buffer)
+static gboolean
+gst_glimage_sink_init_display (GstGLImageSink * glimage_sink)
 {
-  GstGLImageSink *glimagesink;
-  GstGLImage *ximage;
-
-  ximage = GST_BUFFER_PRIVATE (buffer);
-
-  g_assert (GST_IS_GLIMAGESINK (ximage->glimagesink));
-  glimagesink = ximage->glimagesink;
+  gboolean ret;
+  XVisualInfo *visinfo;
+  Screen *screen;
+  Window root;
+  int scrnum;
+  int attrib[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 8,
+    GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None
+  };
+  XSetWindowAttributes attr;
+  int error_base;
+  int event_base;
+  int mask;
+  const char *extstring;
+  Window window;
+
+  GST_ERROR ("initializing display");
+
+  glimage_sink->display = XOpenDisplay (NULL);
+  if (glimage_sink->display == NULL) {
+    GST_ERROR ("Could not open display");
+    return FALSE;
+  }
 
-  /* If our geometry changed we can't reuse that image. */
-  if ((ximage->width != GST_VIDEOSINK_WIDTH (glimagesink)) ||
-      (ximage->height != GST_VIDEOSINK_HEIGHT (glimagesink)))
-    gst_glimagesink_ximage_destroy (glimagesink, ximage);
-  else {                        /* In that case we can reuse the image and add it to our image pool. */
+  screen = XDefaultScreenOfDisplay (glimage_sink->display);
+  scrnum = XScreenNumberOfScreen (screen);
+  root = XRootWindow (glimage_sink->display, scrnum);
 
-    g_mutex_lock (glimagesink->pool_lock);
-    glimagesink->image_pool = g_slist_prepend (glimagesink->image_pool, ximage);
-    g_mutex_unlock (glimagesink->pool_lock);
+  ret = glXQueryExtension (glimage_sink->display, &error_base, &event_base);
+  if (!ret) {
+    GST_ERROR ("No GLX extension");
+    return FALSE;
   }
-}
-
-static GstBuffer *
-gst_glimagesink_buffer_alloc (GstPad * pad, guint64 offset, guint size)
-{
-  GstGLImageSink *glimagesink;
-  GstBuffer *buffer;
-  GstGLImage *ximage = NULL;
-  gboolean not_found = TRUE;
 
-  //printf("Allocating new data buffer\n");
+  visinfo = glXChooseVisual (glimage_sink->display, scrnum, attrib);
+  if (visinfo == NULL) {
+    GST_ERROR ("No usable visual");
+    return FALSE;
+  }
 
-  glimagesink = GST_GLIMAGESINK (gst_pad_get_parent (pad));
+  glimage_sink->visinfo = visinfo;
 
-  g_mutex_lock (glimagesink->pool_lock);
+  glimage_sink->context = glXCreateContext (glimage_sink->display,
+      visinfo, NULL, True);
 
-  /* Walking through the pool cleaning unsuable images and searching for a
-     suitable one */
-  while (not_found && glimagesink->image_pool) {
-    ximage = glimagesink->image_pool->data;
+  attr.background_pixel = 0;
+  attr.border_pixel = 0;
+  attr.colormap = XCreateColormap (glimage_sink->display, root,
+      visinfo->visual, AllocNone);
+  attr.event_mask = StructureNotifyMask | ExposureMask;
+  attr.override_redirect = True;
 
-    if (ximage) {
-      /* Removing from the pool */
-      glimagesink->image_pool = g_slist_delete_link (glimagesink->image_pool,
-          glimagesink->image_pool);
+  //mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+  mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect;
 
-      if ((ximage->width != GST_VIDEOSINK_WIDTH (glimagesink)) || (ximage->height != GST_VIDEOSINK_HEIGHT (glimagesink))) {     /* This image is unusable. Destroying... */
-        gst_glimagesink_ximage_destroy (glimagesink, ximage);
-        ximage = NULL;
-      } else {                  /* We found a suitable image */
+  window = XCreateWindow (glimage_sink->display, root, 0, 0,
+      100, 100, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr);
 
-        break;
-      }
-    }
-  }
+  glXMakeCurrent (glimage_sink->display, window, glimage_sink->context);
 
-  g_mutex_unlock (glimagesink->pool_lock);
+  glGetIntegerv (GL_MAX_TEXTURE_SIZE, &glimage_sink->max_texture_size);
 
-  if (!ximage) {                /* We found no suitable image in the pool. Creating... */
-    ximage = gst_glimagesink_ximage_new (glimagesink,
-        GST_VIDEOSINK_WIDTH (glimagesink), GST_VIDEOSINK_HEIGHT (glimagesink));
+  extstring = (const char *) glGetString (GL_EXTENSIONS);
+#ifdef GL_YCBCR_MESA
+  if (strstr (extstring, "GL_MESA_ycbcr_texture")) {
+    glimage_sink->have_yuv = TRUE;
+  } else {
+    glimage_sink->have_yuv = FALSE;
   }
+#else
+  glimage_sink->have_yuv = FALSE;
+#endif
 
-  if (ximage) {
-    buffer = gst_buffer_new ();
-
-    /* Storing some pointers in the buffer */
-    GST_BUFFER_PRIVATE (buffer) = ximage;
-
-    GST_BUFFER_DATA (buffer) = ximage->data;
-    GST_BUFFER_FREE_DATA_FUNC (buffer) = gst_glimagesink_buffer_free;
-    GST_BUFFER_SIZE (buffer) = ximage->size;
-    return buffer;
-  } else
-    return NULL;
-}
-
-/* Interfaces stuff */
+  glXMakeCurrent (glimage_sink->display, None, NULL);
+  XDestroyWindow (glimage_sink->display, window);
 
-static gboolean
-gst_glimagesink_interface_supported (GstImplementsInterface * iface, GType type)
-{
-  g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_X_OVERLAY);
   return TRUE;
 }
 
 static void
-gst_glimagesink_interface_init (GstImplementsInterfaceClass * klass)
-{
-  klass->supported = gst_glimagesink_interface_supported;
-}
-
-static void
-gst_glimagesink_navigation_send_event (GstNavigation * navigation,
-    GstStructure * structure)
+gst_glimage_sink_push_image (GstGLImageSink * glimage_sink, GstBuffer * buf)
 {
-  GstGLImageSink *glimagesink = GST_GLIMAGESINK (navigation);
-  GstEvent *event;
-  gint x_offset, y_offset;
-  double x, y;
-
-  event = gst_event_new (GST_EVENT_NAVIGATION);
-  event->event_data.structure.structure = structure;
-
-  /* We are not converting the pointer coordinates as there's no hardware 
-     scaling done here. The only possible scaling is done by videoscale and
-     videoscale will have to catch those events and tranform the coordinates
-     to match the applied scaling. So here we just add the offset if the image
-     is centered in the window.  */
-
-  x_offset = glimagesink->window->width - GST_VIDEOSINK_WIDTH (glimagesink);
-  y_offset = glimagesink->window->height - GST_VIDEOSINK_HEIGHT (glimagesink);
-
-  if (gst_structure_get_double (structure, "pointer_x", &x)) {
-    x += x_offset;
-    gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, x, NULL);
-  }
-  if (gst_structure_get_double (structure, "pointer_y", &y)) {
-    y += y_offset;
-    gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, y, NULL);
-  }
-
-  gst_pad_send_event (gst_pad_get_peer (GST_VIDEOSINK_PAD (glimagesink)),
-      event);
-}
+  int texture_size;
+  XWindowAttributes attr;
 
-static void
-gst_glimagesink_navigation_init (GstNavigationInterface * iface)
-{
-  iface->send_event = gst_glimagesink_navigation_send_event;
-}
+  g_return_if_fail (buf != NULL);
 
-static void
-gst_glimagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
-{
-  GstGLImageSink *glimagesink = GST_GLIMAGESINK (overlay);
-  GstGLWindow *xwindow = NULL;
-  XWindowAttributes attr;
+  if (glimage_sink->display == NULL || glimage_sink->window == 0) {
+    g_warning ("display or window not set up\n");
+  }
 
-  printf ("set_xwindow_id\n");
+  glXMakeCurrent (glimage_sink->display, glimage_sink->window,
+      glimage_sink->context);
 
-  g_return_if_fail (GST_IS_GLIMAGESINK (glimagesink));
+  if (glimage_sink->parent_window) {
+    XGetWindowAttributes (glimage_sink->display, glimage_sink->parent_window,
+        &attr);
+    //gst_glimage_sink_set_window_size (glimage_sink, attr.width, attr.height);
+  } else {
+    XGetWindowAttributes (glimage_sink->display, glimage_sink->window, &attr);
+    glViewport (0, 0, attr.width, attr.height);
+  }
 
-  /* If we already use that window return */
-  if (glimagesink->window && (xwindow_id == glimagesink->window->win))
-    return;
+  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
-  /* If the element has not initialized the X11 context try to do so */
-  if (!glimagesink->xcontext)
-    glimagesink->xcontext = gst_glimagesink_xcontext_get (glimagesink);
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
 
-  if (!glimagesink->xcontext) {
-    g_warning ("glimagesink was unable to obtain the X11 context.");
-    return;
-  }
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
 
-  /* Clear image pool as the images are unusable anyway */
-  gst_glimagesink_imagepool_clear (glimagesink);
+  glDisable (GL_CULL_FACE);
+  glEnable (GL_TEXTURE_2D);
+  glEnableClientState (GL_TEXTURE_COORD_ARRAY);
 
-  /* Clear the ximage */
-  if (glimagesink->glimage) {
-    gst_glimagesink_ximage_destroy (glimagesink, glimagesink->glimage);
-    glimagesink->glimage = NULL;
-  }
+  glColor4f (1, 1, 1, 1);
 
-  /* If a window is there already we destroy it */
-  if (glimagesink->window) {
-    gst_glimagesink_xwindow_destroy (glimagesink, glimagesink->window);
-    glimagesink->window = NULL;
-  }
+#define TEXID 1000
+  glBindTexture (GL_TEXTURE_2D, TEXID);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
-  /* If the xid is 0 we go back to an internal window */
-  if (xwindow_id == 0) {
-    /* If no width/height caps nego did not happen window will be created
-       during caps nego then */
-    if (GST_VIDEOSINK_WIDTH (glimagesink) && GST_VIDEOSINK_HEIGHT (glimagesink)) {
-      xwindow = gst_glimagesink_xwindow_new (glimagesink,
-          GST_VIDEOSINK_WIDTH (glimagesink),
-          GST_VIDEOSINK_HEIGHT (glimagesink));
+  for (texture_size = 64;
+      (texture_size < GST_VIDEO_SINK (glimage_sink)->width ||
+          texture_size < GST_VIDEO_SINK (glimage_sink)->height) &&
+      (texture_size > 0); texture_size <<= 1);
+
+  if (glimage_sink->use_rgb) {
+    glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, texture_size,
+        texture_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+    if (glimage_sink->use_rgbx) {
+      glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0,
+          GST_VIDEO_SINK (glimage_sink)->width,
+          GST_VIDEO_SINK (glimage_sink)->height,
+          GL_RGBA, GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
+    } else {
+      glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0,
+          GST_VIDEO_SINK (glimage_sink)->width,
+          GST_VIDEO_SINK (glimage_sink)->height,
+          GL_BGRA, GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
     }
   } else {
-    GST_ELEMENT_ERROR (glimagesink, RESOURCE, TOO_LAZY, (NULL),
-        ("glimagesink is incapable of connecting to other X windows !"));
-    exit (100);
-
-    xwindow = g_new0 (GstGLWindow, 1);
-
-    xwindow->win = xwindow_id;
-
-    /* We get window geometry, set the event we want to receive,
-       and create a GC */
-    g_mutex_lock (glimagesink->x_lock);
-    XGetWindowAttributes (glimagesink->xcontext->disp, xwindow->win, &attr);
-    xwindow->width = attr.width;
-    xwindow->height = attr.height;
-    xwindow->internal = FALSE;
-    XSelectInput (glimagesink->xcontext->disp, xwindow->win, ExposureMask |
-        StructureNotifyMask | PointerMotionMask | KeyPressMask |
-        KeyReleaseMask);
-
-    //xwindow->gc = XCreateGC (glimagesink->xcontext->disp, xwindow->win, 0, NULL);
-    g_mutex_unlock (glimagesink->x_lock);
-
-    /* If that new window geometry differs from our one we try to 
-       renegotiate caps */
-    if (gst_pad_is_negotiated (GST_VIDEOSINK_PAD (glimagesink)) &&
-        (xwindow->width != GST_VIDEOSINK_WIDTH (glimagesink) ||
-            xwindow->height != GST_VIDEOSINK_HEIGHT (glimagesink))) {
-      GstPadLinkReturn r;
-
-      r = gst_pad_try_set_caps (GST_VIDEOSINK_PAD (glimagesink),
-          gst_caps_new_simple ("video/x-raw-rgb",
-              "bpp", G_TYPE_INT, glimagesink->xcontext->bpp,
-              "depth", G_TYPE_INT, glimagesink->xcontext->depth,
-              "endianness", G_TYPE_INT, glimagesink->xcontext->endianness,
-              "red_mask", G_TYPE_INT, glimagesink->xcontext->visual->red_mask,
-              "green_mask", G_TYPE_INT,
-              glimagesink->xcontext->visual->green_mask, "blue_mask",
-              G_TYPE_INT, glimagesink->xcontext->visual->blue_mask, "width",
-              G_TYPE_INT, xwindow->width, "height", G_TYPE_INT, xwindow->height,
-              "framerate", G_TYPE_DOUBLE, glimagesink->framerate, NULL));
-
-      /* If caps nego succeded updating our size */
-      if ((r == GST_PAD_LINK_OK) || (r == GST_PAD_LINK_DONE)) {
-        GST_VIDEOSINK_WIDTH (glimagesink) = xwindow->width;
-        GST_VIDEOSINK_HEIGHT (glimagesink) = xwindow->height;
-      }
+#ifdef GL_YCBCR_MESA
+    glTexImage2D (GL_TEXTURE_2D, 0, GL_YCBCR_MESA, texture_size,
+        texture_size, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, NULL);
+
+    if (glimage_sink->use_yuy2) {
+      glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0,
+          GST_VIDEO_SINK (glimage_sink)->width,
+          GST_VIDEO_SINK (glimage_sink)->height,
+          GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, GST_BUFFER_DATA (buf));
+    } else {
+      glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0,
+          GST_VIDEO_SINK (glimage_sink)->width,
+          GST_VIDEO_SINK (glimage_sink)->height,
+          GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, GST_BUFFER_DATA (buf));
     }
+#else
+    g_assert_not_reached ();
+#endif
   }
 
-  /* Recreating our ximage */
-  if (!glimagesink->glimage &&
-      GST_VIDEOSINK_WIDTH (glimagesink) && GST_VIDEOSINK_HEIGHT (glimagesink)) {
-    glimagesink->glimage = gst_glimagesink_ximage_new (glimagesink,
-        GST_VIDEOSINK_WIDTH (glimagesink), GST_VIDEOSINK_HEIGHT (glimagesink));
-  }
-
-  if (xwindow)
-    glimagesink->window = xwindow;
-}
-
-static void
-gst_glimagesink_get_desired_size (GstXOverlay * overlay,
-    guint * width, guint * height)
-{
-  GstGLImageSink *glimagesink = GST_GLIMAGESINK (overlay);
-
-  *width = GST_VIDEOSINK_WIDTH (glimagesink);
-  *height = GST_VIDEOSINK_HEIGHT (glimagesink);
-}
-
-static void
-gst_glimagesink_expose (GstXOverlay * overlay)
-{
-  GstGLImageSink *glimagesink = GST_GLIMAGESINK (overlay);
-
-  if (!glimagesink->window)
-    return;
+  glColor4f (1, 0, 1, 1);
+  glBegin (GL_QUADS);
 
-  gst_glimagesink_xwindow_update_geometry (glimagesink, glimagesink->window);
+  glNormal3f (0, 0, -1);
 
-  /* We don't act on internal window from outside that could cause some thread
-     race with the video sink own thread checking for configure event */
-  if (glimagesink->window->internal)
-    return;
+  {
+    double xmax = GST_VIDEO_SINK (glimage_sink)->width / (double) texture_size;
+    double ymax = GST_VIDEO_SINK (glimage_sink)->height / (double) texture_size;
 
-  //gst_glimagesink_xwindow_clear (glimagesink, glimagesink->window);
+    glTexCoord2f (xmax, 0);
+    glVertex3f (1.0, 1.0, 0);
+    glTexCoord2f (0, 0);
+    glVertex3f (-1.0, 1.0, 0);
+    glTexCoord2f (0, ymax);
+    glVertex3f (-1.0, -1.0, 0);
+    glTexCoord2f (xmax, ymax);
+    glVertex3f (1.0, -1.0, 0);
+    glEnd ();
+  }
 
-  if (glimagesink->cur_image)
-    gst_glimagesink_ximage_put (glimagesink, glimagesink->cur_image);
+  glFlush ();
+  glXSwapBuffers (glimage_sink->display, glimage_sink->window);
 }
 
-static void
-gst_glimagesink_xoverlay_init (GstXOverlayClass * iface)
-{
-  iface->set_xwindow_id = gst_glimagesink_set_xwindow_id;
-  iface->get_desired_size = gst_glimagesink_get_desired_size;
-  iface->expose = gst_glimagesink_expose;
-}
 
-/* =========================================== */
-/*                                             */
-/*              Init & Class init              */
-/*                                             */
-/* =========================================== */
+#ifdef unused
 
-static void
-gst_glimagesink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstGLImageSink *glimagesink;
 
-  g_return_if_fail (GST_IS_GLIMAGESINK (object));
+static void gst_glimage_sink_set_window_size (GstGLImageSink * glimage_sink,
+    int width, int height);
 
-  glimagesink = GST_GLIMAGESINK (object);
 
-  switch (prop_id) {
-    case ARG_DISPLAY:
-      glimagesink->display_name = g_strdup (g_value_get_string (value));
-      break;
-    case ARG_SYNCHRONOUS:
-      glimagesink->synchronous = g_value_get_boolean (value);
-      if (glimagesink->xcontext) {
-        XSynchronize (glimagesink->xcontext->disp, glimagesink->synchronous);
-    case ARG_SIGNAL_HANDOFFS:
-        glimagesink->signal_handoffs = g_value_get_boolean (value);
-        break;
-      }
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
 
 static void
-gst_glimagesink_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
+gst_glimage_sink_set_window_size (GstGLImageSink * glimage_sink,
+    int width, int height)
 {
-  GstGLImageSink *glimagesink;
-
-  g_return_if_fail (GST_IS_GLIMAGESINK (object));
-
-  glimagesink = GST_GLIMAGESINK (object);
+  GST_DEBUG ("resizing to %d x %d",
+      GST_VIDEO_SINK_WIDTH (glimage_sink),
+      GST_VIDEO_SINK_HEIGHT (glimage_sink));
 
-  switch (prop_id) {
-    case ARG_DISPLAY:
-      g_value_set_string (value, g_strdup (glimagesink->display_name));
-      break;
-    case ARG_SYNCHRONOUS:
-      g_value_set_boolean (value, glimagesink->synchronous);
-      break;
-    case ARG_SIGNAL_HANDOFFS:
-      g_value_set_boolean (value, glimagesink->signal_handoffs);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
+  if (glimage_sink->display && glimage_sink->window) {
+    XResizeWindow (glimage_sink->display, glimage_sink->window, width, height);
+    XSync (glimage_sink->display, False);
+    glViewport (0, 0, width, height);
   }
 }
 
-static void
-gst_glimagesink_finalize (GObject * object)
-{
-  GstGLImageSink *glimagesink;
-
-  glimagesink = GST_GLIMAGESINK (object);
-
-  if (glimagesink->display_name) {
-    g_free (glimagesink->display_name);
-    glimagesink->display_name = NULL;
-  }
 
-  g_mutex_free (glimagesink->x_lock);
-  g_mutex_free (glimagesink->pool_lock);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
 
 static void
-gst_glimagesink_init (GstGLImageSink * glimagesink)
+gst_glimage_sink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
 {
-  GST_VIDEOSINK_PAD (glimagesink) =
-      gst_pad_new_from_template (gst_static_pad_template_get
-      (&gst_glimagesink_sink_template_factory), "sink");
-
-  gst_element_add_pad (GST_ELEMENT (glimagesink),
-      GST_VIDEOSINK_PAD (glimagesink));
-
-  gst_pad_set_chain_function (GST_VIDEOSINK_PAD (glimagesink),
-      gst_glimagesink_chain);
-  gst_pad_set_link_function (GST_VIDEOSINK_PAD (glimagesink),
-      gst_glimagesink_sink_link);
-  gst_pad_set_getcaps_function (GST_VIDEOSINK_PAD (glimagesink),
-      gst_glimagesink_getcaps);
-  gst_pad_set_fixate_function (GST_VIDEOSINK_PAD (glimagesink),
-      gst_glimagesink_fixate);
-  gst_pad_set_bufferalloc_function (GST_VIDEOSINK_PAD (glimagesink),
-      gst_glimagesink_buffer_alloc);
+  GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (overlay);
 
-  glimagesink->display_name = NULL;
-  glimagesink->xcontext = NULL;
-  glimagesink->window = NULL;
-  glimagesink->glimage = NULL;
-  glimagesink->cur_image = NULL;
+  GST_DEBUG ("set_xwindow_id %ld", xwindow_id);
 
-  glimagesink->framerate = 0;
+  g_return_if_fail (GST_IS_GLIMAGE_SINK (glimage_sink));
 
-  glimagesink->x_lock = g_mutex_new ();
-
-  glimagesink->pixel_width = glimagesink->pixel_height = 1;
-
-  glimagesink->image_pool = NULL;
-  glimagesink->pool_lock = g_mutex_new ();
-
-  glimagesink->synchronous = FALSE;
-  glimagesink->signal_handoffs = FALSE;
-
-  GST_OBJECT_FLAG_SET (glimagesink, GST_ELEMENT_THREAD_SUGGESTED);
-  GST_OBJECT_FLAG_SET (glimagesink, GST_ELEMENT_EVENT_AWARE);
-}
+  /* If the element has not initialized the X11 context try to do so */
+  if (!glimage_sink->display) {
+    g_warning ("X display not inited\n");
+  }
 
-static void
-gst_glimagesink_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+  if (glimage_sink->parent_window == xwindow_id)
+    return;
 
-  gst_element_class_set_details (element_class, &gst_glimagesink_details);
+  glimage_sink->parent_window = xwindow_id;
 
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_glimagesink_sink_template_factory));
+  XSync (glimage_sink->display, False);
+  gst_glimage_sink_create_window (glimage_sink);
 }
 
-static void
-gst_glimagesink_class_init (GstGLImageSinkClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-
-  parent_class = g_type_class_ref (GST_TYPE_VIDEOSINK);
-
-  g_object_class_install_property (gobject_class, ARG_DISPLAY,
-      g_param_spec_string ("display", "Display", "X Display name",
-          NULL, G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_SYNCHRONOUS,
-      g_param_spec_boolean ("synchronous", "Synchronous", "When enabled, runs "
-          "the X display in synchronous mode. (used only for debugging)", FALSE,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, ARG_SIGNAL_HANDOFFS,
-      g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
-          "Send a signal before unreffing the buffer, forces YUV, no GL output",
-          FALSE, G_PARAM_READWRITE));
-#if 0                           // needed ?
-  g_object_class_install_property (gobject_class, ARG_SIGNAL_BUFFER_ALLOC,
-      g_param_spec_boolean ("signal-bufferalloc", "Signal buffer allocation",
-          "Asks the application for a buffer allocation", FALSE,
-          G_PARAM_READWRITE));
 #endif
 
-  gst_glimagesink_signals[SIGNAL_HANDOFF] =
-      g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstGLImageSinkClass, handoff), NULL, NULL,
-      gst_marshal_VOID__POINTER_OBJECT, G_TYPE_NONE, 2,
-      GST_TYPE_BUFFER, GST_TYPE_PAD);
-  gst_glimagesink_signals[SIGNAL_BUFALLOC] =
-      g_signal_new ("bufferalloc", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstGLImageSinkClass, bufferalloc), NULL, NULL,
-      gst_marshal_VOID__POINTER_OBJECT, G_TYPE_NONE, 2,
-      GST_TYPE_BUFFER, GST_TYPE_PAD);
-
-  gobject_class->finalize = gst_glimagesink_finalize;
-  gobject_class->set_property = gst_glimagesink_set_property;
-  gobject_class->get_property = gst_glimagesink_get_property;
-
-  gstelement_class->change_state = gst_glimagesink_change_state;
-}
-
-/* ============================================================= */
-/*                                                               */
-/*                       Public Methods                          */
-/*                                                               */
-/* ============================================================= */
-
-/* =========================================== */
-/*                                             */
-/*          Object typing & Creation           */
-/*                                             */
-/* =========================================== */
-
-GType
-gst_glimagesink_get_type (void)
-{
-  static GType glimagesink_type = 0;
-
-  if (!glimagesink_type) {
-    static const GTypeInfo glimagesink_info = {
-      sizeof (GstGLImageSinkClass),
-      gst_glimagesink_base_init,
-      NULL,
-      (GClassInitFunc) gst_glimagesink_class_init,
-      NULL,
-      NULL,
-      sizeof (GstGLImageSink),
-      0,
-      (GInstanceInitFunc) gst_glimagesink_init,
-    };
-    static const GInterfaceInfo iface_info = {
-      (GInterfaceInitFunc) gst_glimagesink_interface_init,
-      NULL,
-      NULL,
-    };
-    static const GInterfaceInfo navigation_info = {
-      (GInterfaceInitFunc) gst_glimagesink_navigation_init,
-      NULL,
-      NULL,
-    };
-    static const GInterfaceInfo overlay_info = {
-      (GInterfaceInitFunc) gst_glimagesink_xoverlay_init,
-      NULL,
-      NULL,
-    };
-
-    glimagesink_type = g_type_register_static (GST_TYPE_VIDEOSINK,
-        "GstGLImageSink", &glimagesink_info, 0);
-
-    g_type_add_interface_static (glimagesink_type,
-        GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
-    g_type_add_interface_static (glimagesink_type, GST_TYPE_NAVIGATION,
-        &navigation_info);
-    g_type_add_interface_static (glimagesink_type, GST_TYPE_X_OVERLAY,
-        &overlay_info);
-  }
-
-  return glimagesink_type;
-}
-
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-  /* Loading the library containing GstVideoSink, our parent object */
-  if (!gst_library_load ("gstvideo"))
-    return FALSE;
-
   if (!gst_element_register (plugin, "glimagesink",
-          GST_RANK_SECONDARY, GST_TYPE_GLIMAGESINK))
+          GST_RANK_SECONDARY, GST_TYPE_GLIMAGE_SINK))
     return FALSE;
 
-  GST_DEBUG_CATEGORY_INIT (gst_debug_glimagesink, "glimagesink", 0,
+  GST_DEBUG_CATEGORY_INIT (gst_debug_glimage_sink, "glimagesink", 0,
       "glimagesink element");
 
   return TRUE;
@@ -1606,5 +809,5 @@ plugin_init (GstPlugin * plugin)
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     GST_VERSION_MINOR,
     "glimagesink",
-    "OpenGL video output plugin based on OpenGL 1.2 calls",
+    "OpenGL video output plugin",
     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
diff --git a/gst/gl/glimagesink.h b/gst/gl/glimagesink.h
deleted file mode 100644 (file)
index 15e866d..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/* GStreamer
- * Copyright (C) <2003> Julien Moutte <julien@moutte.net>
- *
- * 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_GLIMAGESINK_H__
-#define __GST_GLIMAGESINK_H__
-
-#include <gst/video/videosink.h>
-
-#include <X11/Xlib.h>
-#include <GL/glx.h>
-#include <GL/gl.h>
-#include <GL/glu.h>
-
-#include <string.h>
-#include <math.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GLIMAGESINK \
-  (gst_glimagesink_get_type())
-#define GST_GLIMAGESINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_GLIMAGESINK, GstGLImageSink))
-#define GST_GLIMAGESINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_GLIMAGESINK, GstGLImageSink))
-#define GST_IS_GLIMAGESINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_GLIMAGESINK))
-#define GST_IS_GLIMAGESINK_CLASS(obj) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_GLIMAGESINK))
-
-typedef struct _GstXContext GstXContext;
-typedef struct _GstGLWindow GstGLWindow;
-typedef struct _GstGLImage GstGLImage;
-
-typedef struct _GstGLImageSink GstGLImageSink;
-typedef struct _GstGLImageSinkClass GstGLImageSinkClass;
-
-/* Global X Context stuff */
-struct _GstXContext {
-  Display *disp;
-  
-  Screen *screen;
-  gint screen_num;
-  
-  Visual *visual;
-  XVisualInfo *visualinfo;
-  
-  Window root;
-  GLXContext glx;
-  
-  gulong white, black;
-  
-  gint depth;
-  gint bpp;
-  gint endianness;
-  
-  gboolean use_xshm;
-  
-  GstCaps *caps;
-};
-
-/* XWindow stuff */
-struct _GstGLWindow {
-  XSetWindowAttributes attr;
-  Window win;
-  gint width, height;
-  gboolean internal;
-};
-
-/* XImage stuff */
-struct _GstGLImage {
-  /* Reference to the ximagesink we belong to */
-  GstGLImageSink *glimagesink;
-  
-  GLuint texid; 
-  
-  char *data;
-  gint width, height, size;
-};
-
-struct _GstGLImageSink {
-  /* Our element stuff */
-  GstVideoSink videosink;
-
-  char *display_name;
-  
-  GstXContext *xcontext;
-  GstGLWindow *window;
-  GstGLImage *glimage;
-  GstGLImage *cur_image;
-  
-  gdouble framerate;
-  GMutex *x_lock;
-  
-  gint pixel_width, pixel_height;  /* Unused */
-  GstClockTime time;
-  
-  GMutex *pool_lock;
-  GSList *image_pool;
-
-  guint pointer_x, pointer_y;
-  gboolean pointer_moved;
-  gboolean pointer_button[5];
-
-  gboolean synchronous;
-  gboolean signal_handoffs;  
-};
-
-struct _GstGLImageSinkClass {
-  GstVideoSinkClass parent_class;
-
-  /* signals */
-  void (*handoff) (GstElement *element, GstBuffer *buf, GstPad *pad);
-  void (*bufferalloc) (GstElement *element, GstBuffer *buf, GstPad *pad);
-};
-
-GType gst_glimagesink_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_GLIMAGESINK_H__ */