waylandsink: Refactor internal pool handling

This is to make it easier to support more then one allocators
including falling back from one to another.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3801>
This commit is contained in:
Nicolas Dufresne 2023-02-16 13:54:42 -05:00 committed by GStreamer Marge Bot
parent 9084a960a5
commit 965117b400
3 changed files with 124 additions and 79 deletions

View file

@ -109,6 +109,7 @@ typedef struct _GstGtkWaylandSinkPrivate
gboolean video_info_changed;
GstVideoInfo video_info;
GstCaps *caps;
gboolean redraw_pending;
GMutex render_lock;
@ -200,6 +201,7 @@ gst_gtk_wayland_sink_finalize (GObject * object)
gst_gtk_wayland_sink_get_instance_private (self);
g_clear_object (&priv->gtk_widget);
gst_clear_caps (&priv->caps);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -801,30 +803,57 @@ gst_gtk_wayland_sink_get_caps (GstBaseSink * bsink, GstCaps * filter)
return caps;
}
static GstBufferPool *
gst_gtk_wayland_create_pool (GstGtkWaylandSink * self, GstCaps * caps)
static gboolean
gst_gtk_wayland_update_pool (GstGtkWaylandSink * self, GstAllocator * allocator)
{
GstGtkWaylandSinkPrivate *priv =
gst_gtk_wayland_sink_get_instance_private (self);
GstBufferPool *pool = NULL;
GstStructure *structure;
gsize size = priv->video_info.size;
GstAllocator *alloc;
GstStructure *config;
pool = gst_wl_video_buffer_pool_new ();
/* Pools with outstanding buffer cannot be reconfigured, so we must use
* a new pool. */
if (priv->pool) {
gst_buffer_pool_set_active (priv->pool, FALSE);
gst_object_unref (priv->pool);
}
priv->pool = gst_wl_video_buffer_pool_new ();
structure = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (structure, caps, size, 2, 0);
config = gst_buffer_pool_get_config (priv->pool);
gst_buffer_pool_config_set_params (config, priv->caps, size, 2, 0);
gst_buffer_pool_config_set_allocator (config, allocator, NULL);
if (!gst_buffer_pool_set_config (priv->pool, config))
return FALSE;
return gst_buffer_pool_set_active (priv->pool, TRUE);
}
static gboolean
gst_gtk_wayland_activate_shm_pool (GstGtkWaylandSink * self)
{
GstGtkWaylandSinkPrivate *priv =
gst_gtk_wayland_sink_get_instance_private (self);
GstAllocator *alloc = NULL;
if (priv->pool && gst_buffer_pool_is_active (priv->pool)) {
GstStructure *config = gst_buffer_pool_get_config (priv->pool);
gboolean is_shm = FALSE;
if (gst_buffer_pool_config_get_allocator (config, &alloc, NULL) && alloc)
is_shm = GST_IS_WL_SHM_ALLOCATOR (alloc);
gst_structure_free (config);
if (is_shm)
return TRUE;
}
alloc = gst_wl_shm_allocator_get ();
gst_buffer_pool_config_set_allocator (structure, alloc, NULL);
if (!gst_buffer_pool_set_config (pool, structure)) {
g_object_unref (pool);
pool = NULL;
}
g_object_unref (alloc);
gst_gtk_wayland_update_pool (self, alloc);
gst_object_unref (alloc);
return pool;
return TRUE;
}
static gboolean
@ -845,10 +874,11 @@ gst_gtk_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
format = GST_VIDEO_INFO_FORMAT (&priv->video_info);
priv->video_info_changed = TRUE;
/* create a new pool for the new caps */
if (priv->pool)
gst_object_unref (priv->pool);
priv->pool = gst_gtk_wayland_create_pool (self, caps);
/* free pooled buffer used with previous caps */
if (priv->pool) {
gst_buffer_pool_set_active (priv->pool, FALSE);
gst_clear_object (&priv->pool);
}
use_dmabuf = gst_caps_features_contains (gst_caps_get_features (caps, 0),
GST_CAPS_FEATURE_MEMORY_DMABUF);
@ -884,6 +914,8 @@ gst_gtk_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
GST_OBJECT_UNLOCK (self);
priv->use_dmabuf = use_dmabuf;
/* Will be used to create buffer pools */
gst_caps_replace (&priv->caps, caps);
return TRUE;
@ -914,8 +946,14 @@ gst_gtk_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
gst_query_parse_allocation (query, &caps, &need_pool);
if (need_pool)
pool = gst_gtk_wayland_create_pool (self, caps);
if (need_pool) {
GstStructure *config;
pool = gst_wl_video_buffer_pool_new ();
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_allocator (config,
gst_wl_shm_allocator_get (), NULL);
gst_buffer_pool_set_config (pool, config);
}
gst_query_add_allocation_pool (query, pool, priv->video_info.size, 2, 0);
if (pool)
@ -1077,25 +1115,10 @@ gst_gtk_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
"buffer %" GST_PTR_FORMAT " cannot have a wl_buffer, "
"copying to wl_shm memory", buffer);
/* priv->pool always exists (created in set_caps), but it may not
* be active if upstream is not using it */
if (!gst_buffer_pool_is_active (priv->pool)) {
GstStructure *config;
GstCaps *caps;
config = gst_buffer_pool_get_config (priv->pool);
gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL);
/* revert back to default strides and offsets */
gst_video_info_from_caps (&priv->video_info, caps);
gst_buffer_pool_config_set_params (config, caps, priv->video_info.size,
2, 0);
/* This is a video pool, it should not fail with basic settings */
if (!gst_buffer_pool_set_config (priv->pool, config) ||
!gst_buffer_pool_set_active (priv->pool, TRUE))
goto activate_failed;
}
/* ensure the internal pool is configured for SHM */
if (!gst_gtk_wayland_activate_shm_pool (self))
goto activate_failed;
ret = gst_buffer_pool_acquire_buffer (priv->pool, &to_render, NULL);
if (ret != GST_FLOW_OK)

View file

@ -315,6 +315,8 @@ gst_wayland_sink_finalize (GObject * object)
if (self->pool)
gst_object_unref (self->pool);
gst_clear_caps (&self->caps);
g_free (self->display_name);
g_mutex_clear (&self->display_lock);
@ -578,28 +580,53 @@ gst_wayland_sink_get_caps (GstBaseSink * bsink, GstCaps * filter)
return caps;
}
static GstBufferPool *
gst_wayland_create_pool (GstWaylandSink * self, GstCaps * caps)
static gboolean
gst_wayland_update_pool (GstWaylandSink * self, GstAllocator * allocator)
{
GstBufferPool *pool = NULL;
GstStructure *structure;
gsize size = self->video_info.size;
GstAllocator *alloc;
GstStructure *config;
pool = gst_wl_video_buffer_pool_new ();
/* Pools with outstanding buffer cannot be reconfigured, so we must use
* a new pool. */
if (self->pool) {
gst_buffer_pool_set_active (self->pool, FALSE);
gst_object_unref (self->pool);
}
self->pool = gst_wl_video_buffer_pool_new ();
structure = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (structure, caps, size, 2, 0);
config = gst_buffer_pool_get_config (self->pool);
gst_buffer_pool_config_set_params (config, self->caps, size, 2, 0);
gst_buffer_pool_config_set_allocator (config, allocator, NULL);
if (!gst_buffer_pool_set_config (self->pool, config))
return FALSE;
return gst_buffer_pool_set_active (self->pool, TRUE);
}
static gboolean
gst_wayland_activate_shm_pool (GstWaylandSink * self)
{
GstAllocator *alloc = NULL;
if (self->pool && gst_buffer_pool_is_active (self->pool)) {
GstStructure *config = gst_buffer_pool_get_config (self->pool);
gboolean is_shm = FALSE;
if (gst_buffer_pool_config_get_allocator (config, &alloc, NULL) && alloc)
is_shm = GST_IS_WL_SHM_ALLOCATOR (alloc);
gst_structure_free (config);
if (is_shm)
return TRUE;
}
alloc = gst_wl_shm_allocator_get ();
gst_buffer_pool_config_set_allocator (structure, alloc, NULL);
if (!gst_buffer_pool_set_config (pool, structure)) {
g_object_unref (pool);
pool = NULL;
}
g_object_unref (alloc);
gst_wayland_update_pool (self, alloc);
gst_object_unref (alloc);
return pool;
return TRUE;
}
static gboolean
@ -618,10 +645,11 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
format = GST_VIDEO_INFO_FORMAT (&self->video_info);
self->video_info_changed = TRUE;
/* create a new pool for the new caps */
if (self->pool)
gst_object_unref (self->pool);
self->pool = gst_wayland_create_pool (self, caps);
/* free pooled buffer used with previous caps */
if (self->pool) {
gst_buffer_pool_set_active (self->pool, FALSE);
gst_clear_object (&self->pool);
}
use_dmabuf = gst_caps_features_contains (gst_caps_get_features (caps, 0),
GST_CAPS_FEATURE_MEMORY_DMABUF);
@ -636,6 +664,9 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
self->use_dmabuf = use_dmabuf;
/* Will be used to create buffer pools */
gst_caps_replace (&self->caps, caps);
return TRUE;
invalid_format:
@ -663,8 +694,14 @@ gst_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
gst_query_parse_allocation (query, &caps, &need_pool);
if (need_pool)
pool = gst_wayland_create_pool (self, caps);
if (need_pool) {
GstStructure *config;
pool = gst_wl_video_buffer_pool_new ();
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_allocator (config,
gst_wl_shm_allocator_get (), NULL);
gst_buffer_pool_set_config (pool, config);
}
gst_query_add_allocation_pool (query, pool, self->video_info.size, 2, 0);
if (pool)
@ -841,25 +878,9 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
"buffer %" GST_PTR_FORMAT " cannot have a wl_buffer, "
"copying to wl_shm memory", buffer);
/* self->pool always exists (created in set_caps), but it may not
* be active if upstream is not using it */
if (!gst_buffer_pool_is_active (self->pool)) {
GstStructure *config;
GstCaps *caps;
config = gst_buffer_pool_get_config (self->pool);
gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL);
/* revert back to default strides and offsets */
gst_video_info_from_caps (&self->video_info, caps);
gst_buffer_pool_config_set_params (config, caps, self->video_info.size,
2, 0);
/* This is a video pool, it should not fail with basic settings */
if (!gst_buffer_pool_set_config (self->pool, config) ||
!gst_buffer_pool_set_active (self->pool, TRUE))
goto activate_failed;
}
/* ensure the internal pool is configured for SHM */
if (!gst_wayland_activate_shm_pool (self))
goto activate_failed;
ret = gst_buffer_pool_acquire_buffer (self->pool, &to_render, NULL);
if (ret != GST_FLOW_OK)

View file

@ -56,6 +56,7 @@ struct _GstWaylandSink
gboolean video_info_changed;
GstVideoInfo video_info;
gboolean fullscreen;
GstCaps *caps;
gchar *display_name;