mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-08 13:30:08 -05:00
gst: share the core between connections
Make all sources in the same process with the same fd share the connection to the server. This makes it possible to set the same fd on multiple sources/sinks and have them all use the same connection, like when capturing multiple monitors from screencast with the portal. Fixes #241
This commit is contained in:
parent
ba96eecba0
commit
70652d1a37
7 changed files with 328 additions and 188 deletions
|
|
@ -119,9 +119,6 @@ gst_pipewire_sink_finalize (GObject * object)
|
|||
|
||||
g_object_unref (pwsink->pool);
|
||||
|
||||
pw_thread_loop_destroy (pwsink->loop);
|
||||
pwsink->loop = NULL;
|
||||
|
||||
if (pwsink->properties)
|
||||
gst_structure_free (pwsink->properties);
|
||||
g_free (pwsink->path);
|
||||
|
|
@ -261,9 +258,9 @@ pool_activated (GstPipeWirePool *pool, GstPipeWireSink *sink)
|
|||
SPA_PARAM_META_size, SPA_POD_Int(sizeof (struct spa_meta_header)));
|
||||
|
||||
|
||||
pw_thread_loop_lock (sink->loop);
|
||||
pw_thread_loop_lock (sink->core->loop);
|
||||
pw_stream_update_params (sink->stream, port_params, 2);
|
||||
pw_thread_loop_unlock (sink->loop);
|
||||
pw_thread_loop_unlock (sink->core->loop);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -275,10 +272,6 @@ gst_pipewire_sink_init (GstPipeWireSink * sink)
|
|||
sink->fd = -1;
|
||||
|
||||
g_signal_connect (sink->pool, "activated", G_CALLBACK (pool_activated), sink);
|
||||
|
||||
sink->loop = pw_thread_loop_new ("pipewire-sink-loop", NULL);
|
||||
sink->context = pw_context_new (pw_thread_loop_get_loop(sink->loop), NULL, 0);
|
||||
GST_DEBUG ("loop %p context %p", sink->loop, sink->context);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
|
|
@ -469,7 +462,7 @@ on_state_changed (void *data, enum pw_stream_state old, enum pw_stream_state sta
|
|||
("stream error: %s", error), (NULL));
|
||||
break;
|
||||
}
|
||||
pw_thread_loop_signal (pwsink->loop, FALSE);
|
||||
pw_thread_loop_signal (pwsink->core->loop, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -501,7 +494,7 @@ gst_pipewire_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||
|
||||
possible = gst_caps_to_format_all (caps, SPA_PARAM_EnumFormat);
|
||||
|
||||
pw_thread_loop_lock (pwsink->loop);
|
||||
pw_thread_loop_lock (pwsink->core->loop);
|
||||
state = pw_stream_get_state (pwsink->stream, &error);
|
||||
|
||||
if (state == PW_STREAM_STATE_ERROR)
|
||||
|
|
@ -531,7 +524,7 @@ gst_pipewire_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||
if (state == PW_STREAM_STATE_ERROR)
|
||||
goto start_error;
|
||||
|
||||
pw_thread_loop_wait (pwsink->loop);
|
||||
pw_thread_loop_wait (pwsink->core->loop);
|
||||
}
|
||||
}
|
||||
res = TRUE;
|
||||
|
|
@ -541,7 +534,7 @@ gst_pipewire_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||
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);
|
||||
|
||||
pw_thread_loop_unlock (pwsink->loop);
|
||||
pw_thread_loop_unlock (pwsink->core->loop);
|
||||
|
||||
pwsink->negotiated = res;
|
||||
|
||||
|
|
@ -550,7 +543,7 @@ gst_pipewire_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||
start_error:
|
||||
{
|
||||
GST_ERROR ("could not start stream: %s", error);
|
||||
pw_thread_loop_unlock (pwsink->loop);
|
||||
pw_thread_loop_unlock (pwsink->core->loop);
|
||||
g_ptr_array_unref (possible);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -568,7 +561,7 @@ gst_pipewire_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
if (!pwsink->negotiated)
|
||||
goto not_negotiated;
|
||||
|
||||
pw_thread_loop_lock (pwsink->loop);
|
||||
pw_thread_loop_lock (pwsink->core->loop);
|
||||
if (pw_stream_get_state (pwsink->stream, &error) != PW_STREAM_STATE_STREAMING)
|
||||
goto done_unlock;
|
||||
|
||||
|
|
@ -576,7 +569,7 @@ gst_pipewire_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
GstBuffer *b = NULL;
|
||||
GstMapInfo info = { 0, };
|
||||
|
||||
pw_thread_loop_unlock (pwsink->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);
|
||||
|
|
@ -590,7 +583,7 @@ gst_pipewire_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
gst_buffer_resize (b, 0, gst_buffer_get_size (buffer));
|
||||
buffer = b;
|
||||
|
||||
pw_thread_loop_lock (pwsink->loop);
|
||||
pw_thread_loop_lock (pwsink->core->loop);
|
||||
if (pw_stream_get_state (pwsink->stream, &error) != PW_STREAM_STATE_STREAMING)
|
||||
goto done_unlock;
|
||||
}
|
||||
|
|
@ -599,7 +592,7 @@ gst_pipewire_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
|||
do_send_buffer (pwsink, buffer);
|
||||
|
||||
done_unlock:
|
||||
pw_thread_loop_unlock (pwsink->loop);
|
||||
pw_thread_loop_unlock (pwsink->core->loop);
|
||||
done:
|
||||
return res;
|
||||
|
||||
|
|
@ -647,8 +640,8 @@ gst_pipewire_sink_start (GstBaseSink * basesink)
|
|||
props = NULL;
|
||||
}
|
||||
|
||||
pw_thread_loop_lock (pwsink->loop);
|
||||
if ((pwsink->stream = pw_stream_new (pwsink->core, pwsink->client_name, props)) == NULL)
|
||||
pw_thread_loop_lock (pwsink->core->loop);
|
||||
if ((pwsink->stream = pw_stream_new (pwsink->core->core, pwsink->client_name, props)) == NULL)
|
||||
goto no_stream;
|
||||
|
||||
pwsink->pool->stream = pwsink->stream;
|
||||
|
|
@ -658,14 +651,14 @@ gst_pipewire_sink_start (GstBaseSink * basesink)
|
|||
&stream_events,
|
||||
pwsink);
|
||||
|
||||
pw_thread_loop_unlock (pwsink->loop);
|
||||
pw_thread_loop_unlock (pwsink->core->loop);
|
||||
|
||||
return TRUE;
|
||||
|
||||
no_stream:
|
||||
{
|
||||
GST_ELEMENT_ERROR (pwsink, RESOURCE, FAILED, ("can't create stream"), (NULL));
|
||||
pw_thread_loop_unlock (pwsink->loop);
|
||||
pw_thread_loop_unlock (pwsink->core->loop);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -675,81 +668,33 @@ gst_pipewire_sink_stop (GstBaseSink * basesink)
|
|||
{
|
||||
GstPipeWireSink *pwsink = GST_PIPEWIRE_SINK (basesink);
|
||||
|
||||
pw_thread_loop_lock (pwsink->loop);
|
||||
pw_thread_loop_lock (pwsink->core->loop);
|
||||
if (pwsink->stream) {
|
||||
pw_stream_disconnect (pwsink->stream);
|
||||
pw_stream_destroy (pwsink->stream);
|
||||
pwsink->stream = NULL;
|
||||
pwsink->pool->stream = NULL;
|
||||
}
|
||||
pw_thread_loop_unlock (pwsink->loop);
|
||||
pw_thread_loop_unlock (pwsink->core->loop);
|
||||
|
||||
pwsink->negotiated = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void on_core_done (void *object, uint32_t id, int seq)
|
||||
{
|
||||
GstPipeWireSink * pwsink = object;
|
||||
if (id == PW_ID_CORE) {
|
||||
pwsink->last_seq = seq;
|
||||
pw_thread_loop_signal (pwsink->loop, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct pw_core_events core_events = {
|
||||
PW_VERSION_CORE_EVENTS,
|
||||
.done = on_core_done,
|
||||
};
|
||||
|
||||
static void do_sync(GstPipeWireSink * pwsink)
|
||||
{
|
||||
pwsink->pending_seq = pw_core_sync(pwsink->core, 0, pwsink->pending_seq);
|
||||
while (true) {
|
||||
if (pwsink->last_seq == pwsink->pending_seq || pwsink->last_error < 0)
|
||||
break;
|
||||
pw_thread_loop_wait (pwsink->loop);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_pipewire_sink_open (GstPipeWireSink * pwsink)
|
||||
{
|
||||
if (pw_thread_loop_start (pwsink->loop) < 0)
|
||||
goto mainloop_error;
|
||||
|
||||
pw_thread_loop_lock (pwsink->loop);
|
||||
|
||||
if (pwsink->fd == -1)
|
||||
pwsink->core = pw_context_connect (pwsink->context, NULL, 0);
|
||||
else
|
||||
pwsink->core = pw_context_connect_fd (pwsink->context, dup(pwsink->fd), NULL, 0);
|
||||
|
||||
pwsink->core = gst_pipewire_core_get(pwsink->fd);
|
||||
if (pwsink->core == NULL)
|
||||
goto connect_error;
|
||||
|
||||
pw_core_add_listener(pwsink->core,
|
||||
&pwsink->core_listener,
|
||||
&core_events,
|
||||
pwsink);
|
||||
|
||||
pw_thread_loop_unlock (pwsink->loop);
|
||||
goto connect_error;
|
||||
|
||||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
mainloop_error:
|
||||
{
|
||||
GST_ELEMENT_ERROR (pwsink, RESOURCE, FAILED,
|
||||
("Failed to start mainloop"), (NULL));
|
||||
return FALSE;
|
||||
}
|
||||
connect_error:
|
||||
{
|
||||
GST_ELEMENT_ERROR (pwsink, RESOURCE, FAILED,
|
||||
("Failed to connect"), (NULL));
|
||||
pw_thread_loop_unlock (pwsink->loop);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -757,20 +702,17 @@ connect_error:
|
|||
static gboolean
|
||||
gst_pipewire_sink_close (GstPipeWireSink * pwsink)
|
||||
{
|
||||
pw_thread_loop_lock (pwsink->loop);
|
||||
pw_thread_loop_lock (pwsink->core->loop);
|
||||
if (pwsink->stream) {
|
||||
pw_stream_destroy (pwsink->stream);
|
||||
pwsink->stream = NULL;
|
||||
}
|
||||
pw_thread_loop_unlock (pwsink->core->loop);
|
||||
|
||||
if (pwsink->core) {
|
||||
do_sync(pwsink);
|
||||
pw_core_disconnect (pwsink->core);
|
||||
gst_pipewire_core_release (pwsink->core);
|
||||
pwsink->core = NULL;
|
||||
}
|
||||
pw_thread_loop_unlock (pwsink->loop);
|
||||
|
||||
pw_thread_loop_stop (pwsink->loop);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -789,11 +731,15 @@ gst_pipewire_sink_change_state (GstElement * element, GstStateChange transition)
|
|||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||
/* uncork and start play */
|
||||
pw_thread_loop_lock (this->core->loop);
|
||||
pw_stream_set_active(this->stream, true);
|
||||
pw_thread_loop_unlock (this->core->loop);
|
||||
break;
|
||||
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
||||
/* stop play ASAP by corking */
|
||||
pw_thread_loop_lock (this->core->loop);
|
||||
pw_stream_set_active(this->stream, false);
|
||||
pw_thread_loop_unlock (this->core->loop);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue