From bc561013c9a809a90c0d1b84413814ba612f7c44 Mon Sep 17 00:00:00 2001 From: Jack Lau Date: Thu, 18 Sep 2025 09:23:31 +0800 Subject: [PATCH] avformat/whip: add RTX initial support Refer to RFC 4588. Add and set the basic param of RTX like ssrc, payload_type, srtp. Modify the SDP to add RTX info so that the peer be able to parse the RTX packet. There are more pateches to make RTX really work. Signed-off-by: Jack Lau --- libavformat/whip.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/libavformat/whip.c b/libavformat/whip.c index cfdc861c5b..472c6dbf16 100644 --- a/libavformat/whip.c +++ b/libavformat/whip.c @@ -122,6 +122,7 @@ /* Referring to Chrome's definition of RTP payload types. */ #define WHIP_RTP_PAYLOAD_TYPE_H264 106 #define WHIP_RTP_PAYLOAD_TYPE_OPUS 111 +#define WHIP_RTP_PAYLOAD_TYPE_VIDEO_RTX 105 /** * The STUN message header, which is 20 bytes long, comprises the @@ -229,12 +230,14 @@ typedef struct WHIPContext { /* The SSRC of the audio and video stream, generated by the muxer. */ uint32_t audio_ssrc; uint32_t video_ssrc; + uint32_t video_rtx_ssrc; uint16_t audio_first_seq; uint16_t video_first_seq; /* The PT(Payload Type) of stream, generated by the muxer. */ uint8_t audio_payload_type; uint8_t video_payload_type; + uint8_t video_rtx_payload_type; /** * This is the SDP offer generated by the muxer based on the codec parameters, * DTLS, and ICE information. @@ -290,6 +293,7 @@ typedef struct WHIPContext { /* The SRTP send context, to encrypt outgoing packets. */ SRTPContext srtp_audio_send; SRTPContext srtp_video_send; + SRTPContext srtp_video_rtx_send; SRTPContext srtp_rtcp_send; /* The SRTP receive context, to decrypt incoming packets. */ SRTPContext srtp_recv; @@ -602,9 +606,11 @@ static int generate_sdp_offer(AVFormatContext *s) whip->audio_ssrc = av_lfg_get(&whip->rnd); whip->video_ssrc = whip->audio_ssrc + 1; + whip->video_rtx_ssrc = whip->video_ssrc + 1; whip->audio_payload_type = WHIP_RTP_PAYLOAD_TYPE_OPUS; whip->video_payload_type = WHIP_RTP_PAYLOAD_TYPE_H264; + whip->video_rtx_payload_type = WHIP_RTP_PAYLOAD_TYPE_VIDEO_RTX; av_bprintf(&bp, "" "v=0\r\n" @@ -657,7 +663,7 @@ static int generate_sdp_offer(AVFormatContext *s) } av_bprintf(&bp, "" - "m=video 9 UDP/TLS/RTP/SAVPF %u\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF %u %u\r\n" "c=IN IP4 0.0.0.0\r\n" "a=ice-ufrag:%s\r\n" "a=ice-pwd:%s\r\n" @@ -671,9 +677,13 @@ static int generate_sdp_offer(AVFormatContext *s) "a=rtpmap:%u %s/90000\r\n" "a=fmtp:%u level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=%02x%02x%02x\r\n" "a=rtcp-fb%u nack\r\n" + "a=rtpmap:%u rtx/90000\r\n" + "a=fmtp:%u apt=%u\r\n" + "a=ssrc-group:FID %u %u\r\n" "a=ssrc:%u cname:FFmpeg\r\n" "a=ssrc:%u msid:FFmpeg video\r\n", whip->video_payload_type, + whip->video_rtx_payload_type, whip->ice_ufrag_local, whip->ice_pwd_local, whip->dtls_fingerprint, @@ -684,6 +694,11 @@ static int generate_sdp_offer(AVFormatContext *s) profile_iop, level, whip->video_payload_type, + whip->video_rtx_payload_type, + whip->video_rtx_payload_type, + whip->video_payload_type, + whip->video_ssrc, + whip->video_rtx_ssrc, whip->video_ssrc, whip->video_ssrc); } @@ -1408,6 +1423,12 @@ static int setup_srtp(AVFormatContext *s) goto end; } + ret = ff_srtp_set_crypto(&whip->srtp_video_rtx_send, suite, buf); + if (ret < 0) { + av_log(whip, AV_LOG_ERROR, "Failed to set crypto for video rtx send\n"); + goto end; + } + ret = ff_srtp_set_crypto(&whip->srtp_rtcp_send, suite, buf); if (ret < 0) { av_log(whip, AV_LOG_ERROR, "Failed to set crypto for rtcp send\n"); @@ -1924,6 +1945,7 @@ static av_cold void whip_deinit(AVFormatContext *s) av_freep(&whip->key_file); ff_srtp_free(&whip->srtp_audio_send); ff_srtp_free(&whip->srtp_video_send); + ff_srtp_free(&whip->srtp_video_rtx_send); ff_srtp_free(&whip->srtp_rtcp_send); ff_srtp_free(&whip->srtp_recv); ffurl_close(whip->dtls_uc);