From 7c0f8a77ecfaa1b49bc0195e7c914769cec7e9de Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 20 Aug 2010 13:09:12 +0200 Subject: [PATCH] media: don't add udp addresses multiple times Keep track of the udp addresses we added to udpsink and never add the same udp destination twice. This avoids duplicate packets when using multicast. --- gst/rtsp-server/rtsp-media.c | 91 +++++++++++++++++++++++++++++++++--- gst/rtsp-server/rtsp-media.h | 1 + 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 08939c6a69..919622e163 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -1527,6 +1527,89 @@ default_unprepare (GstRTSPMedia * media) return TRUE; } +typedef struct { + gint count; + gchar *dest; + gint min, max; +} RTSPDestination; + + +static gint +dest_compare (RTSPDestination * a, RTSPDestination * b) +{ + if ((a->min == b->min) && (a->max == b->max) && (strcmp (a->dest, b->dest) == 0)) + return 0; + + return 1; +} + +/* FIXME, udpsink should do this for us */ +static void +add_udp_destination (GstRTSPMedia *media, GstRTSPMediaStream *stream, + gchar *dest, gint min, gint max) +{ + RTSPDestination fdest; + RTSPDestination *ndest; + GList *find; + + fdest.dest = dest; + fdest.min = min; + fdest.max = max; + + /* first see if we already added this destination */ + find = g_list_find_custom (stream->destinations, &fdest, (GCompareFunc) dest_compare); + if (find) { + ndest = (RTSPDestination *) find->data; + + GST_INFO ("already streaming to %s:%d-%d with %d clients", dest, min, max, ndest->count); + ndest->count++; + } else { + GST_INFO ("adding %s:%d-%d", dest, min, max); + + g_signal_emit_by_name (stream->udpsink[0], "add", dest, min, NULL); + g_signal_emit_by_name (stream->udpsink[1], "add", dest, max, NULL); + + ndest = g_slice_new (RTSPDestination); + ndest->count = 1; + ndest->dest = g_strdup (dest); + ndest->min = min; + ndest->max = max; + + stream->destinations = g_list_prepend (stream->destinations, ndest); + } +} + +static void +remove_udp_destination (GstRTSPMedia *media, GstRTSPMediaStream *stream, + gchar *dest, gint min, gint max) +{ + RTSPDestination fdest; + RTSPDestination *ndest; + GList *find; + + fdest.dest = dest; + fdest.min = min; + fdest.max = max; + + /* first see if we already added this destination */ + find = g_list_find_custom (stream->destinations, &fdest, (GCompareFunc) dest_compare); + if (!find) + return; + + ndest = (RTSPDestination *) find->data; + if (--ndest->count == 0) { + GST_INFO ("removing %s:%d-%d", dest, min, max); + g_signal_emit_by_name (stream->udpsink[0], "remove", dest, min, NULL); + g_signal_emit_by_name (stream->udpsink[1], "remove", dest, max, NULL); + + stream->destinations = g_list_delete_link (stream->destinations, find); + g_free (ndest->dest); + g_slice_free (RTSPDestination, ndest); + } else { + GST_INFO ("still streaming to %s:%d-%d with %d clients", dest, min, max, ndest->count); + } +} + /** * gst_rtsp_media_set_state: * @media: a #GstRTSPMedia @@ -1610,16 +1693,12 @@ gst_rtsp_media_set_state (GstRTSPMedia * media, GstState state, } if (add && !tr->active) { - GST_INFO ("adding %s:%d-%d", dest, min, max); - g_signal_emit_by_name (stream->udpsink[0], "add", dest, min, NULL); - g_signal_emit_by_name (stream->udpsink[1], "add", dest, max, NULL); + add_udp_destination (media, stream, dest, min, max); stream->transports = g_list_prepend (stream->transports, tr); tr->active = TRUE; media->active++; } else if (remove && tr->active) { - GST_INFO ("removing %s:%d-%d", dest, min, max); - g_signal_emit_by_name (stream->udpsink[0], "remove", dest, min, NULL); - g_signal_emit_by_name (stream->udpsink[1], "remove", dest, max, NULL); + remove_udp_destination (media, stream, dest, min, max); stream->transports = g_list_remove (stream->transports, tr); tr->active = FALSE; media->active--; diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h index ec3e832f65..d3c94db69a 100644 --- a/gst/rtsp-server/rtsp-media.h +++ b/gst/rtsp-server/rtsp-media.h @@ -137,6 +137,7 @@ struct _GstRTSPMediaStream { /* transports we stream to */ GList *transports; + GList *destinations; }; /**