diff --git a/ChangeLog b/ChangeLog index 219554e493..a8cf688c00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2007-04-29 Wim Taymans + + * gst/udp/gstmultiudpsink.c: (leave_multicast), + (gst_multiudpsink_add), (gst_multiudpsink_remove): + Add code to drop membership of a multicast group. + + * gst/udp/gstudpsink.c: (gst_udpsink_update_uri), + (gst_udpsink_set_uri): + Implement URI handler. + + * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_stream_configure_transport), + (gst_rtspsrc_parse_rtpinfo): + Use URI handler to make udpsink instace. + Improve code to configure port and destination. + 2007-04-29 Wim Taymans * gst/udp/gstmultiudpsink.c: (gst_multiudpsink_add): diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c index 64a050a2ca..ee383a455d 100644 --- a/gst/rtsp/gstrtspsrc.c +++ b/gst/rtsp/gstrtspsrc.c @@ -1341,8 +1341,24 @@ use_no_manager: /* configure udpsink back to the server for RTCP messages. */ { GstPad *pad; + gint port; + gchar *destination, *uri; - stream->udpsink = gst_element_factory_make ("udpsink", NULL); + /* get host and port */ + if (transport->lower_transport == RTSP_LOWER_TRANS_UDP_MCAST) + port = transport->port.max; + else + port = transport->server_port.max; + + destination = transport->destination; + if (destination == NULL) + destination = src->addr; + + GST_DEBUG_OBJECT (src, "configure UDP sink for %s:%d", destination, port); + + uri = g_strdup_printf ("udp://%s:%d", destination, port); + stream->udpsink = gst_element_make_from_uri (GST_URI_SINK, uri, NULL); + g_free (uri); if (stream->udpsink == NULL) goto no_sink_element; @@ -1353,10 +1369,6 @@ use_no_manager: /* no sync needed */ g_object_set (G_OBJECT (stream->udpsink), "sync", FALSE, NULL); - /* configure host and port */ - g_object_set (G_OBJECT (stream->udpsink), "host", src->addr, "port", - transport->server_port.max, NULL); - gst_object_ref (stream->udpsink); gst_bin_add (GST_BIN_CAST (src), stream->udpsink); @@ -2819,6 +2831,11 @@ close_failed: /* RTP-Info is of the format: * * url=;[seq=;rtptime=] [, url=...] + * + * rtptime corresponds to the timestamp for the NPT time given in the header + * seqbase corresponds to the next sequence number we received. This number + * indicates the first seqnum after the seek and should be used to discard + * packets that are from before the seek. */ static gboolean gst_rtspsrc_parse_rtpinfo (GstRTSPSrc * src, gchar * rtpinfo) diff --git a/gst/udp/gstmultiudpsink.c b/gst/udp/gstmultiudpsink.c index 72fec4cfc1..21899c95dd 100644 --- a/gst/udp/gstmultiudpsink.c +++ b/gst/udp/gstmultiudpsink.c @@ -400,6 +400,14 @@ join_multicast (GstUDPClient * client) perror ("setsockopt IP_MULTICAST_LOOP\n"); } +static void +leave_multicast (GstUDPClient * client) +{ + if (setsockopt (*(client->sock), IPPROTO_IP, IP_DROP_MEMBERSHIP, + &(client->multi_addr), sizeof (client->multi_addr)) < 0) + perror ("setsockopt IP_DROP_MEMBERSHIP\n"); +} + /* create a socket for sending to remote machine */ static gboolean gst_multiudpsink_init_send (GstMultiUDPSink * sink) @@ -563,6 +571,9 @@ gst_multiudpsink_remove (GstMultiUDPSink * sink, const gchar * host, gint port) g_get_current_time (&now); client->disconnect_time = GST_TIMEVAL_TO_TIME (now); + if (client->multi_addr.imr_multiaddr.s_addr) + leave_multicast (client); + /* Unlock to emit signal before we delete the actual client */ g_mutex_unlock (sink->client_lock); g_signal_emit (G_OBJECT (sink), diff --git a/gst/udp/gstudpsink.c b/gst/udp/gstudpsink.c index 583827dd54..783860628e 100644 --- a/gst/udp/gstudpsink.c +++ b/gst/udp/gstudpsink.c @@ -153,10 +153,59 @@ gst_udpsink_finalize (GstUDPSink * udpsink) G_OBJECT_CLASS (parent_class)->finalize ((GObject *) udpsink); } +static void +gst_udpsink_update_uri (GstUDPSink * sink) +{ + g_free (sink->uri); + sink->uri = g_strdup_printf ("udp://%s:%d", sink->host, sink->port); + + GST_DEBUG_OBJECT (sink, "updated uri to %s", sink->uri); +} + static gboolean gst_udpsink_set_uri (GstUDPSink * sink, const gchar * uri) { - return FALSE; + gchar *protocol; + gchar *location; + gchar *colptr; + + protocol = gst_uri_get_protocol (uri); + if (strcmp (protocol, "udp") != 0) + goto wrong_protocol; + g_free (protocol); + + location = gst_uri_get_location (uri); + if (!location) + return FALSE; + colptr = strstr (location, ":"); + + gst_multiudpsink_remove (GST_MULTIUDPSINK (sink), sink->host, sink->port); + + if (colptr != NULL) { + g_free (sink->host); + sink->host = g_strndup (location, colptr - location); + sink->port = atoi (colptr + 1); + } else { + g_free (sink->host); + sink->host = g_strdup (location); + sink->port = UDP_DEFAULT_PORT; + } + g_free (location); + + gst_multiudpsink_add (GST_MULTIUDPSINK (sink), sink->host, sink->port); + + gst_udpsink_update_uri (sink); + + return TRUE; + + /* ERRORS */ +wrong_protocol: + { + g_free (protocol); + GST_ELEMENT_ERROR (sink, RESOURCE, READ, (NULL), + ("error parsing uri %s: wrong protocol (%s != udp)", uri, protocol)); + return FALSE; + } } static void @@ -216,6 +265,7 @@ gst_udpsink_uri_get_type (void) { return GST_URI_SINK; } + static gchar ** gst_udpsink_uri_get_protocols (void) {