Index: libavformat/udp.c
===================================================================
--- libavformat/udp.c	(revision 25113)
+++ libavformat/udp.c	(working copy)
@@ -55,6 +55,9 @@
     int reuse_socket;
     struct sockaddr_storage dest_addr;
     int dest_addr_len;
+    int include;
+    char * sources[32];
+    int num_sources;
 } UDPContext;
 
 #define UDP_TX_BUF_SIZE 32768
@@ -140,6 +143,53 @@
     return 0;
 }
 
+
+static int udp_block_multicast_sources(int sockfd, struct sockaddr *addr, char **sources, int nb_sources)
+{
+    int i;
+    for(i=0; i<nb_sources; ++i) {
+        struct ip_mreq_source mreqs;
+
+        mreqs.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
+        mreqs.imr_interface.s_addr = INADDR_ANY;
+        if (inet_pton(AF_INET, sources[i], &mreqs.imr_sourceaddr.s_addr) < 0) {
+            av_log(NULL, AV_LOG_ERROR, "inet_pton(%s): %s\n", sources[i], strerror(errno));
+            return -1;
+        }
+
+        if (setsockopt(sockfd, IPPROTO_IP, IP_BLOCK_SOURCE, (const void *)&mreqs, sizeof(mreqs)) < 0) {
+            av_log(NULL, AV_LOG_ERROR, "setsockopt(IP_BLOCK_SOURCE): %s\n", strerror(errno));
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+static int udp_add_multicast_sources(int sockfd, struct sockaddr *addr, char **sources, int nb_sources)
+{
+    int i;
+    for(i=0; i<nb_sources; ++i) {
+        struct ip_mreq_source mreqs;
+
+        mreqs.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
+        mreqs.imr_interface.s_addr = INADDR_ANY;
+        if (inet_pton(AF_INET, sources[i], &mreqs.imr_sourceaddr.s_addr) < 0) {
+            av_log(NULL, AV_LOG_ERROR, "inet_pton(%s): %s\n", sources[i], strerror(errno));
+            return -1;
+        }
+
+        if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, (const void *)&mreqs, sizeof(mreqs)) < 0) {
+            av_log(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_SOURCE_MEMBERSHIP): %s\n", strerror(errno));
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
 static struct addrinfo* udp_resolve_host(const char *hostname, int port,
                                          int type, int family, int flags)
 {
@@ -328,6 +378,7 @@
     h->priv_data = s;
     s->ttl = 16;
     s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE;
+    s->num_sources = 0;
 
     p = strchr(uri, '?');
     if (p) {
@@ -344,6 +395,37 @@
         if (find_info_tag(buf, sizeof(buf), "buffer_size", p)) {
             s->buffer_size = strtol(buf, NULL, 10);
         }
+        if (find_info_tag(buf, sizeof(buf), "include", p)) {
+            s->include = strtol(buf, NULL, 10);
+        }
+        if (find_info_tag(buf, sizeof(buf), "sources", p)) {
+            int source_num;
+            int source_len;
+            char *p1;
+            char *source_start;
+
+            p1 = buf;
+            source_start = p1;
+            source_num = 0;
+            for(;;) {
+                if (p1 == (buf + sizeof(buf))) {
+                    break;
+                }
+                if (*p1 == ',' || *p1 == '\0') {
+                    source_len = p1 - source_start;
+                    s->sources[source_num] = av_malloc(sizeof(char)*source_len+1);
+                    memcpy(s->sources[source_num], source_start, source_len);
+                    s->sources[source_num][source_len] = 0;
+                    source_start = p1 + 1;
+                    ++source_num;
+                    if (source_num > 32 || *p1 == '\0') {
+                        break;
+                    }
+                }
+                ++p1;
+            }
+            s->num_sources = source_num;
+        }
     }
 
     /* fill the dest addr */
@@ -390,8 +472,22 @@
                 goto fail;
         } else {
             /* input */
+            if (s->num_sources == 0 || !s->include) {
             if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
                 goto fail;
+
+                if (s->num_sources) {
+                    if (udp_block_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->sources, s->num_sources) < 0)
+                        goto fail;
+                }
+            } else if (s->include && s->num_sources) {
+                if (udp_add_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->sources, s->num_sources) < 0)
+                    goto fail;
+            }
+            else {
+                av_log(NULL, AV_LOG_ERROR, "invalid udp settings: inclusive multicast but no sources given\n");
+                goto fail;
+            }
         }
     }
 
@@ -481,6 +577,11 @@
 {
     UDPContext *s = h->priv_data;
 
+    int i;
+    for(i=0; i<s->num_sources; ++i) {
+        av_free(s->sources[i]);
+    }
+
     if (s->is_multicast && !(h->flags & URL_WRONLY))
         udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr);
     closesocket(s->udp_fd);
