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=<node_id> ! 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.
This commit is contained in:
Jakub Adam 2021-01-28 19:17:03 +01:00
parent f8d57d03ca
commit c64bf36e8e

View file

@ -580,6 +580,23 @@ gst_pipewire_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
if (!pwsink->negotiated) if (!pwsink->negotiated)
goto not_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); pw_thread_loop_lock (pwsink->core->loop);
if (pw_stream_get_state (pwsink->stream, &error) != PW_STREAM_STATE_STREAMING) if (pw_stream_get_state (pwsink->stream, &error) != PW_STREAM_STATE_STREAMING)
goto done_unlock; goto done_unlock;
@ -591,9 +608,6 @@ gst_pipewire_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
pw_thread_loop_unlock (pwsink->core->loop); 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, &params)) != GST_FLOW_OK) if ((res = gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL_CAST (pwsink->pool), &b, &params)) != GST_FLOW_OK)
goto done; goto done;