media: listen to pad-removed signals
authorWim Taymans <wim.taymans@collabora.co.uk>
Mon, 22 Apr 2013 15:34:37 +0000 (17:34 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Mon, 22 Apr 2013 15:34:37 +0000 (17:34 +0200)
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
gst/rtsp-server/rtsp-media.h

index 5eaf979..e48f70c 100644 (file)
@@ -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);
index 2a7c3db..66e83de 100644 (file)
@@ -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);