From b80b8824be2f792a6d9ac831af185c950cbc56b8 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 22 Apr 2013 17:34:37 +0200 Subject: [PATCH] media: listen to pad-removed signals Listen to the pad-removed signal and remove the stream associated with the removed pad. Add signal to be notified of the removed pad. Remove the fakesink in unprepare() Fix signatures of the signal methods --- gst/rtsp-server/rtsp-media.c | 72 ++++++++++++++++++++++++++++++++++++++++++-- gst/rtsp-server/rtsp-media.h | 9 +++--- 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 5eaf979..e48f70c 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -102,6 +102,7 @@ enum enum { SIGNAL_NEW_STREAM, + SIGNAL_REMOVED_STREAM, SIGNAL_PREPARED, SIGNAL_UNPREPARED, SIGNAL_NEW_STATE, @@ -180,6 +181,12 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass) G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_RTSP_STREAM); + gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM] = + g_signal_new ("removed-stream", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, removed_stream), + NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GST_TYPE_RTSP_STREAM); + gst_rtsp_media_signals[SIGNAL_PREPARED] = g_signal_new ("prepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaClass, prepared), NULL, NULL, @@ -972,6 +979,30 @@ gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader, return stream; } +static void +gst_rtsp_media_remove_stream (GstRTSPMedia * media, GstRTSPStream * stream) +{ + GstRTSPMediaPrivate *priv; + GstPad *srcpad; + + priv = media->priv; + + g_mutex_lock (&priv->lock); + /* remove the ghostpad */ + srcpad = gst_rtsp_stream_get_srcpad (stream); + gst_element_remove_pad (priv->element, srcpad); + gst_object_unref (srcpad); + /* now remove the stream */ + g_object_ref (stream); + g_ptr_array_remove (priv->streams, stream); + g_mutex_unlock (&priv->lock); + + g_signal_emit (media, gst_rtsp_media_signals[SIGNAL_REMOVED_STREAM], 0, + stream, NULL); + + g_object_unref (stream); +} + /** * gst_rtsp_media_n_streams: * @media: a #GstRTSPMedia @@ -1369,6 +1400,8 @@ pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media) /* FIXME, element is likely not a payloader, find the payloader here */ stream = gst_rtsp_media_create_stream (media, element, pad); + g_object_set_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream", stream); + GST_INFO ("pad added %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream); g_rec_mutex_lock (&priv->state_lock); @@ -1387,13 +1420,30 @@ pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media) } static void -no_more_pads_cb (GstElement * element, GstRTSPMedia * media) +pad_removed_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media) { GstRTSPMediaPrivate *priv = media->priv; + GstRTSPStream *stream; + + stream = g_object_get_data (G_OBJECT (pad), "gst-rtsp-dynpad-stream"); + if (stream == NULL) + return; + + GST_INFO ("pad removed %s:%s, stream %p", GST_DEBUG_PAD_NAME (pad), stream); + + g_rec_mutex_lock (&priv->state_lock); + gst_rtsp_stream_leave_bin (stream, GST_BIN (priv->pipeline), priv->rtpbin); + g_rec_mutex_unlock (&priv->state_lock); + + gst_rtsp_media_remove_stream (media, stream); +} + +static void +remove_fakesink (GstRTSPMediaPrivate * priv) +{ GstElement *fakesink; g_mutex_lock (&priv->lock); - GST_INFO ("no more pads"); if ((fakesink = priv->fakesink)) { gst_object_ref (fakesink); priv->fakesink = NULL; @@ -1406,11 +1456,21 @@ no_more_pads_cb (GstElement * element, GstRTSPMedia * media) } } +static void +no_more_pads_cb (GstElement * element, GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + + GST_INFO ("no more pads"); + remove_fakesink (priv); +} + typedef struct _DynPaySignalHandlers DynPaySignalHandlers; struct _DynPaySignalHandlers { gulong pad_added_handler; + gulong pad_removed_handler; gulong no_more_pads_handler; }; @@ -1504,6 +1564,8 @@ gst_rtsp_media_prepare (GstRTSPMedia * media) handlers->pad_added_handler = g_signal_connect (elem, "pad-added", (GCallback) pad_added_cb, media); + handlers->pad_removed_handler = g_signal_connect (elem, "pad-removed", + (GCallback) pad_removed_cb, media); handlers->no_more_pads_handler = g_signal_connect (elem, "no-more-pads", (GCallback) no_more_pads_cb, media); @@ -1608,6 +1670,7 @@ finish_unprepare (GstRTSPMedia * media) GST_DEBUG ("shutting down"); gst_element_set_state (priv->pipeline, GST_STATE_NULL); + remove_fakesink (priv); for (i = 0; i < priv->streams->len; i++) { GstRTSPStream *stream; @@ -1624,11 +1687,14 @@ finish_unprepare (GstRTSPMedia * media) GstElement *elem = walk->data; DynPaySignalHandlers *handlers; - handlers = g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dypay-handlers"); + handlers = + g_object_steal_data (G_OBJECT (elem), "gst-rtsp-dynpay-handlers"); g_assert (handlers != NULL); g_signal_handler_disconnect (G_OBJECT (elem), handlers->pad_added_handler); g_signal_handler_disconnect (G_OBJECT (elem), + handlers->pad_removed_handler); + g_signal_handler_disconnect (G_OBJECT (elem), handlers->no_more_pads_handler); g_slice_free (DynPaySignalHandlers, handlers); diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h index 2a7c3db..66e83de 100644 --- a/gst/rtsp-server/rtsp-media.h +++ b/gst/rtsp-server/rtsp-media.h @@ -102,12 +102,13 @@ struct _GstRTSPMediaClass { gboolean (*unprepare) (GstRTSPMedia *media); /* signals */ - gboolean (*new_stream) (GstRTSPMedia *media, GstRTSPStream * stream); + void (*new_stream) (GstRTSPMedia *media, GstRTSPStream * stream); + void (*removed_stream) (GstRTSPMedia *media, GstRTSPStream * stream); - gboolean (*prepared) (GstRTSPMedia *media); - gboolean (*unprepared) (GstRTSPMedia *media); + void (*prepared) (GstRTSPMedia *media); + void (*unprepared) (GstRTSPMedia *media); - gboolean (*new_state) (GstRTSPMedia *media, GstState state); + void (*new_state) (GstRTSPMedia *media, GstState state); }; GType gst_rtsp_media_get_type (void); -- 2.7.4