summaryrefslogtreecommitdiff
path: root/sys/vdpau/gstvdp/gstvdpbufferpool.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vdpau/gstvdp/gstvdpbufferpool.c')
-rw-r--r--sys/vdpau/gstvdp/gstvdpbufferpool.c358
1 files changed, 358 insertions, 0 deletions
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));
+}