PR #23400 opened by u6bkep URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23400 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23400.patch
Follow-up to #22726 (merged as 45cb56c520), which fixed segment-duration calculation in the HLS muxer when streams have different time bases. In the review of that PR, the suggestion was made to add a regression test: > if you respin this, please consider adding a regression test. The current > HLS FATE coverage in `tests/fate/hlsenc.mak` exercises a number of HLS cases, > including fMP4, but I did not find a mixed audio+video / mixed-time-base > segment-splitting case there. [...] reducing it to a portable lavfi-only FATE > case would make this much harder to regress later. This adds that test, `fate-hls-mixed-timebase`, using lavfi-only input (no external samples required). ## What it does The test reproduces the exact scenario the fix addressed: 1. Generate an mpegts source where the audio stream (`1/48000`) starts 0.5s before the video stream and timestamps carry a large offset (`-output_ts_offset 3600`), so `vs->start_pts` is captured from an audio packet and is non-zero. 2. HLS-mux it with **video passthrough** (`-c:v copy`, time base `1/90000`) + **audio transcode** (`-c:a aac`, time base `1/48000`) into fMP4 segments at `-hls_time 3` - the real-world Blu-ray-remux case from the original report. 3. Assert the resulting `#EXTINF` durations via `sed`/`diff`. ## Why this guards the fix Before the fix, `vs->start_pts` was stored in audio ticks and then subtracted from video PTS without time-base conversion. The cross-time-base elapsed value overflowed `-hls_time`, so every keyframe forced a new segment. Verified against both states of `libavformat/hlsenc.c`: | build | `#EXTINF` output | | --------------------- | ------------------------------------------------------- | | with fix (HEAD) | `3.000000`, `3.000000`, `3.000000`, `1.000000` - passes | | fix reverted (HEAD~1) | 10 * `1.000000` - test fails | The full lavfi-only `hlsenc` FATE group still passes. >From c0a9f5308fd40dda0d1d81d392e824145225b331 Mon Sep 17 00:00:00 2001 From: Ben Kepner <[email protected]> Date: Sun, 7 Jun 2026 15:20:00 -0400 Subject: [PATCH] tests/fate/hlsenc: add regression test for mixed stream time base segmenting Follow-up to 45cb56c520 ("avformat/hlsenc: fix segment duration with mixed stream time bases"), adding the regression test requested in review. The test generates an mpegts source where audio (1/48000) starts before video and timestamps carry a large offset, then HLS-muxes it with video passthrough (1/90000) and audio transcode (1/48000) into fmp4 segments at -hls_time 3, asserting the resulting EXTINF durations. Input is lavfi-only, so no external samples are required. Without the fix, vs->start_pts is captured from the audio packet in audio ticks and subtracted from video PTS without conversion, so every keyframe forces a new segment (ten 1s segments instead of ~3s). The test fails on the pre-fix code and passes with the fix in place. Signed-off-by: Ben Kepner <[email protected]> --- tests/fate/hlsenc.mak | 25 +++++++++++++++++++++++++ tests/ref/fate/hls-mixed-timebase | 4 ++++ 2 files changed, 29 insertions(+) create mode 100644 tests/ref/fate/hls-mixed-timebase diff --git a/tests/fate/hlsenc.mak b/tests/fate/hlsenc.mak index b71fe219a6..7fd407a2d7 100644 --- a/tests/fate/hlsenc.mak +++ b/tests/fate/hlsenc.mak @@ -224,6 +224,31 @@ fate-hls-start-number: tests/data/hls_start_number.m3u8 fate-hls-start-number: CMD = sed -n -e /^\#EXT-X-MEDIA-SEQUENCE:/p -e /^[^\#]/p $(TARGET_PATH)/tests/data/hls_start_number.m3u8 fate-hls-start-number: CMP = diff +# This tests that the HLS muxer splits segments at the right points when the +# audio and video streams have different time bases (1/48000 and 1/90000) and +# the first packet seen is audio. The source is built so audio precedes video +# with a large timestamp offset; the EXTINF durations must honour -hls_time +# rather than splitting on every keyframe. +tests/data/hls_mixed_timebase.m3u8: TAG = GEN +tests/data/hls_mixed_timebase.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ + -f lavfi -i "sine=frequency=440:duration=11:sample_rate=48000" \ + -itsoffset 0.5 -f lavfi -i "testsrc2=size=128x72:rate=24:d=10" \ + -c:v mpeg2video -g 24 -c:a mp2 -b:a 128k -output_ts_offset 3600 \ + -flags +bitexact -f mpegts $(TARGET_PATH)/tests/data/hls_mixed_timebase_src.ts 2>/dev/null && \ + $(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin -copyts \ + -i $(TARGET_PATH)/tests/data/hls_mixed_timebase_src.ts \ + -c:v copy -c:a aac -b:a 128k -flags +bitexact \ + -hls_segment_type fmp4 -hls_fmp4_init_filename hls_mixed_timebase_init.mp4 \ + -f hls -hls_time 3 -hls_list_size 0 -hls_playlist_type vod \ + -hls_segment_filename $(TARGET_PATH)/tests/data/hls_mixed_timebase_%d.m4s \ + $(TARGET_PATH)/tests/data/hls_mixed_timebase.m3u8 2>/dev/null + +FATE_HLSENC_LAVFI-$(call ALLYES, SINE_FILTER TESTSRC2_FILTER LAVFI_INDEV MPEG2VIDEO_ENCODER MP2_ENCODER MP2_DECODER AAC_ENCODER HLS_MUXER MP4_MUXER MPEGTS_MUXER MPEGTS_DEMUXER FILE_PROTOCOL) += fate-hls-mixed-timebase +fate-hls-mixed-timebase: tests/data/hls_mixed_timebase.m3u8 +fate-hls-mixed-timebase: CMD = sed -n -e /^\#EXTINF:/p $(TARGET_PATH)/tests/data/hls_mixed_timebase.m3u8 +fate-hls-mixed-timebase: CMP = diff + FATE_HLSENC_LAVFI-yes := $(if $(call FRAMECRC), $(FATE_HLSENC_LAVFI-yes)) FATE_FFMPEG += $(FATE_HLSENC_LAVFI-yes) diff --git a/tests/ref/fate/hls-mixed-timebase b/tests/ref/fate/hls-mixed-timebase new file mode 100644 index 0000000000..e9560c65c6 --- /dev/null +++ b/tests/ref/fate/hls-mixed-timebase @@ -0,0 +1,4 @@ +#EXTINF:3.000000, +#EXTINF:3.000000, +#EXTINF:3.000000, +#EXTINF:1.000000, -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
