mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-24 07:00:05 -05:00
pinossink: send format change messages
Rework stream connect/disconnect from start/stop Start the stream in setcaps when the format is known. When the stream is already started in setcaps, send a format_change message instead.
This commit is contained in:
parent
4121c421aa
commit
2af64edd29
1 changed files with 94 additions and 56 deletions
|
|
@ -331,85 +331,64 @@ gst_pinos_sink_getcaps (GstBaseSink * bsink, GstCaps * filter)
|
||||||
return GST_BASE_SINK_CLASS (parent_class)->get_caps (bsink, filter);
|
return GST_BASE_SINK_CLASS (parent_class)->get_caps (bsink, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
copy_properties (GQuark field_id,
|
|
||||||
const GValue *value,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
PinosProperties *properties = user_data;
|
|
||||||
|
|
||||||
if (G_VALUE_HOLDS_STRING (value))
|
|
||||||
pinos_properties_set (properties,
|
|
||||||
g_quark_to_string (field_id),
|
|
||||||
g_value_get_string (value));
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstPinosSink *pinossink;
|
GstPinosSink *pinossink;
|
||||||
gchar *str;
|
gchar *str;
|
||||||
GBytes *format;
|
PinosStreamState state;
|
||||||
PinosProperties *props;
|
gboolean res = FALSE;
|
||||||
|
|
||||||
pinossink = GST_PINOS_SINK (bsink);
|
pinossink = GST_PINOS_SINK (bsink);
|
||||||
|
|
||||||
str = gst_caps_to_string (caps);
|
str = gst_caps_to_string (caps);
|
||||||
format = g_bytes_new_take (str, strlen (str) + 1);
|
|
||||||
|
|
||||||
if (pinossink->properties) {
|
|
||||||
props = pinos_properties_new (NULL, NULL);
|
|
||||||
gst_structure_foreach (pinossink->properties, copy_properties, props);
|
|
||||||
} else {
|
|
||||||
props = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pinos_main_loop_lock (pinossink->loop);
|
pinos_main_loop_lock (pinossink->loop);
|
||||||
if (pinossink->stream) {
|
state = pinos_stream_get_state (pinossink->stream);
|
||||||
pinos_stream_stop (pinossink->stream);
|
|
||||||
pinos_stream_disconnect (pinossink->stream);
|
|
||||||
g_clear_object (&pinossink->stream);
|
|
||||||
}
|
|
||||||
pinossink->stream = pinos_stream_new (pinossink->ctx, pinossink->client_name, props);
|
|
||||||
g_signal_connect (pinossink->stream, "notify::state", (GCallback) on_stream_notify, pinossink);
|
|
||||||
g_signal_connect (pinossink->stream, "new-buffer", (GCallback) on_new_buffer, pinossink);
|
|
||||||
|
|
||||||
pinos_stream_connect_provide (pinossink->stream, 0, g_bytes_ref (format));
|
if (state == PINOS_STREAM_STATE_ERROR)
|
||||||
|
goto start_error;
|
||||||
|
|
||||||
while (TRUE) {
|
if (state == PINOS_STREAM_STATE_STREAMING) {
|
||||||
PinosStreamState state = pinos_stream_get_state (pinossink->stream);
|
PinosBufferBuilder builder;
|
||||||
|
PinosPacketFormatChange change;
|
||||||
|
PinosBuffer pbuf;
|
||||||
|
|
||||||
if (state == PINOS_STREAM_STATE_READY)
|
pinos_buffer_builder_init (&builder);
|
||||||
break;
|
|
||||||
|
|
||||||
if (state == PINOS_STREAM_STATE_ERROR)
|
change.id = 1;
|
||||||
goto connect_error;
|
change.format = str;
|
||||||
|
pinos_buffer_builder_add_format_change (&builder, &change);
|
||||||
|
pinos_buffer_builder_end (&builder, &pbuf);
|
||||||
|
|
||||||
pinos_main_loop_wait (pinossink->loop);
|
res = pinos_stream_send_buffer (pinossink->stream, &pbuf);
|
||||||
}
|
pinos_buffer_clear (&pbuf);
|
||||||
|
} else {
|
||||||
|
GBytes *format = g_bytes_new_take (str, strlen (str) + 1);
|
||||||
|
|
||||||
pinos_stream_start (pinossink->stream, format, PINOS_STREAM_MODE_BUFFER);
|
res = pinos_stream_start (pinossink->stream, format, PINOS_STREAM_MODE_BUFFER);
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
PinosStreamState state = pinos_stream_get_state (pinossink->stream);
|
state = pinos_stream_get_state (pinossink->stream);
|
||||||
|
|
||||||
if (state == PINOS_STREAM_STATE_STREAMING)
|
if (state == PINOS_STREAM_STATE_STREAMING)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (state == PINOS_STREAM_STATE_ERROR)
|
if (state == PINOS_STREAM_STATE_ERROR)
|
||||||
goto connect_error;
|
goto start_error;
|
||||||
|
|
||||||
pinos_main_loop_wait (pinossink->loop);
|
pinos_main_loop_wait (pinossink->loop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pinos_main_loop_unlock (pinossink->loop);
|
pinos_main_loop_unlock (pinossink->loop);
|
||||||
|
|
||||||
pinossink->negotiated = TRUE;
|
pinossink->negotiated = res;
|
||||||
|
|
||||||
return TRUE;
|
return res;
|
||||||
|
|
||||||
connect_error:
|
start_error:
|
||||||
{
|
{
|
||||||
|
GST_ERROR ("could not start stream");
|
||||||
pinos_main_loop_unlock (pinossink->loop);
|
pinos_main_loop_unlock (pinossink->loop);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
@ -519,22 +498,81 @@ streaming_error:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
copy_properties (GQuark field_id,
|
||||||
|
const GValue *value,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
PinosProperties *properties = user_data;
|
||||||
|
|
||||||
|
if (G_VALUE_HOLDS_STRING (value))
|
||||||
|
pinos_properties_set (properties,
|
||||||
|
g_quark_to_string (field_id),
|
||||||
|
g_value_get_string (value));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_pinos_sink_start (GstBaseSink * basesink)
|
gst_pinos_sink_start (GstBaseSink * basesink)
|
||||||
{
|
{
|
||||||
GstPinosSink *sink = GST_PINOS_SINK (basesink);
|
GstPinosSink *pinossink = GST_PINOS_SINK (basesink);
|
||||||
|
PinosProperties *props;
|
||||||
|
|
||||||
sink->negotiated = FALSE;
|
pinossink->negotiated = FALSE;
|
||||||
|
|
||||||
|
if (pinossink->properties) {
|
||||||
|
props = pinos_properties_new (NULL, NULL);
|
||||||
|
gst_structure_foreach (pinossink->properties, copy_properties, props);
|
||||||
|
} else {
|
||||||
|
props = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pinos_main_loop_lock (pinossink->loop);
|
||||||
|
pinossink->stream = pinos_stream_new (pinossink->ctx, pinossink->client_name, props);
|
||||||
|
g_signal_connect (pinossink->stream, "notify::state", (GCallback) on_stream_notify, pinossink);
|
||||||
|
g_signal_connect (pinossink->stream, "new-buffer", (GCallback) on_new_buffer, pinossink);
|
||||||
|
|
||||||
|
pinos_stream_connect_provide (pinossink->stream, 0, g_bytes_new_static ("ANY", strlen ("ANY")+1));
|
||||||
|
|
||||||
|
while (TRUE) {
|
||||||
|
PinosStreamState state = pinos_stream_get_state (pinossink->stream);
|
||||||
|
|
||||||
|
if (state == PINOS_STREAM_STATE_READY)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (state == PINOS_STREAM_STATE_ERROR)
|
||||||
|
goto connect_error;
|
||||||
|
|
||||||
|
pinos_main_loop_wait (pinossink->loop);
|
||||||
|
}
|
||||||
|
pinos_main_loop_unlock (pinossink->loop);
|
||||||
|
|
||||||
|
pinossink->negotiated = TRUE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
connect_error:
|
||||||
|
{
|
||||||
|
GST_ERROR ("could not connect stream");
|
||||||
|
pinos_main_loop_unlock (pinossink->loop);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_pinos_sink_stop (GstBaseSink * basesink)
|
gst_pinos_sink_stop (GstBaseSink * basesink)
|
||||||
{
|
{
|
||||||
GstPinosSink *sink = GST_PINOS_SINK (basesink);
|
GstPinosSink *pinossink = GST_PINOS_SINK (basesink);
|
||||||
|
|
||||||
sink->negotiated = FALSE;
|
pinos_main_loop_lock (pinossink->loop);
|
||||||
|
if (pinossink->stream) {
|
||||||
|
pinos_stream_stop (pinossink->stream);
|
||||||
|
pinos_stream_disconnect (pinossink->stream);
|
||||||
|
g_clear_object (&pinossink->stream);
|
||||||
|
}
|
||||||
|
pinos_main_loop_unlock (pinossink->loop);
|
||||||
|
|
||||||
|
pinossink->negotiated = FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue