PR #23259 opened by Kaarle Ritvanen (kunkku) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23259 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23259.patch
Sending of RTCP Receiver Reports has been broken for a decade. This PR remedies the situation with the following changes: * Mark the RTP URL as writable in `sdp_read_header`. This fixes a regression in commit 6f5048f4a0f702d92794dda7752c20ed6033233b that made the RTP stream read-only while unsuccessfully trying to keep the RTCP stream writable. * Revert commit 9faee5bc148fdf4d5340cdcf7e464078972dc72c, which further broke RTCP sending by binding the socket to a multicast address. * As suggested in the commit message of b56fc18b20d62c3d2a134b53738deaabfd491e89, make `rtcp_to_source` the default behavior in case of unicast. >From c7dc586fdfbe38a959436da5250939780dec6741 Mon Sep 17 00:00:00 2001 From: Kaarle Ritvanen <[email protected]> Date: Wed, 13 May 2026 22:47:15 +0300 Subject: [PATCH 1/3] Revert "avformat/udp: modify the not write-only to read-only mode." This reverts commit 9faee5bc148fdf4d5340cdcf7e464078972dc72c. This change was incorrect due to the reason stated in the above comment: nothing can be sent if the socket is bound to a multicast address. Signed-off-by: Kaarle Ritvanen <[email protected]> --- libavformat/udp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/udp.c b/libavformat/udp.c index 0874d18397..ba78a91808 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -820,7 +820,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) * receiving UDP packets from other sources aimed at the same UDP * port. This fails on windows. This makes sending to the same address * using sendto() fail, so only do it if we're opened in read-only mode. */ - if (s->is_multicast && (h->flags & AVIO_FLAG_READ)) { + if (s->is_multicast && !(h->flags & AVIO_FLAG_WRITE)) { bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len); } /* bind to the local address if not multicast or if the multicast -- 2.52.0 >From 69b7127e2af97fc33060f40e728b7486e84921c4 Mon Sep 17 00:00:00 2001 From: Kaarle Ritvanen <[email protected]> Date: Wed, 13 May 2026 13:55:11 +0300 Subject: [PATCH 2/3] rtsp: mark URL as writable to allow RTCP RRs ffurl_write2 fails if the RTP URL is marked read-only, blocking any outgoing RTCP packets. This fixes a regression in commit 6f5048f4a0f702d92794dda7752c20ed6033233b. Signed-off-by: Kaarle Ritvanen <[email protected]> --- libavformat/rtsp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 45b62c4188..9b5f39aa2c 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -2645,6 +2645,9 @@ static int sdp_read_header(AVFormatContext *s) err = AVERROR_INVALIDDATA; goto fail; } + + if (rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE) + rtsp_st->rtp_handle->flags |= AVIO_FLAG_WRITE; } if ((err = ff_rtsp_open_transport_ctx(s, rtsp_st))) goto fail; -- 2.52.0 >From 61725754647b672639bdc2c3bff23fae5e0c806b Mon Sep 17 00:00:00 2001 From: Kaarle Ritvanen <[email protected]> Date: Wed, 13 May 2026 22:58:59 +0300 Subject: [PATCH 3/3] rtsp: send RTCP RR to unicast source by default The rctp_to_source flag is converted to a tri-state boolean, where the default is true for unicast and false for multicast sources. The original flag is deprecated. This change was inspired by the message of commit b56fc18b20d62c3d2a134b53738deaabfd491e89. Signed-off-by: Kaarle Ritvanen <[email protected]> --- libavformat/rtsp.c | 15 ++++++++++----- libavformat/rtsp.h | 1 + 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 9b5f39aa2c..7a2d592ee8 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -113,7 +113,8 @@ const AVOption ff_rtsp_options[] = { static const AVOption sdp_options[] = { RTSP_FLAG_OPTS("sdp_flags", "SDP flags"), { "custom_io", "use custom I/O", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_CUSTOM_IO}, 0, 0, DEC, .unit = "rtsp_flags" }, - { "rtcp_to_source", "send RTCP packets to the source address of received packets", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_RTCP_TO_SOURCE}, 0, 0, DEC, .unit = "rtsp_flags" }, + { "rtcp_to_source", "send RTCP packets to the source address of received packets (deprecated; use rtcp_to_source option)", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_RTCP_TO_SOURCE}, 0, 0, DEC|AV_OPT_FLAG_DEPRECATED, .unit = "rtsp_flags" }, + { "rtcp_to_source", "send RTCP packets to the source address of received packets", OFFSET(rtcp_to_source), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, DEC }, { "listen_timeout", "set maximum timeout (in seconds) to wait for incoming connections", OFFSET(stimeout), AV_OPT_TYPE_DURATION, {.i64 = READ_PACKET_TIMEOUT_S*1000000}, INT_MIN, INT64_MAX, DEC }, { "localaddr", "local address", OFFSET(localaddr),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, \ RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"), @@ -2606,11 +2607,15 @@ static int sdp_read_header(AVFormatContext *s) if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) { AVDictionary *opts = map_to_opts(rt); + int rtcp_to_source = rt->rtcp_to_source; char buf[MAX_URL_SIZE]; const char *p; - err = getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, - sizeof(rtsp_st->sdp_ip), + struct sockaddr *addr = (struct sockaddr*) &rtsp_st->sdp_ip; + if (rtcp_to_source < 0) + rtcp_to_source = rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE || !ff_is_multicast_address(addr); + + err = getnameinfo(addr, sizeof(rtsp_st->sdp_ip), namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); if (err) { av_log(s, AV_LOG_ERROR, "getnameinfo: %s\n", gai_strerror(err)); @@ -2623,7 +2628,7 @@ static int sdp_read_header(AVFormatContext *s) "?localrtpport=%d&ttl=%d&connect=%d&write_to_source=%d", rtsp_st->sdp_port, rtsp_st->sdp_ttl, rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0, - rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE ? 1 : 0); + rtcp_to_source); p = strchr(s->url, '?'); if (p && av_find_info_tag(buf, sizeof(buf), "localaddr", p)) @@ -2646,7 +2651,7 @@ static int sdp_read_header(AVFormatContext *s) goto fail; } - if (rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE) + if (rtcp_to_source) rtsp_st->rtp_handle->flags |= AVIO_FLAG_WRITE; } if ((err = ff_rtsp_open_transport_ctx(s, rtsp_st))) diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 3c9c2c842d..fd5ecf7dd3 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -441,6 +441,7 @@ typedef struct RTSPState { int buffer_size; int pkt_size; char *localaddr; + int rtcp_to_source; /** * Options used for TLS based RTSP streams. -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
