summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2010-09-21 19:07:05 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2010-09-21 19:15:27 +0200
commit528f6e0573bb2856d719349c27c7c0d340b128e6 (patch)
tree07629513d5b9a0e63d54066229f720a216d42599
parent9db0d943641529a4f33be39735b7e7868b02b401 (diff)
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
-rw-r--r--gst/sdp/gstsdpdemux.c195
-rw-r--r--gst/sdp/gstsdpdemux.h2
2 files changed, 134 insertions, 63 deletions
diff --git a/gst/sdp/gstsdpdemux.c b/gst/sdp/gstsdpdemux.c
index 5efc30b1c..72ac8c75d 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 32a532937..94db8d62c 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 {