ext/ffmpeg/gstffmpegcolorspace.c: Implementing gst_pad_alloc_buffer to use optimized...
authorJulien Moutte <julien@moutte.net>
Fri, 9 Jan 2004 18:05:57 +0000 (18:05 +0000)
committerJulien Moutte <julien@moutte.net>
Fri, 9 Jan 2004 18:05:57 +0000 (18:05 +0000)
Original commit message from CVS:
* ext/ffmpeg/gstffmpegcolorspace.c: (gst_ffmpegcsp_chain):
Implementing gst_pad_alloc_buffer to use optimized buffer allocation.
* gst-libs/gst/xoverlay/xoverlay.c:
(gst_x_overlay_got_desired_size): Updating doc for the xid being 0.
* gst/videoscale/gstvideoscale.c: (gst_videoscale_chain):
Implementing gst_pad_alloc_buffer to use optimized buffer allocation.
* gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_get):
Implementing gst_pad_alloc_buffer to use optimized buffer allocation.
* sys/ximage/ximagesink.c: (gst_ximagesink_chain),
(gst_ximagesink_buffer_free), (gst_ximagesink_buffer_alloc),
(gst_ximagesink_set_xwindow_id), (gst_ximagesink_init): Implementing
the bufferalloc_function to replace bufferpools, fixing the XOverlay
interface implementation to handle xid being 0 and fix some bugs
triggered by Benjamin's testcase.
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_chain),
(gst_xvimagesink_buffer_free), (gst_xvimagesink_buffer_alloc),
(gst_xvimagesink_set_xwindow_id), (gst_xvimagesink_init): Implementing
the bufferalloc_function to replace bufferpools, fixing the XOverlay
interface implementation to handle xid being 0 and fix some bugs
triggered by Benjamin's testcase.

ChangeLog
gst-libs/gst/interfaces/xoverlay.c
gst-libs/gst/xoverlay/xoverlay.c
gst/videoscale/gstvideoscale.c
gst/videotestsrc/gstvideotestsrc.c
sys/ximage/ximagesink.c
sys/xvimage/xvimagesink.c

index 295162b..b30c972 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2004-01-09  Julien MOUTTE <julien@moutte.net>
+
+       * ext/ffmpeg/gstffmpegcolorspace.c: (gst_ffmpegcsp_chain):
+       Implementing gst_pad_alloc_buffer to use optimized buffer allocation.
+       * gst-libs/gst/xoverlay/xoverlay.c:
+       (gst_x_overlay_got_desired_size): Updating doc for the xid being 0.
+       * gst/videoscale/gstvideoscale.c: (gst_videoscale_chain):
+       Implementing gst_pad_alloc_buffer to use optimized buffer allocation.
+       * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_get):
+       Implementing gst_pad_alloc_buffer to use optimized buffer allocation.
+       * sys/ximage/ximagesink.c: (gst_ximagesink_chain),
+       (gst_ximagesink_buffer_free), (gst_ximagesink_buffer_alloc),
+       (gst_ximagesink_set_xwindow_id), (gst_ximagesink_init): Implementing
+       the bufferalloc_function to replace bufferpools, fixing the XOverlay
+       interface implementation to handle xid being 0 and fix some bugs
+       triggered by Benjamin's testcase.
+       * sys/xvimage/xvimagesink.c: (gst_xvimagesink_chain),
+       (gst_xvimagesink_buffer_free), (gst_xvimagesink_buffer_alloc),
+       (gst_xvimagesink_set_xwindow_id), (gst_xvimagesink_init): Implementing
+       the bufferalloc_function to replace bufferpools, fixing the XOverlay
+       interface implementation to handle xid being 0 and fix some bugs
+       triggered by Benjamin's testcase.
+
 2004-01-09  David Schleef  <ds@schleef.org>
 
        * ext/librfb/gstrfbsrc.c:  Hacking.  Added actual decoding and
@@ -39,7 +62,7 @@
        * gst/videodrop/gstvideodrop.c: (gst_videodrop_getcaps),
        (gst_videodrop_link), (gst_videodrop_init): Fix negotiation.
 
-2004-01-08  Julien MOUTTE,,,  <julien@moutte.net>
+2004-01-08  Julien MOUTTE  <julien@moutte.net>
 
        * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xevents): A
        configure event is not emiting the desired size signal. That fixes
 
        * gst/modplug/gstmodplug.cc: fix element description
 
-2004-01-07  Julien MOUTTE,,,  <julien@moutte.net>
+2004-01-07  Julien MOUTTE  <julien@moutte.net>
 
        * examples/gstplay/player.c: (got_time_tick), (got_stream_length),
        (got_video_size): Adding some new lines in g_print calls.
index c0bbcec..2efe296 100644 (file)
@@ -103,7 +103,8 @@ gst_x_overlay_base_init (gpointer g_class)
  *
  * This will call the video overlay's set_xwindow_id method. You should
  * use this method to tell to a XOverlay to display video output to a
- * specific XWindow.
+ * specific XWindow. Passing 0 as the xwindow_id will tell the overlay to
+ * stop using that window and create an internal one.
  */
 void
 gst_x_overlay_set_xwindow_id (GstXOverlay *overlay, XID xwindow_id)
@@ -182,4 +183,3 @@ gst_x_overlay_got_desired_size (GstXOverlay *overlay, guint width, guint height)
   g_signal_emit (G_OBJECT (overlay),
                  gst_x_overlay_signals[DESIRED_SIZE], 0, width, height);
 }
-
index c0bbcec..2efe296 100644 (file)
@@ -103,7 +103,8 @@ gst_x_overlay_base_init (gpointer g_class)
  *
  * This will call the video overlay's set_xwindow_id method. You should
  * use this method to tell to a XOverlay to display video output to a
- * specific XWindow.
+ * specific XWindow. Passing 0 as the xwindow_id will tell the overlay to
+ * stop using that window and create an internal one.
  */
 void
 gst_x_overlay_set_xwindow_id (GstXOverlay *overlay, XID xwindow_id)
@@ -182,4 +183,3 @@ gst_x_overlay_got_desired_size (GstXOverlay *overlay, guint width, guint height)
   g_signal_emit (G_OBJECT (overlay),
                  gst_x_overlay_signals[DESIRED_SIZE], 0, width, height);
 }
-
index fece73c..69409a4 100644 (file)
@@ -370,9 +370,11 @@ gst_videoscale_chain (GstPad *pad, GstData *_data)
   g_return_if_fail (size == videoscale->from_buf_size);
 
   outbuf = gst_buffer_new();
-  /* FIXME: handle bufferpools */
-  GST_BUFFER_SIZE(outbuf) = videoscale->to_buf_size;
-  GST_BUFFER_DATA(outbuf) = g_malloc (videoscale->to_buf_size);
+  outbuf = gst_pad_alloc_buffer (gst_pad_get_peer (pad),
+                                 GST_BUFFER_OFFSET_NONE, videoscale->to_buf_size);
+  
+  /*GST_BUFFER_SIZE(outbuf) = videoscale->to_buf_size;*/
+  /*GST_BUFFER_DATA(outbuf) = g_malloc (videoscale->to_buf_size);*/
   GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf);
 
   g_return_if_fail(videoscale->format);
index 6cb8939..e782086 100644 (file)
@@ -418,7 +418,7 @@ gst_videotestsrc_get (GstPad * pad)
 
   GST_DEBUG ("size=%ld %dx%d", newsize, videotestsrc->width, videotestsrc->height);
 
-  buf = gst_buffer_new_and_alloc (newsize);
+  buf = gst_pad_alloc_buffer (pad, GST_BUFFER_OFFSET_NONE, newsize);
   g_return_val_if_fail (GST_BUFFER_DATA (buf) != NULL, NULL);
 
   videotestsrc->make_image (videotestsrc, (void *) GST_BUFFER_DATA (buf),
index 3a7ff12..fda9c89 100644 (file)
@@ -736,14 +736,14 @@ gst_ximagesink_chain (GstPad *pad, GstData *data)
     gst_clock_id_free (id);
   }
   
-#if 0
-  /* If we have a pool and the image is from this pool, simply put it. */
-  if ( (ximagesink->bufferpool) &&
-       (GST_BUFFER_BUFFERPOOL (buf) == ximagesink->bufferpool) )
-    gst_ximagesink_ximage_put (ximagesink, GST_BUFFER_POOL_PRIVATE (buf));
+  /* If this buffer has been allocated using our buffer management we simply
+     put the ximage which is in the PRIVATE pointer */
+  if (GST_BUFFER_BUFFERPOOL (buf) == ximagesink)
+    {
+      gst_ximagesink_ximage_put (ximagesink, GST_BUFFER_POOL_PRIVATE (buf));
+    }
   else /* Else we have to copy the data into our private image, */
     {  /* if we have one... */
-#endif
       if (ximagesink->ximage)
         {
           memcpy (ximagesink->ximage->ximage->data, 
@@ -757,9 +757,8 @@ gst_ximagesink_chain (GstPad *pad, GstData *data)
           gst_element_error (GST_ELEMENT (ximagesink), "no image to draw");
           return;
         }
-#if 0
     }
-#endif
+
   /* set correct time for next buffer */
   if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf) && ximagesink->framerate > 0) {
     ximagesink->time += GST_SECOND / ximagesink->framerate;
@@ -770,18 +769,45 @@ gst_ximagesink_chain (GstPad *pad, GstData *data)
   gst_ximagesink_handle_xevents (ximagesink, pad);
 }
 
-#if 0
-static GstBuffer*
-gst_ximagesink_buffer_new (GstBufferPool *pool,  
-                           gint64 location, guint size, gpointer user_data)
+/* Buffer management */
+
+static void
+gst_ximagesink_buffer_free (GstData *data)
+{
+  GstXImageSink *ximagesink;
+  GstXImage *ximage;
+  GstBuffer *buffer;
+  
+  ximagesink = GST_BUFFER_BUFFERPOOL (data);
+  ximage = GST_BUFFER_POOL_PRIVATE (data);
+  buffer = GST_BUFFER (data);
+  
+  /* If our geometry changed we can't reuse that image. */
+  if ( (ximage->width != GST_VIDEOSINK_WIDTH (ximagesink)) ||
+       (ximage->height != GST_VIDEOSINK_HEIGHT (ximagesink)) )
+    gst_ximagesink_ximage_destroy (ximagesink, ximage);
+  else /* In that case we can reuse the image and add it to our image pool. */
+    {
+      g_mutex_lock (ximagesink->pool_lock);
+      ximagesink->image_pool = g_slist_prepend (ximagesink->image_pool, ximage);
+      g_mutex_unlock (ximagesink->pool_lock);
+    }
+    
+  GST_BUFFER_DATA (buffer) = NULL;
+
+  gst_buffer_default_free (buffer);
+}
+
+static GstBuffer *
+gst_ximagesink_buffer_alloc (GstPad *pad, guint64 offset, guint size)
 {
   GstXImageSink *ximagesink;
   GstBuffer *buffer;
   GstXImage *ximage = NULL;
   gboolean not_found = TRUE;
   
-  ximagesink = GST_XIMAGESINK (user_data);
-  
+  ximagesink = GST_XIMAGESINK (gst_pad_get_parent (pad));
+
   g_mutex_lock (ximagesink->pool_lock);
   
   /* Walking through the pool cleaning unsuable images and searching for a
@@ -803,22 +829,31 @@ gst_ximagesink_buffer_new (GstBufferPool *pool,
               ximage = NULL;
             }
           else /* We found a suitable image */
-            break;
+            {
+              break;
+            }
         }
     }
    
   g_mutex_unlock (ximagesink->pool_lock);
   
   if (!ximage) /* We found no suitable image in the pool. Creating... */
-    ximage = gst_ximagesink_ximage_new (ximagesink,
-                                        GST_VIDEOSINK_WIDTH (ximagesink),
-                                        GST_VIDEOSINK_HEIGHT (ximagesink));
+    {
+      ximage = gst_ximagesink_ximage_new (ximagesink,
+                                          GST_VIDEOSINK_WIDTH (ximagesink),
+                                          GST_VIDEOSINK_HEIGHT (ximagesink));
+    }
   
   if (ximage)
     {
       buffer = gst_buffer_new ();
+      
+      /* Storing some pointers in the buffer (bit hackish) */
+      GST_BUFFER_BUFFERPOOL (buffer) = ximagesink;
       GST_BUFFER_POOL_PRIVATE (buffer) = ximage;
+      
       GST_BUFFER_DATA (buffer) = ximage->ximage->data;
+      GST_DATA_FREE_FUNC (buffer) = gst_ximagesink_buffer_free;
       GST_BUFFER_SIZE (buffer) = ximage->size;
       return buffer;
     }
@@ -827,34 +862,6 @@ gst_ximagesink_buffer_new (GstBufferPool *pool,
 }
 
 static void
-gst_ximagesink_buffer_free (GstBufferPool *pool,
-                            GstBuffer *buffer, gpointer user_data)
-{
-  GstXImageSink *ximagesink;
-  GstXImage *ximage;
-  
-  ximagesink = GST_XIMAGESINK (user_data);
-  
-  ximage = GST_BUFFER_POOL_PRIVATE (buffer);
-  
-  /* If our geometry changed we can't reuse that image. */
-  if ( (ximage->width != GST_VIDEOSINK_WIDTH (ximagesink)) ||
-       (ximage->height != GST_VIDEOSINK_HEIGHT (ximagesink)) )
-    gst_ximagesink_ximage_destroy (ximagesink, ximage);
-  else /* In that case we can reuse the image and add it to our image pool. */
-    {
-      g_mutex_lock (ximagesink->pool_lock);
-      ximagesink->image_pool = g_slist_prepend (ximagesink->image_pool, ximage);
-      g_mutex_unlock (ximagesink->pool_lock);
-    }
-    
-  GST_BUFFER_DATA (buffer) = NULL;
-
-  gst_buffer_default_free (buffer);
-}
-#endif
-
-static void
 gst_ximagesink_imagepool_clear (GstXImageSink *ximagesink)
 {
   g_mutex_lock(ximagesink->pool_lock);
@@ -936,36 +943,112 @@ gst_ximagesink_set_xwindow_id (GstXOverlay *overlay, XID xwindow_id)
   g_return_if_fail (ximagesink != NULL);
   g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
   
+  /* If we already use that window return */
+  if (ximagesink->xwindow && (xwindow_id == ximagesink->xwindow->win))
+    return;
+  
+  /* If the element has not initialized the X11 context try to do so */
   if (!ximagesink->xcontext)
     ximagesink->xcontext = gst_ximagesink_xcontext_get (ximagesink);
   
-  if ( (ximagesink->xwindow) && (ximagesink->ximage) )
-    { /* If we are replacing a window we destroy pictures and window as they
-         are associated */
+  if (!ximagesink->xcontext)
+    {
+      g_warning ("ximagesink was unable to obtain the X11 context.");
+      return;
+    }
+    
+  /* Clear image pool as the images are unusable anyway */
+  gst_ximagesink_imagepool_clear (ximagesink);
+  
+  /* Clear the ximage */
+  if (ximagesink->ximage)
+    {
       gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage);
-      gst_ximagesink_imagepool_clear (ximagesink);
+      ximagesink->ximage = NULL;
+    }
+  
+  /* If a window is there already we destroy it */
+  if (ximagesink->xwindow)
+    {
       gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
+      ximagesink->xwindow = NULL;
     }
     
-  xwindow = g_new0 (GstXWindow, 1);
-  
-  xwindow->win = xwindow_id;
+  /* 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 (ximagesink) &&
+          GST_VIDEOSINK_HEIGHT (ximagesink))
+        {
+          xwindow = gst_ximagesink_xwindow_new (ximagesink,
+                                            GST_VIDEOSINK_WIDTH (ximagesink),
+                                            GST_VIDEOSINK_HEIGHT (ximagesink));
+        }
+    }
+  else
+    {
+      xwindow = g_new0 (GstXWindow, 1);
+
+      xwindow->win = xwindow_id;
   
-  /* We get window geometry, set the event we want to receive, and create a GC */
-  g_mutex_lock (ximagesink->x_lock);
-  XGetWindowAttributes (ximagesink->xcontext->disp, xwindow->win, &attr);
-  xwindow->width = attr.width;
-  xwindow->height = attr.height;
-  xwindow->internal = FALSE;
-  XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask |
-                StructureNotifyMask | PointerMotionMask | KeyPressMask |
-                KeyReleaseMask);
+      /* We get window geometry, set the event we want to receive,
+         and create a GC */
+      g_mutex_lock (ximagesink->x_lock);
+      XGetWindowAttributes (ximagesink->xcontext->disp, xwindow->win, &attr);
+      xwindow->width = attr.width;
+      xwindow->height = attr.height;
+      xwindow->internal = FALSE;
+      XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask |
+                    StructureNotifyMask | PointerMotionMask | KeyPressMask |
+                    KeyReleaseMask);
+  
+      xwindow->gc = XCreateGC (ximagesink->xcontext->disp,
+                               xwindow->win, 0, NULL);
+      g_mutex_unlock (ximagesink->x_lock);
+      
+      /* If that new window geometry differs from our one we try to 
+         renegotiate caps */
+      if (xwindow->width != GST_VIDEOSINK_WIDTH (ximagesink) ||
+          xwindow->height != GST_VIDEOSINK_HEIGHT (ximagesink))
+        {
+          GstPadLinkReturn r;
+          r = gst_pad_try_set_caps (GST_VIDEOSINK_PAD (ximagesink),
+                  gst_caps_new_simple ("video/x-raw-rgb",
+                   "bpp",        G_TYPE_INT, ximagesink->xcontext->bpp,
+                   "depth",      G_TYPE_INT, ximagesink->xcontext->depth,
+                   "endianness", G_TYPE_INT, ximagesink->xcontext->endianness,
+                   "red_mask",   G_TYPE_INT, ximagesink->xcontext->visual->red_mask,
+                   "green_mask", G_TYPE_INT, ximagesink->xcontext->visual->green_mask,
+                   "blue_mask",  G_TYPE_INT, ximagesink->xcontext->visual->blue_mask,
+                   "width",      G_TYPE_INT, xwindow->width & ~3,
+                   "height",     G_TYPE_INT, xwindow->height & ~3,
+                   "framerate",  G_TYPE_DOUBLE, ximagesink->framerate,
+                   NULL));
+          
+          /* If caps nego succeded updating our size */
+          if ( (r == GST_PAD_LINK_OK) || (r == GST_PAD_LINK_DONE) )
+            {
+              GST_VIDEOSINK_WIDTH (ximagesink) = xwindow->width & ~3;
+              GST_VIDEOSINK_HEIGHT (ximagesink) = xwindow->height & ~3;
+            }
+        }
+    }
   
-  xwindow->gc = XCreateGC (ximagesink->xcontext->disp,
-                           xwindow->win, 0, NULL);
-  g_mutex_unlock (ximagesink->x_lock);
+  /* Recreating our ximage */
+  if (!ximagesink->ximage &&
+      GST_VIDEOSINK_WIDTH (ximagesink) &&
+      GST_VIDEOSINK_HEIGHT (ximagesink))
+    {
+      ximagesink->ximage = gst_ximagesink_ximage_new (
+                                            ximagesink,
+                                            GST_VIDEOSINK_WIDTH (ximagesink),
+                                            GST_VIDEOSINK_HEIGHT (ximagesink));
+    }
     
-  ximagesink->xwindow = xwindow;
+  if (xwindow)
+    ximagesink->xwindow = xwindow;
 }
 
 static void
@@ -1040,7 +1123,9 @@ gst_ximagesink_init (GstXImageSink *ximagesink)
                                 gst_ximagesink_getcaps);
   gst_pad_set_fixate_function (GST_VIDEOSINK_PAD (ximagesink),
                                 gst_ximagesink_fixate);
-
+  gst_pad_set_bufferalloc_function (GST_VIDEOSINK_PAD (ximagesink),
+                                    gst_ximagesink_buffer_alloc);
+  
   ximagesink->xcontext = NULL;
   ximagesink->xwindow = NULL;
   ximagesink->ximage = NULL;
index 4fea262..13f5ae6 100644 (file)
@@ -896,14 +896,12 @@ gst_xvimagesink_chain (GstPad *pad, GstData *data)
     gst_clock_id_free (id);
   }
   
-#if 0
-  /* If we have a pool and the image is from this pool, simply put it. */
-  if ( (xvimagesink->bufferpool) &&
-       (GST_BUFFER_BUFFERPOOL (buf) == xvimagesink->bufferpool) )
+  /* If this buffer has been allocated using our buffer management we simply
+     put the ximage which is in the PRIVATE pointer */
+  if (GST_BUFFER_BUFFERPOOL (buf) == xvimagesink)
     gst_xvimagesink_xvimage_put (xvimagesink, GST_BUFFER_POOL_PRIVATE (buf));
   else /* Else we have to copy the data into our private image, */
     {  /* if we have one... */
-#endif
       if (xvimagesink->xvimage)
         {
           memcpy (xvimagesink->xvimage->xvimage->data, 
@@ -917,9 +915,8 @@ gst_xvimagesink_chain (GstPad *pad, GstData *data)
           gst_element_error (GST_ELEMENT (xvimagesink), "no image to draw");
           return;
         }
-#if 0
     }
-#endif
+
   /* set correct time for next buffer */
   if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf) && xvimagesink->framerate > 0) {
     xvimagesink->time += GST_SECOND / xvimagesink->framerate;
@@ -930,18 +927,46 @@ gst_xvimagesink_chain (GstPad *pad, GstData *data)
   gst_xvimagesink_handle_xevents (xvimagesink, pad);
 }
 
-#if 0
-static GstBuffer*
-gst_xvimagesink_buffer_new (GstBufferPool *pool,  
-                            gint64 location, guint size, gpointer user_data)
+/* Buffer management */
+
+static void
+gst_xvimagesink_buffer_free (GstData *data)
+{
+  GstXvImageSink *xvimagesink;
+  GstXvImage *xvimage;
+  GstBuffer *buffer;
+  
+  xvimagesink = GST_BUFFER_BUFFERPOOL (data);
+  xvimage = GST_BUFFER_POOL_PRIVATE (data);
+  buffer = GST_BUFFER (data);
+  
+  /* If our geometry changed we can't reuse that image. */
+  if ( (xvimage->width != GST_VIDEOSINK_WIDTH (xvimagesink)) ||
+       (xvimage->height != GST_VIDEOSINK_HEIGHT (xvimagesink)) )
+    gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage);
+  else /* In that case we can reuse the image and add it to our image pool. */
+    {
+      g_mutex_lock (xvimagesink->pool_lock);
+      xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool,
+                                                 xvimage);
+      g_mutex_unlock (xvimagesink->pool_lock);
+    }
+    
+  GST_BUFFER_DATA (buffer) = NULL;
+
+  gst_buffer_default_free (buffer);
+}
+
+static GstBuffer *
+gst_xvimagesink_buffer_alloc (GstPad *pad, guint64 offset, guint size)
 {
   GstXvImageSink *xvimagesink;
   GstBuffer *buffer;
   GstXvImage *xvimage = NULL;
   gboolean not_found = TRUE;
   
-  xvimagesink = GST_XVIMAGESINK (user_data);
-  
+  xvimagesink = GST_XVIMAGESINK (gst_pad_get_parent (pad));
+
   g_mutex_lock (xvimagesink->pool_lock);
   
   /* Walking through the pool cleaning unsuable images and searching for a
@@ -954,7 +979,7 @@ gst_xvimagesink_buffer_new (GstBufferPool *pool,
         {
           /* Removing from the pool */
           xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
-                                                        xvimagesink->image_pool);
+                                                         xvimagesink->image_pool);
           
           if ( (xvimage->width != GST_VIDEOSINK_WIDTH (xvimagesink)) ||
                (xvimage->height != GST_VIDEOSINK_HEIGHT (xvimagesink)) )
@@ -963,22 +988,31 @@ gst_xvimagesink_buffer_new (GstBufferPool *pool,
               xvimage = NULL;
             }
           else /* We found a suitable image */
-            break;
+            {
+              break;
+            }
         }
     }
    
   g_mutex_unlock (xvimagesink->pool_lock);
   
   if (!xvimage) /* We found no suitable image in the pool. Creating... */
-    xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
-                                        GST_VIDEOSINK_WIDTH (xvimagesink),
-                                        GST_VIDEOSINK_HEIGHT (xvimagesink));
+    {
+      xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
+                                             GST_VIDEOSINK_WIDTH (xvimagesink),
+                                             GST_VIDEOSINK_HEIGHT (xvimagesink));
+    }
   
   if (xvimage)
     {
       buffer = gst_buffer_new ();
+      
+      /* Storing some pointers in the buffer (bit hackish) */
+      GST_BUFFER_BUFFERPOOL (buffer) = xvimagesink;
       GST_BUFFER_POOL_PRIVATE (buffer) = xvimage;
+      
       GST_BUFFER_DATA (buffer) = xvimage->xvimage->data;
+      GST_DATA_FREE_FUNC (buffer) = gst_xvimagesink_buffer_free;
       GST_BUFFER_SIZE (buffer) = xvimage->size;
       return buffer;
     }
@@ -987,35 +1021,6 @@ gst_xvimagesink_buffer_new (GstBufferPool *pool,
 }
 
 static void
-gst_xvimagesink_buffer_free (GstBufferPool *pool,
-                            GstBuffer *buffer, gpointer user_data)
-{
-  GstXvImageSink *xvimagesink;
-  GstXvImage *xvimage;
-  
-  xvimagesink = GST_XVIMAGESINK (user_data);
-  
-  xvimage = GST_BUFFER_POOL_PRIVATE (buffer);
-  
-  /* If our geometry changed we can't reuse that image. */
-  if ( (xvimage->width != GST_VIDEOSINK_WIDTH (xvimagesink)) ||
-       (xvimage->height != GST_VIDEOSINK_HEIGHT (xvimagesink)) )
-    gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage);
-  else /* In that case we can reuse the image and add it to our image pool. */
-    {
-      g_mutex_lock (xvimagesink->pool_lock);
-      xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool,
-                                                 xvimage);
-      g_mutex_unlock (xvimagesink->pool_lock);
-    }
-    
-  GST_BUFFER_DATA (buffer) = NULL;
-
-  gst_buffer_default_free (buffer);
-}
-#endif
-
-static void
 gst_xvimagesink_imagepool_clear (GstXvImageSink *xvimagesink)
 {
   g_mutex_lock(xvimagesink->pool_lock);
@@ -1091,36 +1096,85 @@ gst_xvimagesink_set_xwindow_id (GstXOverlay *overlay, XID xwindow_id)
   g_return_if_fail (xvimagesink != NULL);
   g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
   
+  /* If we already use that window return */
+  if (xvimagesink->xwindow && (xwindow_id == xvimagesink->xwindow->win))
+    return;
+  
+  /* If the element has not initialized the X11 context try to do so */
   if (!xvimagesink->xcontext)
     xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink);
   
-  if ( (xvimagesink->xwindow) && (xvimagesink->xvimage) )
-    { /* If we are replacing a window we destroy pictures and window as they
-         are associated */
+  if (!xvimagesink->xcontext)
+    {
+      g_warning ("xvimagesink was unable to obtain the X11 context.");
+      return;
+    }
+    
+  /* Clear image pool as the images are unusable anyway */
+  gst_xvimagesink_imagepool_clear (xvimagesink);
+  
+  /* Clear the xvimage */
+  if (xvimagesink->xvimage)
+    {
       gst_xvimagesink_xvimage_destroy (xvimagesink, xvimagesink->xvimage);
-      gst_xvimagesink_imagepool_clear (xvimagesink);
+      xvimagesink->xvimage = NULL;
+    }
+  
+  /* If a window is there already we destroy it */
+  if (xvimagesink->xwindow)
+    {
       gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
+      xvimagesink->xwindow = NULL;
     }
     
-  xwindow = g_new0 (GstXWindow, 1);
-  
-  xwindow->win = xwindow_id;
+  /* 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 (xvimagesink) &&
+          GST_VIDEOSINK_HEIGHT (xvimagesink))
+        {
+          xwindow = gst_xvimagesink_xwindow_new (xvimagesink,
+                                            GST_VIDEOSINK_WIDTH (xvimagesink),
+                                            GST_VIDEOSINK_HEIGHT (xvimagesink));
+        }
+    }
+  else
+    {
+      xwindow = g_new0 (GstXWindow, 1);
+
+      xwindow->win = xwindow_id;
   
-  /* We get window geometry, set the event we want to receive, and create a GC */
-  g_mutex_lock (xvimagesink->x_lock);
-  XGetWindowAttributes (xvimagesink->xcontext->disp, xwindow->win, &attr);
-  xwindow->width = attr.width;
-  xwindow->height = attr.height;
-  xwindow->internal = FALSE;
-  XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
-                StructureNotifyMask | PointerMotionMask | KeyPressMask |
-                KeyReleaseMask);
+      /* We get window geometry, set the event we want to receive,
+         and create a GC */
+      g_mutex_lock (xvimagesink->x_lock);
+      XGetWindowAttributes (xvimagesink->xcontext->disp, xwindow->win, &attr);
+      xwindow->width = attr.width;
+      xwindow->height = attr.height;
+      xwindow->internal = FALSE;
+      XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
+                    StructureNotifyMask | PointerMotionMask | KeyPressMask |
+                    KeyReleaseMask);
+  
+      xwindow->gc = XCreateGC (xvimagesink->xcontext->disp,
+                               xwindow->win, 0, NULL);
+      g_mutex_unlock (xvimagesink->x_lock);
+    }
   
-  xwindow->gc = XCreateGC (xvimagesink->xcontext->disp,
-                           xwindow->win, 0, NULL);
-  g_mutex_unlock (xvimagesink->x_lock);
+  /* Recreating our xvimage */
+  if (!xvimagesink->xvimage &&
+      GST_VIDEOSINK_WIDTH (xvimagesink) &&
+      GST_VIDEOSINK_HEIGHT (xvimagesink))
+    {
+      xvimagesink->xvimage = gst_xvimagesink_xvimage_new (
+                                            xvimagesink,
+                                            GST_VIDEOSINK_WIDTH (xvimagesink),
+                                            GST_VIDEOSINK_HEIGHT (xvimagesink));
+    }
     
-  xvimagesink->xwindow = xwindow;
+  if (xwindow)
+    xvimagesink->xwindow = xwindow;
 }
 
 static void
@@ -1195,7 +1249,9 @@ gst_xvimagesink_init (GstXvImageSink *xvimagesink)
                                 gst_xvimagesink_getcaps);
   gst_pad_set_fixate_function (GST_VIDEOSINK_PAD (xvimagesink),
                                 gst_xvimagesink_fixate);
-
+  gst_pad_set_bufferalloc_function (GST_VIDEOSINK_PAD (xvimagesink),
+                                    gst_xvimagesink_buffer_alloc);
+  
   xvimagesink->xcontext = NULL;
   xvimagesink->xwindow = NULL;
   xvimagesink->xvimage = NULL;