mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-24 16:18:16 +00:00
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:
parent
9db0d94364
commit
528f6e0573
2 changed files with 132 additions and 61 deletions
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue