From patchwork Mon Apr 18 12:07:04 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Gaignard X-Patchwork-Id: 1072 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:48:51 -0000 Delivered-To: patches@linaro.org Received: by 10.224.67.148 with SMTP id r20cs32534qai; Mon, 18 Apr 2011 05:07:05 -0700 (PDT) Received: by 10.68.41.136 with SMTP id f8mr6615390pbl.357.1303128424621; Mon, 18 Apr 2011 05:07:04 -0700 (PDT) Received: from mail-px0-f172.google.com (mail-px0-f172.google.com [209.85.212.172]) by mx.google.com with ESMTPS id b3si10284145pbm.230.2011.04.18.05.07.04 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 18 Apr 2011 05:07:04 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.212.172 is neither permitted nor denied by best guess record for domain of benjamin.gaignard@linaro.org) client-ip=209.85.212.172; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.172 is neither permitted nor denied by best guess record for domain of benjamin.gaignard@linaro.org) smtp.mail=benjamin.gaignard@linaro.org Received: by pxi6 with SMTP id 6so6766547pxi.17 for ; Mon, 18 Apr 2011 05:07:04 -0700 (PDT) MIME-Version: 1.0 Received: by 10.142.154.12 with SMTP id b12mr2701236wfe.160.1303128424135; Mon, 18 Apr 2011 05:07:04 -0700 (PDT) Received: by 10.142.132.3 with HTTP; Mon, 18 Apr 2011 05:07:04 -0700 (PDT) Date: Mon, 18 Apr 2011 14:07:04 +0200 Message-ID: Subject: [GStreamer] xvimagesink: use buffer pool From: Benjamin Gaignard To: Patch Tracking Hi, This patches has been upstreamed in gst-0.11 branch (the dev branch from gstreamer 1.0) http://cgit.freedesktop.org/gstreamer/gst-plugins-base/commit/?h=0.11&id=15c49a4d6344a35463fa129de6a419699e89852f Benjamin >From 69fba30ffe3fec25df6c53bd971813a74bf9acc7 Mon Sep 17 00:00:00 2001 From: benjamin gaignard 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 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 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 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