plugins: fix GstVaapiVideoMemory to allocate VA surface proxies.

Make sure GstVaapiVideoMemory allocates VA surface proxies from a
pool stored in the parent VA memory allocator.

This fixes the following scenario:
- VA video buffer 1 is allocated from a buffer pool
- Another video buffer is created, and inherits info from buffer 1
- Buffer 1 is released, thus pushing it back to the buffer pool
- New buffer alloc request comes it, this yields buffer 1 back
- At this stage, buffers 1 and 2 still share the same underlying VA
  surface, but buffer 2 was already submitted downstream for further
  processing, thus conflicting with additional processing we were
  about to perform on buffer 1.

Maybe the core GstBufferPool implementation should have been fixed
instead to actually make sure that the returned GstBuffer memory we
found from the pool is writable?
This commit is contained in:
Gwenole Beauchesne 2013-10-09 09:33:56 +02:00
parent cc9afca3ed
commit 4df68163dc
2 changed files with 51 additions and 8 deletions

View file

@ -83,18 +83,32 @@ new_surface(GstVaapiDisplay *display, const GstVideoInfo *vip)
GST_VIDEO_INFO_WIDTH(vip), GST_VIDEO_INFO_HEIGHT(vip)); GST_VIDEO_INFO_WIDTH(vip), GST_VIDEO_INFO_HEIGHT(vip));
} }
static GstVaapiSurfaceProxy *
new_surface_proxy(GstVaapiVideoMemory *mem)
{
GstVaapiVideoAllocator * const allocator =
GST_VAAPI_VIDEO_ALLOCATOR_CAST(GST_MEMORY_CAST(mem)->allocator);
return gst_vaapi_surface_proxy_new_from_pool(
GST_VAAPI_SURFACE_POOL(allocator->surface_pool));
}
static gboolean static gboolean
ensure_surface(GstVaapiVideoMemory *mem) ensure_surface(GstVaapiVideoMemory *mem)
{ {
if (!mem->surface) { if (!mem->proxy) {
GstVaapiDisplay * const display = gst_vaapi_surface_proxy_replace(&mem->proxy,
gst_vaapi_video_meta_get_display(mem->meta); gst_vaapi_video_meta_get_surface_proxy(mem->meta));
mem->surface = new_surface(display, mem->surface_info); if (!mem->proxy) {
if (!mem->surface) mem->proxy = new_surface_proxy(mem);
if (!mem->proxy)
return FALSE; return FALSE;
gst_vaapi_video_meta_set_surface_proxy(mem->meta, mem->proxy);
} }
gst_vaapi_video_meta_set_surface(mem->meta, mem->surface); mem->surface = GST_VAAPI_SURFACE_PROXY_SURFACE(mem->proxy);
}
g_return_val_if_fail(mem->surface != NULL, FALSE);
return TRUE; return TRUE;
} }
@ -236,7 +250,8 @@ gst_vaapi_video_memory_new(GstAllocator *base_allocator,
static void static void
gst_vaapi_video_memory_free(GstVaapiVideoMemory *mem) gst_vaapi_video_memory_free(GstVaapiVideoMemory *mem)
{ {
gst_vaapi_object_replace(&mem->surface, NULL); mem->surface = NULL;
gst_vaapi_surface_proxy_replace(&mem->proxy, NULL);
gst_vaapi_object_replace(&mem->image, NULL); gst_vaapi_object_replace(&mem->image, NULL);
gst_vaapi_video_meta_unref(mem->meta); gst_vaapi_video_meta_unref(mem->meta);
gst_object_unref(GST_MEMORY_CAST(mem)->allocator); gst_object_unref(GST_MEMORY_CAST(mem)->allocator);
@ -360,14 +375,27 @@ gst_vaapi_video_allocator_free(GstAllocator *allocator, GstMemory *mem)
gst_vaapi_video_memory_free(GST_VAAPI_VIDEO_MEMORY_CAST(mem)); gst_vaapi_video_memory_free(GST_VAAPI_VIDEO_MEMORY_CAST(mem));
} }
static void
gst_vaapi_video_allocator_finalize(GObject *object)
{
GstVaapiVideoAllocator * const allocator =
GST_VAAPI_VIDEO_ALLOCATOR_CAST(object);
gst_vaapi_video_pool_replace(&allocator->surface_pool, NULL);
G_OBJECT_CLASS(gst_vaapi_video_allocator_parent_class)->finalize(object);
}
static void static void
gst_vaapi_video_allocator_class_init(GstVaapiVideoAllocatorClass *klass) gst_vaapi_video_allocator_class_init(GstVaapiVideoAllocatorClass *klass)
{ {
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
GstAllocatorClass * const allocator_class = GST_ALLOCATOR_CLASS(klass); GstAllocatorClass * const allocator_class = GST_ALLOCATOR_CLASS(klass);
GST_DEBUG_CATEGORY_INIT(gst_debug_vaapivideomemory, GST_DEBUG_CATEGORY_INIT(gst_debug_vaapivideomemory,
"vaapivideomemory", 0, "VA-API video memory allocator"); "vaapivideomemory", 0, "VA-API video memory allocator");
object_class->finalize = gst_vaapi_video_allocator_finalize;
allocator_class->alloc = gst_vaapi_video_allocator_alloc; allocator_class->alloc = gst_vaapi_video_allocator_alloc;
allocator_class->free = gst_vaapi_video_allocator_free; allocator_class->free = gst_vaapi_video_allocator_free;
} }
@ -478,6 +506,11 @@ gst_vaapi_video_allocator_new(GstVaapiDisplay *display, GstCaps *caps)
gst_vaapi_object_unref(image); gst_vaapi_object_unref(image);
} }
allocator->surface_pool = gst_vaapi_surface_pool_new(display,
&allocator->surface_info);
if (!allocator->surface_pool)
goto error_create_pool;
allocator->image_info = *vip; allocator->image_info = *vip;
if (GST_VIDEO_INFO_FORMAT(vip) == GST_VIDEO_FORMAT_ENCODED) if (GST_VIDEO_INFO_FORMAT(vip) == GST_VIDEO_FORMAT_ENCODED)
gst_video_info_set_format(&allocator->image_info, GST_VIDEO_FORMAT_NV12, gst_video_info_set_format(&allocator->image_info, GST_VIDEO_FORMAT_NV12,
@ -498,4 +531,12 @@ gst_vaapi_video_allocator_new(GstVaapiDisplay *display, GstCaps *caps)
gst_vaapi_object_unref(image); gst_vaapi_object_unref(image);
} }
return GST_ALLOCATOR_CAST(allocator); return GST_ALLOCATOR_CAST(allocator);
/* ERRORS */
error_create_pool:
{
GST_ERROR("failed to allocate VA surface pool");
gst_object_unref(allocator);
return NULL;
}
} }

View file

@ -25,6 +25,7 @@
#include <gst/gstallocator.h> #include <gst/gstallocator.h>
#include <gst/video/video-info.h> #include <gst/video/video-info.h>
#include <gst/vaapi/gstvaapidisplay.h> #include <gst/vaapi/gstvaapidisplay.h>
#include <gst/vaapi/gstvaapisurfacepool.h>
#include "gstvaapivideometa.h" #include "gstvaapivideometa.h"
G_BEGIN_DECLS G_BEGIN_DECLS
@ -126,6 +127,7 @@ struct _GstVaapiVideoAllocator {
/*< private >*/ /*< private >*/
GstVideoInfo video_info; GstVideoInfo video_info;
GstVideoInfo surface_info; GstVideoInfo surface_info;
GstVaapiVideoPool *surface_pool;
GstVideoInfo image_info; GstVideoInfo image_info;
gboolean has_direct_rendering; gboolean has_direct_rendering;
}; };