PR #23245 opened by Kacper Michajłow (kasper93)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23245
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23245.patch

Some CDNs prepend a small non-TS header to MPEG-TS payloads to bypass
image-only Content-Type filtering. The image demuxer's signature then
wins probe, against the mpegts_probe() score.

Look ahead for CHECK_SYNC sync-aligned packets at any offset in the
first 1 KiB. If found, the stream is unambiguously MPEG-TS.
mpegts_resync() already skips the leading bytes on the read side.


From 3b7fa272392f28f761c78be76ca82595094dd4a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]>
Date: Wed, 27 May 2026 00:09:03 +0200
Subject: [PATCH] avformat/mpegts: probe streams with a leading non-TS prefix
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Some CDNs prepend a small non-TS header to MPEG-TS payloads to bypass
image-only Content-Type filtering. The image demuxer's signature then
wins probe, against the mpegts_probe() score.

Look ahead for CHECK_SYNC sync-aligned packets at any offset in the
first 1 KiB. If found, the stream is unambiguously MPEG-TS.
mpegts_resync() already skips the leading bytes on the read side.

Signed-off-by: Kacper Michajłow <[email protected]>
---
 libavformat/mpegts.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 210635c9c9..9de6a9e2d4 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -3311,10 +3311,27 @@ static int mpegts_probe(const AVProbeData *p)
     int check_count = size / TS_FEC_PACKET_SIZE;
 #define CHECK_COUNT 10
 #define CHECK_BLOCK 100
+#define CHECK_SYNC 5
 
     if (!check_count)
         return 0;
 
+    /* Some CDNs prepend a non-TS prefix (e.g. a 70-byte 1x1 PNG) to bypass
+     * Content-Type filtering, which makes the image demuxer win probe over
+     * the scoring below. Look ahead for several sync-aligned packets in the
+     * first 1 KiB to confirm the stream really is MPEG-TS. */
+    const int max_off = FFMIN(1024, size - (CHECK_SYNC - 1) * TS_PACKET_SIZE);
+    for (int off = 0; off < max_off; off++) {
+        int k;
+        if (p->buf[off] != SYNC_BYTE)
+            continue;
+        for (k = 1; k < CHECK_SYNC; k++)
+            if (p->buf[off + k * TS_PACKET_SIZE] != SYNC_BYTE)
+                break;
+        if (k == CHECK_SYNC)
+            return AVPROBE_SCORE_MAX;
+    }
+
     for (i = 0; i<check_count; i+=CHECK_BLOCK) {
         int left = FFMIN(check_count - i, CHECK_BLOCK);
         int score      = analyze(p->buf + TS_PACKET_SIZE     *i, 
TS_PACKET_SIZE     *left, TS_PACKET_SIZE     , 1);
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to