gleglimage: cache EGL images per DmabufUpload
Do not store cached EGL images in GstMemory QData. Instead, use a per-DmabufUpload GHashTable to store cache entries with a weak reference to the GstMemory. This allows two glupload elements on separate tee branches to have their own EGL image cache. For this pipeline: gst-launch-1.0 v4l2src ! tee name=t \ t. ! queue ! glupload ! fakesink t. ! queue ! glupload ! fakesink this gets rid of the occasional critical error message: GStreamer-CRITICAL **: 08:26:33.194: gst_mini_object_unref: assertion 'GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) > 0' failed Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3880>
This commit is contained in:
parent
3943503fc1
commit
485c8ef4b5
@ -486,11 +486,24 @@ static const UploadMethod _gl_memory_upload = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if GST_GL_HAVE_DMABUF
|
#if GST_GL_HAVE_DMABUF
|
||||||
|
typedef struct _GstEGLImageCacheEntry
|
||||||
|
{
|
||||||
|
GstEGLImage *eglimage[GST_VIDEO_MAX_PLANES];
|
||||||
|
} GstEGLImageCacheEntry;
|
||||||
|
|
||||||
|
typedef struct _GstEGLImageCache
|
||||||
|
{
|
||||||
|
gint ref_count;
|
||||||
|
GHashTable *hash_table; /* for GstMemory -> GstEGLImageCacheEntry lookup */
|
||||||
|
GMutex lock; /* protects hash_table */
|
||||||
|
} GstEGLImageCache;
|
||||||
|
|
||||||
struct DmabufUpload
|
struct DmabufUpload
|
||||||
{
|
{
|
||||||
GstGLUpload *upload;
|
GstGLUpload *upload;
|
||||||
|
|
||||||
GstEGLImage *eglimage[GST_VIDEO_MAX_PLANES];
|
GstEGLImage *eglimage[GST_VIDEO_MAX_PLANES];
|
||||||
|
GstEGLImageCache *eglimage_cache;
|
||||||
GstGLFormat formats[GST_VIDEO_MAX_PLANES];
|
GstGLFormat formats[GST_VIDEO_MAX_PLANES];
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
GstGLVideoAllocationParams *params;
|
GstGLVideoAllocationParams *params;
|
||||||
@ -503,6 +516,111 @@ struct DmabufUpload
|
|||||||
gpointer out_caps;
|
gpointer out_caps;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_egl_image_cache_ref (GstEGLImageCache * cache)
|
||||||
|
{
|
||||||
|
g_atomic_int_inc (&cache->ref_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_egl_image_cache_unref (GstEGLImageCache * cache)
|
||||||
|
{
|
||||||
|
if (g_atomic_int_dec_and_test (&cache->ref_count)) {
|
||||||
|
g_hash_table_unref (cache->hash_table);
|
||||||
|
g_mutex_clear (&cache->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_egl_image_cache_entry_remove (GstEGLImageCache * cache, GstMiniObject * mem)
|
||||||
|
{
|
||||||
|
g_mutex_lock (&cache->lock);
|
||||||
|
g_hash_table_remove (cache->hash_table, mem);
|
||||||
|
g_mutex_unlock (&cache->lock);
|
||||||
|
gst_egl_image_cache_unref (cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstEGLImageCacheEntry *
|
||||||
|
gst_egl_image_cache_entry_new (GstEGLImageCache * cache, GstMemory * mem)
|
||||||
|
{
|
||||||
|
GstEGLImageCacheEntry *cache_entry;
|
||||||
|
|
||||||
|
cache_entry = g_new0 (GstEGLImageCacheEntry, 1);
|
||||||
|
gst_egl_image_cache_ref (cache);
|
||||||
|
gst_mini_object_weak_ref (GST_MINI_OBJECT (mem),
|
||||||
|
(GstMiniObjectNotify) gst_egl_image_cache_entry_remove, cache);
|
||||||
|
g_mutex_lock (&cache->lock);
|
||||||
|
g_hash_table_insert (cache->hash_table, mem, cache_entry);
|
||||||
|
g_mutex_unlock (&cache->lock);
|
||||||
|
|
||||||
|
return cache_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_egl_image_cache_entry_free (GstEGLImageCacheEntry * cache_entry)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
||||||
|
if (cache_entry->eglimage[i])
|
||||||
|
gst_egl_image_unref (cache_entry->eglimage[i]);
|
||||||
|
}
|
||||||
|
g_free (cache_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Looks up a cache_entry for mem if mem is different from previous_mem.
|
||||||
|
* If mem is the same as previous_mem, the costly lookup is skipped and the
|
||||||
|
* provided (previous) cache_entry is used instead.
|
||||||
|
*
|
||||||
|
* Returns the cached eglimage for the given plane from the cache_entry, or
|
||||||
|
* NULL. previous_mem is set to mem.
|
||||||
|
*/
|
||||||
|
static GstEGLImage *
|
||||||
|
gst_egl_image_cache_lookup (GstEGLImageCache * cache, GstMemory * mem,
|
||||||
|
gint plane, GstMemory ** previous_mem, GstEGLImageCacheEntry ** cache_entry)
|
||||||
|
{
|
||||||
|
if (mem != *previous_mem) {
|
||||||
|
g_mutex_lock (&cache->lock);
|
||||||
|
*cache_entry = g_hash_table_lookup (cache->hash_table, mem);
|
||||||
|
g_mutex_unlock (&cache->lock);
|
||||||
|
*previous_mem = mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*cache_entry)
|
||||||
|
return (*cache_entry)->eglimage[plane];
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a new cache_entry for mem if no cache_entry is provided.
|
||||||
|
* Stores the eglimage for the given plane in the cache_entry.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
gst_egl_image_cache_store (GstEGLImageCache * cache, GstMemory * mem,
|
||||||
|
gint plane, GstEGLImage * eglimage, GstEGLImageCacheEntry ** cache_entry)
|
||||||
|
{
|
||||||
|
if (!(*cache_entry))
|
||||||
|
*cache_entry = gst_egl_image_cache_entry_new (cache, mem);
|
||||||
|
(*cache_entry)->eglimage[plane] = eglimage;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstEGLImageCache *
|
||||||
|
gst_egl_image_cache_new (void)
|
||||||
|
{
|
||||||
|
GstEGLImageCache *cache;
|
||||||
|
|
||||||
|
cache = g_new0 (GstEGLImageCache, 1);
|
||||||
|
cache->ref_count = 1;
|
||||||
|
|
||||||
|
cache->hash_table = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||||
|
NULL, (GDestroyNotify) gst_egl_image_cache_entry_free);
|
||||||
|
g_mutex_init (&cache->lock);
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
static GstStaticCaps _dma_buf_upload_caps =
|
static GstStaticCaps _dma_buf_upload_caps =
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
||||||
(GST_CAPS_FEATURE_MEMORY_DMABUF,
|
(GST_CAPS_FEATURE_MEMORY_DMABUF,
|
||||||
@ -514,6 +632,7 @@ _dma_buf_upload_new (GstGLUpload * upload)
|
|||||||
{
|
{
|
||||||
struct DmabufUpload *dmabuf = g_new0 (struct DmabufUpload, 1);
|
struct DmabufUpload *dmabuf = g_new0 (struct DmabufUpload, 1);
|
||||||
dmabuf->upload = upload;
|
dmabuf->upload = upload;
|
||||||
|
dmabuf->eglimage_cache = gst_egl_image_cache_new ();
|
||||||
dmabuf->target = GST_GL_TEXTURE_TARGET_2D;
|
dmabuf->target = GST_GL_TEXTURE_TARGET_2D;
|
||||||
return dmabuf;
|
return dmabuf;
|
||||||
}
|
}
|
||||||
@ -576,38 +695,6 @@ _dma_buf_upload_transform_caps (gpointer impl, GstGLContext * context,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GQuark
|
|
||||||
_eglimage_quark (gint plane)
|
|
||||||
{
|
|
||||||
static GQuark quark[5] = { 0 };
|
|
||||||
static const gchar *quark_str[] = {
|
|
||||||
"GstGLDMABufEGLImage0",
|
|
||||||
"GstGLDMABufEGLImage1",
|
|
||||||
"GstGLDMABufEGLImage2",
|
|
||||||
"GstGLDMABufEGLImage3",
|
|
||||||
"GstGLDMABufEGLImage",
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!quark[plane])
|
|
||||||
quark[plane] = g_quark_from_static_string (quark_str[plane]);
|
|
||||||
|
|
||||||
return quark[plane];
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstEGLImage *
|
|
||||||
_get_cached_eglimage (GstMemory * mem, gint plane)
|
|
||||||
{
|
|
||||||
return gst_mini_object_get_qdata (GST_MINI_OBJECT (mem),
|
|
||||||
_eglimage_quark (plane));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_set_cached_eglimage (GstMemory * mem, GstEGLImage * eglimage, gint plane)
|
|
||||||
{
|
|
||||||
return gst_mini_object_set_qdata (GST_MINI_OBJECT (mem),
|
|
||||||
_eglimage_quark (plane), eglimage, (GDestroyNotify) gst_egl_image_unref);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
|
_dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
|
||||||
GstCaps * out_caps)
|
GstCaps * out_caps)
|
||||||
@ -619,6 +706,8 @@ _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
|
|||||||
GstVideoMeta *meta;
|
GstVideoMeta *meta;
|
||||||
guint n_mem;
|
guint n_mem;
|
||||||
GstMemory *mems[GST_VIDEO_MAX_PLANES];
|
GstMemory *mems[GST_VIDEO_MAX_PLANES];
|
||||||
|
GstMemory *previous_mem = NULL;
|
||||||
|
GstEGLImageCacheEntry *cache_entry = NULL;
|
||||||
gsize offset[GST_VIDEO_MAX_PLANES];
|
gsize offset[GST_VIDEO_MAX_PLANES];
|
||||||
gint fd[GST_VIDEO_MAX_PLANES];
|
gint fd[GST_VIDEO_MAX_PLANES];
|
||||||
guint i;
|
guint i;
|
||||||
@ -745,12 +834,14 @@ _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
|
|||||||
} else
|
} else
|
||||||
dmabuf->n_mem = n_planes;
|
dmabuf->n_mem = n_planes;
|
||||||
|
|
||||||
/* Now create an EGLImage for each dmabufs */
|
/* Now create an EGLImage for each dmabuf */
|
||||||
for (i = 0; i < dmabuf->n_mem; i++) {
|
for (i = 0; i < dmabuf->n_mem; i++) {
|
||||||
gint cache_id = dmabuf->direct ? 4 : i;
|
/*
|
||||||
|
* Check if an EGLImage is cached. Remember the previous memory and cache
|
||||||
/* check if one is cached */
|
* entry to avoid repeated lookups if all mems[i] point to the same memory.
|
||||||
dmabuf->eglimage[i] = _get_cached_eglimage (mems[i], cache_id);
|
*/
|
||||||
|
dmabuf->eglimage[i] = gst_egl_image_cache_lookup (dmabuf->eglimage_cache,
|
||||||
|
mems[i], i, &previous_mem, &cache_entry);
|
||||||
if (dmabuf->eglimage[i]) {
|
if (dmabuf->eglimage[i]) {
|
||||||
dmabuf->formats[i] = dmabuf->eglimage[i]->format;
|
dmabuf->formats[i] = dmabuf->eglimage[i]->format;
|
||||||
continue;
|
continue;
|
||||||
@ -770,7 +861,8 @@ _dma_buf_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_set_cached_eglimage (mems[i], dmabuf->eglimage[i], cache_id);
|
gst_egl_image_cache_store (dmabuf->eglimage_cache, mems[i], i,
|
||||||
|
dmabuf->eglimage[i], &cache_entry);
|
||||||
dmabuf->formats[i] = dmabuf->eglimage[i]->format;
|
dmabuf->formats[i] = dmabuf->eglimage[i]->format;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -836,6 +928,7 @@ _dma_buf_upload_free (gpointer impl)
|
|||||||
|
|
||||||
if (dmabuf->params)
|
if (dmabuf->params)
|
||||||
gst_gl_allocation_params_free ((GstGLAllocationParams *) dmabuf->params);
|
gst_gl_allocation_params_free ((GstGLAllocationParams *) dmabuf->params);
|
||||||
|
gst_egl_image_cache_unref (dmabuf->eglimage_cache);
|
||||||
|
|
||||||
g_free (impl);
|
g_free (impl);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user