filter_session_media (GstRTSPSession * sess, GstRTSPSessionMedia * sessmedia,
gpointer user_data)
{
- gst_rtsp_session_media_set_state (sessmedia, GST_STATE_NULL);
+ gboolean *closed = user_data;
+ GstRTSPMedia *media;
+ guint i, n_streams;
+ gboolean is_all_udp = TRUE;
+
+ media = gst_rtsp_session_media_get_media (sessmedia);
+ n_streams = gst_rtsp_media_n_streams (media);
+
+ for (i = 0; i < n_streams; i++) {
+ GstRTSPStreamTransport *transport =
+ gst_rtsp_session_media_get_transport (sessmedia, i);
+ const GstRTSPTransport *rtsp_transport;
- return GST_RTSP_FILTER_REMOVE;
+ if (!transport)
+ continue;
+
+ rtsp_transport = gst_rtsp_stream_transport_get_transport (transport);
+ if (rtsp_transport
+ && rtsp_transport->lower_transport != GST_RTSP_LOWER_TRANS_UDP
+ && rtsp_transport->lower_transport != GST_RTSP_LOWER_TRANS_UDP_MCAST) {
+ is_all_udp = FALSE;
+ break;
+ }
+ }
+
+ if (!is_all_udp || gst_rtsp_media_is_stop_on_disconnect (media)) {
+ gst_rtsp_session_media_set_state (sessmedia, GST_STATE_NULL);
+ return GST_RTSP_FILTER_REMOVE;
+ } else {
+ *closed = FALSE;
+ return GST_RTSP_FILTER_KEEP;
+ }
}
static void
cleanup_session (GstRTSPClient * client, GstRTSPSession * sess,
gpointer user_data)
{
+ gboolean *closed = user_data;
+
/* unlink all media managed in this session. This needs to happen
* without the client lock, so we really want to do it here. */
- gst_rtsp_session_filter (sess, filter_session_media, client);
+ gst_rtsp_session_filter (sess, filter_session_media, user_data);
- return GST_RTSP_FILTER_REMOVE;
+ if (*closed)
+ return GST_RTSP_FILTER_REMOVE;
+ else
+ return GST_RTSP_FILTER_KEEP;
}
static void
client_watch_notify (GstRTSPClient * client)
{
GstRTSPClientPrivate *priv = client->priv;
+ gboolean closed = TRUE;
GST_INFO ("client %p: watch destroyed", client);
priv->watch = NULL;
- /* remove all sessions and so drop the extra client ref */
- gst_rtsp_client_session_filter (client, cleanup_session, NULL);
- g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_CLOSED], 0, NULL);
+ /* remove all sessions if the media says so and so drop the extra client ref */
+ gst_rtsp_client_session_filter (client, cleanup_session, &closed);
+ if (closed)
+ g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_CLOSED], 0, NULL);
g_object_unref (client);
}
guint buffer_size;
GstRTSPAddressPool *pool;
GstRTSPTransportMode transport_mode;
+ gboolean stop_on_disconnect;
GstClockTime rtx_time;
guint latency;
#define DEFAULT_BUFFER_SIZE 0x80000
#define DEFAULT_LATENCY 200
#define DEFAULT_TRANSPORT_MODE GST_RTSP_TRANSPORT_MODE_PLAY
+#define DEFAULT_STOP_ON_DISCONNECT TRUE
enum
{
PROP_BUFFER_SIZE,
PROP_LATENCY,
PROP_TRANSPORT_MODE,
+ PROP_STOP_ON_DISCONNECT,
PROP_LAST
};
GST_TYPE_RTSP_TRANSPORT_MODE, DEFAULT_TRANSPORT_MODE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_STOP_ON_DISCONNECT,
+ g_param_spec_boolean ("stop-on-disconnect", "Stop On Disconnect",
+ "If media from this factory should be stopped "
+ "when a client disconnects without TEARDOWN",
+ DEFAULT_STOP_ON_DISCONNECT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONSTRUCTED] =
g_signal_new ("media-constructed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaFactoryClass,
priv->buffer_size = DEFAULT_BUFFER_SIZE;
priv->latency = DEFAULT_LATENCY;
priv->transport_mode = DEFAULT_TRANSPORT_MODE;
+ priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
g_mutex_init (&priv->lock);
g_mutex_init (&priv->medias_lock);
g_value_set_flags (value,
gst_rtsp_media_factory_get_transport_mode (factory));
break;
+ case PROP_STOP_ON_DISCONNECT:
+ g_value_set_boolean (value,
+ gst_rtsp_media_factory_is_stop_on_disonnect (factory));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
gst_rtsp_media_factory_set_transport_mode (factory,
g_value_get_flags (value));
break;
+ case PROP_STOP_ON_DISCONNECT:
+ gst_rtsp_media_factory_set_stop_on_disconnect (factory,
+ g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
}
/**
+ * gst_rtsp_media_factory_set_stop_on_disconnect:
+ * @factory: a #GstRTSPMediaFactory
+ * @stop_on_disconnect: the new value
+ *
+ * Configure if media created from this factory should be stopped
+ * when a client disconnects without sending TEARDOWN.
+ */
+void
+gst_rtsp_media_factory_set_stop_on_disconnect (GstRTSPMediaFactory * factory,
+ gboolean stop_on_disconnect)
+{
+ GstRTSPMediaFactoryPrivate *priv;
+
+ g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
+
+ priv = factory->priv;
+
+ GST_RTSP_MEDIA_FACTORY_LOCK (factory);
+ priv->stop_on_disconnect = stop_on_disconnect;
+ GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
+}
+
+/**
+ * gst_rtsp_media_factory_is_stop_on_disconnect:
+ * @factory: a #GstRTSPMediaFactory
+ *
+ * Get if media created from this factory should be stopped when a client
+ * disconnects without sending TEARDOWN.
+ *
+ * Returns: %TRUE if the media will be stopped when a client disconnects
+ * without sending TEARDOWN.
+ */
+gboolean
+gst_rtsp_media_factory_is_stop_on_disonnect (GstRTSPMediaFactory * factory)
+{
+ GstRTSPMediaFactoryPrivate *priv;
+ gboolean result;
+
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), TRUE);
+
+ priv = factory->priv;
+
+ GST_RTSP_MEDIA_FACTORY_LOCK (factory);
+ result = priv->stop_on_disconnect;
+ GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
+
+ return result;
+}
+
+/**
* gst_rtsp_media_factory_set_retransmission_time:
* @factory: a #GstRTSPMediaFactory
* @time: a #GstClockTime
default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
{
GstRTSPMediaFactoryPrivate *priv = factory->priv;
- gboolean shared, eos_shutdown;
+ gboolean shared, eos_shutdown, stop_on_disconnect;
guint size;
GstRTSPSuspendMode suspend_mode;
GstRTSPProfile profiles;
rtx_time = priv->rtx_time;
latency = priv->latency;
transport_mode = priv->transport_mode;
+ stop_on_disconnect = priv->stop_on_disconnect;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
gst_rtsp_media_set_suspend_mode (media, suspend_mode);
gst_rtsp_media_set_retransmission_time (media, rtx_time);
gst_rtsp_media_set_latency (media, latency);
gst_rtsp_media_set_transport_mode (media, transport_mode);
+ gst_rtsp_media_set_stop_on_disconnect (media, stop_on_disconnect);
if ((pool = gst_rtsp_media_factory_get_address_pool (factory))) {
gst_rtsp_media_set_address_pool (media, pool);
gboolean shared);
gboolean gst_rtsp_media_factory_is_shared (GstRTSPMediaFactory *factory);
+void gst_rtsp_media_factory_set_stop_on_disconnect (GstRTSPMediaFactory *factory,
+ gboolean stop_on_disconnect);
+gboolean gst_rtsp_media_factory_is_stop_on_disonnect (GstRTSPMediaFactory *factory);
+
void gst_rtsp_media_factory_set_suspend_mode (GstRTSPMediaFactory *factory,
GstRTSPSuspendMode mode);
GstRTSPSuspendMode gst_rtsp_media_factory_get_suspend_mode (GstRTSPMediaFactory *factory);
GstRTSPAddressPool *pool;
gboolean blocked;
GstRTSPTransportMode transport_mode;
+ gboolean stop_on_disconnect;
GstElement *element;
GRecMutex state_lock; /* locking order: state lock, lock */
#define DEFAULT_TIME_PROVIDER FALSE
#define DEFAULT_LATENCY 200
#define DEFAULT_TRANSPORT_MODE GST_RTSP_TRANSPORT_MODE_PLAY
+#define DEFAULT_STOP_ON_DISCONNECT TRUE
/* define to dump received RTCP packets */
#undef DUMP_STATS
PROP_TIME_PROVIDER,
PROP_LATENCY,
PROP_TRANSPORT_MODE,
+ PROP_STOP_ON_DISCONNECT,
PROP_LAST
};
GST_TYPE_RTSP_TRANSPORT_MODE, DEFAULT_TRANSPORT_MODE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_STOP_ON_DISCONNECT,
+ g_param_spec_boolean ("stop-on-disconnect", "Stop On Disconnect",
+ "If this media pipeline should be stopped "
+ "when a client disconnects without TEARDOWN",
+ DEFAULT_STOP_ON_DISCONNECT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL,
priv->buffer_size = DEFAULT_BUFFER_SIZE;
priv->time_provider = DEFAULT_TIME_PROVIDER;
priv->transport_mode = DEFAULT_TRANSPORT_MODE;
+ priv->stop_on_disconnect = DEFAULT_STOP_ON_DISCONNECT;
}
static void
case PROP_TRANSPORT_MODE:
g_value_set_flags (value, gst_rtsp_media_get_transport_mode (media));
break;
+ case PROP_STOP_ON_DISCONNECT:
+ g_value_set_boolean (value, gst_rtsp_media_is_stop_on_disconnect (media));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
case PROP_TRANSPORT_MODE:
gst_rtsp_media_set_transport_mode (media, g_value_get_flags (value));
break;
+ case PROP_STOP_ON_DISCONNECT:
+ gst_rtsp_media_set_stop_on_disconnect (media,
+ g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
}
/**
+ * gst_rtsp_media_set_stop_on_disconnect:
+ * @media: a #GstRTSPMedia
+ * @stop_on_disconnect: the new value
+ *
+ * Set or unset if the pipeline for @media should be stopped when a
+ * client disconnects without sending TEARDOWN.
+ */
+void
+gst_rtsp_media_set_stop_on_disconnect (GstRTSPMedia * media,
+ gboolean stop_on_disconnect)
+{
+ GstRTSPMediaPrivate *priv;
+
+ g_return_if_fail (GST_IS_RTSP_MEDIA (media));
+
+ priv = media->priv;
+
+ g_mutex_lock (&priv->lock);
+ priv->stop_on_disconnect = stop_on_disconnect;
+ g_mutex_unlock (&priv->lock);
+}
+
+/**
+ * gst_rtsp_media_is_stop_on_disconnect:
+ * @media: a #GstRTSPMedia
+ *
+ * Check if the pipeline for @media will be stopped when a client disconnects
+ * without sending TEARDOWN.
+ *
+ * Returns: %TRUE if the media will be stopped when a client disconnects
+ * without sending TEARDOWN.
+ */
+gboolean
+gst_rtsp_media_is_stop_on_disconnect (GstRTSPMedia * media)
+{
+ GstRTSPMediaPrivate *priv;
+ gboolean res;
+
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), TRUE);
+
+ priv = media->priv;
+
+ g_mutex_lock (&priv->lock);
+ res = priv->stop_on_disconnect;
+ g_mutex_unlock (&priv->lock);
+
+ return res;
+}
+
+/**
* gst_rtsp_media_set_retransmission_time:
* @media: a #GstRTSPMedia
* @time: the new value
/* do remainder in context */
source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) start_prepare,
- g_object_ref (media), (GDestroyNotify) g_object_unref);
+ g_object_ref (media), (GDestroyNotify) g_object_unref);
g_source_attach (source, context);
g_source_unref (source);
void gst_rtsp_media_set_shared (GstRTSPMedia *media, gboolean shared);
gboolean gst_rtsp_media_is_shared (GstRTSPMedia *media);
+void gst_rtsp_media_set_stop_on_disconnect (GstRTSPMedia *media, gboolean stop_on_disconnect);
+gboolean gst_rtsp_media_is_stop_on_disconnect (GstRTSPMedia *media);
+
void gst_rtsp_media_set_transport_mode (GstRTSPMedia *media, GstRTSPTransportMode mode);
GstRTSPTransportMode gst_rtsp_media_get_transport_mode (GstRTSPMedia *media);