[FFmpeg-devel] [PATCH] avformat/rtpproto: add support for RTP/UDP socket reuse

Camille Oudot camille+ffmpeg-devel at voila.events
Tue Jan 3 21:13:12 EET 2023


Why does the "reuse" option exists on the "udp" protocol in the first
place? Why would it not apply to "rtp" also?

Here is the original patch proposal on udp:
http://ffmpeg.org/pipermail/ffmpeg-devel/2006-October/thread.html#18946

> Sure. But then that does not solve the problem of RTCP mux and SDP
> bundle, which normally would use the exact same IP address and port
> number on the local end (and also on the far end, if set).

I confirm the requirement is to send several RTP streams with FFmpeg
with identical proto/src_ip/src_port/dst_ip/dst_port.

> > 
> It's not that simple. The semantics of REUSEPORT varies between Linux
> and BSD. IIRC, REUSEPORT was originally meant by BSD to allow
> multiple processes to listen on the same multicast group, but then
> Linux redefined it with radically different semantics, for receive
> load-balancing purpose.

They added SO_REUSEPORT_LB in BSD to mimic the Linux behavior.

> 
> Repeating myself, but I don't see how that solves the problem. You
> don't need REUSEADDR for two sockets to send to the same remote
> IP/port, and you cannot rely on it to send from the same local
> IP/port.

It *does* work, at least on Linux: I can send several RTP streams from
the exact same local IP/port (and _to_ the same IP/port too but that's
not a problem in general as you point it) with either REUSEADDR or
REUSEPORT options set.

Here are ffmpeg strace traces for local RTCP port == local RTP port.
The command sends a video stream to the following RTP URL (RTP and are
sent from the same local source port):

rtp://127.0.0.1:40000?localaddr=127.0.0.1&localport=22300&localrtcpport
=22300&rtcpport=40000

without SO_REUSEPORT
====================
...
socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP) = 4
bind(4, {sa_family=AF_INET, sin_port=htons(22300),
    sin_addr=inet_addr("127.0.0.1")}, 16) = 0
getsockname(4, {sa_family=AF_INET, sin_port=htons(22300),
    in_addr=inet_addr("127.0.0.1")}, [128->16]) = 0
setsockopt(4, SOL_SOCKET, SO_SNDBUF, [32768], 4) = 0
socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP) = 5
bind(5, {sa_family=AF_INET, sin_port=htons(22300),
    in_addr=inet_addr("127.0.0.1")}, 16) = -1 EADDRINUSE (Address
    already in use)

with SO_REUSEPORT
=================
...
socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP) = 4
setsockopt(4, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
bind(4, {sa_family=AF_INET, sin_port=htons(22300),
    sin_addr=inet_addr("127.0.0.1")}, 16) = 0
getsockname(4, {sa_family=AF_INET, sin_port=htons(22300),
sin_addr=inet_addr("127.0.0.1")}, [128->16]) = 0
setsockopt(4, SOL_SOCKET, SO_SNDBUF, [32768], 4) = 0
socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP) = 5
setsockopt(5, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
bind(5, {sa_family=AF_INET, sin_port=htons(22300),
    sin_addr=inet_addr("127.0.0.1")}, 16) = 0


Regards

-- 
Camille



More information about the ffmpeg-devel mailing list