decoder: simplify acquisition/release of spare surface.

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.
This commit is contained in:
Gwenole Beauchesne 2013-04-03 11:37:44 +02:00
parent e76089f98b
commit e22a863084
7 changed files with 71 additions and 22 deletions

View file

@ -401,6 +401,7 @@ gst_vaapi_context_get_profile
gst_vaapi_context_set_profile gst_vaapi_context_set_profile
gst_vaapi_context_get_entrypoint gst_vaapi_context_get_entrypoint
gst_vaapi_context_get_size gst_vaapi_context_get_size
gst_vaapi_context_get_surface_proxy
gst_vaapi_context_get_surface gst_vaapi_context_get_surface
gst_vaapi_context_get_surface_count gst_vaapi_context_get_surface_count
gst_vaapi_context_put_surface 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_surface_id
gst_vaapi_surface_proxy_get_user_data gst_vaapi_surface_proxy_get_user_data
gst_vaapi_surface_proxy_new gst_vaapi_surface_proxy_new
gst_vaapi_surface_proxy_new_from_pool
gst_vaapi_surface_proxy_ref gst_vaapi_surface_proxy_ref
gst_vaapi_surface_proxy_replace gst_vaapi_surface_proxy_replace
gst_vaapi_surface_proxy_set_context gst_vaapi_surface_proxy_set_context

View file

@ -32,6 +32,7 @@
#include "gstvaapisurface.h" #include "gstvaapisurface.h"
#include "gstvaapisurface_priv.h" #include "gstvaapisurface_priv.h"
#include "gstvaapisurfacepool.h" #include "gstvaapisurfacepool.h"
#include "gstvaapisurfaceproxy.h"
#include "gstvaapiimage.h" #include "gstvaapiimage.h"
#include "gstvaapisubpicture.h" #include "gstvaapisubpicture.h"
#include "gstvaapiminiobject.h" #include "gstvaapiminiobject.h"
@ -503,6 +504,7 @@ gst_vaapi_context_create_surfaces(GstVaapiContext *context)
); );
if (!surface) if (!surface)
return FALSE; return FALSE;
gst_vaapi_surface_set_parent_context(surface, context);
g_ptr_array_add(priv->surfaces, surface); g_ptr_array_add(priv->surfaces, surface);
if (!gst_vaapi_video_pool_add_object(priv->surfaces_pool, surface)) if (!gst_vaapi_video_pool_add_object(priv->surfaces_pool, surface))
return FALSE; return FALSE;
@ -998,6 +1000,30 @@ gst_vaapi_context_get_size(
*pheight = context->priv->height; *pheight = context->priv->height;
} }
/**
* 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: * gst_vaapi_context_get_surface:
* @context: a #GstVaapiContext * @context: a #GstVaapiContext
@ -1012,16 +1038,9 @@ gst_vaapi_context_get_size(
GstVaapiSurface * GstVaapiSurface *
gst_vaapi_context_get_surface(GstVaapiContext *context) gst_vaapi_context_get_surface(GstVaapiContext *context)
{ {
GstVaapiSurface *surface;
g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL); g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL);
surface = gst_vaapi_video_pool_get_object(context->priv->surfaces_pool); return gst_vaapi_video_pool_get_object(context->priv->surfaces_pool);
if (!surface)
return NULL;
gst_vaapi_surface_set_parent_context(surface, context);
return surface;
} }
/** /**
@ -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_CONTEXT(context));
g_return_if_fail(GST_VAAPI_IS_SURFACE(surface)); 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); gst_vaapi_video_pool_put_object(context->priv->surfaces_pool, surface);
} }

View file

@ -143,6 +143,9 @@ gst_vaapi_context_get_size(
guint *pheight guint *pheight
); );
GstVaapiSurfaceProxy *
gst_vaapi_context_get_surface_proxy(GstVaapiContext *context);
GstVaapiSurface * GstVaapiSurface *
gst_vaapi_context_get_surface(GstVaapiContext *context); gst_vaapi_context_get_surface(GstVaapiContext *context);

View file

@ -75,10 +75,6 @@ gst_vaapi_picture_destroy(GstVaapiPicture *picture)
gst_vaapi_surface_proxy_unref(picture->proxy); gst_vaapi_surface_proxy_unref(picture->proxy);
picture->proxy = NULL; 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_id = VA_INVALID_ID;
picture->surface = NULL; picture->surface = NULL;
@ -103,7 +99,6 @@ gst_vaapi_picture_create(
GstVaapiPicture * const parent_picture = GST_VAAPI_PICTURE(args->data); GstVaapiPicture * const parent_picture = GST_VAAPI_PICTURE(args->data);
picture->proxy = gst_vaapi_surface_proxy_ref(parent_picture->proxy); 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->type = parent_picture->type;
picture->pts = parent_picture->pts; picture->pts = parent_picture->pts;
picture->poc = parent_picture->poc; picture->poc = parent_picture->poc;
@ -137,18 +132,15 @@ gst_vaapi_picture_create(
picture->type = GST_VAAPI_PICTURE_TYPE_NONE; picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
picture->pts = GST_CLOCK_TIME_NONE; picture->pts = GST_CLOCK_TIME_NONE;
picture->surface = gst_vaapi_context_get_surface(GET_CONTEXT(picture));
if (!picture->surface)
return FALSE;
picture->proxy = picture->proxy =
gst_vaapi_surface_proxy_new(GET_CONTEXT(picture), picture->surface); gst_vaapi_context_get_surface_proxy(GET_CONTEXT(picture));
if (!picture->proxy) if (!picture->proxy)
return FALSE; return FALSE;
picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME; picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_FF); 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->surface_id = gst_vaapi_surface_get_id(picture->surface);
picture->param_id = VA_INVALID_ID; picture->param_id = VA_INVALID_ID;

View file

@ -140,6 +140,7 @@ typedef enum {
typedef struct _GstVaapiSurface GstVaapiSurface; typedef struct _GstVaapiSurface GstVaapiSurface;
typedef struct _GstVaapiSurfacePrivate GstVaapiSurfacePrivate; typedef struct _GstVaapiSurfacePrivate GstVaapiSurfacePrivate;
typedef struct _GstVaapiSurfaceClass GstVaapiSurfaceClass; typedef struct _GstVaapiSurfaceClass GstVaapiSurfaceClass;
typedef struct _GstVaapiSurfaceProxy GstVaapiSurfaceProxy;
/** /**
* GstVaapiSurface: * GstVaapiSurface:

View file

@ -43,6 +43,7 @@ struct _GstVaapiSurfaceProxy {
/*< private >*/ /*< private >*/
GstVaapiMiniObject parent_instance; GstVaapiMiniObject parent_instance;
GstVaapiVideoPool *pool;
GstVaapiContext *context; GstVaapiContext *context;
GstVaapiSurface *surface; GstVaapiSurface *surface;
}; };
@ -87,11 +88,37 @@ gst_vaapi_surface_proxy_new(GstVaapiContext *context, GstVaapiSurface *surface)
if (!proxy) if (!proxy)
return NULL; return NULL;
proxy->pool = NULL;
proxy->context = g_object_ref(context); proxy->context = g_object_ref(context);
proxy->surface = g_object_ref(surface); proxy->surface = g_object_ref(surface);
return proxy; 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: * gst_vaapi_surface_proxy_ref:
* @proxy: a #GstVaapiSurfaceProxy * @proxy: a #GstVaapiSurfaceProxy
@ -272,12 +299,16 @@ gst_vaapi_surface_proxy_set_surface(
g_return_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy)); g_return_if_fail(GST_VAAPI_IS_SURFACE_PROXY(proxy));
if (proxy->surface) { 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); gst_vaapi_context_put_surface(proxy->context, proxy->surface);
g_object_unref(proxy->surface); g_object_unref(proxy->surface);
proxy->surface = NULL; proxy->surface = NULL;
} }
g_clear_object(&proxy->pool);
if (surface) if (surface)
proxy->surface = g_object_ref(surface); proxy->surface = g_object_ref(surface);
} }

View file

@ -25,11 +25,10 @@
#include <gst/vaapi/gstvaapicontext.h> #include <gst/vaapi/gstvaapicontext.h>
#include <gst/vaapi/gstvaapisurface.h> #include <gst/vaapi/gstvaapisurface.h>
#include <gst/vaapi/gstvaapisurfacepool.h>
G_BEGIN_DECLS G_BEGIN_DECLS
typedef struct _GstVaapiSurfaceProxy GstVaapiSurfaceProxy;
/** /**
* GST_VAAPI_SURFACE_PROXY_SURFACE: * GST_VAAPI_SURFACE_PROXY_SURFACE:
* @surface: a #GstVaapiSurfaceProxy * @surface: a #GstVaapiSurfaceProxy
@ -42,6 +41,9 @@ typedef struct _GstVaapiSurfaceProxy GstVaapiSurfaceProxy;
GstVaapiSurfaceProxy * GstVaapiSurfaceProxy *
gst_vaapi_surface_proxy_new(GstVaapiContext *context, GstVaapiSurface *surface); gst_vaapi_surface_proxy_new(GstVaapiContext *context, GstVaapiSurface *surface);
GstVaapiSurfaceProxy *
gst_vaapi_surface_proxy_new_from_pool(GstVaapiSurfacePool *pool);
GstVaapiSurfaceProxy * GstVaapiSurfaceProxy *
gst_vaapi_surface_proxy_ref(GstVaapiSurfaceProxy *proxy); gst_vaapi_surface_proxy_ref(GstVaapiSurfaceProxy *proxy);