mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
vaapivideomemory: add support for raw pixels mappings.
Allow raw pixels of the whole frame to be mapped read-only. i.e. in cases where the buffer pool is allocated without VideoMeta API, thus individual planes cannot be mapped. This is initial support for Firefox >= 30. https://bugzilla.gnome.org/show_bug.cgi?id=731886
This commit is contained in:
parent
9cb3acc813
commit
9cad85a936
2 changed files with 92 additions and 17 deletions
|
@ -35,6 +35,20 @@ GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapivideomemory);
|
||||||
/* --- GstVaapiVideoMemory --- */
|
/* --- GstVaapiVideoMemory --- */
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static guchar *
|
||||||
|
get_image_data(GstVaapiImage *image)
|
||||||
|
{
|
||||||
|
guchar *data;
|
||||||
|
VAImage va_image;
|
||||||
|
|
||||||
|
data = gst_vaapi_image_get_plane(image, 0);
|
||||||
|
if (!data || !gst_vaapi_image_get_image(image, &va_image))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
data -= va_image.offsets[0];
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
static GstVaapiImage *
|
static GstVaapiImage *
|
||||||
new_image(GstVaapiDisplay *display, const GstVideoInfo *vip)
|
new_image(GstVaapiDisplay *display, const GstVideoInfo *vip)
|
||||||
{
|
{
|
||||||
|
@ -289,40 +303,98 @@ gst_vaapi_video_memory_reset_surface(GstVaapiVideoMemory *mem)
|
||||||
static gpointer
|
static gpointer
|
||||||
gst_vaapi_video_memory_map(GstVaapiVideoMemory *mem, gsize maxsize, guint flags)
|
gst_vaapi_video_memory_map(GstVaapiVideoMemory *mem, gsize maxsize, guint flags)
|
||||||
{
|
{
|
||||||
if (mem->map_type &&
|
gpointer data;
|
||||||
mem->map_type != GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE)
|
|
||||||
goto error_incompatible_map;
|
|
||||||
|
|
||||||
if (mem->map_count == 0) {
|
if (mem->map_count == 0) {
|
||||||
gst_vaapi_surface_proxy_replace(&mem->proxy,
|
switch (flags & GST_MAP_READWRITE) {
|
||||||
gst_vaapi_video_meta_get_surface_proxy(mem->meta));
|
case 0:
|
||||||
|
// No flags set: return a GstVaapiSurfaceProxy
|
||||||
|
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;
|
||||||
|
break;
|
||||||
|
case GST_MAP_READ:
|
||||||
|
// Only read flag set: return raw pixels
|
||||||
|
if (!ensure_surface(mem))
|
||||||
|
return NULL;
|
||||||
|
if (!ensure_image(mem))
|
||||||
|
goto error_ensure_image;
|
||||||
|
if (!mem->use_direct_rendering)
|
||||||
|
gst_vaapi_surface_get_image(mem->surface, mem->image);
|
||||||
|
if (!gst_vaapi_image_map(mem->image))
|
||||||
|
goto error_map_image;
|
||||||
|
mem->map_type = GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_LINEAR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto error_unsupported_map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mem->map_type) {
|
||||||
|
case GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE:
|
||||||
if (!mem->proxy)
|
if (!mem->proxy)
|
||||||
goto error_no_surface_proxy;
|
goto error_no_surface_proxy;
|
||||||
mem->map_type = GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE;
|
data = mem->proxy;
|
||||||
|
break;
|
||||||
|
case GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_LINEAR:
|
||||||
|
if (!mem->image)
|
||||||
|
goto error_no_image;
|
||||||
|
data = get_image_data(mem->image);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto error_unsupported_map_type;
|
||||||
}
|
}
|
||||||
mem->map_count++;
|
mem->map_count++;
|
||||||
return mem->proxy;
|
return data;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
error_incompatible_map:
|
error_unsupported_map:
|
||||||
GST_ERROR("failed to map memory to a GstVaapiSurfaceProxy");
|
GST_ERROR("unsupported map flags (0x%x)", flags);
|
||||||
|
return NULL;
|
||||||
|
error_unsupported_map_type:
|
||||||
|
GST_ERROR("unsupported map type (%d)", mem->map_type);
|
||||||
return NULL;
|
return NULL;
|
||||||
error_no_surface_proxy:
|
error_no_surface_proxy:
|
||||||
GST_ERROR("failed to extract GstVaapiSurfaceProxy from video meta");
|
GST_ERROR("failed to extract GstVaapiSurfaceProxy from video meta");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
error_no_image:
|
||||||
|
GST_ERROR("failed to extract raw pixels from mapped VA image");
|
||||||
|
return NULL;
|
||||||
|
error_ensure_image:
|
||||||
|
{
|
||||||
|
const GstVideoInfo * const vip = mem->image_info;
|
||||||
|
GST_ERROR("failed to create %s image of size %ux%u",
|
||||||
|
GST_VIDEO_INFO_FORMAT_STRING(vip),
|
||||||
|
GST_VIDEO_INFO_WIDTH(vip), GST_VIDEO_INFO_HEIGHT(vip));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
error_map_image:
|
||||||
|
{
|
||||||
|
GST_ERROR("failed to map image %" GST_VAAPI_ID_FORMAT,
|
||||||
|
GST_VAAPI_ID_ARGS(gst_vaapi_image_get_id(mem->image)));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_vaapi_video_memory_unmap(GstVaapiVideoMemory *mem)
|
gst_vaapi_video_memory_unmap(GstVaapiVideoMemory *mem)
|
||||||
{
|
{
|
||||||
if (mem->map_type &&
|
if (mem->map_count == 1) {
|
||||||
mem->map_type != GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE)
|
switch (mem->map_type) {
|
||||||
goto error_incompatible_map;
|
case GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE:
|
||||||
|
gst_vaapi_surface_proxy_replace(&mem->proxy, NULL);
|
||||||
if (--mem->map_count == 0) {
|
break;
|
||||||
gst_vaapi_surface_proxy_replace(&mem->proxy, NULL);
|
case GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_LINEAR:
|
||||||
|
gst_vaapi_image_unmap(mem->image);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto error_incompatible_map;
|
||||||
|
}
|
||||||
mem->map_type = 0;
|
mem->map_type = 0;
|
||||||
}
|
}
|
||||||
|
mem->map_count--;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
|
|
|
@ -51,15 +51,18 @@ typedef struct _GstVaapiVideoAllocatorClass GstVaapiVideoAllocatorClass;
|
||||||
/**
|
/**
|
||||||
* GstVaapiVideoMemoryMapType:
|
* GstVaapiVideoMemoryMapType:
|
||||||
* @GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE: map with gst_buffer_map()
|
* @GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE: map with gst_buffer_map()
|
||||||
* as a whole and return a #GstVaapiSurfaceProxy
|
* and flags = 0x00 to return a #GstVaapiSurfaceProxy
|
||||||
* @GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR: map individual plane with
|
* @GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR: map individual plane with
|
||||||
* gst_video_frame_map()
|
* gst_video_frame_map()
|
||||||
|
* @GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_LINEAR: map with gst_buffer_map()
|
||||||
|
* and flags = GST_MAP_READ to return the raw pixels of the whole image
|
||||||
*
|
*
|
||||||
* The set of all #GstVaapiVideoMemory map types.
|
* The set of all #GstVaapiVideoMemory map types.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE = 1,
|
GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE = 1,
|
||||||
GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR
|
GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR,
|
||||||
|
GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_LINEAR
|
||||||
} GstVaapiVideoMemoryMapType;
|
} GstVaapiVideoMemoryMapType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue