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.
This commit is contained in:
Carl-Anton Ingmarsson 2010-07-30 10:55:56 +02:00
parent 093fcacc20
commit 7320eedc04
5 changed files with 581 additions and 0 deletions

View file

@ -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 \

View file

@ -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;
}

View file

@ -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

View file

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

View file

@ -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_ */