PR #22726 opened by u6bkep URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22726 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22726.patch
The segment split logic in hlsenc compares `pkt->pts - vs->start_pts` without normalizing time bases. When audio packets arrive before video, `start_pts` gets stored in the audio stream's time base (e.g. 1/48000), but the comparison runs against video packets in a different time base (e.g. 1/90000). The cross-timebase subtraction produces a wildly inflated elapsed time, so every keyframe triggers a segment split regardless of `-hls_time`. The fix normalizes `start_pts` to AV_TIME_BASE_Q on assignment and converts `pkt->pts` before comparison. I have a stand alone reproducer script if reviewers want. This may have been hitting users transcoding Blu-ray remuxes with video passthrough + audio transcode (fmp4 segments, non-zero starting PTS): - https://github.com/jellyfin/jellyfin/issues/14702 - https://github.com/jellyfin/jellyfin/issues/15656 I noticed it during testing for some tangentially related work I am doing on jellyfin. From 45cb56c52030395ef40e480594e6c0eab9f018df Mon Sep 17 00:00:00 2001 From: Ben Kepner <[email protected]> Date: Sun, 5 Apr 2026 16:53:06 -0400 Subject: [PATCH] avformat/hlsenc: fix segment duration with mixed stream time bases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When audio and video streams have different time bases (e.g. video at 1/90000 and audio at 1/48000), vs->start_pts was stored as a raw PTS from whichever stream's packet arrived first. The segment split comparison then subtracted this value from the current packet's PTS without accounting for the time base difference, producing incorrect elapsed time calculations. This caused segments to be split at wrong points — either too frequently (on every keyframe) or not at all, depending on the relative magnitudes of the time bases. Fix by normalizing vs->start_pts to AV_TIME_BASE_Q at the point of assignment and converting pkt->pts to the same base before comparison. This ensures the segment split decision is always unit-consistent regardless of which stream's packet is being evaluated. The bug is most easily triggered by HLS muxing with video passthrough and audio transcode, where the video retains its container time base while the audio encoder outputs in its native time base. Signed-off-by: Ben Kepner <[email protected]> --- libavformat/hlsenc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 8eaab37a2c..db2ae2125d 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -2448,13 +2448,16 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) } if (vs->start_pts == AV_NOPTS_VALUE) { - vs->start_pts = pkt->pts; + vs->start_pts = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q); if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) vs->start_pts_from_audio = 1; } - if (vs->start_pts_from_audio && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && vs->start_pts > pkt->pts) { - vs->start_pts = pkt->pts; - vs->start_pts_from_audio = 0; + if (vs->start_pts_from_audio && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + int64_t video_start = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q); + if (vs->start_pts > video_start) { + vs->start_pts = video_start; + vs->start_pts_from_audio = 0; + } } if (vs->has_video) { @@ -2485,8 +2488,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) } can_split = can_split && (pkt->pts - vs->end_pts > 0); - if (vs->packets_written && can_split && av_compare_ts(pkt->pts - vs->start_pts, st->time_base, - end_pts, AV_TIME_BASE_Q) >= 0) { + if (vs->packets_written && can_split && (av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q) - vs->start_pts + >= end_pts)) { int64_t new_start_pos; int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); double cur_duration; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
