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]

Reply via email to