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]
