media-factory: add eos-shutdown property
authorWim Taymans <wim.taymans@collabora.co.uk>
Fri, 20 Aug 2010 16:17:08 +0000 (18:17 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Fri, 20 Aug 2010 16:17:08 +0000 (18:17 +0200)
Add an eos-shutdown property that will send an EOS to the pipeline before
shutting it down. This allows for nice cleanup in case of a muxer.

Fixes #625597

gst/rtsp-server/rtsp-media-factory.c
gst/rtsp-server/rtsp-media-factory.h
gst/rtsp-server/rtsp-media.c
gst/rtsp-server/rtsp-media.h

index 44d8098..92591aa 100644 (file)
 
 #define DEFAULT_LAUNCH         NULL
 #define DEFAULT_SHARED         FALSE
+#define DEFAULT_EOS_SHUTDOWN   FALSE
 
 enum
 {
   PROP_0,
   PROP_LAUNCH,
   PROP_SHARED,
+  PROP_EOS_SHUTDOWN,
   PROP_LAST
 };
 
@@ -82,6 +84,11 @@ gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
       g_param_spec_boolean ("shared", "Shared", "If media from this factory is shared",
           DEFAULT_SHARED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
+      g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
+        "Send EOS down the pipeline before shutting down",
+          DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   klass->gen_key = default_gen_key;
   klass->get_element = default_get_element;
   klass->construct = default_construct;
@@ -96,6 +103,7 @@ gst_rtsp_media_factory_init (GstRTSPMediaFactory * factory)
 {
   factory->launch = g_strdup (DEFAULT_LAUNCH);
   factory->shared = DEFAULT_SHARED;
+  factory->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
 
   factory->lock = g_mutex_new ();
   factory->medias_lock = g_mutex_new ();
@@ -129,6 +137,9 @@ gst_rtsp_media_factory_get_property (GObject *object, guint propid,
     case PROP_SHARED:
       g_value_set_boolean (value, gst_rtsp_media_factory_is_shared (factory));
       break;
+    case PROP_EOS_SHUTDOWN:
+      g_value_set_boolean (value, gst_rtsp_media_factory_is_eos_shutdown (factory));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
   }
@@ -147,6 +158,9 @@ gst_rtsp_media_factory_set_property (GObject *object, guint propid,
     case PROP_SHARED:
       gst_rtsp_media_factory_set_shared (factory, g_value_get_boolean (value));
       break;
+    case PROP_EOS_SHUTDOWN:
+      gst_rtsp_media_factory_set_eos_shutdown (factory, g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
   }
@@ -260,6 +274,48 @@ gst_rtsp_media_factory_is_shared (GstRTSPMediaFactory *factory)
   return result;
 }
 
+/**
+ * gst_rtsp_media_factory_set_eos_shutdown:
+ * @factory: a #GstRTSPMediaFactory
+ * @eos_shutdown: the new value
+ *
+ * Configure if media created from this factory will have an EOS sent to the
+ * pipeline before shutdown.
+ */
+void
+gst_rtsp_media_factory_set_eos_shutdown (GstRTSPMediaFactory *factory,
+    gboolean eos_shutdown)
+{
+  g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
+
+  g_mutex_lock (factory->lock);
+  factory->eos_shutdown = eos_shutdown;
+  g_mutex_unlock (factory->lock);
+}
+
+/**
+ * gst_rtsp_media_factory_is_eos_shutdown:
+ * @factory: a #GstRTSPMediaFactory
+ *
+ * Get if media created from this factory will have an EOS event sent to the
+ * pipeline before shutdown.
+ *
+ * Returns: %TRUE if the media will receive EOS before shutdown.
+ */
+gboolean
+gst_rtsp_media_factory_is_eos_shutdown (GstRTSPMediaFactory *factory)
+{
+  gboolean result;
+
+  g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE);
+
+  g_mutex_lock (factory->lock);
+  result = factory->eos_shutdown;
+  g_mutex_unlock (factory->lock);
+
+  return result;
+}
+
 static gboolean
 compare_media (gpointer key, GstRTSPMedia *media1, GstRTSPMedia *media2)
 {
@@ -536,12 +592,14 @@ no_element:
 static void
 default_configure (GstRTSPMediaFactory *factory, GstRTSPMedia *media)
 {
-  gboolean shared;
+  gboolean shared, eos_shutdown;
 
   /* configure the sharedness */
   g_mutex_lock (factory->lock);
   shared = factory->shared;
+  eos_shutdown = factory->eos_shutdown;
   g_mutex_unlock (factory->lock);
 
   gst_rtsp_media_set_shared (media, shared);
+  gst_rtsp_media_set_eos_shutdown (media, eos_shutdown);
 }
index 3d1ac9b..d462914 100644 (file)
@@ -57,6 +57,7 @@ struct _GstRTSPMediaFactory {
   GMutex       *lock;
   gchar        *launch;
   gboolean      shared;
+  gboolean      eos_shutdown;
 
   GMutex       *medias_lock;
   GHashTable   *medias;
@@ -107,6 +108,10 @@ void                  gst_rtsp_media_factory_set_shared   (GstRTSPMediaFactory *
                                                            gboolean shared);
 gboolean              gst_rtsp_media_factory_is_shared    (GstRTSPMediaFactory *factory);
 
+void                  gst_rtsp_media_factory_set_eos_shutdown   (GstRTSPMediaFactory *factory,
+                                                                 gboolean eos_shutdown);
+gboolean              gst_rtsp_media_factory_is_eos_shutdown    (GstRTSPMediaFactory *factory);
+
 /* creating the media from the factory and a url */
 GstRTSPMedia *        gst_rtsp_media_factory_construct    (GstRTSPMediaFactory *factory,
                                                            const GstRTSPUrl *url);
index c2dc996..02a9317 100644 (file)
@@ -29,6 +29,7 @@
 #define DEFAULT_REUSABLE       FALSE
 #define DEFAULT_PROTOCOLS      GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_TCP
 //#define DEFAULT_PROTOCOLS      GST_RTSP_LOWER_TRANS_UDP_MCAST
+#define DEFAULT_EOS_SHUTDOWN   FALSE
 
 /* define to dump received RTCP packets */
 #undef DUMP_STATS
@@ -39,6 +40,7 @@ enum
   PROP_SHARED,
   PROP_REUSABLE,
   PROP_PROTOCOLS,
+  PROP_EOS_SHUTDOWN,
   PROP_LAST
 };
 
@@ -96,6 +98,11 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
           "Allowed lower transport protocols", GST_TYPE_RTSP_LOWER_TRANS,
           DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_EOS_SHUTDOWN,
+      g_param_spec_boolean ("eos-shutdown", "EOS Shutdown",
+          "Send an EOS event to the pipeline before unpreparing",
+          DEFAULT_EOS_SHUTDOWN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gst_rtsp_media_signals[SIGNAL_UNPREPARED] =
       g_signal_new ("unprepared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       G_STRUCT_OFFSET (GstRTSPMediaClass, unprepared), NULL, NULL,
@@ -124,6 +131,7 @@ gst_rtsp_media_init (GstRTSPMedia * media)
   media->shared = DEFAULT_SHARED;
   media->reusable = DEFAULT_REUSABLE;
   media->protocols = DEFAULT_PROTOCOLS;
+  media->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
 }
 
 /* FIXME. this should be done in multiudpsink */
@@ -245,6 +253,9 @@ gst_rtsp_media_get_property (GObject * object, guint propid,
     case PROP_PROTOCOLS:
       g_value_set_flags (value, gst_rtsp_media_get_protocols (media));
       break;
+    case PROP_EOS_SHUTDOWN:
+      g_value_set_boolean (value, gst_rtsp_media_is_eos_shutdown (media));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
   }
@@ -266,6 +277,9 @@ gst_rtsp_media_set_property (GObject * object, guint propid,
     case PROP_PROTOCOLS:
       gst_rtsp_media_set_protocols (media, g_value_get_flags (value));
       break;
+    case PROP_EOS_SHUTDOWN:
+      gst_rtsp_media_set_eos_shutdown (media, g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
   }
@@ -445,6 +459,39 @@ gst_rtsp_media_get_protocols (GstRTSPMedia * media)
 }
 
 /**
+ * gst_rtsp_media_set_eos_shutdown:
+ * @media: a #GstRTSPMedia
+ * @eos_shutdown: the new value
+ *
+ * Set or unset if an EOS event will be sent to the pipeline for @media before
+ * it is unprepared.
+ */
+void
+gst_rtsp_media_set_eos_shutdown (GstRTSPMedia *media, gboolean eos_shutdown)
+{
+  g_return_if_fail (GST_IS_RTSP_MEDIA (media));
+
+  media->eos_shutdown = eos_shutdown;
+}
+
+/**
+ * gst_rtsp_media_is_eos_shutdown:
+ * @media: a #GstRTSPMedia
+ *
+ * Check if the pipeline for @media will send an EOS down the pipeline before
+ * unpreparing.
+ *
+ * Returns: %TRUE if the media will send EOS before unpreparing.
+ */
+gboolean
+gst_rtsp_media_is_eos_shutdown (GstRTSPMedia *media)
+{
+  g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
+
+  return media->eos_shutdown;
+}
+
+/**
  * gst_rtsp_media_n_streams:
  * @media: a #GstRTSPMedia
  *
@@ -1328,6 +1375,15 @@ default_handle_message (GstRTSPMedia * media, GstMessage * message)
 
       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED);
       break;
+    case GST_MESSAGE_EOS:
+      GST_INFO ("%p: got EOS", media);
+      if (media->eos_pending) {
+        GST_DEBUG ("shutting down after EOS");
+        gst_element_set_state (media->pipeline, GST_STATE_NULL);
+        media->eos_pending = FALSE;
+        g_object_unref (media);
+      }
+      break;
     default:
       GST_INFO ("%p: got message type %s", media,
           gst_message_type_get_name (type));
@@ -1572,8 +1628,19 @@ gst_rtsp_media_unprepare (GstRTSPMedia * media)
 static gboolean
 default_unprepare (GstRTSPMedia * media)
 {
-  gst_element_set_state (media->pipeline, GST_STATE_NULL);
-
+  if (media->eos_shutdown) {
+    GST_DEBUG ("sending EOS for shutdown");
+    /* ref so that we don't disappear */
+    g_object_ref (media);
+    media->eos_pending = TRUE;
+    gst_element_send_event (media->pipeline, gst_event_new_eos());
+    /* we need to go to playing again for the EOS to propagate, normally in this
+     * state, nothing is receiving data from us anymore so this is ok. */
+    gst_element_set_state (media->pipeline, GST_STATE_PLAYING);
+  } else {
+    GST_DEBUG ("shutting down");
+    gst_element_set_state (media->pipeline, GST_STATE_NULL);
+  }
   return TRUE;
 }
 
index 0dea08a..9f62074 100644 (file)
@@ -200,12 +200,14 @@ struct _GstRTSPMedia {
   GstRTSPLowerTrans  protocols;
   gboolean           reused;
   gboolean           is_ipv6;
+  gboolean           eos_shutdown;
 
   GstElement        *element;
   GArray            *streams;
   GList             *dynamic;
   GstRTSPMediaStatus status;
   gint               active;
+  gboolean           eos_pending;
 
   /* the pipeline for the media */
   GstElement        *pipeline;
@@ -265,6 +267,9 @@ gboolean              gst_rtsp_media_is_reusable      (GstRTSPMedia *media);
 void                  gst_rtsp_media_set_protocols    (GstRTSPMedia *media, GstRTSPLowerTrans protocols);
 GstRTSPLowerTrans     gst_rtsp_media_get_protocols    (GstRTSPMedia *media);
 
+void                  gst_rtsp_media_set_eos_shutdown (GstRTSPMedia *media, gboolean eos_shutdown);
+gboolean              gst_rtsp_media_is_eos_shutdown  (GstRTSPMedia *media);
+
 /* prepare the media for playback */
 gboolean              gst_rtsp_media_prepare          (GstRTSPMedia *media);
 gboolean              gst_rtsp_media_is_prepared      (GstRTSPMedia *media);