From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 5363C46AB2 for ; Wed, 26 Feb 2025 13:53:14 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id AF9BD68C974; Wed, 26 Feb 2025 15:53:10 +0200 (EET) Received: from mail-yw1-f182.google.com (mail-yw1-f182.google.com [209.85.128.182]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 15B2C68C257 for ; Wed, 26 Feb 2025 15:53:04 +0200 (EET) Received: by mail-yw1-f182.google.com with SMTP id 00721157ae682-6ef60e500d7so55188557b3.0 for ; Wed, 26 Feb 2025 05:53:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1740577982; x=1741182782; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=TdBv5FW8CugrI8RJjAoVdNaJWb5eN0ynKXCV0oGLGPQ=; b=FKF/a909G4EThbQlKOAUTp4u+OiwzVyj9mzAVOfZlqr8V9lTSBWlVayqTRxNxlGshT B6T54NccK/TR0PcMGkOGq6RfymkTGKZsmGTgx+vKYTe4yfHokGun7TI+OYSA7oIg26J4 c++l9ZkOfv4vEoFuA/WRoTNegTwolkrLkkbosU45i2MKAMnsVWMwdMoOP+qDruwdAfW9 8AqWzm72Bg2Lm13wh4T5zg2XN1bOOogdtwWDG7ta4hfkJ+6i29IDPchvGplg84pXbR1K e1G53EvOh/bMmNl2Vw9rpDN7+Hp3cg0D2jbbaKVmvfsg/F32PTJU2AIqGrLYGjqgygi8 YRDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740577982; x=1741182782; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=TdBv5FW8CugrI8RJjAoVdNaJWb5eN0ynKXCV0oGLGPQ=; b=Hv4r4DcB6FYzsy0OhEQzLFayrL7WNgoiw+HWFxNGdjkO22KTBdeP379nvLkugnMAl5 XVeOGoE6IQbaUuT9gIG0inLdBrg+FcsHATeiwmGFcJc+hPSp6a4QXAStyY2Gd1EWEYVt ZcHCQwXeqCvyvr7+7sFQAiEvbSzaszs7Xe7Bd6lGNI2AobFlwq3n04lJOTIgEH9E8djH LTBH80hiIpHCkkTlo/hLrPi+IXLcKKbftbUXgljzAHtLo///j6F9jgKCxKuEfUZyH30G RqJ57Uofx5GNJy7dU8XkvUEiGCw/So6OnKWxh9T1amN8BAPhzW7J82yFUNbf6GKQuRK1 9lGQ== X-Gm-Message-State: AOJu0YwgUAzilcQkQHMPDE+9Qehiw1Gfgwxn8FDgnwQpr4Z0zKwgcHrz Id0GUjw/eiOG+QL66fKXcmhhNhoECo3+JdxE6ihKBZvgO9VvN19rrpTn7A== X-Gm-Gg: ASbGnctydFgMAyz/+zvWMAXPvErBm60GVPPLeZ9VmLv4zGlGcM4Wj2TPNm4wpyTsVe6 fOjLu8Oa4N06pw4Fto9thw1XYrLcQlpHDWeJB9bE+dVrJd91XqHnCN/cR7wosvevE0RSOB6Y50o 3GjnDtCqAFaBRVmnYuaCHoM+QB8dkRIa5ddkM2FSzinUsEtirQsMNQNFSxXbj7nuRr+gJJpVgB6 l8ihdHlOrmNhhyA0IHW1jstDz05Vxz1kEs+5DiAbeFMwUBmAkF761RiKkEaB16iqZG7eW3iepeG cc3WcvOpzR9DL/cciRblt9i7HjzJiGKM2c1w73xy+N10//oK8xsF1DaRWDj6W9ycRUYoJC9FilH gVL05IM/a7ivxW5VcWFu0 X-Google-Smtp-Source: AGHT+IGqxfvmIEzXzVEILHQ0lcMveEzDWQwGExY96OKseffFtjMKshsh+slAogSrzjq3/tM+mxBlNQ== X-Received: by 2002:a05:690c:670c:b0:6f6:ca28:8400 with SMTP id 00721157ae682-6fbcc7a90aemr176770497b3.17.1740577981916; Wed, 26 Feb 2025 05:53:01 -0800 (PST) Received: from localhost.localdomain (108-65-109-112.lightspeed.tukrga.sbcglobal.net. [108.65.109.112]) by smtp.gmail.com with ESMTPSA id 00721157ae682-6fd349e029asm708897b3.122.2025.02.26.05.53.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Feb 2025 05:53:01 -0800 (PST) From: Rashad Tatum To: ffmpeg-devel@ffmpeg.org Date: Wed, 26 Feb 2025 08:52:53 -0500 Message-ID: <20250226135256.1142476-1-tatum.rashad@gmail.com> X-Mailer: git-send-email 2.48.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6] libavformat/rtsp: Make source specific multicast work for rtsp streams X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Rashad Tatum Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: by first changing the RTSPSource to track the destination address obtained from the source filter. For each RTSPStream, only add the source filter from the sdp if sdp_ip string matches source-filter's destination address. Before issuing the setup request, change the lower_transport to multicast if the sdp_ip is a multicast address. Change the multicast case to append sources (from the source-filter) to the rtp url to make the source specific multicast join work. Support wildcard source-filter destinations. Change source-filter processing to only happen after the first media description was processed and either when the next one starts or when we have reached the end of the sdp. This handles a wider variety of cases and doesn't rely on any optional media descriptions. --- libavformat/rtsp.c | 108 +++++++++++++++++++++++++++++++++------------ libavformat/rtsp.h | 3 +- 2 files changed, 81 insertions(+), 30 deletions(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 5ea471b40c..25a7602832 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "config_components.h" #include "libavutil/avassert.h" @@ -389,16 +391,19 @@ typedef struct SDPParseState { } SDPParseState; static void copy_default_source_addrs(struct RTSPSource **addrs, int count, - struct RTSPSource ***dest, int *dest_count) + struct RTSPSource ***dest, int *dest_count, const char* sdp_ip_str) { RTSPSource *rtsp_src, *rtsp_src2; int i; + const char* wildcard_dest = "*"; for (i = 0; i < count; i++) { rtsp_src = addrs[i]; - rtsp_src2 = av_memdup(rtsp_src, sizeof(*rtsp_src)); - if (!rtsp_src2) - continue; - dynarray_add(dest, dest_count, rtsp_src2); + if ((strcmp(rtsp_src->dest_addr, sdp_ip_str) == 0) || (strcmp(rtsp_src->dest_addr, wildcard_dest) == 0)) { + rtsp_src2 = av_memdup(rtsp_src, sizeof(*rtsp_src)); + if (!rtsp_src2) + continue; + dynarray_add(dest, dest_count, rtsp_src2); + } } } @@ -423,7 +428,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, { RTSPState *rt = s->priv_data; char buf1[64], st_type[64]; - const char *p; + const char *p, *dest_addr; enum AVMediaType codec_type; int payload_type; AVStream *st; @@ -448,6 +453,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, get_word_sep(buf1, sizeof(buf1), "/", &p); if (get_sockaddr(s, buf1, &sdp_ip)) return; + ttl = 16; if (*p == '/') { p++; @@ -461,6 +467,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1]; rtsp_st->sdp_ip = sdp_ip; rtsp_st->sdp_ttl = ttl; + } break; case 's': @@ -504,14 +511,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, rtsp_st->sdp_ip = s1->default_ip; rtsp_st->sdp_ttl = s1->default_ttl; - copy_default_source_addrs(s1->default_include_source_addrs, - s1->nb_default_include_source_addrs, - &rtsp_st->include_source_addrs, - &rtsp_st->nb_include_source_addrs); - copy_default_source_addrs(s1->default_exclude_source_addrs, - s1->nb_default_exclude_source_addrs, - &rtsp_st->exclude_source_addrs, - &rtsp_st->nb_exclude_source_addrs); + get_word(buf1, sizeof(buf1), &p); /* port */ rtsp_st->sdp_port = atoi(buf1); @@ -672,11 +672,15 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, // not checking that the destination address actually matches or is wildcard get_word(buf1, sizeof(buf1), &p); + dest_addr = av_strdup(buf1); while (*p != '\0') { rtsp_src = av_mallocz(sizeof(*rtsp_src)); - if (!rtsp_src) + if (!rtsp_src) { + av_freep(&dest_addr); return; - get_word(rtsp_src->addr, sizeof(rtsp_src->addr), &p); + } + av_strlcpy(rtsp_src->dest_addr, dest_addr, sizeof(rtsp_src->dest_addr)); + get_word(rtsp_src->src_addr, sizeof(rtsp_src->src_addr), &p); if (exclude) { if (s->nb_streams == 0) { dynarray_add(&s1->default_exclude_source_addrs, &s1->nb_default_exclude_source_addrs, rtsp_src); @@ -693,6 +697,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, } } } + av_freep(&dest_addr); } else { if (rt->server_type == RTSP_SERVER_WMS) ff_wms_parse_sdp_a_line(s, p); @@ -717,13 +722,31 @@ int ff_sdp_parse(AVFormatContext *s, const char *content) { const char *p; int letter, i; - char buf[SDP_MAX_SIZE], *q; + char buf[SDP_MAX_SIZE], sdp_ip_str[50], *q; + bool parsed_first_media_desc = false; SDPParseState sdp_parse_state = { { 0 } }, *s1 = &sdp_parse_state; p = content; for (;;) { p += strspn(p, SPACE_CHARS); letter = *p; + if(parsed_first_media_desc && (letter == 'm' || letter == '\0')) { + RTSPState *rt = s->priv_data; + RTSPStream *rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1]; + getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, + sizeof(rtsp_st->sdp_ip), + sdp_ip_str, sizeof(sdp_ip_str), NULL, 0, NI_NUMERICHOST); + copy_default_source_addrs(s1->default_include_source_addrs, + s1->nb_default_include_source_addrs, + &rtsp_st->include_source_addrs, + &rtsp_st->nb_include_source_addrs, + sdp_ip_str); + copy_default_source_addrs(s1->default_exclude_source_addrs, + s1->nb_default_exclude_source_addrs, + &rtsp_st->exclude_source_addrs, + &rtsp_st->nb_exclude_source_addrs, + sdp_ip_str); + } if (letter == '\0') break; p++; @@ -738,7 +761,11 @@ int ff_sdp_parse(AVFormatContext *s, const char *content) p++; } *q = '\0'; + sdp_parse_line(s, s1, letter, buf); + if(letter == 'm') + parsed_first_media_desc = true; + next_line: while (*p != '\n' && *p != '\0') p++; @@ -859,10 +886,11 @@ int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) rtsp_st->transport_priv = ff_rdt_parse_open(s, st->index, rtsp_st->dynamic_protocol_context, rtsp_st->dynamic_handler); - else if (CONFIG_RTPDEC) + else if (CONFIG_RTPDEC) { rtsp_st->transport_priv = ff_rtp_parse_open(s, st, rtsp_st->sdp_payload_type, reordering_queue_size); + } if (!rtsp_st->transport_priv) { return AVERROR(ENOMEM); @@ -1452,6 +1480,18 @@ retry: return 0; } +static void append_source_addrs(char *buf, int size, const char *name, + int count, struct RTSPSource **addrs) +{ + int i; + if (!count) + return; + av_strlcatf(buf, size, "&%s=%s", name, addrs[0]->src_addr); + for (i = 1; i < count; i++) { + av_strlcatf(buf, size, ",%s", addrs[i]->src_addr); + } +} + int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, int lower_transport, const char *real_challenge) { @@ -1510,6 +1550,11 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, } else rtsp_st = rt->rtsp_streams[i]; + /* RTP/UDP Source Specific Multicast (SSM) */ + if (ff_is_multicast_address((struct sockaddr*) &rtsp_st->sdp_ip)) { + lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST; + } + /* RTP/UDP */ if (lower_transport == RTSP_LOWER_TRANSPORT_UDP) { char buf[256]; @@ -1666,7 +1711,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, break; } case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: { - char url[MAX_URL_SIZE], namebuf[50], optbuf[20] = ""; + char url[MAX_URL_SIZE], namebuf[50], optbuf[1024] = ""; struct sockaddr_storage addr; int port, ttl; AVDictionary *opts = map_to_opts(rt); @@ -1682,6 +1727,20 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, } if (ttl > 0) snprintf(optbuf, sizeof(optbuf), "?ttl=%d", ttl); + + if (rtsp_st->nb_include_source_addrs > 0) { + if(strlen(optbuf) == 0 ) { + snprintf(optbuf, sizeof(optbuf), "?"); + } + + append_source_addrs(optbuf, sizeof(optbuf), "sources", + rtsp_st->nb_include_source_addrs, + rtsp_st->include_source_addrs); + append_source_addrs(optbuf, sizeof(optbuf), "block", + rtsp_st->nb_exclude_source_addrs, + rtsp_st->exclude_source_addrs); + } + getnameinfo((struct sockaddr*) &addr, sizeof(addr), namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); ff_url_join(url, sizeof(url), "rtp", NULL, namebuf, @@ -2383,16 +2442,7 @@ static int sdp_probe(const AVProbeData *p1) return 0; } -static void append_source_addrs(char *buf, int size, const char *name, - int count, struct RTSPSource **addrs) -{ - int i; - if (!count) - return; - av_strlcatf(buf, size, "&%s=%s", name, addrs[0]->addr); - for (i = 1; i < count; i++) - av_strlcatf(buf, size, ",%s", addrs[i]->addr); -} + static int sdp_read_header(AVFormatContext *s) { diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 83b2e3f4fb..61de5cfb17 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -432,7 +432,8 @@ typedef struct RTSPState { #define RTSP_FLAG_SATIP_RAW 0x20 /**< Export SAT>IP stream as raw MPEG-TS */ typedef struct RTSPSource { - char addr[128]; /**< Source-specific multicast include source IP address (from SDP content) */ + char dest_addr[128]; /**< Source-specific multicast destination IP address (from SDP content) */ + char src_addr[128]; /**< Source-specific multicast include source IP address (from SDP content) */ } RTSPSource; /** -- 2.48.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".