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(-)
@@ -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;
@@ -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(-)
@@ -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(-)
@@ -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;
@@ -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