From 998e1d3d79b416422e2b1d4f9a5ffb92062db256 Mon Sep 17 00:00:00 2001 From: Camille Oudot Date: Fri, 16 Dec 2022 15:30:02 +0100 Subject: [PATCH] avformat/rtpproto: add support for RTP/UDP socket reuse This patch introduces a "reuse" option over the RTP protocol. It simply passes the value to the underlying UDP protocol's "reuse" option. Some RTP peers expect multiple streams to come from the same IP/port, e.g. when RTP BUNDLE is involved (different streams sent from/to the same srcIP/srcPort/dspIp/dspPort tuple), or when rtcp-mux is involved (RTP and RTCP packets are muxed together). This patch allows ffmpeg to bundle RTP streams and mux RTP/RTCP together by setting the "reuse" option, and fiddling with the "localaddr", "localport", "localrtcpport" and "rtcpport" options. Signed-off-by: Camille Oudot --- Changelog | 1 + libavformat/rtpproto.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/Changelog b/Changelog index f3a6abb9cd..39b68f1702 100644 --- a/Changelog +++ b/Changelog @@ -28,6 +28,7 @@ version : - showcwt multimedia filter - corr video filter - adrc audio filter +- Add RTP protocol "reuse" option to allow UDP socket reuse version 5.1: diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index b970901d01..e135907127 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -55,6 +55,7 @@ typedef struct RTPContext { int buffer_size; int rtcp_port, local_rtpport, local_rtcpport; int connect; + int reuse_socket; int pkt_size; int dscp; char *sources; @@ -74,6 +75,7 @@ static const AVOption options[] = { { "local_rtpport", "Local rtp port", OFFSET(local_rtpport), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "local_rtcpport", "Local rtcp port", OFFSET(local_rtcpport), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "connect", "Connect socket", OFFSET(connect), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E }, + { "reuse", "Explicitly allow reusing UDP sockets", OFFSET(reuse_socket), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E }, { "write_to_source", "Send packets to the source address of the latest received packet", OFFSET(write_to_source), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E }, { "pkt_size", "Maximum packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "dscp", "DSCP class", OFFSET(dscp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, @@ -191,6 +193,8 @@ static void build_udp_url(RTPContext *s, url_add_option(buf, buf_size, "pkt_size=%d", s->pkt_size); if (s->connect) url_add_option(buf, buf_size, "connect=1"); + if (s->reuse_socket) + url_add_option(buf, buf_size, "reuse=1"); if (s->dscp >= 0) url_add_option(buf, buf_size, "dscp=%d", s->dscp); url_add_option(buf, buf_size, "fifo_size=0"); @@ -266,6 +270,13 @@ static int rtp_open(URLContext *h, const char *uri, int flags) if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { s->connect = strtol(buf, NULL, 10); } + if (av_find_info_tag(buf, sizeof(buf), "reuse", p)) { + char *endptr = NULL; + s->reuse_socket = strtol(buf, &endptr, 10); + /* assume if no digits were found it is a request to enable it */ + if (buf == endptr) + s->reuse_socket = 1; + } if (av_find_info_tag(buf, sizeof(buf), "write_to_source", p)) { s->write_to_source = strtol(buf, NULL, 10); } -- 2.30.2