mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-20 15:27:07 +00:00
vaapivideomemory: lock map and unmap operations
In order to avoid race condition when two threads call map/unmap the same VA surface, this patch mutex these operations. https://bugzilla.gnome.org/show_bug.cgi?id=774213
This commit is contained in:
parent
4ae9428072
commit
3fa9af225f
2 changed files with 30 additions and 11 deletions
|
@ -294,6 +294,7 @@ gboolean
|
|||
gst_video_meta_map_vaapi_memory (GstVideoMeta * meta, guint plane,
|
||||
GstMapInfo * info, gpointer * data, gint * stride, GstMapFlags flags)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GstAllocator *allocator;
|
||||
GstVaapiVideoMemory *const mem =
|
||||
GST_VAAPI_VIDEO_MEMORY_CAST (gst_buffer_peek_memory (meta->buffer, 0));
|
||||
|
@ -303,13 +304,14 @@ gst_video_meta_map_vaapi_memory (GstVideoMeta * meta, guint plane,
|
|||
g_return_val_if_fail (GST_VAAPI_IS_VIDEO_ALLOCATOR (allocator), FALSE);
|
||||
g_return_val_if_fail (mem->meta, FALSE);
|
||||
|
||||
g_mutex_lock (&mem->lock);
|
||||
if (mem->map_type && mem->map_type != GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR)
|
||||
goto error_incompatible_map;
|
||||
|
||||
/* Map for writing */
|
||||
if (mem->map_count == 0) {
|
||||
if (!map_vaapi_memory (mem, flags))
|
||||
return FALSE;
|
||||
goto out;
|
||||
mem->map_type = GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_PLANAR;
|
||||
}
|
||||
mem->map_count++;
|
||||
|
@ -317,13 +319,17 @@ gst_video_meta_map_vaapi_memory (GstVideoMeta * meta, guint plane,
|
|||
*data = gst_vaapi_image_get_plane (mem->image, plane);
|
||||
*stride = gst_vaapi_image_get_pitch (mem->image, plane);
|
||||
info->flags = flags;
|
||||
return TRUE;
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
g_mutex_unlock (&mem->lock);
|
||||
return ret;
|
||||
|
||||
/* ERRORS */
|
||||
error_incompatible_map:
|
||||
{
|
||||
GST_ERROR ("incompatible map type (%d)", mem->map_type);
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -342,6 +348,7 @@ gst_video_meta_unmap_vaapi_memory (GstVideoMeta * meta, guint plane,
|
|||
g_return_val_if_fail (mem->surface, FALSE);
|
||||
g_return_val_if_fail (mem->image, FALSE);
|
||||
|
||||
g_mutex_lock (&mem->lock);
|
||||
if (--mem->map_count == 0) {
|
||||
mem->map_type = 0;
|
||||
|
||||
|
@ -349,6 +356,7 @@ gst_video_meta_unmap_vaapi_memory (GstVideoMeta * meta, guint plane,
|
|||
if (info->flags & GST_MAP_READWRITE)
|
||||
unmap_vaapi_memory (mem, info->flags);
|
||||
}
|
||||
g_mutex_unlock (&mem->lock);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -381,6 +389,7 @@ gst_vaapi_video_memory_new (GstAllocator * base_allocator,
|
|||
mem->map_type = 0;
|
||||
mem->map_count = 0;
|
||||
mem->usage_flag = allocator->usage_flag;
|
||||
g_mutex_init (&mem->lock);
|
||||
|
||||
GST_VAAPI_VIDEO_MEMORY_FLAG_SET (mem,
|
||||
GST_VAAPI_VIDEO_MEMORY_FLAG_SURFACE_IS_CURRENT);
|
||||
|
@ -395,6 +404,7 @@ gst_vaapi_video_memory_free (GstVaapiVideoMemory * mem)
|
|||
gst_vaapi_surface_proxy_replace (&mem->proxy, NULL);
|
||||
gst_vaapi_video_meta_replace (&mem->meta, NULL);
|
||||
gst_object_unref (GST_MEMORY_CAST (mem)->allocator);
|
||||
g_mutex_clear (&mem->lock);
|
||||
g_slice_free (GstVaapiVideoMemory, mem);
|
||||
}
|
||||
|
||||
|
@ -442,11 +452,12 @@ static gpointer
|
|||
gst_vaapi_video_memory_map (GstVaapiVideoMemory * mem, gsize maxsize,
|
||||
guint flags)
|
||||
{
|
||||
gpointer data;
|
||||
gpointer data = NULL;
|
||||
|
||||
g_return_val_if_fail (mem, NULL);
|
||||
g_return_val_if_fail (mem->meta, NULL);
|
||||
|
||||
g_mutex_lock (&mem->lock);
|
||||
if (mem->map_count == 0) {
|
||||
switch (flags & GST_MAP_READWRITE) {
|
||||
case 0:
|
||||
|
@ -461,7 +472,7 @@ gst_vaapi_video_memory_map (GstVaapiVideoMemory * mem, gsize maxsize,
|
|||
break;
|
||||
case GST_MAP_READ:
|
||||
if (!map_vaapi_memory (mem, flags))
|
||||
return NULL;
|
||||
goto out;
|
||||
mem->map_type = GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_LINEAR;
|
||||
break;
|
||||
default:
|
||||
|
@ -484,39 +495,43 @@ gst_vaapi_video_memory_map (GstVaapiVideoMemory * mem, gsize maxsize,
|
|||
goto error_unsupported_map_type;
|
||||
}
|
||||
mem->map_count++;
|
||||
|
||||
out:
|
||||
g_mutex_unlock (&mem->lock);
|
||||
return data;
|
||||
|
||||
/* ERRORS */
|
||||
error_unsupported_map:
|
||||
{
|
||||
GST_ERROR ("unsupported map flags (0x%x)", flags);
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
error_unsupported_map_type:
|
||||
{
|
||||
GST_ERROR ("unsupported map type (%d)", mem->map_type);
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
error_no_surface_proxy:
|
||||
{
|
||||
GST_ERROR ("failed to extract GstVaapiSurfaceProxy from video meta");
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
error_no_current_surface:
|
||||
{
|
||||
GST_ERROR ("failed to make surface current");
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
error_no_image:
|
||||
{
|
||||
GST_ERROR ("failed to extract VA image from video buffer");
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vaapi_video_memory_unmap_full (GstVaapiVideoMemory * mem, GstMapInfo * info)
|
||||
{
|
||||
g_mutex_lock (&mem->lock);
|
||||
if (mem->map_count == 1) {
|
||||
switch (mem->map_type) {
|
||||
case GST_VAAPI_VIDEO_MEMORY_MAP_TYPE_SURFACE:
|
||||
|
@ -531,13 +546,16 @@ gst_vaapi_video_memory_unmap_full (GstVaapiVideoMemory * mem, GstMapInfo * info)
|
|||
mem->map_type = 0;
|
||||
}
|
||||
mem->map_count--;
|
||||
|
||||
out:
|
||||
g_mutex_unlock (&mem->lock);
|
||||
return;
|
||||
|
||||
/* ERRORS */
|
||||
error_incompatible_map:
|
||||
{
|
||||
GST_ERROR ("incompatible map type (%d)", mem->map_type);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,7 @@ struct _GstVaapiVideoMemory
|
|||
guint map_type;
|
||||
gint map_count;
|
||||
GstVaapiImageUsageFlags usage_flag;
|
||||
GMutex lock;
|
||||
};
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
|
|
Loading…
Reference in a new issue