Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH] avformat/whip: add rtp history store and find method (PR #20703)
@ 2025-10-14  9:29 Jack Lau via ffmpeg-devel
  0 siblings, 0 replies; only message in thread
From: Jack Lau via ffmpeg-devel @ 2025-10-14  9:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Jack Lau

PR #20703 opened by Jack Lau (JackLau)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20703
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20703.patch

This patch aims to enable rtp history store for RTX

TODO:
handle the rtx send to make rtx really work


>From 90b863a2f54964009cff4dcf367e38267a0ad01b Mon Sep 17 00:00:00 2001
From: Jack Lau <jacklau1222@qq.com>
Date: Fri, 3 Oct 2025 10:33:55 +0800
Subject: [PATCH 1/2] avformat/whip: add rtp history store and find method

This patch aims to enable rtp history store for RTX

TODO:
handle the rtx send to make rtx really work

Signed-off-by: Jack Lau <jacklau1222@qq.com>
---
 doc/muxers.texi    |  4 +++
 libavformat/whip.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 9889bd2ff6..91dc90008c 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -3959,6 +3959,10 @@ Default value is 1200.
 Set the buffer size, in bytes, of underlying protocol.
 Default value is -1(auto). The UDP auto selects a reasonable value.
 
+@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 e809075643..0f00a6652b 100644
--- a/libavformat/whip.c
+++ b/libavformat/whip.c
@@ -168,6 +168,19 @@
 #define WHIP_ICE_CONSENT_CHECK_INTERVAL 5000
 #define WHIP_ICE_CONSENT_EXPIRED_TIMER 30000
 
+/**
+ * RTP history packet size.
+ * Target: hold 1000ms of RTP traffic.
+ *
+ * Formula:
+ * 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)
 
@@ -211,6 +224,12 @@ enum WHIPState {
     WHIP_STATE_FAILED,
 };
 
+typedef struct RtpHistoryItem {
+    uint16_t seq;
+    int size;
+    uint8_t *buf;
+} RtpHistoryItem;
+
 typedef struct WHIPContext {
     AVClass *av_class;
 
@@ -329,6 +348,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;
 
 /**
@@ -418,6 +442,17 @@ static av_cold int initialize(AVFormatContext *s)
     whip->audio_first_seq = av_lfg_get(&whip->rnd) & 0x0fff;
     whip->video_first_seq = whip->audio_first_seq + 1;
 
+    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->pkt_size < ideal_pkt_size)
         av_log(whip, AV_LOG_WARNING, "pkt_size=%d(<%d) is too small, may cause packet loss\n",
                whip->pkt_size, ideal_pkt_size);
@@ -1473,6 +1508,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.
  *
@@ -1509,6 +1566,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);
@@ -1997,6 +2060,8 @@ static av_cold void whip_deinit(AVFormatContext *s)
     ff_srtp_free(&whip->srtp_recv);
     ffurl_close(whip->dtls_uc);
     ffurl_closep(&whip->udp);
+    av_freep(&whip->hist_pool);
+    av_freep(&whip->hist);
 }
 
 static int whip_check_bitstream(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
@@ -2024,6 +2089,7 @@ 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 },
+    { "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 },
-- 
2.49.1


>From dc5fc6315374ca8d1d113a6af4448f74fb9b55c8 Mon Sep 17 00:00:00 2001
From: Jack Lau <jacklau1222@qq.com>
Date: Tue, 14 Oct 2025 17:24:10 +0800
Subject: [PATCH 2/2] avformat/whip: reindent the options

Signed-off-by: Jack Lau <jacklau1222@qq.com>
---
 libavformat/whip.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/whip.c b/libavformat/whip.c
index 0f00a6652b..8000bad3a4 100644
--- a/libavformat/whip.c
+++ b/libavformat/whip.c
@@ -2092,7 +2092,7 @@ static const AVOption options[] = {
     { "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 },
+    { "key_file",           "The optional private key file path for DTLS",              OFFSET(key_file),           AV_OPT_TYPE_STRING, { .str = NULL },     0,       0, ENC },
     { NULL },
 };
 
-- 
2.49.1

_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2025-10-14  9:30 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-10-14  9:29 [FFmpeg-devel] [PATCH] avformat/whip: add rtp history store and find method (PR #20703) Jack Lau via ffmpeg-devel

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git