diff --git a/gst/udp/gstmultiudpsink.c b/gst/udp/gstmultiudpsink.c
index a6afc9a..6b5ca4d 100644
--- a/gst/udp/gstmultiudpsink.c
+++ b/gst/udp/gstmultiudpsink.c
@@ -723,14 +723,26 @@ gst_multiudpsink_init_send (GstMultiUDPSink * sink)
   sink->bytes_to_serve = 0;
   sink->bytes_served = 0;
 
-  gst_udp_set_loop_ttl (sink->sock, sink->loop, sink->ttl);
   gst_multiudpsink_setup_qos_dscp (sink);
 
-  /* look for multicast clients and join multicast groups appropriately */
+  /* look for multicast clients and join multicast groups appropriately
+     set also ttl and multicast loopback delivery appropriately  */
   for (clients = sink->clients; clients; clients = g_list_next (clients)) {
     client = (GstUDPClient *) clients->data;
-    if (sink->auto_multicast && gst_udp_is_multicast (&client->theiraddr))
-      gst_udp_join_group (*(client->sock), &client->theiraddr, NULL);
+    if (gst_udp_is_multicast (&client->theiraddr)) {
+      if (sink->auto_multicast) {
+        if (gst_udp_join_group (*(client->sock), &client->theiraddr, NULL)
+            != 0)
+          goto join_group_failed;
+      }
+      if (gst_udp_set_loop (sink->sock, sink->loop) != 0)
+        goto loop_failed;
+      if (gst_udp_set_ttl (sink->sock, sink->ttl, TRUE) != 0)
+        goto ttl_failed;
+    } else {
+      if (gst_udp_set_ttl (sink->sock, sink->ttl, FALSE) != 0)
+        goto ttl_failed;
+    }
   }
   return TRUE;
 
@@ -749,6 +761,29 @@ no_broadcast:
             g_strerror (errno)));
     return FALSE;
   }
+join_group_failed:
+  {
+    CLOSE_IF_REQUESTED (sink);
+    GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL),
+        ("Could not join multicast group (%d): %s", errno, g_strerror (errno)));
+    return FALSE;
+  }
+ttl_failed:
+  {
+    CLOSE_IF_REQUESTED (sink);
+    GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL),
+        ("Could not set TTL socket option (%d): %s", errno,
+            g_strerror (errno)));
+    return FALSE;
+  }
+loop_failed:
+  {
+    CLOSE_IF_REQUESTED (sink);
+    GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL),
+        ("Could not set loopback socket option (%d): %s", errno,
+            g_strerror (errno)));
+    return FALSE;
+  }
 }
 
 static void
diff --git a/gst/udp/gstudpnetutils.c b/gst/udp/gstudpnetutils.c
index 2ed65e6..322351a 100644
--- a/gst/udp/gstudpnetutils.c
+++ b/gst/udp/gstudpnetutils.c
@@ -113,7 +113,7 @@ beach:
 }
 
 int
-gst_udp_set_loop_ttl (int sockfd, gboolean loop, int ttl)
+gst_udp_set_loop (int sockfd, gboolean loop)
 {
   socklen_t socklen;
   struct sockaddr_storage addr;
@@ -128,29 +128,70 @@ gst_udp_set_loop_ttl (int sockfd, gboolean loop, int ttl)
   switch (addr.ss_family) {
     case AF_INET:
     {
-      if ((ret =
-              setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &l,
-                  sizeof (l))) < 0)
+      ret = setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &l, sizeof (l));
+      if (ret < 0)
         return ret;
 
-      if ((ret =
-              setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
-                  sizeof (ttl))) < 0)
-        return ret;
       break;
     }
     case AF_INET6:
     {
-      if ((ret =
-              setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &l,
-                  sizeof (l))) < 0)
+      ret =
+          setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &l,
+          sizeof (l));
+      if (ret < 0)
         return ret;
 
-      if ((ret =
-              setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl,
-                  sizeof (ttl))) < 0)
+      break;
+    }
+    default:
+#ifdef G_OS_WIN32
+      WSASetLastError (WSAEAFNOSUPPORT);
+#else
+      errno = EAFNOSUPPORT;
+#endif
+  }
+
+  return ret;
+}
+
+int
+gst_udp_set_ttl (int sockfd, int ttl, gboolean is_multicast)
+{
+  socklen_t socklen;
+  struct sockaddr_storage addr;
+  int optname = -1;
+  int ret = -1;
+
+  socklen = sizeof (addr);
+  if ((ret = getsockname (sockfd, (struct sockaddr *) &addr, &socklen)) < 0) {
+    return ret;
+  }
+
+  switch (addr.ss_family) {
+    case AF_INET:
+    {
+      optname = (is_multicast == TRUE) ? IP_MULTICAST_TTL : IP_TTL;
+      ret = setsockopt (sockfd, IPPROTO_IP, optname, &ttl, sizeof (ttl));
+      if (ret < 0)
+        return ret;
+      break;
+    }
+    case AF_INET6:
+    {
+      optname =
+          (is_multicast == TRUE) ? IPV6_MULTICAST_HOPS : IPV6_UNICAST_HOPS;
+      ret = setsockopt (sockfd, IPPROTO_IPV6, optname, &ttl, sizeof (ttl));
+      if (ret < 0)
         return ret;
 
+      /* When using IPV4 address with IPV6 socket, both TTL values
+         must be set in order to actually use the given value.
+         Has no effect when IPV6 address is used. */
+      optname = (is_multicast == TRUE) ? IP_MULTICAST_TTL : IP_TTL;
+      ret = setsockopt (sockfd, IPPROTO_IP, optname, &ttl, sizeof (ttl));
+      if (ret < 0)
+        return ret;
       break;
     }
     default:
diff --git a/gst/udp/gstudpnetutils.h b/gst/udp/gstudpnetutils.h
index b8f49a7..faaece9 100644
--- a/gst/udp/gstudpnetutils.h
+++ b/gst/udp/gstudpnetutils.h
@@ -80,7 +80,8 @@ int gst_udp_get_sockaddr_length(struct sockaddr_storage *addr);
 int gst_udp_get_addr      (const char *hostname, int port, struct sockaddr_storage *addr);
 int gst_udp_is_multicast  (struct sockaddr_storage *addr);
 
-int gst_udp_set_loop_ttl  (int sockfd, gboolean loop, int ttl);
+int gst_udp_set_loop      (int sockfd, gboolean loop);
+int gst_udp_set_ttl       (int sockfd, int ttl, gboolean is_multicast);
 
 int gst_udp_join_group    (int sockfd, struct sockaddr_storage *addr,
                            gchar *iface);
