This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit e7757d8f2e6ffd35dd1e224be553130382d36d7f Author: Jack Lau <[email protected]> AuthorDate: Fri Oct 3 10:33:55 2025 +0800 Commit: Jack Lau <[email protected]> CommitDate: Fri Feb 27 12:42:05 2026 +0000 avformat/whip: add rtp history store and find method This patch aims to enable rtp history store for RTX Signed-off-by: Jack Lau <[email protected]> --- doc/muxers.texi | 4 ++++ libavformat/whip.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/doc/muxers.texi b/doc/muxers.texi index e1f737b1d9..643981fc20 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -3967,6 +3967,10 @@ Possible values: The muxer will try to set dtls active role and send the first client hello. @end table +@item rtp_history @var{integer} +Set the number of RTP history items to store. +Default value is 512. + @item authorization @var{string} The optional Bearer token for WHIP Authorization. diff --git a/libavformat/whip.c b/libavformat/whip.c index 8306296b20..bc3f5a9c6d 100644 --- a/libavformat/whip.c +++ b/libavformat/whip.c @@ -169,6 +169,17 @@ #define WHIP_ICE_CONSENT_CHECK_INTERVAL 5000 #define WHIP_ICE_CONSENT_EXPIRED_TIMER 30000 +/** + * RTP history packet size. + * Target is buffering 1000ms of RTP history packets. + * + * bandwidth_bps = (RTP payload bytes) * (RTP history size) * 8 + * Assumes average RTP payload is 1184 bytes (MTU - SRTP_CHECKSUM_LEN). + */ +#define WHIP_RTP_HISTORY_MIN 64 /* around 0.61 Mbps */ +#define WHIP_RTP_HISTORY_DEFAULT 512 /* around 4.85 Mbps */ +#define WHIP_RTP_HISTORY_MAX 2048 /* around 19.40 Mbps */ + /* Calculate the elapsed time from starttime to endtime in milliseconds. */ #define ELAPSED(starttime, endtime) ((float)(endtime - starttime) / 1000) @@ -216,6 +227,12 @@ typedef enum WHIPFlags { WHIP_DTLS_ACTIVE = (1 << 0), } WHIPFlags; +typedef struct RtpHistoryItem { + uint16_t seq; + int size; + uint8_t *buf; +} RtpHistoryItem; + typedef struct WHIPContext { AVClass *av_class; @@ -333,6 +350,11 @@ typedef struct WHIPContext { /* The certificate and private key used for DTLS handshake. */ char* cert_file; char* key_file; + + int hist_sz; + RtpHistoryItem *hist; + uint8_t *hist_pool; + int hist_head; } WHIPContext; /** @@ -452,6 +474,17 @@ static av_cold int initialize(AVFormatContext *s) av_log(whip, AV_LOG_WARNING, "pkt_size=%d(<%d) is too small, may cause packet loss\n", whip->pkt_size, ideal_pkt_size); + whip->hist = av_calloc(whip->hist_sz, sizeof(*whip->hist)); + if (!whip->hist) + return AVERROR(ENOMEM); + + whip->hist_pool = av_calloc(whip->hist_sz, whip->pkt_size - DTLS_SRTP_CHECKSUM_LEN); + if (!whip->hist_pool) + return AVERROR(ENOMEM); + + for (int i = 0; i < whip->hist_sz; i++) + whip->hist[i].buf = whip->hist_pool + i * (whip->pkt_size - DTLS_SRTP_CHECKSUM_LEN); + if (whip->state < WHIP_STATE_INIT) whip->state = WHIP_STATE_INIT; whip->whip_init_time = av_gettime_relative(); @@ -1476,6 +1509,28 @@ end: return ret; } +static int rtp_history_store(WHIPContext *whip, const uint8_t *buf, int size) +{ + uint16_t seq = AV_RB16(buf + 2); + uint32_t pos = ((uint32_t)seq - (uint32_t)whip->video_first_seq) % (uint32_t)whip->hist_sz; + RtpHistoryItem *it = &whip->hist[pos]; + if (size > whip->pkt_size - DTLS_SRTP_CHECKSUM_LEN) + return AVERROR_INVALIDDATA; + memcpy(it->buf, buf, size); + it->size = size; + it->seq = seq; + + whip->hist_head = ++pos; + return 0; +} + +static const RtpHistoryItem *rtp_history_find(WHIPContext *whip, uint16_t seq) +{ + uint32_t pos = ((uint32_t)seq - (uint32_t)whip->video_first_seq) % (uint32_t)whip->hist_sz; + const RtpHistoryItem *it = &whip->hist[pos]; + return it->seq == seq ? it : NULL; +} + /** * Callback triggered by the RTP muxer when it creates and sends out an RTP packet. * @@ -1512,6 +1567,12 @@ static int on_rtp_write_packet(void *opaque, const uint8_t *buf, int buf_size) return 0; } + if (is_video) { + ret = rtp_history_store(whip, buf, buf_size); + if (ret < 0) + return ret; + } + ret = ffurl_write(whip->udp, whip->buf, cipher_size); if (ret < 0) { av_log(whip, AV_LOG_ERROR, "Failed to write packet=%dB, ret=%d\n", cipher_size, ret); @@ -1981,6 +2042,8 @@ static av_cold void whip_deinit(AVFormatContext *s) s->streams[i]->priv_data = NULL; } + av_freep(&whip->hist_pool); + av_freep(&whip->hist); av_freep(&whip->sdp_offer); av_freep(&whip->sdp_answer); av_freep(&whip->whip_resource_url); @@ -2028,6 +2091,7 @@ static const AVOption options[] = { { "ts_buffer_size", "The buffer size, in bytes, of underlying protocol", OFFSET(ts_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ENC }, { "whip_flags", "Set flags affecting WHIP connection behavior", OFFSET(flags), AV_OPT_TYPE_FLAGS, { .i64 = 0}, 0, UINT_MAX, ENC, .unit = "flags" }, { "dtls_active", "Set dtls role as active", 0, AV_OPT_TYPE_CONST, { .i64 = WHIP_DTLS_ACTIVE}, 0, UINT_MAX, ENC, .unit = "flags" }, + { "rtp_history", "The number of RTP history items to store", OFFSET(hist_sz), AV_OPT_TYPE_INT, { .i64 = WHIP_RTP_HISTORY_DEFAULT }, WHIP_RTP_HISTORY_MIN, WHIP_RTP_HISTORY_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 }, _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
