From 2af64edd29a84fde0c052a8ce095209c8ca43b91 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 7 Apr 2016 11:39:52 +0200 Subject: [PATCH] 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. --- pinos/gst/gstpinossink.c | 150 ++++++++++++++++++++++++--------------- 1 file changed, 94 insertions(+), 56 deletions(-) diff --git a/pinos/gst/gstpinossink.c b/pinos/gst/gstpinossink.c index 1d58bfda7..18615b096 100644 --- a/pinos/gst/gstpinossink.c +++ b/pinos/gst/gstpinossink.c @@ -331,85 +331,64 @@ gst_pinos_sink_getcaps (GstBaseSink * bsink, GstCaps * 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 gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps) { GstPinosSink *pinossink; gchar *str; - GBytes *format; - PinosProperties *props; + PinosStreamState state; + gboolean res = FALSE; pinossink = GST_PINOS_SINK (bsink); 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); - if (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); + state = pinos_stream_get_state (pinossink->stream); - pinos_stream_connect_provide (pinossink->stream, 0, g_bytes_ref (format)); + if (state == PINOS_STREAM_STATE_ERROR) + goto start_error; - while (TRUE) { - PinosStreamState state = pinos_stream_get_state (pinossink->stream); + if (state == PINOS_STREAM_STATE_STREAMING) { + PinosBufferBuilder builder; + PinosPacketFormatChange change; + PinosBuffer pbuf; - if (state == PINOS_STREAM_STATE_READY) - break; + pinos_buffer_builder_init (&builder); - if (state == PINOS_STREAM_STATE_ERROR) - goto connect_error; + change.id = 1; + 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) { - PinosStreamState state = pinos_stream_get_state (pinossink->stream); + while (TRUE) { + state = pinos_stream_get_state (pinossink->stream); - if (state == PINOS_STREAM_STATE_STREAMING) - break; + if (state == PINOS_STREAM_STATE_STREAMING) + break; - if (state == PINOS_STREAM_STATE_ERROR) - goto connect_error; + if (state == PINOS_STREAM_STATE_ERROR) + goto start_error; - pinos_main_loop_wait (pinossink->loop); + pinos_main_loop_wait (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); 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 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; + +connect_error: + { + GST_ERROR ("could not connect stream"); + pinos_main_loop_unlock (pinossink->loop); + return FALSE; + } } static gboolean 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; }