From 528f6e0573bb2856d719349c27c7c0d340b128e6 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 21 Sep 2010 19:07:05 +0200 Subject: [PATCH] sdpdemux: add property to disable redirect Add a property to avoid redirection to the rtsp-sdp:// url but instead embeds an rtspsrc element inside sdpdemux as the session manager. Based on patch by Marco Ballesio. Fixes #630046 --- gst/sdp/gstsdpdemux.c | 195 ++++++++++++++++++++++++++++++++++---------------- gst/sdp/gstsdpdemux.h | 2 + 2 files changed, 134 insertions(+), 63 deletions(-) diff --git a/gst/sdp/gstsdpdemux.c b/gst/sdp/gstsdpdemux.c index 5efc30b..72ac8c7 100644 --- a/gst/sdp/gstsdpdemux.c +++ b/gst/sdp/gstsdpdemux.c @@ -103,13 +103,16 @@ enum #define DEFAULT_DEBUG FALSE #define DEFAULT_TIMEOUT 10000000 #define DEFAULT_LATENCY_MS 200 +#define DEFAULT_REDIRECT TRUE enum { PROP_0, PROP_DEBUG, PROP_TIMEOUT, - PROP_LATENCY + PROP_LATENCY, + PROP_REDIRECT, + PROP_LAST }; static void gst_sdp_demux_finalize (GObject * object); @@ -192,6 +195,11 @@ gst_sdp_demux_class_init (GstSDPDemuxClass * klass) "Amount of ms to buffer", 0, G_MAXUINT, DEFAULT_LATENCY_MS, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (gobject_class, PROP_REDIRECT, + g_param_spec_boolean ("redirect", "Redirect", + "Sends a redirection message instead of using a custom session element", + DEFAULT_REDIRECT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + gstelement_class->change_state = gst_sdp_demux_change_state; gstbin_class->handle_message = gst_sdp_demux_handle_message; @@ -249,6 +257,9 @@ gst_sdp_demux_set_property (GObject * object, guint prop_id, case PROP_LATENCY: demux->latency = g_value_get_uint (value); break; + case PROP_REDIRECT: + demux->redirect = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -273,6 +284,9 @@ gst_sdp_demux_get_property (GObject * object, guint prop_id, GValue * value, case PROP_LATENCY: g_value_set_uint (value, demux->latency); break; + case PROP_REDIRECT: + g_value_set_boolean (value, demux->redirect); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -382,12 +396,12 @@ is_multicast_address (const gchar * host_name) for (ai = res; !ret && ai; ai = ai->ai_next) { if (ai->ai_family == AF_INET) ret = - IN_MULTICAST (ntohl (((struct sockaddr_in *) ai->ai_addr)->sin_addr. - s_addr)); + IN_MULTICAST (ntohl (((struct sockaddr_in *) ai->ai_addr)-> + sin_addr.s_addr)); else ret = - IN6_IS_ADDR_MULTICAST (&((struct sockaddr_in6 *) ai->ai_addr)-> - sin6_addr); + IN6_IS_ADDR_MULTICAST (&((struct sockaddr_in6 *) ai-> + ai_addr)->sin6_addr); } freeaddrinfo (res); @@ -489,6 +503,14 @@ gst_sdp_demux_cleanup (GstSDPDemux * demux) g_signal_handler_disconnect (demux->session, demux->session_sig_id); demux->session_sig_id = 0; } + if (demux->session_nmp_id) { + g_signal_handler_disconnect (demux->session, demux->session_nmp_id); + demux->session_nmp_id = 0; + } + if (demux->session_ptmap_id) { + g_signal_handler_disconnect (demux->session, demux->session_ptmap_id); + demux->session_ptmap_id = 0; + } gst_element_set_state (demux->session, GST_STATE_NULL); gst_bin_remove (GST_BIN_CAST (demux), demux->session); demux->session = NULL; @@ -794,6 +816,29 @@ unknown_stream: } } +static void +rtsp_session_pad_added (GstElement * session, GstPad * pad, GstSDPDemux * demux) +{ + GstPad *srcpad = NULL; + gchar *name; + + GST_DEBUG_OBJECT (demux, "got new session pad %" GST_PTR_FORMAT, pad); + + name = gst_pad_get_name (pad); + srcpad = gst_ghost_pad_new (name, pad); + g_free (name); + + gst_pad_set_active (srcpad, TRUE); + gst_element_add_pad (GST_ELEMENT_CAST (demux), srcpad); +} + +static void +rtsp_session_no_more_pads (GstElement * session, GstSDPDemux * demux) +{ + GST_DEBUG_OBJECT (demux, "got no-more-pads"); + gst_element_no_more_pads (GST_ELEMENT_CAST (demux)); +} + static GstCaps * request_pt_map (GstElement * sess, guint session, guint pt, GstSDPDemux * demux) { @@ -880,37 +925,46 @@ on_timeout (GstElement * manager, guint session, guint32 ssrc, /* try to get and configure a manager */ static gboolean -gst_sdp_demux_configure_manager (GstSDPDemux * demux) +gst_sdp_demux_configure_manager (GstSDPDemux * demux, char *rtsp_sdp) { - GstStateChangeReturn ret; - /* configure the session manager */ - if (!(demux->session = gst_element_factory_make ("gstrtpbin", NULL))) - goto manager_failed; - - /* we manage this element */ - gst_bin_add (GST_BIN_CAST (demux), demux->session); - - ret = gst_element_set_state (demux->session, GST_STATE_PAUSED); - if (ret == GST_STATE_CHANGE_FAILURE) - goto start_session_failure; + if (rtsp_sdp != NULL) { + if (!(demux->session = gst_element_factory_make ("rtspsrc", NULL))) + goto rtspsrc_failed; + + g_object_set (demux->session, "location", rtsp_sdp, NULL); + + GST_DEBUG_OBJECT (demux, "connect to signals on rtspsrc"); + demux->session_sig_id = + g_signal_connect (demux->session, "pad-added", + (GCallback) rtsp_session_pad_added, demux); + demux->session_nmp_id = + g_signal_connect (demux->session, "no-more-pads", + (GCallback) rtsp_session_no_more_pads, demux); + } else { + if (!(demux->session = gst_element_factory_make ("gstrtpbin", NULL))) + goto manager_failed; + + /* connect to signals if we did not already do so */ + GST_DEBUG_OBJECT (demux, "connect to signals on session manager"); + demux->session_sig_id = + g_signal_connect (demux->session, "pad-added", + (GCallback) new_session_pad, demux); + demux->session_ptmap_id = + g_signal_connect (demux->session, "request-pt-map", + (GCallback) request_pt_map, demux); + g_signal_connect (demux->session, "on-bye-ssrc", (GCallback) on_bye_ssrc, + demux); + g_signal_connect (demux->session, "on-bye-timeout", (GCallback) on_timeout, + demux); + g_signal_connect (demux->session, "on-timeout", (GCallback) on_timeout, + demux); + } g_object_set (demux->session, "latency", demux->latency, NULL); - /* connect to signals if we did not already do so */ - GST_DEBUG_OBJECT (demux, "connect to signals on session manager"); - demux->session_sig_id = - g_signal_connect (demux->session, "pad-added", - (GCallback) new_session_pad, demux); - demux->session_ptmap_id = - g_signal_connect (demux->session, "request-pt-map", - (GCallback) request_pt_map, demux); - g_signal_connect (demux->session, "on-bye-ssrc", (GCallback) on_bye_ssrc, - demux); - g_signal_connect (demux->session, "on-bye-timeout", (GCallback) on_timeout, - demux); - g_signal_connect (demux->session, "on-timeout", (GCallback) on_timeout, - demux); + /* we manage this element */ + gst_bin_add (GST_BIN_CAST (demux), demux->session); return TRUE; @@ -920,12 +974,9 @@ manager_failed: GST_DEBUG_OBJECT (demux, "no session manager element gstrtpbin found"); return FALSE; } -start_session_failure: +rtspsrc_failed: { - GST_DEBUG_OBJECT (demux, "could not start session"); - gst_element_set_state (demux->session, GST_STATE_NULL); - gst_bin_remove (GST_BIN_CAST (demux), demux->session); - demux->session = NULL; + GST_DEBUG_OBJECT (demux, "no manager element rtspsrc found"); return FALSE; } } @@ -1245,6 +1296,8 @@ gst_sdp_demux_start (GstSDPDemux * demux) GstSDPMessage sdp = { 0 }; GstSDPStream *stream = NULL; GList *walk; + gchar *uri = NULL; + GstStateChangeReturn ret; /* grab the lock so that no state change can interfere */ GST_SDP_STREAM_LOCK (demux); @@ -1305,48 +1358,56 @@ gst_sdp_demux_start (GstSDPDemux * demux) } if (control) { - gchar *uri; - - /* we have RTSP redirect now */ + /* we have RTSP now */ uri = gst_sdp_message_as_uri ("rtsp-sdp", &sdp); - GST_INFO_OBJECT (demux, "redirect to %s", uri); + if (demux->redirect) { + GST_INFO_OBJECT (demux, "redirect to %s", uri); - gst_element_post_message (GST_ELEMENT_CAST (demux), - gst_message_new_element (GST_OBJECT_CAST (demux), - gst_structure_new ("redirect", - "new-location", G_TYPE_STRING, uri, NULL))); - goto sent_redirect; + gst_element_post_message (GST_ELEMENT_CAST (demux), + gst_message_new_element (GST_OBJECT_CAST (demux), + gst_structure_new ("redirect", + "new-location", G_TYPE_STRING, uri, NULL))); + goto sent_redirect; + } } } /* try to get and configure a manager */ - if (!gst_sdp_demux_configure_manager (demux)) - goto no_manager; + if (uri) { + /* we get here when we didn't do a redirect */ + if (!gst_sdp_demux_configure_manager (demux, uri)) + goto no_manager; + } else { - /* create streams with UDP sources and sinks */ - n_streams = gst_sdp_message_medias_len (&sdp); - for (i = 0; i < n_streams; i++) { - stream = gst_sdp_demux_create_stream (demux, &sdp, i); + /* create streams with UDP sources and sinks */ + n_streams = gst_sdp_message_medias_len (&sdp); + for (i = 0; i < n_streams; i++) { + stream = gst_sdp_demux_create_stream (demux, &sdp, i); - GST_DEBUG_OBJECT (demux, "configuring transport for stream %p", stream); + GST_DEBUG_OBJECT (demux, "configuring transport for stream %p", stream); - if (!gst_sdp_demux_stream_configure_udp (demux, stream)) - goto transport_failed; - if (!gst_sdp_demux_stream_configure_udp_sink (demux, stream)) - goto transport_failed; + if (!gst_sdp_demux_stream_configure_udp (demux, stream)) + goto transport_failed; + if (!gst_sdp_demux_stream_configure_udp_sink (demux, stream)) + goto transport_failed; + } } /* set target state on session manager */ - gst_element_set_state (demux->session, demux->target); + ret = gst_element_set_state (demux->session, demux->target); + if (ret == GST_STATE_CHANGE_FAILURE) + goto start_session_failure; - /* activate all streams */ - for (walk = demux->streams; walk; walk = g_list_next (walk)) { - stream = (GstSDPStream *) walk->data; + if (!uri) { + /* activate all streams */ + for (walk = demux->streams; walk; walk = g_list_next (walk)) { + stream = (GstSDPStream *) walk->data; - /* configure target state on udp sources */ - gst_element_set_state (stream->udpsrc[0], demux->target); - gst_element_set_state (stream->udpsrc[1], demux->target); + /* configure target state on udp sources */ + gst_element_set_state (stream->udpsrc[0], demux->target); + gst_element_set_state (stream->udpsrc[1], demux->target); + } } GST_SDP_STREAM_UNLOCK (demux); @@ -1384,6 +1445,14 @@ sent_redirect: GST_SDP_STREAM_UNLOCK (demux); return FALSE; } +start_session_failure: + { + GST_DEBUG_OBJECT (demux, "could not start session"); + gst_element_set_state (demux->session, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (demux), demux->session); + demux->session = NULL; + return FALSE; + } } static gboolean diff --git a/gst/sdp/gstsdpdemux.h b/gst/sdp/gstsdpdemux.h index 32a5329..94db8d6 100644 --- a/gst/sdp/gstsdpdemux.h +++ b/gst/sdp/gstsdpdemux.h @@ -97,11 +97,13 @@ struct _GstSDPDemux { gboolean debug; guint64 udp_timeout; guint latency; + gboolean redirect; /* session management */ GstElement *session; gulong session_sig_id; gulong session_ptmap_id; + gulong session_nmp_id; }; struct _GstSDPDemuxClass { -- 2.7.4