plugins: allow buffer mappings to GstVaapiSurfaceProxy.

Allow plain gst_buffer_map() interface to work with gstreamer-vaapi
video buffers, i.e. expose the underlying GstVaapiSurfaceProxy to the
caller. This is the only sensible enough thing to do in this mode as
the underlying surface pixels need to be extracted through an explicit
call to the gst_video_frame_map() function instead.

A possible use-case of this is to implement a "handoff" signal handler
to fakesink or identity element for further processing.
This commit is contained in:
Gwenole Beauchesne 2013-06-05 11:01:51 +02:00
parent eb9dd361f8
commit e712abba11
2 changed files with 80 additions and 3 deletions

View file

@ -107,6 +107,9 @@ gst_video_meta_map_vaapi_memory(GstVideoMeta *meta, guint plane,
allocator), FALSE);
g_return_val_if_fail(mem->meta, FALSE);
if (mem->map_type &&
mem->map_type != GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR)
goto error_incompatible_map;
if ((flags & GST_MAP_READWRITE) != GST_MAP_WRITE)
goto error_unsupported_map;
@ -118,6 +121,7 @@ gst_video_meta_map_vaapi_memory(GstVideoMeta *meta, guint plane,
goto error_ensure_image;
if (!gst_vaapi_image_map(mem->image))
goto error_map_image;
mem->map_type = GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR;
}
*data = gst_vaapi_image_get_plane(mem->image, plane);
@ -126,6 +130,11 @@ gst_video_meta_map_vaapi_memory(GstVideoMeta *meta, guint plane,
return TRUE;
/* ERRORS */
error_incompatible_map:
{
GST_ERROR("incompatible map type (%d)", mem->map_type);
return FALSE;
}
error_unsupported_map:
{
GST_ERROR("unsupported map flags (0x%x)", flags);
@ -170,6 +179,8 @@ gst_video_meta_unmap_vaapi_memory(GstVideoMeta *meta, guint plane,
g_return_val_if_fail(mem->image, FALSE);
if (--mem->map_count == 0) {
mem->map_type = 0;
/* Unmap VA image used for read/writes */
if (info->flags & GST_MAP_READWRITE)
gst_vaapi_image_unmap(mem->image);
@ -207,11 +218,13 @@ gst_vaapi_video_memory_new(GstAllocator *base_allocator,
gst_memory_init(&mem->parent_instance, 0, base_allocator, NULL,
GST_VIDEO_INFO_SIZE(vip), 0, 0, GST_VIDEO_INFO_SIZE(vip));
mem->proxy = NULL;
mem->surface_info = &allocator->surface_info;
mem->surface = NULL;
mem->image_info = &allocator->image_info;
mem->image = NULL;
mem->meta = gst_vaapi_video_meta_ref(meta);
mem->map_type = 0;
mem->map_count = 0;
mem->use_direct_rendering = allocator->has_direct_rendering;
return GST_MEMORY_CAST(mem);
@ -229,21 +242,69 @@ gst_vaapi_video_memory_free(GstVaapiVideoMemory *mem)
static gpointer
gst_vaapi_video_memory_map(GstVaapiVideoMemory *mem, gsize maxsize, guint flags)
{
GST_FIXME("unimplemented GstVaapiVideoAllocator::mem_map() hook");
if (mem->map_type &&
mem->map_type != GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE)
goto error_incompatible_map;
if (mem->map_count == 0) {
gst_vaapi_surface_proxy_replace(&mem->proxy,
gst_vaapi_video_meta_get_surface_proxy(mem->meta));
if (!mem->proxy)
goto error_no_surface_proxy;
mem->map_type = GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE;
}
mem->map_count++;
return mem->proxy;
/* ERRORS */
error_incompatible_map:
GST_ERROR("failed to map memory to a GstVaapiSurfaceProxy");
return NULL;
error_no_surface_proxy:
GST_ERROR("failed to extract GstVaapiSurfaceProxy from video meta");
return NULL;
}
static void
gst_vaapi_video_memory_unmap(GstVaapiVideoMemory *mem)
{
GST_FIXME("unimplemented GstVaapiVideoAllocator::mem_unmap() hook");
if (mem->map_type &&
mem->map_type != GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE)
goto error_incompatible_map;
if (--mem->map_count == 0) {
gst_vaapi_surface_proxy_replace(&mem->proxy, NULL);
mem->map_type = 0;
}
return;
/* ERRORS */
error_incompatible_map:
GST_ERROR("incompatible map type (%d)", mem->map_type);
return;
}
static GstVaapiVideoMemory *
gst_vaapi_video_memory_copy(GstVaapiVideoMemory *mem,
gssize offset, gssize size)
{
GST_FIXME("unimplemented GstVaapiVideoAllocator::mem_copy() hook");
GstMemory *out_mem;
if (offset != 0 || size != -1)
goto error_unsupported;
out_mem = gst_vaapi_video_memory_new(mem->parent_instance.allocator,
mem->meta);
if (!out_mem)
goto error_allocate_memory;
return GST_VAAPI_VIDEO_MEMORY_CAST(out_mem);
/* ERRORS */
error_unsupported:
GST_ERROR("failed to copy partial memory (unsupported operation)");
return NULL;
error_allocate_memory:
GST_ERROR("failed to allocate GstVaapiVideoMemory copy");
return NULL;
}

View file

@ -42,6 +42,20 @@ typedef struct _GstVaapiVideoAllocatorClass GstVaapiVideoAllocatorClass;
#define GST_VAAPI_VIDEO_MEMORY_NAME "GstVaapiVideoMemory"
/**
* GstVaapiVideoMemoryMapType:
* @GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE: map with gst_buffer_map()
* as a whole and return a #GstVaapiSurfaceProxy
* @GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR: map individual plane with
* gst_video_frame_map()
*
* The set of all #GstVaapiVideoMemory map types.
*/
typedef enum {
GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE = 1,
GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR
} GstVaapiVideoMemoryMapType;
/**
* GstVaapiVideoMemory:
*
@ -52,11 +66,13 @@ struct _GstVaapiVideoMemory {
GstMemory parent_instance;
/*< private >*/
GstVaapiSurfaceProxy *proxy;
const GstVideoInfo *surface_info;
GstVaapiSurface *surface;
const GstVideoInfo *image_info;
GstVaapiImage *image;
GstVaapiVideoMeta *meta;
guint map_type;
gint map_count;
gboolean use_direct_rendering;
};