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
This commit is contained in:
Wim Taymans 2010-08-20 18:17:08 +02:00
parent a900866570
commit dc33070da3
4 changed files with 138 additions and 3 deletions

View file

@ -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);
}

View 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);

View 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);
}
@ -444,6 +458,39 @@ gst_rtsp_media_get_protocols (GstRTSPMedia * media)
return media->protocols;
}
/**
* 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;
}

View 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);