This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 848fb754dd8ac26e1fa42a94d1034af3eabcea0d
Author:     Kacper Michajłow <[email protected]>
AuthorDate: Wed Jul 8 03:56:24 2026 +0200
Commit:     Kacper Michajłow <[email protected]>
CommitDate: Tue Jul 28 18:01:18 2026 +0200

    avformat/hls: don't discard target segment's first keyframe when seeking
    
    Segment starts on the seek timeline are derived from EXTINF durations,
    so the first keyframe of the target segment can have a slightly lower
    DTS than the snapped seek position, in which case the packet discard
    loop would skip it and resume playback one segment late. Make sure we
    start at the very beginning of the stream in this case.
    
    Signed-off-by: Kacper Michajłow <[email protected]>
---
 libavformat/hls.c  | 11 +++++++++++
 tests/ref/seek/hls | 18 +++++++++---------
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index ed6fe7ef5b..569bc889e8 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -2909,6 +2909,7 @@ static int hls_read_seek(AVFormatContext *s, int 
stream_index,
     int stream_subdemuxer_index;
     int64_t first_timestamp, seek_timestamp, duration;
     int64_t seq_no, seg_start_ts;
+    int snapped_to_segment = 0;
 
     if ((flags & AVSEEK_FLAG_BYTE) || (c->ctx->ctx_flags & 
AVFMTCTX_UNSEEKABLE))
         return AVERROR(ENOSYS);
@@ -2952,6 +2953,7 @@ static int hls_read_seek(AVFormatContext *s, int 
stream_index,
         /* Seeking to start of segment ensures we seek to a keyframe located
          * before the given timestamp. */
         seek_timestamp = seg_start_ts;
+        snapped_to_segment = 1;
     }
 
     av_log(s, AV_LOG_DEBUG, "Seek to %"PRId64" mapped to segment %"PRId64
@@ -3005,6 +3007,15 @@ static int hls_read_seek(AVFormatContext *s, int 
stream_index,
             pls->seek_timestamp = seek_timestamp;
         pls->seek_flags = flags;
 
+        if (pls == seek_pls && snapped_to_segment) {
+            /* The first keyframe of the target segment may have a slightly
+             * lower DTS than the EXTINF-derived seg_start_ts. Relax the cutoff
+             * to not discard the keyframe and land one segment late. */
+            int64_t idx = seq_no - pls->start_seq_no;
+            if (idx >= 0 && idx < pls->n_segments)
+                pls->seek_timestamp -= pls->segments[idx]->duration;
+        }
+
         if (pls != seek_pls) {
             /* set closest segment seq_no for playlists not handled above */
             find_timestamp_in_playlist(c, pls, seek_timestamp, 
&pls->cur_seq_no, NULL);
diff --git a/tests/ref/seek/hls b/tests/ref/seek/hls
index a9b3badaf8..7f3025ef70 100644
--- a/tests/ref/seek/hls
+++ b/tests/ref/seek/hls
@@ -2,7 +2,7 @@ ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:   
 564 size:  3913
 ret: 0         st:-1 flags:0  ts:-1.000000
 ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st:-1 flags:1  ts:-0.105833
-ret: 0         st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos:     -1 size:  
1254
+ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st: 0 flags:0  ts: 0.788333
 ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st: 0 flags:1  ts: 1.682500
@@ -10,11 +10,11 @@ ret: 0         st: 0 flags:1 dts: 1.698078 pts: 1.698078 
pos:  11092 size:  1253
 ret: 0         st: 1 flags:0  ts: 2.576667
 ret: 0         st: 0 flags:1 dts: 2.586233 pts: 2.586233 pos:  55836 size:  
1254
 ret: 0         st: 1 flags:1  ts: 3.470833
-ret: 0         st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos:     -1 size:  
1254
+ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st:-1 flags:0  ts: 4.365002
 ret: 0         st: 0 flags:1 dts: 4.388689 pts: 4.388689 pos:  45308 size:  
1254
 ret: 0         st:-1 flags:1  ts:-0.740831
-ret: 0         st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos:     -1 size:  
1254
+ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st: 0 flags:0  ts: 0.153333
 ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st: 0 flags:1  ts: 1.047500
@@ -22,11 +22,11 @@ ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 
pos:    564 size:  3913
 ret: 0         st: 1 flags:0  ts: 1.941667
 ret: 0         st: 0 flags:1 dts: 1.959300 pts: 1.959300 pos:  24252 size:  
1254
 ret: 0         st: 1 flags:1  ts: 2.835833
-ret: 0         st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos:     -1 size:  
1254
+ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st:-1 flags:0  ts: 3.730004
 ret: 0         st: 0 flags:1 dts: 3.735622 pts: 3.735622 pos:     -1 size:  
1254
 ret: 0         st:-1 flags:1  ts: 4.624171
-ret: 0         st: 0 flags:1 dts: 4.493178 pts: 4.493178 pos:  50572 size:  
1254
+ret: 0         st: 1 flags:1 dts: 4.200000 pts: 4.500000 pos:    564 size:  
5196
 ret: 0         st: 0 flags:0  ts:-0.481667
 ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st: 0 flags:1  ts: 0.412500
@@ -34,11 +34,11 @@ ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 
pos:    564 size:  3913
 ret: 0         st: 1 flags:0  ts: 1.306667
 ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st: 1 flags:1  ts: 2.200844
-ret: 0         st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos:     -1 size:  
1254
+ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st:-1 flags:0  ts: 3.095006
 ret: 0         st: 0 flags:1 dts: 3.108689 pts: 3.108689 pos:  82156 size:  
1254
 ret: 0         st:-1 flags:1  ts: 3.989173
-ret: 0         st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos:     -1 size:  
1254
+ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st: 0 flags:0  ts: 4.883344
 ret: 0         st: 0 flags:1 dts: 4.885011 pts: 4.885011 pos:     -1 size:  
1253
 ret: 0         st: 0 flags:1  ts:-0.222489
@@ -46,8 +46,8 @@ ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos: 
   564 size:  3913
 ret: 0         st: 1 flags:0  ts: 0.671678
 ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st: 1 flags:1  ts: 1.565844
-ret: 0         st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos:     -1 size:  
1254
+ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913
 ret: 0         st:-1 flags:0  ts: 2.460008
 ret: 0         st: 0 flags:1 dts: 2.481744 pts: 2.481744 pos:  50572 size:  
1254
 ret: 0         st:-1 flags:1  ts: 3.354175
-ret: 0         st: 0 flags:1 dts: 1.515211 pts: 1.515211 pos:     -1 size:  
1254
+ret: 0         st: 1 flags:1 dts: 1.400000 pts: 1.500000 pos:    564 size:  
3913

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

Reply via email to