From: <wt...@fr...> - 2006-02-16 10:46:00
|
CVS Root: /cvs/gstreamer Module: gst-plugins-good Changes by: wtay Date: Thu Feb 16 2006 02:42:37 PST Log message: * gst/rtsp/README: Updated README. * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_get_type), (gst_rtspsrc_class_init), (gst_rtspsrc_set_property), (gst_rtspsrc_get_property), (gst_rtspsrc_stream_setup_rtp): * gst/rtsp/gstrtspsrc.h: Make sure the RTP port is an even port an try to allocate another if not. Added retry property to control max retries for port allocation. Make sure RTCP port is RTP port+1. Cleanup when port allocation fails. Fixes #319183. Modified files: . : ChangeLog gst/rtsp : README gstrtspsrc.c gstrtspsrc.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-good/ChangeLog.diff?r1=1.2154&r2=1.2155 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-good/gst/rtsp/README.diff?r1=1.4&r2=1.5 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-good/gst/rtsp/gstrtspsrc.c.diff?r1=1.21&r2=1.22 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-good/gst/rtsp/gstrtspsrc.h.diff?r1=1.5&r2=1.6 ====Begin Diffs==== Index: ChangeLog =================================================================== RCS file: /cvs/gstreamer/gst-plugins-good/ChangeLog,v retrieving revision 1.2154 retrieving revision 1.2155 diff -u -d -r1.2154 -r1.2155 --- ChangeLog 16 Feb 2006 09:17:58 -0000 1.2154 +++ ChangeLog 16 Feb 2006 10:42:24 -0000 1.2155 @@ -1,3 +1,19 @@ +2006-02-16 Wim Taymans <wi...@fl...> + + * gst/rtsp/README: + Updated README. + * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_get_type), + (gst_rtspsrc_class_init), (gst_rtspsrc_set_property), + (gst_rtspsrc_get_property), (gst_rtspsrc_stream_setup_rtp): + * gst/rtsp/gstrtspsrc.h: + Make sure the RTP port is an even port an try to allocate + another if not. + Added retry property to control max retries for port allocation. + Make sure RTCP port is RTP port+1. + Cleanup when port allocation fails. + Fixes #319183. + 2006-02-16 Tim-Philipp Müller <tim at centricular dot net> * gst/alpha/gstalpha.c: (gst_alpha_change_state): Index: README RCS file: /cvs/gstreamer/gst-plugins-good/gst/rtsp/README,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- README 15 Aug 2005 13:29:41 -0000 1.4 +++ README 16 Feb 2006 10:42:25 -0000 1.5 @@ -40,9 +40,15 @@ to allocate two local UDP ports for receiving the RTP and RTCP data because we need to send the port numbers to the server in the next request. - In RTSPSrc we create two elements that can handle the udp://0.0.0.0:0 uri. This - will create an udp source element. We get the port number by getting the "port" - property of the element after setting the element to PAUSED. + In RTSPSrc we first create an element that can handle the udp://0.0.0.0:0 uri. This + will create an udp source element with a random port number. We get the port + number by getting the "port" property of the element after setting the element to + PAUSED. This element is used for the RTP packets and has to be an even number. If + the random port number is not an even number we retry to allocate a new udp source. + We then create another UDP source element with the next (uneven) port number to + receive the RTCP packet on. After this step we have two udp ports we can use to + accept RTP packets. +-----------------+ | +------------+ | @@ -129,7 +135,7 @@ << Session: 5d5cb94413288ccd << - This means that RTP/RTCP messages will be send on channel 0/1 respectively and that + This means that RTP/RTCP messages will be sent on channel 0/1 respectively and that the data will be received on the same connection as the RTSP connection. At this point, we remove the UDP source elements as we don't need them anymore. We @@ -303,7 +309,7 @@ +------------+ +-------------+ The server would set the above pipeline to PAUSE to make sure no data - is send to the client yet. + is sent to the client yet. optionally udpsrc elements can be configured to receive client RTP and RTSP messages. Index: gstrtspsrc.c RCS file: /cvs/gstreamer/gst-plugins-good/gst/rtsp/gstrtspsrc.c,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- gstrtspsrc.c 9 Feb 2006 14:20:14 -0000 1.21 +++ gstrtspsrc.c 16 Feb 2006 10:42:25 -0000 1.22 @@ -27,11 +27,14 @@ #include "gstrtspsrc.h" #include "sdp.h" +GST_DEBUG_CATEGORY (rtspsrc_debug); +#define GST_CAT_DEFAULT (rtspsrc_debug) /* elementfactory information */ static GstElementDetails gst_rtspsrc_details = GST_ELEMENT_DETAILS ("RTSP packet receiver", "Source/Network", - "Receive data over the network via RTSP", + "Receive data over the network via RTSP (RFC 2326)", "Wim Taymans <wi...@fl...>"); static GstStaticPadTemplate rtptemplate = @@ -55,6 +58,7 @@ #define DEFAULT_LOCATION NULL #define DEFAULT_PROTOCOLS GST_RTSP_PROTO_UDP_UNICAST | GST_RTSP_PROTO_UDP_MULTICAST | GST_RTSP_PROTO_TCP #define DEFAULT_DEBUG FALSE +#define DEFAULT_RETRY 20 enum { @@ -62,6 +66,7 @@ PROP_LOCATION, PROP_PROTOCOLS, PROP_DEBUG, + PROP_RETRY, /* FILL ME */ }; @@ -129,6 +134,8 @@ NULL }; + GST_DEBUG_CATEGORY_INIT (rtspsrc_debug, "rtspsrc", 0, "RTSP src"); rtspsrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstRTSPSrc", &rtspsrc_info, 0); @@ -166,21 +173,27 @@ gobject_class->set_property = gst_rtspsrc_set_property; gobject_class->get_property = gst_rtspsrc_get_property; - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LOCATION, + g_object_class_install_property (gobject_class, PROP_LOCATION, g_param_spec_string ("location", "RTSP Location", "Location of the RTSP url to read", DEFAULT_LOCATION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PROTOCOLS, + g_object_class_install_property (gobject_class, PROP_PROTOCOLS, g_param_spec_flags ("protocols", "Protocols", "Allowed protocols", GST_TYPE_RTSP_PROTO, DEFAULT_PROTOCOLS, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEBUG, + g_object_class_install_property (gobject_class, PROP_DEBUG, g_param_spec_boolean ("debug", "Debug", "Dump request and response messages to stdout", DEFAULT_DEBUG, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (gobject_class, PROP_RETRY, + g_param_spec_uint ("retry", "Retry", + "Max number of retries when allocating RTP ports.", + 0, G_MAXUINT16, DEFAULT_RETRY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); gstelement_class->change_state = gst_rtspsrc_change_state; } @@ -208,6 +221,9 @@ case PROP_DEBUG: rtspsrc->debug = g_value_get_boolean (value); break; + case PROP_RETRY: + rtspsrc->retry = g_value_get_uint (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -232,6 +248,9 @@ g_value_set_boolean (value, rtspsrc->debug); + g_value_set_uint (value, rtspsrc->retry); @@ -476,59 +495,139 @@ GstStateChangeReturn ret; GstRTSPSrc *src; GstCaps *caps; + GstElement *tmp, *rtp, *rtcp; + gint tmp_rtp, tmp_rtcp; + guint count; src = stream->parent; - if (!(stream->rtpsrc = - gst_element_make_from_uri (GST_URI_SRC, "udp://0.0.0.0:0", NULL))) - goto no_udp_rtp_protocol; + tmp = NULL; + rtp = NULL; + rtcp = NULL; + count = 0; - /* we manage this element */ - gst_rtspsrc_add_element (src, stream->rtpsrc); + /* try to allocate 2 udp ports, the RTP port should be an even + * number and the RTCP port should be the next (uneven) port */ +again: + rtp = gst_element_make_from_uri (GST_URI_SRC, "udp://0.0.0.0:0", NULL); + if (rtp == NULL) + goto no_udp_rtp_protocol; - ret = gst_element_set_state (stream->rtpsrc, GST_STATE_PAUSED); + ret = gst_element_set_state (rtp, GST_STATE_PAUSED); if (ret == GST_STATE_CHANGE_FAILURE) goto start_rtp_failure; - if (!(stream->rtcpsrc = + g_object_get (G_OBJECT (rtp), "port", &tmp_rtp, NULL); + GST_DEBUG_OBJECT (src, "got RTP port %d", tmp_rtp); + /* check if port is even */ + if ((tmp_rtp & 0x01) != 0) { + /* port not even, close and allocate another */ + count++; + if (count > src->retry) + goto no_ports; + GST_DEBUG_OBJECT (src, "RTP port not even, retry %d", count); + /* have to keep port allocated so we can get a new one */ + if (tmp != NULL) { + GST_DEBUG_OBJECT (src, "free temp"); + gst_element_set_state (tmp, GST_STATE_NULL); + gst_object_unref (tmp); + } + tmp = rtp; + GST_DEBUG_OBJECT (src, "retry %d", count); + goto again; + } + /* free leftover temp element/port */ + if (tmp) { + gst_element_set_state (tmp, GST_STATE_NULL); + gst_object_unref (tmp); + tmp = NULL; + /* allocate port+1 for RTCP now */ + rtcp = gst_element_make_from_uri (GST_URI_SRC, "udp://0.0.0.0", NULL); + if (rtcp == NULL) goto no_udp_rtcp_protocol; - gst_rtspsrc_add_element (src, stream->rtcpsrc); + /* set port */ + tmp_rtcp = tmp_rtp + 1; + g_object_set (G_OBJECT (rtcp), "port", tmp_rtcp, NULL); - ret = gst_element_set_state (stream->rtcpsrc, GST_STATE_PAUSED); + GST_DEBUG_OBJECT (src, "starting RTCP on port %d", tmp_rtcp); + ret = gst_element_set_state (rtcp, GST_STATE_PAUSED); + /* FIXME, this could fail if the next port is not free, we + * should retry with another port then */ goto start_rtcp_failure; + /* all fine, do port check */ + g_object_get (G_OBJECT (rtp), "port", rtpport, NULL); + g_object_get (G_OBJECT (rtcp), "port", rtcpport, NULL); + /* this should not happen */ + if (*rtpport != tmp_rtp || *rtcpport != tmp_rtcp) + goto port_error; + /* we manage these elements */ + stream->rtpsrc = rtp; + gst_rtspsrc_add_element (src, stream->rtpsrc); + stream->rtcpsrc = rtcp; + gst_rtspsrc_add_element (src, stream->rtcpsrc); caps = gst_rtspsrc_media_to_caps (media); + /* set caps */ g_object_set (G_OBJECT (stream->rtpsrc), "caps", caps, NULL); - g_object_get (G_OBJECT (stream->rtpsrc), "port", rtpport, NULL); - g_object_get (G_OBJECT (stream->rtcpsrc), "port", rtcpport, NULL); - return TRUE; - /* ERRORS, FIXME, cleanup */ + /* ERRORS */ no_udp_rtp_protocol: { - GST_DEBUG ("could not get UDP source for rtp"); - return FALSE; + GST_DEBUG ("could not get UDP source for RTP"); + goto cleanup; } -no_udp_rtcp_protocol: +start_rtp_failure: - GST_DEBUG ("could not get UDP source for rtcp"); + GST_DEBUG ("could not start UDP source for RTP"); -start_rtp_failure: +no_ports: - GST_DEBUG ("could not start UDP source for rtp"); + GST_DEBUG ("could not allocate UDP port pair after %d retries", count); +no_udp_rtcp_protocol: + { + GST_DEBUG ("could not get UDP source for RTCP"); start_rtcp_failure: - GST_DEBUG ("could not start UDP source for rtcp"); + GST_DEBUG ("could not start UDP source for RTCP"); +port_error: + GST_DEBUG ("ports don't match rtp: %d<->%d, rtcp: %d<->%d", + tmp_rtp, *rtpport, tmp_rtcp, *rtcpport); +cleanup: + if (tmp) { + if (rtp) { + gst_element_set_state (rtp, GST_STATE_NULL); + gst_object_unref (rtp); + if (rtcp) { + gst_element_set_state (rtcp, GST_STATE_NULL); + gst_object_unref (rtcp); return FALSE; Index: gstrtspsrc.h RCS file: /cvs/gstreamer/gst-plugins-good/gst/rtsp/gstrtspsrc.h,v retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- gstrtspsrc.h 6 Dec 2005 19:44:55 -0000 1.5 +++ gstrtspsrc.h 16 Feb 2006 10:42:25 -0000 1.6 @@ -86,6 +86,7 @@ gchar *location; gboolean debug; + guint retry; GstRTSPProto protocols; /* supported options */ |