From b0493e729c533b8aaa7f1ad4e85bc364aa2f2cde Mon Sep 17 00:00:00 2001 From: gb Date: Wed, 21 Apr 2010 15:03:31 +0000 Subject: [PATCH] Add a means to cap the number of objects allocated in the pool. --- gst-libs/gst/vaapi/gstvaapivideopool.c | 187 +++++++++++++++++++++++++++++++-- gst-libs/gst/vaapi/gstvaapivideopool.h | 19 ++++ 2 files changed, 197 insertions(+), 9 deletions(-) diff --git a/gst-libs/gst/vaapi/gstvaapivideopool.c b/gst-libs/gst/vaapi/gstvaapivideopool.c index 5593612..985742e 100644 --- a/gst-libs/gst/vaapi/gstvaapivideopool.c +++ b/gst-libs/gst/vaapi/gstvaapivideopool.c @@ -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; +} diff --git a/gst-libs/gst/vaapi/gstvaapivideopool.h b/gst-libs/gst/vaapi/gstvaapivideopool.h index d779f43..5dce39f 100644 --- a/gst-libs/gst/vaapi/gstvaapivideopool.h +++ b/gst-libs/gst/vaapi/gstvaapivideopool.h @@ -21,6 +21,7 @@ #ifndef GST_VAAPI_VIDEO_POOL_H #define GST_VAAPI_VIDEO_POOL_H +#include #include #include @@ -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 */ -- 2.7.4