mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +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 --- */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
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 *
|
||||
new_image(GstVaapiDisplay *display, const GstVideoInfo *vip)
|
||||
{
|
||||
|
@ -289,40 +303,98 @@ gst_vaapi_video_memory_reset_surface(GstVaapiVideoMemory *mem)
|
|||
static gpointer
|
||||
gst_vaapi_video_memory_map(GstVaapiVideoMemory *mem, gsize maxsize, guint flags)
|
||||
{
|
||||
if (mem->map_type &&
|
||||
mem->map_type != GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE)
|
||||
goto error_incompatible_map;
|
||||
gpointer data;
|
||||
|
||||
if (mem->map_count == 0) {
|
||||
gst_vaapi_surface_proxy_replace(&mem->proxy,
|
||||
gst_vaapi_video_meta_get_surface_proxy(mem->meta));
|
||||
switch (flags & GST_MAP_READWRITE) {
|
||||
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)
|
||||
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++;
|
||||
return mem->proxy;
|
||||
return data;
|
||||
|
||||
/* ERRORS */
|
||||
error_incompatible_map:
|
||||
GST_ERROR("failed to map memory to a GstVaapiSurfaceProxy");
|
||||
error_unsupported_map:
|
||||
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;
|
||||
error_no_surface_proxy:
|
||||
GST_ERROR("failed to extract GstVaapiSurfaceProxy from video meta");
|
||||
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
|
||||
gst_vaapi_video_memory_unmap(GstVaapiVideoMemory *mem)
|
||||
{
|
||||
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);
|
||||
if (mem->map_count == 1) {
|
||||
switch (mem->map_type) {
|
||||
case GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE:
|
||||
gst_vaapi_surface_proxy_replace(&mem->proxy, NULL);
|
||||
break;
|
||||
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_count--;
|
||||
return;
|
||||
|
||||
/* ERRORS */
|
||||
|
|
|
@ -51,15 +51,18 @@ typedef struct _GstVaapiVideoAllocatorClass GstVaapiVideoAllocatorClass;
|
|||
/**
|
||||
* GstVaapiVideoMemoryMapType:
|
||||
* @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_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.
|
||||
*/
|
||||
typedef enum {
|
||||
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;
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue