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
This commit is contained in:
Wim Taymans 2010-09-21 19:07:05 +02:00
parent 9db0d94364
commit 528f6e0573
2 changed files with 132 additions and 61 deletions

View file

@ -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;
if (rtsp_sdp != NULL) {
if (!(demux->session = gst_element_factory_make ("rtspsrc", NULL)))
goto rtspsrc_failed;
/* we manage this element */
gst_bin_add (GST_BIN_CAST (demux), demux->session);
g_object_set (demux->session, "location", rtsp_sdp, NULL);
ret = gst_element_set_state (demux->session, GST_STATE_PAUSED);
if (ret == GST_STATE_CHANGE_FAILURE)
goto start_session_failure;
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

View file

@ -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 {