Add a means to cap the number of objects allocated in the pool.
authorgb <gb@5584edef-b1fe-4b99-b61b-dd2bab72e969>
Wed, 21 Apr 2010 15:03:31 +0000 (15:03 +0000)
committergb <gb@5584edef-b1fe-4b99-b61b-dd2bab72e969>
Wed, 21 Apr 2010 15:03:31 +0000 (15:03 +0000)
gst-libs/gst/vaapi/gstvaapivideopool.c
gst-libs/gst/vaapi/gstvaapivideopool.h

index 5593612..985742e 100644 (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;
+}
index d779f43..5dce39f 100644 (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 */