From c64bf36e8ea9811155ffd053ecc7919692c6f4f2 Mon Sep 17 00:00:00 2001 From: Jakub Adam Date: Thu, 28 Jan 2021 19:17:03 +0100 Subject: [PATCH] gst: avoid crash with zero SPA_PARAM_BUFFERS_size With sending and receiving pipelines: gst-launch videotestsrc ! tee ! pipewiresink mode=provide gst-launch pipewiresrc path= ! videoconvert ! autovideosink The first pipeline crashes when the other connects. It happens because SPA_PARAM_BUFFERS_size passed to pw_stream_update_params() upon pipewiresink's buffer pool activation is zero. As a consequence, in gst_pipewire_pool_wrap_buffer(), d->type will be SPA_ID_INVALID and the created GstBuffer will have no memory appended. This ultimately leads to segfault in do_send_buffer(). If size hasn't been set in GstPipeWirePool's config before the first buffer is to be rendered by pipewiresink, configure the pool with the size of that first incoming buffer and activate the pool. --- src/gst/gstpipewiresink.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/gst/gstpipewiresink.c b/src/gst/gstpipewiresink.c index 1861e5504..e15e6a8af 100644 --- a/src/gst/gstpipewiresink.c +++ b/src/gst/gstpipewiresink.c @@ -580,6 +580,23 @@ gst_pipewire_sink_render (GstBaseSink * bsink, GstBuffer * buffer) if (!pwsink->negotiated) goto not_negotiated; + if (buffer->pool != GST_BUFFER_POOL_CAST (pwsink->pool) && + !gst_buffer_pool_is_active (GST_BUFFER_POOL_CAST (pwsink->pool))) { + GstStructure *config; + GstCaps *caps; + guint size, min_buffers, max_buffers; + + config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pwsink->pool)); + gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers); + + size = (size == 0) ? gst_buffer_get_size (buffer) : size; + + gst_buffer_pool_config_set_params (config, caps, size, min_buffers, max_buffers); + gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pwsink->pool), config); + + gst_buffer_pool_set_active (GST_BUFFER_POOL_CAST (pwsink->pool), TRUE); + } + pw_thread_loop_lock (pwsink->core->loop); if (pw_stream_get_state (pwsink->stream, &error) != PW_STREAM_STATE_STREAMING) goto done_unlock; @@ -591,9 +608,6 @@ gst_pipewire_sink_render (GstBaseSink * bsink, GstBuffer * buffer) pw_thread_loop_unlock (pwsink->core->loop); - if (!gst_buffer_pool_is_active (GST_BUFFER_POOL_CAST (pwsink->pool))) - gst_buffer_pool_set_active (GST_BUFFER_POOL_CAST (pwsink->pool), TRUE); - if ((res = gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL_CAST (pwsink->pool), &b, ¶ms)) != GST_FLOW_OK) goto done;