From dc33070da3c28f81b083f20881234a712babe0fc Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 20 Aug 2010 18:17:08 +0200 Subject: [PATCH] media-factory: add eos-shutdown property 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 | 60 +++++++++++++++++++++++++++++- gst/rtsp-server/rtsp-media-factory.h | 5 +++ gst/rtsp-server/rtsp-media.c | 71 +++++++++++++++++++++++++++++++++++- gst/rtsp-server/rtsp-media.h | 5 +++ 4 files changed, 138 insertions(+), 3 deletions(-) diff --git a/gst/rtsp-server/rtsp-media-factory.c b/gst/rtsp-server/rtsp-media-factory.c index 44d8098..92591aa 100644 --- a/gst/rtsp-server/rtsp-media-factory.c +++ b/gst/rtsp-server/rtsp-media-factory.c @@ -21,12 +21,14 @@ #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); } diff --git a/gst/rtsp-server/rtsp-media-factory.h b/gst/rtsp-server/rtsp-media-factory.h index 3d1ac9b..d462914 100644 --- a/gst/rtsp-server/rtsp-media-factory.h +++ b/gst/rtsp-server/rtsp-media-factory.h @@ -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); diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index c2dc996..02a9317 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -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; } diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h index 0dea08a..9f62074 100644 --- a/gst/rtsp-server/rtsp-media.h +++ b/gst/rtsp-server/rtsp-media.h @@ -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); -- 2.7.4