summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2014-09-09 18:11:39 +0200
committerWim Taymans <wtaymans@redhat.com>2014-09-16 10:46:13 +0200
commit0292be09eaf338f16c752aee0c317b1e6b3971e2 (patch)
treeb8baffbf1be03e51a69930ca5f14427e9c5fbace
parentea5d4cfc7e29d010c0d7b6a2f606de76a6d117f4 (diff)
client: simplify session transport handling
link/unlink of the transport in a session was done to keep track of all TCP transports and to send RTP/RTCP data to the streams. We can simplify that by putting all the TCP transports in a hashtable indexed with the channel number. We also don't need to link/unlink the transports when we pause/resume the streams. The same effect is already achieved when we pause/play the media. Indeed, when we pause the media, the transport is removed from the media and the callbacks will not be called anymore. See https://bugzilla.gnome.org/show_bug.cgi?id=736041
-rw-r--r--gst/rtsp-server/rtsp-client.c154
1 files changed, 23 insertions, 131 deletions
diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c
index 77dc1d0..eb87c84 100644
--- a/gst/rtsp-server/rtsp-client.c
+++ b/gst/rtsp-server/rtsp-client.c
@@ -82,7 +82,7 @@ struct _GstRTSPClientPrivate
gchar *path;
GstRTSPMedia *media;
- GList *transports;
+ GHashTable *transports;
GList *sessions;
guint sessions_cookie;
@@ -134,8 +134,6 @@ static void gst_rtsp_client_set_property (GObject * object, guint propid,
static void gst_rtsp_client_finalize (GObject * obj);
static GstSDPMessage *create_sdp (GstRTSPClient * client, GstRTSPMedia * media);
-static void unlink_session_transports (GstRTSPClient * client,
- GstRTSPSession * session, GstRTSPSessionMedia * sessmedia);
static gboolean default_configure_client_media (GstRTSPClient * client,
GstRTSPMedia * media, GstRTSPStream * stream, GstRTSPContext * ctx);
static gboolean default_configure_client_transport (GstRTSPClient * client,
@@ -282,18 +280,15 @@ gst_rtsp_client_init (GstRTSPClient * client)
g_mutex_init (&priv->watch_lock);
priv->close_seq = 0;
priv->drop_backlog = DEFAULT_DROP_BACKLOG;
+ priv->transports = g_hash_table_new (g_direct_hash, g_direct_equal);
}
static GstRTSPFilterResult
filter_session_media (GstRTSPSession * sess, GstRTSPSessionMedia * sessmedia,
gpointer user_data)
{
- GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
-
gst_rtsp_session_media_set_state (sessmedia, GST_STATE_NULL);
- unlink_session_transports (client, sess, sessmedia);
- /* unmanage the media in the session */
return GST_RTSP_FILTER_REMOVE;
}
@@ -386,6 +381,8 @@ gst_rtsp_client_finalize (GObject * obj)
g_assert (priv->sessions == NULL);
g_assert (priv->session_removed_id == 0);
+ g_hash_table_unref (priv->transports);
+
if (priv->connection)
gst_rtsp_connection_free (priv->connection);
if (priv->session_pool) {
@@ -715,92 +712,6 @@ do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client)
return TRUE;
}
-static void
-link_transport (GstRTSPClient * client, GstRTSPSession * session,
- GstRTSPStreamTransport * trans)
-{
- GstRTSPClientPrivate *priv = client->priv;
-
- GST_DEBUG ("client %p: linking transport %p", client, trans);
-
- gst_rtsp_stream_transport_set_callbacks (trans,
- (GstRTSPSendFunc) do_send_data,
- (GstRTSPSendFunc) do_send_data, client, NULL);
-
- priv->transports = g_list_prepend (priv->transports, trans);
-
- /* make sure our session can't expire */
- gst_rtsp_session_prevent_expire (session);
-}
-
-static void
-link_session_transports (GstRTSPClient * client, GstRTSPSession * session,
- GstRTSPSessionMedia * sessmedia)
-{
- guint n_streams, i;
-
- n_streams =
- gst_rtsp_media_n_streams (gst_rtsp_session_media_get_media (sessmedia));
- for (i = 0; i < n_streams; i++) {
- GstRTSPStreamTransport *trans;
- const GstRTSPTransport *tr;
-
- /* get the transport, if there is no transport configured, skip this stream */
- trans = gst_rtsp_session_media_get_transport (sessmedia, i);
- if (trans == NULL)
- continue;
-
- tr = gst_rtsp_stream_transport_get_transport (trans);
-
- if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
- /* for TCP, link the stream to the TCP connection of the client */
- link_transport (client, session, trans);
- }
- }
-}
-
-static void
-unlink_transport (GstRTSPClient * client, GstRTSPSession * session,
- GstRTSPStreamTransport * trans)
-{
- GstRTSPClientPrivate *priv = client->priv;
-
- GST_DEBUG ("client %p: unlinking transport %p", client, trans);
-
- gst_rtsp_stream_transport_set_callbacks (trans, NULL, NULL, NULL, NULL);
-
- priv->transports = g_list_remove (priv->transports, trans);
-
- /* our session can now expire */
- gst_rtsp_session_allow_expire (session);
-}
-
-static void
-unlink_session_transports (GstRTSPClient * client, GstRTSPSession * session,
- GstRTSPSessionMedia * sessmedia)
-{
- guint n_streams, i;
-
- n_streams =
- gst_rtsp_media_n_streams (gst_rtsp_session_media_get_media (sessmedia));
- for (i = 0; i < n_streams; i++) {
- GstRTSPStreamTransport *trans;
- const GstRTSPTransport *tr;
-
- /* get the transport, if there is no transport configured, skip this stream */
- trans = gst_rtsp_session_media_get_transport (sessmedia, i);
- if (trans == NULL)
- continue;
-
- tr = gst_rtsp_stream_transport_get_transport (trans);
-
- if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
- /* for TCP, unlink the stream from the TCP connection of the client */
- unlink_transport (client, session, trans);
- }
- }
-}
-
/**
* gst_rtsp_client_close:
* @client: a #GstRTSPClient
@@ -895,9 +806,6 @@ handle_teardown_request (GstRTSPClient * client, GstRTSPContext * ctx)
if (priv->watch != NULL)
gst_rtsp_watch_set_flushing (priv->watch, TRUE);
- /* unlink the all TCP callbacks */
- unlink_session_transports (client, session, sessmedia);
-
gst_rtsp_session_media_set_state (sessmedia, GST_STATE_NULL);
/* allow messages again so that we can send the reply */
@@ -1084,9 +992,6 @@ handle_pause_request (GstRTSPClient * client, GstRTSPContext * ctx)
rtspstate != GST_RTSP_STATE_RECORDING)
goto invalid_state;
- /* unlink the all TCP callbacks */
- unlink_session_transports (client, session, sessmedia);
-
/* then pause sending */
gst_rtsp_session_media_set_state (sessmedia, GST_STATE_PAUSED);
@@ -1223,9 +1128,6 @@ handle_play_request (GstRTSPClient * client, GstRTSPContext * ctx)
}
}
- /* link the all TCP callbacks */
- link_session_transports (client, session, sessmedia);
-
/* grab RTPInfo from the media now */
rtpinfo = gst_rtsp_session_media_get_rtpinfo (sessmedia);
@@ -1926,11 +1828,22 @@ handle_setup_request (GstRTSPClient * client, GstRTSPContext * ctx)
/* configure the url used to set this transport, this we will use when
* generating the response for the PLAY request */
gst_rtsp_stream_transport_set_url (trans, uri);
-
/* configure keepalive for this transport */
gst_rtsp_stream_transport_set_keepalive (trans,
(GstRTSPKeepAliveFunc) do_keepalive, session, NULL);
+ if (ct->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
+ /* our callbacks to send data on this TCP connection */
+ gst_rtsp_stream_transport_set_callbacks (trans,
+ (GstRTSPSendFunc) do_send_data,
+ (GstRTSPSendFunc) do_send_data, client, NULL);
+
+ g_hash_table_insert (priv->transports,
+ GINT_TO_POINTER (ct->interleaved.min), trans);
+ g_hash_table_insert (priv->transports,
+ GINT_TO_POINTER (ct->interleaved.max), trans);
+ }
+
/* create and serialize the server transport */
st = make_server_transport (client, ctx, ct);
trans_str = gst_rtsp_transport_as_text (st);
@@ -2610,11 +2523,10 @@ handle_data (GstRTSPClient * client, GstRTSPMessage * message)
GstRTSPClientPrivate *priv = client->priv;
GstRTSPResult res;
guint8 channel;
- GList *walk;
guint8 *data;
guint size;
GstBuffer *buffer;
- gboolean handled;
+ GstRTSPStreamTransport *trans;
/* find the stream for this message */
res = gst_rtsp_message_parse_data (message, &channel);
@@ -2625,33 +2537,13 @@ handle_data (GstRTSPClient * client, GstRTSPMessage * message)
buffer = gst_buffer_new_wrapped (data, size);
- handled = FALSE;
- for (walk = priv->transports; walk; walk = g_list_next (walk)) {
- GstRTSPStreamTransport *trans;
- GstRTSPStream *stream;
- const GstRTSPTransport *tr;
-
- trans = walk->data;
-
- tr = gst_rtsp_stream_transport_get_transport (trans);
- stream = gst_rtsp_stream_transport_get_stream (trans);
-
- /* check for TCP transport */
- if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
- /* dispatch to the stream based on the channel number */
- if (tr->interleaved.min == channel) {
- gst_rtsp_stream_recv_rtp (stream, buffer);
- handled = TRUE;
- break;
- } else if (tr->interleaved.max == channel) {
- gst_rtsp_stream_recv_rtcp (stream, buffer);
- handled = TRUE;
- break;
- }
- }
- }
- if (!handled)
+ trans = g_hash_table_lookup (priv->transports, GINT_TO_POINTER (channel));
+ if (trans) {
+ /* dispatch to the stream based on the channel number */
+ gst_rtsp_stream_transport_recv_data (trans, channel, buffer);
+ } else {
gst_buffer_unref (buffer);
+ }
}
/**