mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
rtsp-media: Add property to decide if sending media should be stopped when a client disconnects without TEARDOWN
Without TEARDOWN it might be desireable to keep the media running and continue sending data to the client, even if the RTSP connection itself is disconnected. Only do this for session medias that have only UDP transports. If there's at least on TCP transport, it will stop working and cause problems when the connection is disconnected. https://bugzilla.gnome.org/show_bug.cgi?id=758999
This commit is contained in:
parent
5dd1166259
commit
c8f179948e
5 changed files with 191 additions and 9 deletions
|
@ -332,9 +332,38 @@ static GstRTSPFilterResult
|
|||
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;
|
||||
|
||||
return GST_RTSP_FILTER_REMOVE;
|
||||
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;
|
||||
|
||||
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
|
||||
|
@ -395,11 +424,16 @@ static GstRTSPFilterResult
|
|||
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
|
||||
|
@ -3784,12 +3818,14 @@ 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ struct _GstRTSPMediaFactoryPrivate
|
|||
guint buffer_size;
|
||||
GstRTSPAddressPool *pool;
|
||||
GstRTSPTransportMode transport_mode;
|
||||
gboolean stop_on_disconnect;
|
||||
|
||||
GstClockTime rtx_time;
|
||||
guint latency;
|
||||
|
@ -80,6 +81,7 @@ struct _GstRTSPMediaFactoryPrivate
|
|||
#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
|
||||
{
|
||||
|
@ -93,6 +95,7 @@ enum
|
|||
PROP_BUFFER_SIZE,
|
||||
PROP_LATENCY,
|
||||
PROP_TRANSPORT_MODE,
|
||||
PROP_STOP_ON_DISCONNECT,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
|
@ -202,6 +205,13 @@ gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass)
|
|||
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,
|
||||
|
@ -240,6 +250,7 @@ gst_rtsp_media_factory_init (GstRTSPMediaFactory * factory)
|
|||
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);
|
||||
|
@ -304,6 +315,10 @@ gst_rtsp_media_factory_get_property (GObject * object, guint propid,
|
|||
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);
|
||||
}
|
||||
|
@ -347,6 +362,10 @@ gst_rtsp_media_factory_set_property (GObject * object, guint propid,
|
|||
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);
|
||||
}
|
||||
|
@ -862,6 +881,56 @@ gst_rtsp_media_factory_get_protocols (GstRTSPMediaFactory * factory)
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -1270,7 +1339,7 @@ static void
|
|||
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;
|
||||
|
@ -1292,6 +1361,7 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
|
|||
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);
|
||||
|
@ -1303,6 +1373,7 @@ default_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
|
|||
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);
|
||||
|
|
|
@ -118,6 +118,10 @@ void gst_rtsp_media_factory_set_shared (GstRTSPMediaFacto
|
|||
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);
|
||||
|
|
|
@ -102,6 +102,7 @@ struct _GstRTSPMediaPrivate
|
|||
GstRTSPAddressPool *pool;
|
||||
gboolean blocked;
|
||||
GstRTSPTransportMode transport_mode;
|
||||
gboolean stop_on_disconnect;
|
||||
|
||||
GstElement *element;
|
||||
GRecMutex state_lock; /* locking order: state lock, lock */
|
||||
|
@ -151,6 +152,7 @@ struct _GstRTSPMediaPrivate
|
|||
#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
|
||||
|
@ -169,6 +171,7 @@ enum
|
|||
PROP_TIME_PROVIDER,
|
||||
PROP_LATENCY,
|
||||
PROP_TRANSPORT_MODE,
|
||||
PROP_STOP_ON_DISCONNECT,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
|
@ -329,6 +332,13 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
|
|||
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,
|
||||
|
@ -396,6 +406,7 @@ gst_rtsp_media_init (GstRTSPMedia * media)
|
|||
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
|
||||
|
@ -472,6 +483,9 @@ gst_rtsp_media_get_property (GObject * object, guint propid,
|
|||
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);
|
||||
}
|
||||
|
@ -518,6 +532,10 @@ gst_rtsp_media_set_property (GObject * object, guint propid,
|
|||
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);
|
||||
}
|
||||
|
@ -1167,6 +1185,56 @@ gst_rtsp_media_get_buffer_size (GstRTSPMedia * media)
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -2604,7 +2672,7 @@ default_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
|
|||
/* 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);
|
||||
|
||||
|
|
|
@ -186,6 +186,9 @@ GstRTSPPermissions * gst_rtsp_media_get_permissions (GstRTSPMedia *media);
|
|||
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue