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_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

View 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;
@ -998,6 +1000,30 @@ gst_vaapi_context_get_size(
*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:
* @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);
}

View 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);

View 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;

View file

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

View 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);
}

View file

@ -25,11 +25,10 @@
#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
@ -42,6 +41,9 @@ typedef struct _GstVaapiSurfaceProxy GstVaapiSurfaceProxy;
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);