From 69fba30ffe3fec25df6c53bd971813a74bf9acc7 Mon Sep 17 00:00:00 2001
From: benjamin gaignard <benjamin.gaignard@stericsson.com>
Date: Thu, 24 Feb 2011 11:36:01 +0100
Subject: [PATCH 1/3] XvImage: add support of bufferpool

---
 sys/xvimage/xvimagesink.c |  249 +++++++++++++++++++++++++++++++++------------
 sys/xvimage/xvimagesink.h |   40 ++++----
 2 files changed, 205 insertions(+), 84 deletions(-)

diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c
index f5ee866..3bfbd61 100644
--- a/sys/xvimage/xvimagesink.c
+++ b/sys/xvimage/xvimagesink.c
@@ -153,6 +153,10 @@ static gint gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
     GstCaps * caps);
 static void gst_xvimagesink_expose (GstXOverlay * overlay);
 
+static GstXvImageBuffer *gst_xvimagesink_xvimage_new (GstXvImageSink *
+    xvimagesink, GstCaps * caps);
+
+
 /* Default template - initiated with class struct to allow gst-register to work
    without X running */
 static GstStaticPadTemplate gst_xvimagesink_sink_template_factory =
@@ -313,15 +317,6 @@ gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage)
         xvimage->width, xvimage->height,
         xvimagesink->video_width, xvimagesink->video_height);
     gst_xvimage_buffer_destroy (xvimage);
-  } else {
-    /* In that case we can reuse the image and add it to our image pool. */
-    GST_LOG_OBJECT (xvimage, "recycling image in pool");
-    /* need to increment the refcount again to recycle */
-    gst_buffer_ref (GST_BUFFER_CAST (xvimage));
-    g_mutex_lock (xvimagesink->pool_lock);
-    xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool,
-        xvimage);
-    g_mutex_unlock (xvimagesink->pool_lock);
   }
   return;
 
@@ -353,12 +348,12 @@ gst_xvimage_buffer_init (GstXvImageBuffer * xvimage, gpointer g_class)
 static void
 gst_xvimage_buffer_class_init (gpointer g_class, gpointer class_data)
 {
-  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
+  //GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
 
   xvimage_buffer_parent_class = g_type_class_peek_parent (g_class);
 
-  mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
-      gst_xvimage_buffer_finalize;
+  /*mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
+     gst_xvimage_buffer_finalize; */
 }
 
 static GType
@@ -385,6 +380,169 @@ gst_xvimage_buffer_get_type (void)
   return _gst_xvimage_buffer_type;
 }
 
+/* buffer pool functions */
+
+typedef struct _GstXvImageBufferPool GstXvImageBufferPool;
+typedef struct _GstXvImageBufferPoolClass GstXvImageBufferPoolClass;
+
+struct _GstXvImageBufferPool
+{
+  GstBufferPool bufferpool;
+
+  GstCaps *caps;
+  GstXvImageSink *sink;
+};
+
+struct _GstXvImageBufferPoolClass
+{
+  GstBufferPoolClass parent_class;
+};
+
+static GstBufferPoolClass *xvimagesink_bufferpool_parent_class = NULL;
+
+GType gst_xvimagesink_buffer_pool_get_type (void);
+
+G_DEFINE_TYPE (GstXvImageBufferPool, gst_xvimagesink_buffer_pool,
+    GST_TYPE_BUFFER_POOL);
+
+#define GST_TYPE_XVIMAGE_BUFFER_POOL (gst_xvimagesink_buffer_pool_get_type())
+#define GST_IS_XVIMAGE_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XVIMAGE_BUFFER_POOL))
+#define GST_XVIMAGE_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XVIMAGE_BUFFER_POOL, GstXvImageBufferPool))
+#define GST_XVIMAGE_BUFFER_POOL_CAST(obj) ((GstXvImageBufferPool*)(obj))
+#define GST_XVIMAGE_BUFFER_POOL_CAPS(obj) (GST_XVIMAGE_BUFFER_POOL_CAST(obj)->caps)
+
+
+static GstFlowReturn
+gst_xvimagesink_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer,
+    GstBufferPoolParams * params)
+{
+  GstXvImageBufferPool *xvpool = (GstXvImageBufferPool *) pool;
+  GstXvImageBuffer *xvbuffer = NULL;
+
+  GST_DEBUG_OBJECT (xvpool->sink, "allocate XvImage buffer");
+  xvbuffer = gst_xvimagesink_xvimage_new (xvpool->sink, xvpool->caps);
+
+  if (!xvbuffer) {
+    return GST_FLOW_ERROR;
+  }
+
+  GST_DEBUG_OBJECT (xvpool->sink, "set pool %p to buffer %p", pool, xvbuffer);
+  GST_BUFFER_CAST (xvbuffer)->pool = pool;
+
+  *buffer = (GstBuffer *) xvbuffer;
+  return GST_FLOW_OK;
+}
+
+static void
+gst_xvimagesink_free_buffer (GstBufferPool * pool, GstBuffer * buffer)
+{
+  /* finalize XvImageBuffer */
+  gst_xvimage_buffer_finalize ((GstXvImageBuffer *) buffer);
+}
+
+static GstXvImageBufferPool *
+gst_xvimagesink_new_buffer_pool (GstXvImageSink * xvimagesink, GstCaps * caps)
+{
+  GstXvImageBufferPool *pool =
+      g_object_new (GST_TYPE_XVIMAGE_BUFFER_POOL, 0, NULL);
+
+  pool->sink = gst_object_ref (xvimagesink);
+  pool->caps = gst_caps_ref (caps);
+
+  GST_LOG_OBJECT (xvimagesink, "XvImage new buffer pool");
+  /* overload default pool function for buffer alloc/free */
+  GST_BUFFER_POOL_GET_CLASS (pool)->alloc_buffer =
+      GST_DEBUG_FUNCPTR (gst_xvimagesink_alloc_buffer);
+  GST_BUFFER_POOL_GET_CLASS (pool)->free_buffer =
+      GST_DEBUG_FUNCPTR (gst_xvimagesink_free_buffer);
+
+  return pool;
+}
+
+static void
+gst_xvimagesink_buffer_pool_finalize (GObject * object)
+{
+  GstXvImageBufferPool *pool = (GstXvImageBufferPool *) object;
+
+  GST_LOG_OBJECT (pool->sink, "finalize XvImage buffer pool");
+  /* we could have keep a ref on sink and caps */
+  if (pool->sink) {
+    gst_object_unref (pool->sink);
+  }
+
+  if (pool->caps) {
+    gst_caps_unref (pool->caps);
+  }
+
+  G_OBJECT_CLASS (xvimagesink_bufferpool_parent_class)->finalize (object);
+}
+
+void
+gst_xvimagesink_buffer_pool_init (GstXvImageBufferPool * pool)
+{
+  pool->caps = NULL;
+  pool->sink = NULL;
+}
+
+void
+gst_xvimagesink_buffer_pool_class_init (GstXvImageBufferPoolClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  xvimagesink_bufferpool_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->finalize = gst_xvimagesink_buffer_pool_finalize;
+}
+
+static GstXvImageBuffer *
+gst_xvimagesink_buffer_pool_acquire_buffer (GstXvImageSink * xvimagesink,
+    GstCaps * caps)
+{
+  GstXvImageBufferPool *xvpool = (GstXvImageBufferPool *) xvimagesink->pool;
+  GstXvImageBuffer *xvbuffer = NULL;
+
+new_pool:
+  if (xvpool == NULL) {
+    /* allocate a new strucure for pool configuration */
+    GstStructure *config;
+    GST_DEBUG_OBJECT (xvimagesink, "create a new pool");
+    /* get a new pool */
+    xvpool = gst_xvimagesink_new_buffer_pool (xvimagesink, caps);
+    if (xvpool == NULL) {
+      GST_WARNING_OBJECT (xvimagesink, "can't get a pool");
+      return NULL;
+    }
+
+    xvimagesink->pool = (GstBufferPool *) xvpool;
+
+    /* set pool configuration only max_buffer set to 0 is important here
+     * during Xv buffer allocation we don't take care of size, align ...*/
+    GST_DEBUG_OBJECT (xvimagesink, "set pool configuration");
+    config = gst_buffer_pool_get_config (xvimagesink->pool);
+    gst_buffer_pool_config_set (config, 0, 0, 0, 0, 0, 0);
+    gst_buffer_pool_set_config (xvimagesink->pool, config);
+
+    /* activate the pool */
+    GST_DEBUG_OBJECT (xvimagesink, "activate pool");
+    gst_buffer_pool_set_active ((GstBufferPool *) xvpool, TRUE);
+
+  } else {
+    if (!gst_caps_is_equal (GST_XVIMAGE_BUFFER_POOL_CAPS (xvpool), caps)) {
+      /* caps have changed discard previous pool */
+      gst_buffer_pool_set_active ((GstBufferPool *) xvpool, FALSE);
+      gst_object_unref (xvpool);
+      xvpool = NULL;
+      goto new_pool;
+    }
+  }
+
+  /* try to acquire a buffer now */
+  GST_DEBUG_OBJECT (xvimagesink, "get a buffer from the pool");
+  gst_buffer_pool_acquire_buffer ((GstBufferPool *) xvpool,
+      (GstBuffer **) & xvbuffer, NULL);
+
+  return xvbuffer;
+}
+
 /* X11 stuff */
 
 static gboolean error_caught = FALSE;
@@ -2012,14 +2170,11 @@ gst_xvimagesink_imagepool_clear (GstXvImageSink * xvimagesink)
 {
   g_mutex_lock (xvimagesink->pool_lock);
 
-  while (xvimagesink->image_pool) {
-    GstXvImageBuffer *xvimage = xvimagesink->image_pool->data;
-
-    xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
-        xvimagesink->image_pool);
-    gst_xvimage_buffer_free (xvimage);
+  if (xvimagesink->pool) {
+    gst_buffer_pool_set_active (xvimagesink->pool, FALSE);
+    gst_object_unref (xvimagesink->pool);
+    xvimagesink->pool = NULL;
   }
-
   g_mutex_unlock (xvimagesink->pool_lock);
 }
 
@@ -2297,16 +2452,12 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
       gst_xvimagesink_manage_event_thread (xvimagesink);
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
-      g_mutex_lock (xvimagesink->pool_lock);
-      xvimagesink->pool_invalid = FALSE;
-      g_mutex_unlock (xvimagesink->pool_lock);
+      gst_xvimagesink_imagepool_clear (xvimagesink);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
-      g_mutex_lock (xvimagesink->pool_lock);
-      xvimagesink->pool_invalid = TRUE;
-      g_mutex_unlock (xvimagesink->pool_lock);
+      gst_xvimagesink_imagepool_clear (xvimagesink);
       break;
     default:
       break;
@@ -2377,7 +2528,9 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
     if (!xvimagesink->xvimage) {
       GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
 
-      xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
+      /* acquire a buffer from the pool */
+      xvimagesink->xvimage =
+          gst_xvimagesink_buffer_pool_acquire_buffer (xvimagesink,
           GST_BUFFER_CAPS (buf));
 
       if (!xvimagesink->xvimage)
@@ -2390,7 +2543,7 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
                 xvimagesink->xvimage->width, xvimagesink->xvimage->height),
             ("XServer allocated buffer size did not match input buffer"));
 
-        gst_xvimage_buffer_destroy (xvimagesink->xvimage);
+        gst_object_unref (xvimagesink->xvimage);
         xvimagesink->xvimage = NULL;
         goto no_image;
       }
@@ -2516,8 +2669,6 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
   xvimagesink = GST_XVIMAGESINK (bsink);
 
   g_mutex_lock (xvimagesink->pool_lock);
-  if (G_UNLIKELY (xvimagesink->pool_invalid))
-    goto invalid;
 
   if (G_LIKELY (xvimagesink->xcontext->last_caps &&
           gst_caps_is_equal (caps, xvimagesink->xcontext->last_caps))) {
@@ -2636,35 +2787,9 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
 
 reuse_last_caps:
 
-  /* Walking through the pool cleaning unusable images and searching for a
-     suitable one */
-  while (xvimagesink->image_pool) {
-    xvimage = xvimagesink->image_pool->data;
-
-    if (xvimage) {
-      /* Removing from the pool */
-      xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
-          xvimagesink->image_pool);
-
-      /* We check for geometry or image format changes */
-      if ((xvimage->width != width) ||
-          (xvimage->height != height) || (xvimage->im_format != image_format)) {
-        /* This image is unusable. Destroying... */
-        gst_xvimage_buffer_free (xvimage);
-        xvimage = NULL;
-      } else {
-        /* We found a suitable image */
-        GST_LOG_OBJECT (xvimagesink, "found usable image in pool");
-        break;
-      }
-    }
-  }
-
-  if (!xvimage) {
-    /* We found no suitable image in the pool. Creating... */
-    GST_DEBUG_OBJECT (xvimagesink, "no usable image in pool, creating xvimage");
-    xvimage = gst_xvimagesink_xvimage_new (xvimagesink, intersection);
-  }
+  GST_DEBUG_OBJECT (xvimagesink, "get XvImage buffer from the pool");
+  xvimage =
+      gst_xvimagesink_buffer_pool_acquire_buffer (xvimagesink, intersection);
   g_mutex_unlock (xvimagesink->pool_lock);
 
   if (xvimage) {
@@ -3394,12 +3519,6 @@ gst_xvimagesink_reset (GstXvImageSink * xvimagesink)
   xvimagesink->event_thread = NULL;
   GST_OBJECT_UNLOCK (xvimagesink);
 
-  /* invalidate the pool, current allocations continue, new buffer_alloc fails
-   * with wrong_state */
-  g_mutex_lock (xvimagesink->pool_lock);
-  xvimagesink->pool_invalid = TRUE;
-  g_mutex_unlock (xvimagesink->pool_lock);
-
   /* Wait for our event thread to finish before we clean up our stuff. */
   if (thread)
     g_thread_join (thread);
@@ -3489,7 +3608,7 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink)
   xvimagesink->x_lock = g_mutex_new ();
   xvimagesink->flow_lock = g_mutex_new ();
 
-  xvimagesink->image_pool = NULL;
+  xvimagesink->pool = NULL;
   xvimagesink->pool_lock = g_mutex_new ();
 
   xvimagesink->synchronous = FALSE;
diff --git a/sys/xvimage/xvimagesink.h b/sys/xvimage/xvimagesink.h
index 0181018..5c6e54f 100644
--- a/sys/xvimage/xvimagesink.h
+++ b/sys/xvimage/xvimagesink.h
@@ -43,7 +43,6 @@
 #include <stdlib.h>
 
 G_BEGIN_DECLS
-
 #define GST_TYPE_XVIMAGESINK \
   (gst_xvimagesink_get_type())
 #define GST_XVIMAGESINK(obj) \
@@ -54,7 +53,6 @@ G_BEGIN_DECLS
   (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_XVIMAGESINK))
 #define GST_IS_XVIMAGESINK_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_XVIMAGESINK))
-
 typedef struct _GstXContext GstXContext;
 typedef struct _GstXWindow GstXWindow;
 typedef struct _GstXvImageFormat GstXvImageFormat;
@@ -93,7 +91,8 @@ typedef struct _GstXvImageSinkClass GstXvImageSinkClass;
  * Structure used to store various informations collected/calculated for a
  * Display.
  */
-struct _GstXContext {
+struct _GstXContext
+{
   Display *disp;
 
   Screen *screen;
@@ -117,7 +116,7 @@ struct _GstXContext {
 
   XvPortID xv_port_id;
   guint nb_adaptors;
-  gchar ** adaptors;
+  gchar **adaptors;
   gint im_format;
 
   GList *formats_list;
@@ -143,7 +142,8 @@ struct _GstXContext {
  *
  * Structure used to store informations about a Window.
  */
-struct _GstXWindow {
+struct _GstXWindow
+{
   Window win;
   gint width, height;
   gboolean internal;
@@ -157,7 +157,8 @@ struct _GstXWindow {
  *
  * Structure storing image format to #GstCaps association.
  */
-struct _GstXvImageFormat {
+struct _GstXvImageFormat
+{
   gint format;
   GstCaps *caps;
 };
@@ -173,8 +174,9 @@ struct _GstXvImageFormat {
  *
  * Subclass of #GstBuffer containing additional information about an XvImage.
  */
-struct _GstXvImageBuffer {
-  GstBuffer   buffer;
+struct _GstXvImageBuffer
+{
+  GstBuffer buffer;
 
   /* Reference to the xvimagesink we belong to */
   GstXvImageSink *xvimagesink;
@@ -183,7 +185,7 @@ struct _GstXvImageBuffer {
 
 #ifdef HAVE_XSHM
   XShmSegmentInfo SHMInfo;
-#endif /* HAVE_XSHM */
+#endif                          /* HAVE_XSHM */
 
   gint width, height, im_format;
   size_t size;
@@ -208,7 +210,7 @@ struct _GstXvImageBuffer {
  * events from @event_thread or methods from the #GstXOverlay interface
  * @par: used to override calculated pixel aspect ratio from @xcontext
  * @pool_lock: used to protect the buffer pool
- * @image_pool: a list of #GstXvImageBuffer that could be reused at next buffer
+ * @pool: a pool of #GstXvImageBuffer that could be reused at next buffer
  * allocation call
  * @synchronous: used to store if XSynchronous should be used or not (for
  * debugging purpose only)
@@ -225,7 +227,8 @@ struct _GstXvImageBuffer {
  *
  * The #GstXvImageSink data structure.
  */
-struct _GstXvImageSink {
+struct _GstXvImageSink
+{
   /* Our element stuff */
   GstVideoSink videosink;
 
@@ -250,8 +253,7 @@ struct _GstXvImageSink {
   GValue *par;
 
   GMutex *pool_lock;
-  gboolean pool_invalid;
-  GSList *image_pool;
+  GstBufferPool *pool;
 
   gboolean synchronous;
   gboolean double_buffer;
@@ -276,14 +278,14 @@ struct _GstXvImageSink {
   /* port attributes */
   gboolean autopaint_colorkey;
   gint colorkey;
-  
+
   gboolean draw_borders;
-  
+
   /* port features */
   gboolean have_autopaint_colorkey;
   gboolean have_colorkey;
   gboolean have_double_buffer;
-  
+
   /* stream metadata */
   gchar *media_title;
 
@@ -292,12 +294,12 @@ struct _GstXvImageSink {
   gboolean have_render_rect;
 };
 
-struct _GstXvImageSinkClass {
+struct _GstXvImageSinkClass
+{
   GstVideoSinkClass parent_class;
 };
 
-GType gst_xvimagesink_get_type(void);
+GType gst_xvimagesink_get_type (void);
 
 G_END_DECLS
-
 #endif /* __GST_XVIMAGESINK_H__ */
-- 
1.7.0.4


From 5cf543c1686f8e73bd47bc6cf56819c23f8f5be9 Mon Sep 17 00:00:00 2001
From: benjamin gaignard <benjamin.gaignard@linaro.org>
Date: Wed, 2 Mar 2011 11:57:34 +0100
Subject: [PATCH 2/3] xvimagesink: code clean up

---
 sys/xvimage/xvimagesink.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c
index 3bfbd61..8c6fdde 100644
--- a/sys/xvimage/xvimagesink.c
+++ b/sys/xvimage/xvimagesink.c
@@ -348,12 +348,7 @@ gst_xvimage_buffer_init (GstXvImageBuffer * xvimage, gpointer g_class)
 static void
 gst_xvimage_buffer_class_init (gpointer g_class, gpointer class_data)
 {
-  //GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
-
   xvimage_buffer_parent_class = g_type_class_peek_parent (g_class);
-
-  /*mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
-     gst_xvimage_buffer_finalize; */
 }
 
 static GType
-- 
1.7.0.4


From 59322c7f20f3a3fb1ea323cae8cbc5a3af9b7a24 Mon Sep 17 00:00:00 2001
From: benjamin gaignard <benjamin.gaignard@linaro.org>
Date: Wed, 2 Mar 2011 11:58:52 +0100
Subject: [PATCH 3/3] Ximage: add support of buffer pool

---
 sys/ximage/ximagesink.c |  219 +++++++++++++++++++++++++++++++++++++----------
 sys/ximage/ximagesink.h |    4 +-
 2 files changed, 174 insertions(+), 49 deletions(-)

diff --git a/sys/ximage/ximagesink.c b/sys/ximage/ximagesink.c
index d1780fc..aab773e 100644
--- a/sys/ximage/ximagesink.c
+++ b/sys/ximage/ximagesink.c
@@ -134,6 +134,9 @@ static void gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
 static void gst_ximagesink_xwindow_update_geometry (GstXImageSink * ximagesink);
 static void gst_ximagesink_expose (GstXOverlay * overlay);
 
+static GstXImageBuffer *gst_ximagesink_ximage_new (GstXImageSink * ximagesink,
+    GstCaps * caps);
+
 static GstStaticPadTemplate gst_ximagesink_sink_template_factory =
 GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -213,17 +216,7 @@ gst_ximage_buffer_finalize (GstXImageBuffer * ximage)
         ximage, ximage->width, ximage->height,
         GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink));
     gst_ximagesink_ximage_destroy (ximagesink, ximage);
-  } else {
-    /* In that case we can reuse the image and add it to our image pool. */
-    GST_LOG_OBJECT (ximagesink, "recycling image %p in pool", ximage);
-    /* need to increment the refcount again to recycle */
-    gst_buffer_ref (GST_BUFFER_CAST (ximage));
-    g_mutex_lock (ximagesink->pool_lock);
-    ximagesink->buffer_pool = g_slist_prepend (ximagesink->buffer_pool, ximage);
-    g_mutex_unlock (ximagesink->pool_lock);
-    recycled = TRUE;
   }
-
   if (!recycled)
     GST_MINI_OBJECT_CLASS (ximage_buffer_parent_class)->finalize
         (GST_MINI_OBJECT (ximage));
@@ -253,12 +246,7 @@ gst_ximage_buffer_init (GstXImageBuffer * ximage_buffer, gpointer g_class)
 static void
 gst_ximage_buffer_class_init (gpointer g_class, gpointer class_data)
 {
-  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
-
   ximage_buffer_parent_class = g_type_class_peek_parent (g_class);
-
-  mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
-      gst_ximage_buffer_finalize;
 }
 
 static GType
@@ -285,6 +273,169 @@ gst_ximage_buffer_get_type (void)
   return _gst_ximage_buffer_type;
 }
 
+/* buffer pool functions */
+
+typedef struct _GstXImageBufferPool GstXImageBufferPool;
+typedef struct _GstXImageBufferPoolClass GstXImageBufferPoolClass;
+
+struct _GstXImageBufferPool
+{
+  GstBufferPool bufferpool;
+
+  GstCaps *caps;
+  GstXImageSink *sink;
+};
+
+struct _GstXImageBufferPoolClass
+{
+  GstBufferPoolClass parent_class;
+};
+
+static GstBufferPoolClass *ximagesink_bufferpool_parent_class = NULL;
+
+GType gst_ximagesink_buffer_pool_get_type (void);
+
+G_DEFINE_TYPE (GstXImageBufferPool, gst_ximagesink_buffer_pool,
+    GST_TYPE_BUFFER_POOL);
+
+#define GST_TYPE_XIMAGE_BUFFER_POOL (gst_ximagesink_buffer_pool_get_type())
+#define GST_IS_XIMAGE_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XIMAGE_BUFFER_POOL))
+#define GST_XIMAGE_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XIMAGE_BUFFER_POOL, GstXImageBufferPool))
+#define GST_XIMAGE_BUFFER_POOL_CAST(obj) ((GstXImageBufferPool*)(obj))
+#define GST_XIMAGE_BUFFER_POOL_CAPS(obj) (GST_XIMAGE_BUFFER_POOL_CAST(obj)->caps)
+
+
+static GstFlowReturn
+gst_ximagesink_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer,
+    GstBufferPoolParams * params)
+{
+  GstXImageBufferPool *xpool = (GstXImageBufferPool *) pool;
+  GstXImageBuffer *xbuffer = NULL;
+
+  GST_DEBUG_OBJECT (xpool->sink, "allocate XImage buffer");
+  xbuffer = gst_ximagesink_ximage_new (xpool->sink, xpool->caps);
+
+  if (!xbuffer) {
+    return GST_FLOW_ERROR;
+  }
+
+  GST_DEBUG_OBJECT (xpool->sink, "set pool %p to buffer %p", pool, xbuffer);
+  GST_BUFFER_CAST (xbuffer)->pool = pool;
+
+  *buffer = (GstBuffer *) xbuffer;
+  return GST_FLOW_OK;
+}
+
+static void
+gst_ximagesink_free_buffer (GstBufferPool * pool, GstBuffer * buffer)
+{
+  /* finalize xImageBuffer */
+  gst_ximage_buffer_finalize ((GstXImageBuffer *) buffer);
+}
+
+static GstXImageBufferPool *
+gst_ximagesink_new_buffer_pool (GstXImageSink * ximagesink, GstCaps * caps)
+{
+  GstXImageBufferPool *pool =
+      g_object_new (GST_TYPE_XIMAGE_BUFFER_POOL, 0, NULL);
+
+  pool->sink = gst_object_ref (ximagesink);
+  pool->caps = gst_caps_ref (caps);
+
+  GST_LOG_OBJECT (ximagesink, "XImage new buffer pool");
+  /* overload default pool function for buffer alloc/free */
+  GST_BUFFER_POOL_GET_CLASS (pool)->alloc_buffer =
+      GST_DEBUG_FUNCPTR (gst_ximagesink_alloc_buffer);
+  GST_BUFFER_POOL_GET_CLASS (pool)->free_buffer =
+      GST_DEBUG_FUNCPTR (gst_ximagesink_free_buffer);
+
+  return pool;
+}
+
+static void
+gst_ximagesink_buffer_pool_finalize (GObject * object)
+{
+  GstXImageBufferPool *pool = (GstXImageBufferPool *) object;
+
+  GST_LOG_OBJECT (pool->sink, "finalize XImage buffer pool");
+  /* we could have keep a ref on sink and caps */
+  if (pool->sink) {
+    gst_object_unref (pool->sink);
+  }
+
+  if (pool->caps) {
+    gst_caps_unref (pool->caps);
+  }
+
+  G_OBJECT_CLASS (ximagesink_bufferpool_parent_class)->finalize (object);
+}
+
+void
+gst_ximagesink_buffer_pool_init (GstXImageBufferPool * pool)
+{
+  pool->caps = NULL;
+  pool->sink = NULL;
+}
+
+void
+gst_ximagesink_buffer_pool_class_init (GstXImageBufferPoolClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  ximagesink_bufferpool_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->finalize = gst_ximagesink_buffer_pool_finalize;
+}
+
+static GstXImageBuffer *
+gst_ximagesink_buffer_pool_acquire_buffer (GstXImageSink * ximagesink,
+    GstCaps * caps)
+{
+  GstXImageBufferPool *xpool = (GstXImageBufferPool *) ximagesink->pool;
+  GstXImageBuffer *xbuffer = NULL;
+
+new_pool:
+  if (xpool == NULL) {
+    /* allocate a new strucure for pool configuration */
+    GstStructure *config;
+    GST_DEBUG_OBJECT (ximagesink, "create a new pool");
+    /* get a new pool */
+    xpool = gst_ximagesink_new_buffer_pool (ximagesink, caps);
+    if (xpool == NULL) {
+      GST_WARNING_OBJECT (ximagesink, "can't get a pool");
+      return NULL;
+    }
+
+    ximagesink->pool = (GstBufferPool *) xpool;
+
+    /* set pool configuration only max_buffer set to 0 is important here
+     * during X buffer allocation we don't take care of size, align ...*/
+    GST_DEBUG_OBJECT (ximagesink, "set pool configuration");
+    config = gst_buffer_pool_get_config (ximagesink->pool);
+    gst_buffer_pool_config_set (config, 0, 0, 0, 0, 0, 0);
+    gst_buffer_pool_set_config (ximagesink->pool, config);
+
+    /* activate the pool */
+    GST_DEBUG_OBJECT (ximagesink, "activate pool");
+    gst_buffer_pool_set_active ((GstBufferPool *) xpool, TRUE);
+
+  } else {
+    if (!gst_caps_is_equal (GST_XIMAGE_BUFFER_POOL_CAPS (xpool), caps)) {
+      /* caps have changed discard previous pool */
+      gst_buffer_pool_set_active ((GstBufferPool *) xpool, FALSE);
+      gst_object_unref (xpool);
+      xpool = NULL;
+      goto new_pool;
+    }
+  }
+
+  /* try to acquire a buffer now */
+  GST_DEBUG_OBJECT (ximagesink, "get a buffer from the pool");
+  gst_buffer_pool_acquire_buffer ((GstBufferPool *) xpool,
+      (GstBuffer **) & xbuffer, NULL);
+
+  return xbuffer;
+}
+
 /* X11 stuff */
 
 static gboolean error_caught = FALSE;
@@ -1416,12 +1567,10 @@ gst_ximagesink_bufferpool_clear (GstXImageSink * ximagesink)
 
   g_mutex_lock (ximagesink->pool_lock);
 
-  while (ximagesink->buffer_pool) {
-    GstXImageBuffer *ximage = ximagesink->buffer_pool->data;
-
-    ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool,
-        ximagesink->buffer_pool);
-    gst_ximage_buffer_free (ximage);
+  if (ximagesink->pool) {
+    gst_buffer_pool_set_active (ximagesink->pool, FALSE);
+    gst_object_unref (ximagesink->pool);
+    ximagesink->pool = NULL;
   }
 
   g_mutex_unlock (ximagesink->pool_lock);
@@ -1896,32 +2045,8 @@ gst_ximagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
   }
 
 alloc:
-  /* Inspect our buffer pool */
-  g_mutex_lock (ximagesink->pool_lock);
-  while (ximagesink->buffer_pool) {
-    ximage = (GstXImageBuffer *) ximagesink->buffer_pool->data;
-
-    if (ximage) {
-      /* Removing from the pool */
-      ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool,
-          ximagesink->buffer_pool);
-
-      /* If the ximage is invalid for our need, destroy */
-      if ((ximage->width != width) || (ximage->height != height)) {
-        gst_ximage_buffer_free (ximage);
-        ximage = NULL;
-      } else {
-        /* We found a suitable ximage */
-        break;
-      }
-    }
-  }
-  g_mutex_unlock (ximagesink->pool_lock);
+  ximage = gst_ximagesink_buffer_pool_acquire_buffer (ximagesink, alloc_caps);
 
-  /* We haven't found anything, creating a new one */
-  if (!ximage) {
-    ximage = gst_ximagesink_ximage_new (ximagesink, alloc_caps);
-  }
   /* Now we should have a ximage, set appropriate caps on it */
   if (ximage) {
     /* Make sure the buffer is cleared of any previously used flags */
@@ -2342,7 +2467,7 @@ gst_ximagesink_init (GstXImageSink * ximagesink)
   ximagesink->par = NULL;
 
   ximagesink->pool_lock = g_mutex_new ();
-  ximagesink->buffer_pool = NULL;
+  ximagesink->pool = NULL;
 
   ximagesink->synchronous = FALSE;
   ximagesink->keep_aspect = FALSE;
diff --git a/sys/ximage/ximagesink.h b/sys/ximage/ximagesink.h
index 83e973f..c880ed6 100644
--- a/sys/ximage/ximagesink.h
+++ b/sys/ximage/ximagesink.h
@@ -175,7 +175,7 @@ struct _GstXImageBuffer
  * events from @event_thread or methods from the #GstXOverlay interface
  * @par: used to override calculated pixel aspect ratio from @xcontext
  * @pool_lock: used to protect the buffer pool
- * @buffer_pool: a list of #GstXImageBuffer that could be reused at next buffer
+ * @pool: a pool of #GstXImageBuffer that could be reused at next buffer
  * allocation call
  * @synchronous: used to store if XSynchronous should be used or not (for 
  * debugging purpose only)
@@ -211,7 +211,7 @@ struct _GstXImageSink
   GValue *par;
 
   GMutex *pool_lock;
-  GSList *buffer_pool;
+  GstBufferPool *pool;
 
   gboolean synchronous;
   gboolean keep_aspect;
-- 
1.7.0.4
