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 5eaf97907518b46c0d2a748941a8c6798ecce28d..e48f70cdf1b08104ac1794e2e2b2e38a75dce3f3 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,10 +1687,13 @@ 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);
 
index 2a7c3dbaa5c93496ef3879bafdc55ca3923d62dd..66e83de033e4482caf165b4a4729ca0813f7bb98 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);