PR #20965 opened by Jack Lau (JackLau) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20965 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20965.patch
>From cebbb7f74bcff89761b80d6ec0aad627dd4c2232 Mon Sep 17 00:00:00 2001 From: Jack Lau <[email protected]> Date: Sat, 23 Aug 2025 09:09:47 +0800 Subject: [PATCH 1/6] avformat/whip: fix ssrc might be same use audio_ssrc + 1 for video_ssrc to avoid ssrc collision See RFC 3550 Section 8, The SSRC identifier carried in the RTP header and in various fields of RTCP packets is a random 32 bit number that is required to be globally unique within an RTP session. simply + 1 also can get an unique ssrc, and faster than generating new unique ssrc. Signed-off-by: Jack Lau <[email protected]> (cherry picked from commit b3ea5584929f16785cc45ad386998ff42fa72110) --- libavformat/whip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/whip.c b/libavformat/whip.c index 3bc485f993..ee88e7b0ac 100644 --- a/libavformat/whip.c +++ b/libavformat/whip.c @@ -615,7 +615,7 @@ static int generate_sdp_offer(AVFormatContext *s) av_lfg_get(&whip->rnd)); whip->audio_ssrc = av_lfg_get(&whip->rnd); - whip->video_ssrc = av_lfg_get(&whip->rnd); + whip->video_ssrc = whip->audio_ssrc + 1; whip->audio_payload_type = WHIP_RTP_PAYLOAD_TYPE_OPUS; whip->video_payload_type = WHIP_RTP_PAYLOAD_TYPE_H264; -- 2.49.1 >From b6627be7da3245b88f6382367dec59f8acbf94c9 Mon Sep 17 00:00:00 2001 From: Jack Lau <[email protected]> Date: Thu, 4 Sep 2025 07:49:41 +0800 Subject: [PATCH 2/6] avformat/whip: fix SDP ICE candidates parsing fix issue #20407 Refer to RFC 5245 15.1, the foundation may be any string up to 32 chars. The old code could misread foundations as transport("udp"). This patch fully parse all these attr to avoid parsing error. Signed-off-by: Jack Lau <[email protected]> (cherry picked from commit b41f8207c4cfebf9bb6b66a9f354c8bbba3036b5) --- libavformat/whip.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/whip.c b/libavformat/whip.c index ee88e7b0ac..885dc8acbb 100644 --- a/libavformat/whip.c +++ b/libavformat/whip.c @@ -880,12 +880,12 @@ static int parse_answer(AVFormatContext *s) goto end; } } else if (av_strstart(line, "a=candidate:", &ptr) && !whip->ice_protocol) { - ptr = av_stristr(ptr, "udp"); if (ptr && av_stristr(ptr, "host")) { - char protocol[17], host[129]; - int priority, port; - ret = sscanf(ptr, "%16s %d %128s %d typ host", protocol, &priority, host, &port); - if (ret != 4) { + /* Refer to RFC 5245 15.1 */ + char foundation[33], protocol[17], host[129]; + int component_id, priority, port; + ret = sscanf(ptr, "%32s %d %16s %d %128s %d typ host", foundation, &component_id, protocol, &priority, host, &port); + if (ret != 6) { av_log(whip, AV_LOG_ERROR, "Failed %d to parse line %d %s from %s\n", ret, i, line, whip->sdp_answer); ret = AVERROR(EIO); -- 2.49.1 >From 5baee5e376c5590c9ebda436bdb2b627ff18829c Mon Sep 17 00:00:00 2001 From: Jack Lau <[email protected]> Date: Thu, 28 Aug 2025 07:22:04 +0800 Subject: [PATCH 3/6] avformat/whip: fix 8 bits overflow and map constraint_set bits for H264 profile_iop is an 8 bits field. Previous code copied AVCodecParameters::profile (which can contain bits beyond 8 bits) into profile_iop, producing overflow and wrong values. This patch maps the constrained flags into the proper profile_iop bits (constraint_set1 / 3) Signed-off-by: Jack Lau <[email protected]> (cherry picked from commit 6c2768bf8c059126ea89ec14f1fe0c903f4f90c5) --- libavformat/whip.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavformat/whip.c b/libavformat/whip.c index 885dc8acbb..b57d607a5b 100644 --- a/libavformat/whip.c +++ b/libavformat/whip.c @@ -594,7 +594,7 @@ static int parse_codec(AVFormatContext *s) */ static int generate_sdp_offer(AVFormatContext *s) { - int ret = 0, profile, level, profile_iop; + int ret = 0, profile, level, profile_iop = 0; const char *acodec_name = NULL, *vcodec_name = NULL; AVBPrint bp; WHIPContext *whip = s->priv_data; @@ -662,11 +662,12 @@ static int generate_sdp_offer(AVFormatContext *s) } if (whip->video_par) { - profile_iop = profile = whip->video_par->profile; + profile = whip->video_par->profile; level = whip->video_par->level; if (whip->video_par->codec_id == AV_CODEC_ID_H264) { vcodec_name = "H264"; - profile_iop &= AV_PROFILE_H264_CONSTRAINED; + profile_iop |= profile & AV_PROFILE_H264_CONSTRAINED ? 1 << 6 : 0; + profile_iop |= profile & AV_PROFILE_H264_INTRA ? 1 << 4 : 0; profile &= (~AV_PROFILE_H264_CONSTRAINED); } -- 2.49.1 >From 0129d0dd24dbaaba9eff610b6c9040306bb857f8 Mon Sep 17 00:00:00 2001 From: Jack Lau <[email protected]> Date: Thu, 28 Aug 2025 07:40:40 +0800 Subject: [PATCH 4/6] avformat/whip: fix potential 8bit overflow for profile_idc The profile contains profile_idc and constraint_set*_flag, throws away high 8 bit flags and then we get profile_idc. Signed-off-by: Jack Lau <[email protected]> (cherry picked from commit 785a4e0d6c80f475f7891d33dfa2927faa51da21) --- libavformat/whip.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libavformat/whip.c b/libavformat/whip.c index b57d607a5b..adfbfeff7d 100644 --- a/libavformat/whip.c +++ b/libavformat/whip.c @@ -594,7 +594,7 @@ static int parse_codec(AVFormatContext *s) */ static int generate_sdp_offer(AVFormatContext *s) { - int ret = 0, profile, level, profile_iop = 0; + int ret = 0, profile_idc = 0, level, profile_iop = 0; const char *acodec_name = NULL, *vcodec_name = NULL; AVBPrint bp; WHIPContext *whip = s->priv_data; @@ -662,13 +662,12 @@ static int generate_sdp_offer(AVFormatContext *s) } if (whip->video_par) { - profile = whip->video_par->profile; level = whip->video_par->level; if (whip->video_par->codec_id == AV_CODEC_ID_H264) { vcodec_name = "H264"; - profile_iop |= profile & AV_PROFILE_H264_CONSTRAINED ? 1 << 6 : 0; - profile_iop |= profile & AV_PROFILE_H264_INTRA ? 1 << 4 : 0; - profile &= (~AV_PROFILE_H264_CONSTRAINED); + profile_iop |= whip->video_par->profile & AV_PROFILE_H264_CONSTRAINED ? 1 << 6 : 0; + profile_iop |= whip->video_par->profile & AV_PROFILE_H264_INTRA ? 1 << 4 : 0; + profile_idc = whip->video_par->profile & 0x00ff; } av_bprintf(&bp, "" @@ -694,7 +693,7 @@ static int generate_sdp_offer(AVFormatContext *s) whip->video_payload_type, vcodec_name, whip->video_payload_type, - profile, + profile_idc, profile_iop, level, whip->video_ssrc, -- 2.49.1 >From 519e4702ea39b5dc30ce737e136181e1a57eed06 Mon Sep 17 00:00:00 2001 From: Jack Lau <[email protected]> Date: Wed, 17 Sep 2025 10:25:41 +0800 Subject: [PATCH 5/6] avformat/whip: pass through buffer_size option to udp Signed-off-by: Jack Lau <[email protected]> (cherry picked from commit b3793d9941516ea8c3511ca2b7db339148e3f122) --- doc/muxers.texi | 4 ++++ libavformat/whip.c | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 8c45b7d47a..18c99e57b6 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -3955,6 +3955,10 @@ Default value is 5000. Set the maximum size, in bytes, of RTP packets that send out. Default value is 1500. +@item buffer_size @var{integer} +Set the buffer size, in bytes, of underlying protocol. +Default value is -1(auto). The UDP auto selects a reasonable value. + @item authorization @var{string} The optional Bearer token for WHIP Authorization. diff --git a/libavformat/whip.c b/libavformat/whip.c index adfbfeff7d..45e0b8b577 100644 --- a/libavformat/whip.c +++ b/libavformat/whip.c @@ -295,6 +295,7 @@ typedef struct WHIPContext { * Note that pion requires a smaller value, for example, 1200. */ int pkt_size; + int buffer_size;/* Underlying protocol send/receive buffer size */ /** * The optional Bearer token for WHIP Authorization. * See https://www.ietf.org/archive/id/draft-ietf-wish-whip-08.html#name-authentication-and-authoriz @@ -1195,8 +1196,9 @@ static int udp_connect(AVFormatContext *s) av_dict_set_int(&opts, "connect", 1, 0); av_dict_set_int(&opts, "fifo_size", 0, 0); - /* Set the max packet size to the buffer size. */ + /* Pass through the pkt_size and buffer_size to underling protocol */ av_dict_set_int(&opts, "pkt_size", whip->pkt_size, 0); + av_dict_set_int(&opts, "buffer_size", whip->buffer_size, 0); ret = ffurl_open_whitelist(&whip->udp, url, AVIO_FLAG_WRITE, &s->interrupt_callback, &opts, s->protocol_whitelist, s->protocol_blacklist, NULL); @@ -1898,6 +1900,7 @@ static int whip_check_bitstream(AVFormatContext *s, AVStream *st, const AVPacket static const AVOption options[] = { { "handshake_timeout", "Timeout in milliseconds for ICE and DTLS handshake.", OFFSET(handshake_timeout), AV_OPT_TYPE_INT, { .i64 = 5000 }, -1, INT_MAX, ENC }, { "pkt_size", "The maximum size, in bytes, of RTP packets that send out", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = 1200 }, -1, INT_MAX, ENC }, + { "buffer_size", "The buffer size, in bytes, of underlying protocol", OFFSET(buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ENC }, { "authorization", "The optional Bearer token for WHIP Authorization", OFFSET(authorization), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, ENC }, { "cert_file", "The optional certificate file path for DTLS", OFFSET(cert_file), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, ENC }, { "key_file", "The optional private key file path for DTLS", OFFSET(key_file), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, ENC }, -- 2.49.1 >From 70e129a79f23920c511e04da18a81c41c2e82a46 Mon Sep 17 00:00:00 2001 From: Jack Lau <[email protected]> Date: Wed, 17 Sep 2025 10:50:18 +0800 Subject: [PATCH 6/6] avformat/whip: remind user increase -buffer_size The udp buffer size might be too small to easily be full temporarily and return WSAEWOULDBLOCK. The udp code will handle the windows error code and convert it to AVERROR(EAGAIN). This issue just can be reproduced on windows. If sleep a interval and retry to send pkt when hit EAGAIN, it will increase latency, and appropriate interval is hard to define. So this patch just remind user increase the buffer size via -buffer_size to avoid this issue. Signed-off-by: Jack Lau <[email protected]> (cherry picked from commit ec0a04de0d46b6104a4d92570b2412df5fafb483) --- libavformat/whip.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/whip.c b/libavformat/whip.c index 45e0b8b577..b914404f91 100644 --- a/libavformat/whip.c +++ b/libavformat/whip.c @@ -1817,8 +1817,10 @@ static int whip_write_packet(AVFormatContext *s, AVPacket *pkt) if (ret == AVERROR(EINVAL)) { av_log(whip, AV_LOG_WARNING, "Ignore failed to write packet=%dB, ret=%d\n", pkt->size, ret); ret = 0; + } else if (ret == AVERROR(EAGAIN)) { + av_log(whip, AV_LOG_ERROR, "UDP send blocked, please increase the buffer via -buffer_size\n"); } else - av_log(whip, AV_LOG_ERROR, "Failed to write packet, size=%d\n", pkt->size); + av_log(whip, AV_LOG_ERROR, "Failed to write packet, size=%d, ret=%d\n", pkt->size, ret); goto end; } -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
