Multicast transmission from defined interface fails for "non-default" interfaces when using gstreamers udpsink multicast-iface on windows 10
This is related to the following issues:
https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues/472
When using the following pipelines for a closed, local network:
gst-launch-1.0 videotestsrc ! "video/x-raw, format=UYVY, depth=8, width=800, height=600, framerate=30/1" ! rtpvrawpay ! udpsink host=224.0.0.1 port=5000 multicast-iface=192.168.1.3
gst-launch-1.0 udpsrc port=5000 multicast-group=224.0.0.1 auto-multicast=true ! application/x-rtp, media=video, clock-rate=90000, encoding-name=RAW, sampling=YCbCr-4:2:2, depth=8, width=800, height=600, colorimetry=BT709-2, payload=96, a-framerate=30" ! rtpvrawdepay ! videoconvert ! queue ! autovideosink
If "192.168.1.3" is the non-default interface, and the receivers is only in the non-default interface's network, nothing will be received. Unless I'm using gstreamer wrong, it seems to me that the fix was incomplete.
I found a potential fix that made it work for me and was hoping to contribute it to GLib. It seems that transmitting interface, for sending IPv4 multicast traffic, for windows, isn't getting set. Setting interface for multicast transmission can be done like this.
result = setsockopt (socket->priv->fd, IPPROTO_IP, optname,
&mc_req, sizeof (mc_req));
#if def(G_OS_WIN32)
if(join_group)
result & setsockopt(socket->priv->fd, IPPROTO_IP, IP_MULTICAST_IF,
&mc_req.imr_interface.s_addr, sizeof(mc_req.imr_interface.s_addr));
#endif
There is also an issue with the fix when a non-ip-adress is used as input. For windows at least, gstreamer will run without any complains when interface-iface is an invalid non-ip-adress-string. The fix returns INADDR_NONE and as INADDR_NONE = 255.255.255.255, it is a "valid adress". So a test for INADDR_NONE at that point could prevent that.
#elif defined(G_OS_WIN32)
if (iface)
{
mc_req.imr_interface.s_addr = g_socket_w32_get_adapter_ipv4_addr (iface);
if (mc_req.imr_interface.s_addr == INADDR_NONE)
{
//g_set_error( ...
return FALSE;
}
}