diff options
author | Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> | 2010-07-30 10:55:56 +0200 |
---|---|---|
committer | Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> | 2010-07-30 11:33:13 +0200 |
commit | 7320eedc04602afc46994256093cf49a8e444d17 (patch) | |
tree | b5f1f89c5b4053837a9a70648075f6ddf814320f | |
parent | 093fcacc20a9a84a12e59f027a0f0921ff02d304 (diff) | |
download | gstreamer-plugins-bad-7320eedc04602afc46994256093cf49a8e444d17.tar.gz |
vdpau: add GstVdpBufferPool base class
GstVdpBufferPool will be used to cache GstVdp[Video|Output]Buffers since
creating these can be a costly operation on some hardware.
-rw-r--r-- | sys/vdpau/gstvdp/Makefile.am | 4 | ||||
-rw-r--r-- | sys/vdpau/gstvdp/gstvdpbuffer.c | 86 | ||||
-rw-r--r-- | sys/vdpau/gstvdp/gstvdpbuffer.h | 59 | ||||
-rw-r--r-- | sys/vdpau/gstvdp/gstvdpbufferpool.c | 358 | ||||
-rw-r--r-- | sys/vdpau/gstvdp/gstvdpbufferpool.h | 74 |
5 files changed, 581 insertions, 0 deletions
diff --git a/sys/vdpau/gstvdp/Makefile.am b/sys/vdpau/gstvdp/Makefile.am index 13ba6bdef..44a0b9e95 100644 --- a/sys/vdpau/gstvdp/Makefile.am +++ b/sys/vdpau/gstvdp/Makefile.am @@ -3,6 +3,8 @@ lib_LTLIBRARIES = libgstvdp-@GST_MAJORMINOR@.la libgstvdp_@GST_MAJORMINOR@_la_SOURCES = \ gstvdpdevice.c \ gstvdputils.c \ + gstvdpbuffer.c \ + gstvdpbufferpool.c \ gstvdpvideobuffer.c \ gstvdpoutputbuffer.c \ gstvdpvideosrcpad.c \ @@ -14,6 +16,8 @@ libgstvdp_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/ libgstvdp_@GST_MAJORMINOR@include_HEADERS = \ gstvdpdevice.h \ gstvdputils.h \ + gstvdpbuffer.h \ + gstvdpbufferpool.h \ gstvdpvideobuffer.h \ gstvdpoutputbuffer.h \ gstvdpvideosrcpad.h \ diff --git a/sys/vdpau/gstvdp/gstvdpbuffer.c b/sys/vdpau/gstvdp/gstvdpbuffer.c new file mode 100644 index 000000000..c2292cd7d --- /dev/null +++ b/sys/vdpau/gstvdp/gstvdpbuffer.c @@ -0,0 +1,86 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstvdpbuffer.h" + +static GObjectClass *gst_vdp_buffer_parent_class; + +void +gst_vdp_buffer_set_buffer_pool (GstVdpBuffer * buffer, GstVdpBufferPool * bpool) +{ + g_return_if_fail (GST_IS_VDP_BUFFER (buffer)); + + if (bpool) { + g_return_if_fail (GST_IS_VDP_BUFFER_POOL (bpool)); + g_object_add_weak_pointer (G_OBJECT (bpool), (void **) &buffer->bpool); + } + + buffer->bpool = bpool; +} + +gboolean +gst_vdp_buffer_revive (GstVdpBuffer * buffer) +{ + if (buffer->bpool) + return gst_vdp_buffer_pool_put_buffer (buffer->bpool, buffer); + + return FALSE; +} + +static void +gst_vdp_buffer_init (GstVdpBuffer * buffer, gpointer g_class) +{ + buffer->bpool = NULL; +} + +static void +gst_vdp_buffer_class_init (gpointer g_class, gpointer class_data) +{ + gst_vdp_buffer_parent_class = g_type_class_peek_parent (g_class); +} + + +GType +gst_vdp_buffer_get_type (void) +{ + static GType _gst_vdp_buffer_type; + + if (G_UNLIKELY (_gst_vdp_buffer_type == 0)) { + static const GTypeInfo info = { + sizeof (GstBufferClass), + NULL, + NULL, + gst_vdp_buffer_class_init, + NULL, + NULL, + sizeof (GstVdpBuffer), + 0, + (GInstanceInitFunc) gst_vdp_buffer_init, + NULL + }; + _gst_vdp_buffer_type = g_type_register_static (GST_TYPE_BUFFER, + "GstVdpBuffer", &info, 0); + } + return _gst_vdp_buffer_type; +} diff --git a/sys/vdpau/gstvdp/gstvdpbuffer.h b/sys/vdpau/gstvdp/gstvdpbuffer.h new file mode 100644 index 000000000..fc8b57812 --- /dev/null +++ b/sys/vdpau/gstvdp/gstvdpbuffer.h @@ -0,0 +1,59 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GST_VDP_BUFFER_H_ +#define _GST_VDP_BUFFER_H_ + +#include <gst/gst.h> + +typedef struct _GstVdpBuffer GstVdpBuffer; + +#include "gstvdpbufferpool.h" + +#define GST_TYPE_VDP_BUFFER (gst_vdp_buffer_get_type()) + +#define GST_IS_VDP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDP_BUFFER)) +#define GST_VDP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDP_BUFFER, GstVdpBuffer)) +#define GST_VDP_BUFFER_CAST(obj) ((GstVdpBuffer *)obj) + +struct _GstVdpBuffer { + GstBuffer buffer; + + GstVdpBufferPool *bpool; +}; + +void gst_vdp_buffer_set_buffer_pool (GstVdpBuffer *buffer, GstVdpBufferPool *bpool); +gboolean gst_vdp_buffer_revive (GstVdpBuffer * buffer); + +static inline GstVdpBuffer * +gst_vdp_buffer_ref (GstVdpBuffer *buffer) +{ + return (GstVdpBuffer *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (buffer)); +} + +static inline void +gst_vdp_buffer_unref (GstVdpBuffer *buffer) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (buffer)); +} + +GType gst_vdp_buffer_get_type (void); + +#endif
\ No newline at end of file diff --git a/sys/vdpau/gstvdp/gstvdpbufferpool.c b/sys/vdpau/gstvdp/gstvdpbufferpool.c new file mode 100644 index 000000000..fea8aea4f --- /dev/null +++ b/sys/vdpau/gstvdp/gstvdpbufferpool.c @@ -0,0 +1,358 @@ +/* + * GStreamer + * Copyright (C) 2010 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#include "gstvdpbufferpool.h" + +struct _GstVdpBufferPoolPrivate +{ + GQueue *buffers; + GMutex *mutex; + + /* properties */ + guint max_buffers; + GstCaps *caps; + GstVdpDevice *device; +}; + +enum +{ + PROP_0, + PROP_DEVICE, + PROP_CAPS, + PROP_MAX_BUFFERS +}; + +G_DEFINE_TYPE (GstVdpBufferPool, gst_vdp_buffer_pool, G_TYPE_OBJECT); + +#define DEFAULT_MAX_BUFFERS 20 + +static void +gst_vdp_buffer_free (GstVdpBuffer * buf) +{ + gst_vdp_buffer_set_buffer_pool (buf, NULL); + gst_vdp_buffer_unref (buf); +} + +static void +gst_vdp_buffer_pool_clear (GstVdpBufferPool * bpool) +{ + GstVdpBufferPoolPrivate *priv = bpool->priv; + + g_queue_foreach (priv->buffers, (GFunc) gst_vdp_buffer_free, NULL); + g_queue_clear (priv->buffers); +} + +gboolean +gst_vdp_buffer_pool_put_buffer (GstVdpBufferPool * bpool, GstVdpBuffer * buf) +{ + GstVdpBufferPoolPrivate *priv; + + gboolean res; + GstVdpBufferPoolClass *bpool_class; + GstCaps *caps; + + g_return_val_if_fail (GST_IS_VDP_BUFFER_POOL (bpool), FALSE); + g_return_val_if_fail (GST_IS_VDP_BUFFER (buf), FALSE); + + priv = bpool->priv; + g_return_val_if_fail (priv->caps, FALSE); + + g_mutex_lock (priv->mutex); + + if (priv->buffers->length == priv->max_buffers) { + res = FALSE; + goto done; + } + + bpool_class = GST_VDP_BUFFER_POOL_GET_CLASS (bpool); + caps = GST_BUFFER_CAPS (buf); + if (!caps) + goto no_caps; + + if (!bpool_class->check_caps (bpool, caps)) { + res = FALSE; + goto done; + } + + gst_vdp_buffer_ref (buf); + g_queue_push_tail (priv->buffers, buf); + res = TRUE; + +done: + g_mutex_unlock (priv->mutex); + + return res; + +no_caps: + GST_WARNING ("Buffer doesn't have any caps"); + res = FALSE; + goto done; +} + +GstVdpBuffer * +gst_vdp_buffer_pool_get_buffer (GstVdpBufferPool * bpool, GError ** error) +{ + GstVdpBufferPoolPrivate *priv; + GstVdpBuffer *buf; + + g_return_val_if_fail (GST_IS_VDP_BUFFER_POOL (bpool), NULL); + + priv = bpool->priv; + g_return_val_if_fail (priv->caps, NULL); + + g_mutex_lock (priv->mutex); + + buf = g_queue_pop_head (priv->buffers); + if (!buf) { + GstVdpBufferPoolClass *bpool_class = GST_VDP_BUFFER_POOL_GET_CLASS (bpool); + + buf = bpool_class->alloc_buffer (bpool, error); + if (!buf) + goto done; + gst_buffer_set_caps (GST_BUFFER_CAST (buf), priv->caps); + gst_vdp_buffer_set_buffer_pool (buf, bpool); + } + +done: + g_mutex_unlock (priv->mutex); + return buf; +} + +void +gst_vdp_buffer_pool_set_max_buffers (GstVdpBufferPool * bpool, + guint max_buffers) +{ + GstVdpBufferPoolPrivate *priv; + + g_return_if_fail (GST_IS_VDP_BUFFER_POOL (bpool)); + g_return_if_fail (max_buffers >= -1); + + priv = bpool->priv; + + g_mutex_lock (priv->mutex); + + if (max_buffers != -1) { + while (max_buffers < priv->buffers->length) { + GstVdpBuffer *buf; + + buf = g_queue_pop_tail (priv->buffers); + gst_vdp_buffer_unref (buf); + } + } + + priv->max_buffers = max_buffers; + + g_mutex_unlock (priv->mutex); +} + +guint +gst_vdp_buffer_pool_get_max_buffers (GstVdpBufferPool * bpool) +{ + g_return_val_if_fail (GST_IS_VDP_BUFFER_POOL (bpool), 0); + + return bpool->priv->max_buffers; +} + +void +gst_vdp_buffer_pool_set_caps (GstVdpBufferPool * bpool, const GstCaps * caps) +{ + GstVdpBufferPoolPrivate *priv; + GstVdpBufferPoolClass *bpool_class; + gboolean clear_bufs; + + g_return_if_fail (GST_IS_VDP_BUFFER_POOL (bpool)); + g_return_if_fail (GST_IS_CAPS (caps)); + + priv = bpool->priv; + bpool_class = GST_VDP_BUFFER_POOL_GET_CLASS (bpool); + + g_mutex_lock (priv->mutex); + + if (!bpool_class->set_caps (bpool, caps, &clear_bufs)) + goto invalid_caps; + + if (clear_bufs) + gst_vdp_buffer_pool_clear (bpool); + + if (priv->caps) + gst_caps_unref (priv->caps); + + priv->caps = gst_caps_copy (caps); + +done: + g_mutex_unlock (priv->mutex); + return; + +invalid_caps: + GST_WARNING ("Subclass didn't accept caps: %" GST_PTR_FORMAT, caps); + goto done; +} + +const GstCaps * +gst_vdp_buffer_pool_get_caps (GstVdpBufferPool * bpool) +{ + g_return_val_if_fail (GST_IS_VDP_BUFFER_POOL (bpool), NULL); + + return bpool->priv->caps; +} + +GstVdpDevice * +gst_vdp_buffer_pool_get_device (GstVdpBufferPool * bpool) +{ + g_return_val_if_fail (GST_IS_VDP_BUFFER_POOL (bpool), NULL); + + return bpool->priv->device; +} + +static void +gst_vdp_buffer_pool_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstVdpBufferPool *bpool = (GstVdpBufferPool *) object; + GstVdpBufferPoolPrivate *priv = bpool->priv; + + switch (prop_id) { + case PROP_DEVICE: + g_value_set_object (value, priv->device); + break; + + case PROP_CAPS: + g_value_set_pointer (value, priv->caps); + break; + + case PROP_MAX_BUFFERS: + g_value_set_uint (value, priv->max_buffers); + break; + + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdp_buffer_pool_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVdpBufferPool *bpool = (GstVdpBufferPool *) object; + GstVdpBufferPoolPrivate *priv = bpool->priv; + + switch (prop_id) { + case PROP_DEVICE: + priv->device = g_value_get_object (value); + break; + + case PROP_CAPS: + gst_vdp_buffer_pool_set_caps (bpool, g_value_get_pointer (value)); + break; + + case PROP_MAX_BUFFERS: + gst_vdp_buffer_pool_set_max_buffers (bpool, g_value_get_uint (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdp_buffer_pool_finalize (GObject * object) +{ + GstVdpBufferPool *bpool = GST_VDP_BUFFER_POOL (object); + GstVdpBufferPoolPrivate *priv = bpool->priv; + + g_mutex_free (priv->mutex); + + if (priv->caps) + gst_caps_unref (priv->caps); + + G_OBJECT_CLASS (gst_vdp_buffer_pool_parent_class)->finalize (object); +} + +static void +gst_vdp_buffer_pool_init (GstVdpBufferPool * bpool) +{ + GstVdpBufferPoolPrivate *priv; + + bpool->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (bpool, + GST_TYPE_VDP_BUFFER_POOL, GstVdpBufferPoolPrivate); + + priv->buffers = g_queue_new (); + priv->mutex = g_mutex_new (); + + /* properties */ + priv->caps = NULL; + priv->max_buffers = DEFAULT_MAX_BUFFERS; +} + +static void +gst_vdp_buffer_pool_class_init (GstVdpBufferPoolClass * bpool_klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (bpool_klass); + + g_type_class_add_private (bpool_klass, sizeof (GstVdpBufferPoolPrivate)); + + object_class->get_property = gst_vdp_buffer_pool_get_property; + object_class->set_property = gst_vdp_buffer_pool_set_property; + + object_class->finalize = gst_vdp_buffer_pool_finalize; + + /** + * GstVdpBufferPool:device: + * + * The #GstVdpDevice this pool is bound to. + */ + g_object_class_install_property + (object_class, + PROP_DEVICE, + g_param_spec_object ("device", + "Device", + "The GstVdpDevice this pool is bound to", + GST_TYPE_VDP_DEVICE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /** + * GstVdpBufferPool:caps: + * + * The video object capabilities represented as a #GstCaps. This + * shall hold at least the "width" and "height" properties. + */ + g_object_class_install_property + (object_class, + PROP_CAPS, + g_param_spec_pointer ("caps", + "Caps", "The buffer capabilities", G_PARAM_READWRITE)); + + /** + * GstVdpBufferPool:max-buffers: + * + * The maximum number of buffer in the pool. Or -1, the pool + * will hold as many objects as possible. + */ + g_object_class_install_property + (object_class, + PROP_MAX_BUFFERS, + g_param_spec_int ("max-buffers", + "Max Buffers", + "The maximum number of buffers in the pool, or -1 for unlimited", + -1, G_MAXINT32, DEFAULT_MAX_BUFFERS, G_PARAM_READWRITE)); +} diff --git a/sys/vdpau/gstvdp/gstvdpbufferpool.h b/sys/vdpau/gstvdp/gstvdpbufferpool.h new file mode 100644 index 000000000..4f3d92c68 --- /dev/null +++ b/sys/vdpau/gstvdp/gstvdpbufferpool.h @@ -0,0 +1,74 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GST_VDP_BUFFER_POOL_H_ +#define _GST_VDP_BUFFER_POOL_H_ + +#include <gst/gst.h> + +typedef struct _GstVdpBufferPool GstVdpBufferPool; + +#include "gstvdpdevice.h" +#include "gstvdpbuffer.h" + +G_BEGIN_DECLS + +#define GST_TYPE_VDP_BUFFER_POOL (gst_vdp_buffer_pool_get_type ()) +#define GST_VDP_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDP_BUFFER_POOL, GstVdpBufferPool)) +#define GST_VDP_BUFFER_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VDP_BUFFER_POOL, GstVdpBufferPoolClass)) +#define GST_IS_VDP_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDP_BUFFER_POOL)) +#define GST_IS_VDP_BUFFER_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VDP_BUFFER_POOL)) +#define GST_VDP_BUFFER_POOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDP_BUFFER_POOL, GstVdpBufferPoolClass)) + +typedef struct _GstVdpBufferPoolClass GstVdpBufferPoolClass; +typedef struct _GstVdpBufferPoolPrivate GstVdpBufferPoolPrivate; + +struct _GstVdpBufferPool +{ + GObject object; + + GstVdpBufferPoolPrivate *priv; +}; + +struct _GstVdpBufferPoolClass +{ + GObjectClass object_class; + + GstVdpBuffer *(*alloc_buffer) (GstVdpBufferPool *bpool, GError **error); + gboolean (*set_caps) (GstVdpBufferPool *bpool, const GstCaps *caps, gboolean *clear_bufs); + gboolean (*check_caps) (GstVdpBufferPool *bpool, const GstCaps *caps); +}; + +gboolean gst_vdp_buffer_pool_put_buffer (GstVdpBufferPool *bpool, GstVdpBuffer *buf); +GstVdpBuffer *gst_vdp_buffer_pool_get_buffer (GstVdpBufferPool * bpool, GError **error); + +void gst_vdp_buffer_pool_set_max_buffers (GstVdpBufferPool *bpool, guint max_buffers); +guint gst_vdp_buffer_pool_get_max_buffers (GstVdpBufferPool *bpool); + +void gst_vdp_buffer_pool_set_caps (GstVdpBufferPool *bpool, const GstCaps *caps); +const GstCaps *gst_vdp_buffer_pool_get_caps (GstVdpBufferPool * bpool); + +GstVdpDevice *gst_vdp_buffer_pool_get_device (GstVdpBufferPool * bpool); + +GType gst_vdp_buffer_pool_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* _GST_VDP_BUFFER_POOL_H_ */ |