Add a means to cap the number of objects allocated in the pool.

This commit is contained in:
gb 2010-04-21 15:03:31 +00:00
parent 30fbcb1ee8
commit b0493e729c
2 changed files with 197 additions and 9 deletions

View file

@ -41,6 +41,8 @@ struct _GstVaapiVideoPoolPrivate {
GQueue free_objects;
GList *used_objects;
GstCaps *caps;
guint used_count;
guint capacity;
};
enum {
@ -48,11 +50,20 @@ enum {
PROP_DISPLAY,
PROP_CAPS,
PROP_CAPACITY
};
static void
gst_vaapi_video_pool_set_caps(GstVaapiVideoPool *pool, GstCaps *caps);
static inline gpointer
gst_vaapi_video_pool_alloc_object(GstVaapiVideoPool *pool)
{
GstVaapiVideoPoolClass * const klass = GST_VAAPI_VIDEO_POOL_GET_CLASS(pool);
return klass->alloc_object(pool, pool->priv->display);
}
static void
gst_vaapi_video_pool_clear(GstVaapiVideoPool *pool)
{
@ -114,6 +125,9 @@ gst_vaapi_video_pool_set_property(
case PROP_CAPS:
gst_vaapi_video_pool_set_caps(pool, g_value_get_pointer(value));
break;
case PROP_CAPACITY:
gst_vaapi_video_pool_set_capacity(pool, g_value_get_uint(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -137,6 +151,9 @@ gst_vaapi_video_pool_get_property(
case PROP_CAPS:
g_value_set_pointer(value, gst_vaapi_video_pool_get_caps(pool));
break;
case PROP_CAPACITY:
g_value_set_uint(value, gst_vaapi_video_pool_get_capacity(pool));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@ -181,6 +198,21 @@ gst_vaapi_video_pool_class_init(GstVaapiVideoPoolClass *klass)
"caps",
"The video object capabilities",
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
/**
* GstVaapiVidePool:capacity:
*
* The maximum number of objects in the pool. Or zero, the pool
* will allocate as many objects as possible.
*/
g_object_class_install_property
(object_class,
PROP_CAPACITY,
g_param_spec_uint("capacity",
"capacity",
"The maximum number of objects in the pool",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE));
}
static void
@ -192,6 +224,8 @@ gst_vaapi_video_pool_init(GstVaapiVideoPool *pool)
priv->display = NULL;
priv->used_objects = NULL;
priv->caps = NULL;
priv->used_count = 0;
priv->capacity = 0;
g_queue_init(&priv->free_objects);
}
@ -245,32 +279,36 @@ gst_vaapi_video_pool_set_caps(GstVaapiVideoPool *pool, GstCaps *caps)
gpointer
gst_vaapi_video_pool_get_object(GstVaapiVideoPool *pool)
{
GstVaapiVideoPoolPrivate *priv;
gpointer object;
g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), NULL);
object = g_queue_pop_head(&pool->priv->free_objects);
priv = pool->priv;
if (priv->capacity && priv->used_count >= priv->capacity)
return NULL;
object = g_queue_pop_head(&priv->free_objects);
if (!object) {
object = GST_VAAPI_VIDEO_POOL_GET_CLASS(pool)->alloc_object(
pool,
pool->priv->display
);
object = gst_vaapi_video_pool_alloc_object(pool);
if (!object)
return NULL;
}
pool->priv->used_objects = g_list_prepend(pool->priv->used_objects, object);
++priv->used_count;
priv->used_objects = g_list_prepend(priv->used_objects, object);
return g_object_ref(object);
}
/**
* gst_vaapi_video_pool_put_object:
* @pool: a #GstVaapiVideoPool
* @object: the object to add to the pool
* @object: the object to add back to the pool
*
* Pushes the @object back into the pool. The @object shall be
* previously allocated from the @pool. Calling this function with an
* arbitrary object yields undefined behaviour.
* obtained from the @pool through gst_vaapi_video_pool_get_object().
* Calling this function with an arbitrary object yields undefined
* behaviour.
*/
void
gst_vaapi_video_pool_put_object(GstVaapiVideoPool *pool, gpointer object)
@ -287,6 +325,137 @@ gst_vaapi_video_pool_put_object(GstVaapiVideoPool *pool, gpointer object)
return;
g_object_unref(object);
--priv->used_count;
priv->used_objects = g_list_delete_link(priv->used_objects, elem);
g_queue_push_tail(&priv->free_objects, object);
}
/**
* gst_vaapi_video_pool_add_object:
* @pool: a #GstVaapiVideoPool
* @object: the object to add to the pool
*
* Adds the @object to the pool. The pool then holds a reference on
* the @object. This operation does not change the capacity of the
* pool.
*
* Return value: %TRUE on success.
*/
gboolean
gst_vaapi_video_pool_add_object(GstVaapiVideoPool *pool, gpointer object)
{
g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), FALSE);
g_return_val_if_fail(G_IS_OBJECT(object), FALSE);
g_queue_push_tail(&pool->priv->free_objects, g_object_ref(object));
return TRUE;
}
/**
* gst_vaapi_video_pool_add_objects:
* @pool: a #GstVaapiVideoPool
* @objects: a #GPtrArray of objects
*
* Adds the @objects to the pool. The pool then holds a reference on
* the @objects. This operation does not change the capacity of the
* pool and is just a wrapper around gst_vaapi_video_pool_add_object().
*
* Return value: %TRUE on success.
*/
gboolean
gst_vaapi_video_pool_add_objects(GstVaapiVideoPool *pool, GPtrArray *objects)
{
guint i;
g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), FALSE);
for (i = 0; i < objects->len; i++) {
gpointer const object = g_ptr_array_index(objects, i);
if (!gst_vaapi_video_pool_add_object(pool, object))
return FALSE;
}
return TRUE;
}
/**
* gst_vaapi_video_pool_get_size:
* @pool: a #GstVaapiVideoPool
*
* Returns the number of free objects available in the pool.
*
* Return value: number of free objects in the pool
*/
guint
gst_vaapi_video_pool_get_size(GstVaapiVideoPool *pool)
{
g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), 0);
return g_queue_get_length(&pool->priv->free_objects);
}
/**
* gst_vaapi_video_pool_reserve:
* @pool: a #GstVaapiVideoPool
* @n: the number of objects to pre-allocate
*
* Pre-allocates up to @n objects in the pool. If @n is less than or
* equal to the number of free and used objects in the pool, this call
* has no effect. Otherwise, it is a request for allocation of
* additional objects.
*
* Return value: %TRUE on success
*/
gboolean
gst_vaapi_video_pool_reserve(GstVaapiVideoPool *pool, guint n)
{
guint i, num_allocated;
g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), 0);
num_allocated = gst_vaapi_video_pool_get_size(pool) + pool->priv->used_count;
if (n < num_allocated)
return TRUE;
if ((n -= num_allocated) > pool->priv->capacity)
n = pool->priv->capacity;
for (i = num_allocated; i < n; i++) {
gpointer const object = gst_vaapi_video_pool_alloc_object(pool);
if (!object)
return FALSE;
g_queue_push_tail(&pool->priv->free_objects, object);
}
return TRUE;
}
/**
* gst_vaapi_video_pool_get_capacity:
* @pool: a #GstVaapiVideoPool
*
* Returns the maximum number of objects in the pool. i.e. the maximum
* number of objects that can be returned by gst_vaapi_video_pool_get_object().
*
* Return value: the capacity of the pool
*/
guint
gst_vaapi_video_pool_get_capacity(GstVaapiVideoPool *pool)
{
g_return_val_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool), 0);
return pool->priv->capacity;
}
/**
* gst_vaapi_video_pool_set_capacity:
* @pool: a #GstVaapiVideoPool
* @capacity: the maximal capacity of the pool
*
* Sets the maximum number of objects that can be allocated in the pool.
*/
void
gst_vaapi_video_pool_set_capacity(GstVaapiVideoPool *pool, guint capacity)
{
g_return_if_fail(GST_VAAPI_IS_VIDEO_POOL(pool));
pool->priv->capacity = capacity;
}

View file

@ -21,6 +21,7 @@
#ifndef GST_VAAPI_VIDEO_POOL_H
#define GST_VAAPI_VIDEO_POOL_H
#include <glib.h>
#include <gst/gstcaps.h>
#include <gst/vaapi/gstvaapidisplay.h>
@ -95,6 +96,24 @@ gst_vaapi_video_pool_get_object(GstVaapiVideoPool *pool);
void
gst_vaapi_video_pool_put_object(GstVaapiVideoPool *pool, gpointer object);
gboolean
gst_vaapi_video_pool_add_object(GstVaapiVideoPool *pool, gpointer object);
gboolean
gst_vaapi_video_pool_add_objects(GstVaapiVideoPool *pool, GPtrArray *objects);
guint
gst_vaapi_video_pool_get_size(GstVaapiVideoPool *pool);
gboolean
gst_vaapi_video_pool_reserve(GstVaapiVideoPool *pool, guint n);
guint
gst_vaapi_video_pool_get_capacity(GstVaapiVideoPool *pool);
void
gst_vaapi_video_pool_set_capacity(GstVaapiVideoPool *pool, guint capacity);
G_END_DECLS
#endif /* GST_VAAPI_VIDEO_POOL_H */