[FFmpeg-devel] [PATCH v2] avformat/hlsenc: fix hls_time not respected

Ingo Oppermann ingo at datarhei.com
Mon Jan 27 11:09:30 EET 2025


This fixes the criterion when to split the segments based on the
elapsed time for the current segment instead of using the theoretical
elapsed time since start based on hls_time and the number of written
segments.

hls_time is used to define the minimum length of a segment, however
this is not respected in all cases when a stream has variable GOP
sizes.

Imagine a stream starts with a key frame every 10 seconds for
e.g. 30 seconds. After that, key frames will come every second. This
will result in segments that are first 10 seconds (as expected), then
1 second for some time (not as expected) and later 2 seconds (as
expected).

How to reproduce:
ffmpeg -t 30 -f lavfi -i testsrc2 -codec:v libx264 -g 250 part1.mp4
ffmpeg -t 30 -f lavfi -i testsrc2 -codec:v libx264 -g 25 part2.mp4
echo "file part1.mp4\nfile part2.mp4" > list.txt
ffmpeg -f concat -i list.txt -codec copy \
    -f hls -hls_time 2 -hls_list_size 0 parts.m3u8
cat parts.m3u8

Signed-off-by: Ingo Oppermann <ingo at datarhei.com>
---
 libavformat/hlsenc.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 6148685f40..2c5d60500d 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -2474,7 +2474,6 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
     HLSContext *hls = s->priv_data;
     AVFormatContext *oc = NULL;
     AVStream *st = s->streams[pkt->stream_index];
-    int64_t end_pts = 0;
     int is_ref_pkt = 1;
     int ret = 0, can_split = 1, i, j;
     int stream_index = 0;
@@ -2512,14 +2511,9 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
         return AVERROR(ENOMEM);
     }
 
-    end_pts = hls->recording_time * vs->number;
-
     if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) {
-        /* reset end_pts, hls->recording_time at end of the init hls list */
-        int64_t init_list_dur = hls->init_time * vs->nb_entries;
-        int64_t after_init_list_dur = (vs->sequence - hls->start_sequence - vs->nb_entries) * hls->time;
+        /* reset hls->recording_time at end of the init hls list */
         hls->recording_time = hls->time;
-        end_pts = init_list_dur + after_init_list_dur ;
     }
 
     if (vs->start_pts == AV_NOPTS_VALUE) {
@@ -2560,8 +2554,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_compare_ts(pkt->pts - vs->end_pts, st->time_base,
+                                                          hls->recording_time, AV_TIME_BASE_Q) >= 0) {
         int64_t new_start_pos;
         int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
         double cur_duration;

base-commit: f632ab53d98168b9b731cf5696547c26059c0822
-- 
2.39.5 (Apple Git-154)



More information about the ffmpeg-devel mailing list