decoder: simplify acquisition/release of spare surface.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Wed, 3 Apr 2013 09:37:44 +0000 (11:37 +0200)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Wed, 3 Apr 2013 11:34:59 +0000 (13:34 +0200)
Introduce gst_vaapi_surface_proxy_new_from_pool() to allocate a new surface
proxy from the context surface pool. This change also makes sure to retain
the parent surface pool in the proxy.

Besides, it was also totally useless to attach/detach parent context to
VA surface each time we acquire/release it. Since the whole context owns
all associated VA surfaces, we can mark this as such only once and for all.

docs/reference/libs/libs-sections.txt
gst-libs/gst/vaapi/gstvaapicontext.c
gst-libs/gst/vaapi/gstvaapicontext.h
gst-libs/gst/vaapi/gstvaapidecoder_objects.c
gst-libs/gst/vaapi/gstvaapisurface.h
gst-libs/gst/vaapi/gstvaapisurfaceproxy.c
gst-libs/gst/vaapi/gstvaapisurfaceproxy.h

index 1402323..fcb701e 100644 (file)
@@ -401,6 +401,7 @@ gst_vaapi_context_get_profile
 gst_vaapi_context_set_profile
 gst_vaapi_context_get_entrypoint
 gst_vaapi_context_get_size
+gst_vaapi_context_get_surface_proxy
 gst_vaapi_context_get_surface
 gst_vaapi_context_get_surface_count
 gst_vaapi_context_put_surface
@@ -528,6 +529,7 @@ gst_vaapi_surface_proxy_get_surface
 gst_vaapi_surface_proxy_get_surface_id
 gst_vaapi_surface_proxy_get_user_data
 gst_vaapi_surface_proxy_new
+gst_vaapi_surface_proxy_new_from_pool
 gst_vaapi_surface_proxy_ref
 gst_vaapi_surface_proxy_replace
 gst_vaapi_surface_proxy_set_context
index 8d5a6d1..44cafc4 100644 (file)
@@ -32,6 +32,7 @@
 #include "gstvaapisurface.h"
 #include "gstvaapisurface_priv.h"
 #include "gstvaapisurfacepool.h"
+#include "gstvaapisurfaceproxy.h"
 #include "gstvaapiimage.h"
 #include "gstvaapisubpicture.h"
 #include "gstvaapiminiobject.h"
@@ -503,6 +504,7 @@ gst_vaapi_context_create_surfaces(GstVaapiContext *context)
         );
         if (!surface)
             return FALSE;
+        gst_vaapi_surface_set_parent_context(surface, context);
         g_ptr_array_add(priv->surfaces, surface);
         if (!gst_vaapi_video_pool_add_object(priv->surfaces_pool, surface))
             return FALSE;
@@ -999,6 +1001,30 @@ gst_vaapi_context_get_size(
 }
 
 /**
+ * gst_vaapi_context_get_surface_proxy:
+ * @context: a #GstVaapiContext
+ *
+ * Acquires a free surface, wrapped into a #GstVaapiSurfaceProxy. The
+ * returned surface will be automatically released when the proxy is
+ * destroyed. So, it is enough to call gst_vaapi_surface_proxy_unref()
+ * after usage.
+ *
+ * This function returns %NULL if there is no free surface available
+ * in the pool. The surfaces are pre-allocated during context creation
+ * though.
+ *
+ * Return value: a free surface, or %NULL if none is available
+ */
+GstVaapiSurfaceProxy *
+gst_vaapi_context_get_surface_proxy(GstVaapiContext *context)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL);
+
+    return gst_vaapi_surface_proxy_new_from_pool(
+        GST_VAAPI_SURFACE_POOL(context->priv->surfaces_pool));
+}
+
+/**
  * gst_vaapi_context_get_surface:
  * @context: a #GstVaapiContext
  *
@@ -1012,16 +1038,9 @@ gst_vaapi_context_get_size(
 GstVaapiSurface *
 gst_vaapi_context_get_surface(GstVaapiContext *context)
 {
-    GstVaapiSurface *surface;
-
     g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL);
 
-    surface = gst_vaapi_video_pool_get_object(context->priv->surfaces_pool);
-    if (!surface)
-        return NULL;
-
-    gst_vaapi_surface_set_parent_context(surface, context);
-    return surface;
+    return gst_vaapi_video_pool_get_object(context->priv->surfaces_pool);
 }
 
 /**
@@ -1053,7 +1072,6 @@ gst_vaapi_context_put_surface(GstVaapiContext *context, GstVaapiSurface *surface
     g_return_if_fail(GST_VAAPI_IS_CONTEXT(context));
     g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));
 
-    gst_vaapi_surface_set_parent_context(surface, NULL);
     gst_vaapi_video_pool_put_object(context->priv->surfaces_pool, surface);
 }
 
index 41ce0c5..11c38ff 100644 (file)
@@ -143,6 +143,9 @@ gst_vaapi_context_get_size(
     guint           *pheight
 );
 
+GstVaapiSurfaceProxy *
+gst_vaapi_context_get_surface_proxy(GstVaapiContext *context);
+
 GstVaapiSurface *
 gst_vaapi_context_get_surface(GstVaapiContext *context);
 
index 9b450bb..dfa8418 100644 (file)
@@ -75,10 +75,6 @@ gst_vaapi_picture_destroy(GstVaapiPicture *picture)
         gst_vaapi_surface_proxy_unref(picture->proxy);
         picture->proxy = NULL;
     }
-    else if (picture->surface) {
-        /* Explicitly release any surface that was not bound to a proxy */
-        gst_vaapi_context_put_surface(GET_CONTEXT(picture), picture->surface);
-    }
     picture->surface_id = VA_INVALID_ID;
     picture->surface = NULL;
 
@@ -103,7 +99,6 @@ gst_vaapi_picture_create(
         GstVaapiPicture * const parent_picture = GST_VAAPI_PICTURE(args->data);
 
         picture->proxy   = gst_vaapi_surface_proxy_ref(parent_picture->proxy);
-        picture->surface = gst_vaapi_surface_proxy_get_surface(picture->proxy);
         picture->type    = parent_picture->type;
         picture->pts     = parent_picture->pts;
         picture->poc     = parent_picture->poc;
@@ -137,18 +132,15 @@ gst_vaapi_picture_create(
         picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
         picture->pts  = GST_CLOCK_TIME_NONE;
 
-        picture->surface = gst_vaapi_context_get_surface(GET_CONTEXT(picture));
-        if (!picture->surface)
-            return FALSE;
-
         picture->proxy =
-            gst_vaapi_surface_proxy_new(GET_CONTEXT(picture), picture->surface);
+            gst_vaapi_context_get_surface_proxy(GET_CONTEXT(picture));
         if (!picture->proxy)
             return FALSE;
 
         picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
         GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_FF);
     }
+    picture->surface    = gst_vaapi_surface_proxy_get_surface(picture->proxy);
     picture->surface_id = gst_vaapi_surface_get_id(picture->surface);
 
     picture->param_id = VA_INVALID_ID;
index 9b74e7a..2d98b5e 100644 (file)
@@ -140,6 +140,7 @@ typedef enum {
 typedef struct _GstVaapiSurface                 GstVaapiSurface;
 typedef struct _GstVaapiSurfacePrivate          GstVaapiSurfacePrivate;
 typedef struct _GstVaapiSurfaceClass            GstVaapiSurfaceClass;
+typedef struct _GstVaapiSurfaceProxy            GstVaapiSurfaceProxy;
 
 /**
  * GstVaapiSurface:
index db0db25..84b4256 100644 (file)
@@ -43,6 +43,7 @@ struct _GstVaapiSurfaceProxy {
     /*< private >*/
     GstVaapiMiniObject  parent_instance;
 
+    GstVaapiVideoPool  *pool;
     GstVaapiContext    *context;
     GstVaapiSurface    *surface;
 };
@@ -87,11 +88,37 @@ gst_vaapi_surface_proxy_new(GstVaapiContext *context, GstVaapiSurface *surface)
     if (!proxy)
         return NULL;
 
+    proxy->pool    = NULL;
     proxy->context = g_object_ref(context);
     proxy->surface = g_object_ref(surface);
     return proxy;
 }
 
+GstVaapiSurfaceProxy *
+gst_vaapi_surface_proxy_new_from_pool(GstVaapiSurfacePool *pool)
+{
+    GstVaapiSurfaceProxy *proxy;
+
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE_POOL(pool), NULL);
+
+    proxy = (GstVaapiSurfaceProxy *)
+        gst_vaapi_mini_object_new(gst_vaapi_surface_proxy_class());
+    if (!proxy)
+        return NULL;
+
+    proxy->pool    = g_object_ref(pool);
+    proxy->context = NULL;
+    proxy->surface = gst_vaapi_video_pool_get_object(proxy->pool);
+    if (!proxy->surface)
+        goto error;
+    g_object_ref(proxy->surface);
+    return proxy;
+
+error:
+    gst_vaapi_surface_proxy_unref(proxy);
+    return NULL;
+}
+
 /**
  * gst_vaapi_surface_proxy_ref:
  * @proxy: a #GstVaapiSurfaceProxy
@@ -272,12 +299,16 @@ gst_vaapi_surface_proxy_set_surface(
     g_return_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy));
 
     if (proxy->surface) {
-        if (proxy->context)
+        if (proxy->pool)
+            gst_vaapi_video_pool_put_object(proxy->pool, proxy->surface);
+        else if (proxy->context)
             gst_vaapi_context_put_surface(proxy->context, proxy->surface);
         g_object_unref(proxy->surface);
         proxy->surface = NULL;
     }
 
+    g_clear_object(&proxy->pool);
+
     if (surface)
         proxy->surface = g_object_ref(surface);
 }
index a8fe2d1..15a933a 100644 (file)
 
 #include <gst/vaapi/gstvaapicontext.h>
 #include <gst/vaapi/gstvaapisurface.h>
+#include <gst/vaapi/gstvaapisurfacepool.h>
 
 G_BEGIN_DECLS
 
-typedef struct _GstVaapiSurfaceProxy            GstVaapiSurfaceProxy;
-
 /**
  * GST_VAAPI_SURFACE_PROXY_SURFACE:
  * @surface: a #GstVaapiSurfaceProxy
@@ -43,6 +42,9 @@ GstVaapiSurfaceProxy *
 gst_vaapi_surface_proxy_new(GstVaapiContext *context, GstVaapiSurface *surface);
 
 GstVaapiSurfaceProxy *
+gst_vaapi_surface_proxy_new_from_pool(GstVaapiSurfacePool *pool);
+
+GstVaapiSurfaceProxy *
 gst_vaapi_surface_proxy_ref(GstVaapiSurfaceProxy *proxy);
 
 void