Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Gustav Grusell <gustav.grusell@gmail.com>
To: ffmpeg-devel@ffmpeg.org
Cc: Gustav Grusell <gustav.grusell@gmail.com>
Subject: [FFmpeg-devel] [PATCH v3] avformat/hls Implement support for using AVSEEK_FLAG_BACKWARD when seeking
Date: Fri, 28 Jan 2022 19:52:54 +0100
Message-ID: <20220128185254.1662873-1-gustav.grusell@gmail.com> (raw)
In-Reply-To: <CANPC24Gqk0NTsztZtE5KADMpr8+PTUoZpB3AaUKi3wh7Lph3Ug@mail.gmail.com>

Before, seeking in hls streams would always seek to the next keyframe
after the given timestamp. With this fix, if seeking in videostream and
AVSEEK_FLAG_BACKWARD is set, seeking will be to the first keyframe of
the segment containing the given timestamp. This fixes #7485.

Signed-off-by: Gustav Grusell <gustav.grusell@gmail.com>
---
 libavformat/hls.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index 4568e72cb2..44afdaab42 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -1653,7 +1653,8 @@ static void add_metadata_from_renditions(AVFormatContext *s, struct playlist *pl
 /* if timestamp was in valid range: returns 1 and sets seq_no
  * if not: returns 0 and sets seq_no to closest segment */
 static int find_timestamp_in_playlist(HLSContext *c, struct playlist *pls,
-                                      int64_t timestamp, int64_t *seq_no)
+                                      int64_t timestamp, int64_t *seq_no,
+                                      int64_t *seg_start_ts)
 {
     int i;
     int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ?
@@ -1668,6 +1669,9 @@ static int find_timestamp_in_playlist(HLSContext *c, struct playlist *pls,
         int64_t diff = pos + pls->segments[i]->duration - timestamp;
         if (diff > 0) {
             *seq_no = pls->start_seq_no + i;
+            if (seg_start_ts) {
+                *seg_start_ts = pos;
+            }
             return 1;
         }
         pos += pls->segments[i]->duration;
@@ -1691,7 +1695,7 @@ static int64_t select_cur_seq_no(HLSContext *c, struct playlist *pls)
      * playlist) and this is a complete file, find the matching segment
      * by counting durations. */
     if (pls->finished && c->cur_timestamp != AV_NOPTS_VALUE) {
-        find_timestamp_in_playlist(c, pls, c->cur_timestamp, &seq_no);
+        find_timestamp_in_playlist(c, pls, c->cur_timestamp, &seq_no, NULL);
         return seq_no;
     }
 
@@ -2362,7 +2366,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
     int i, j;
     int stream_subdemuxer_index;
     int64_t first_timestamp, seek_timestamp, duration;
-    int64_t seq_no;
+    int64_t seq_no, seg_start_ts;
 
     if ((flags & AVSEEK_FLAG_BYTE) || (c->ctx->ctx_flags & AVFMTCTX_UNSEEKABLE))
         return AVERROR(ENOSYS);
@@ -2372,8 +2376,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
 
     seek_timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE,
                                     s->streams[stream_index]->time_base.den,
-                                    flags & AVSEEK_FLAG_BACKWARD ?
-                                    AV_ROUND_DOWN : AV_ROUND_UP);
+                                    AV_ROUND_DOWN);
 
     duration = s->duration == AV_NOPTS_VALUE ?
                0 : s->duration;
@@ -2394,9 +2397,16 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
     }
     /* check if the timestamp is valid for the playlist with the
      * specified stream index */
-    if (!seek_pls || !find_timestamp_in_playlist(c, seek_pls, seek_timestamp, &seq_no))
+    if (!seek_pls || !find_timestamp_in_playlist(c, seek_pls, seek_timestamp, &seq_no, &seg_start_ts))
         return AVERROR(EIO);
 
+    if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
+        flags & AVSEEK_FLAG_BACKWARD && !(flags & AVSEEK_FLAG_ANY)) {
+        /* Seeking to start of segment ensures we seek to a keyframe located
+         * before the given timestamp. */
+        seek_timestamp = seg_start_ts;
+    }
+
     /* set segment now so we do not need to search again below */
     seek_pls->cur_seq_no = seq_no;
     seek_pls->seek_stream_index = stream_subdemuxer_index;
@@ -2423,7 +2433,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
 
         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);
+            find_timestamp_in_playlist(c, pls, seek_timestamp, &pls->cur_seq_no, NULL);
             /* seek the playlist to the given position without taking
              * keyframes into account since this playlist does not have the
              * specified stream where we should look for the keyframes */
-- 
2.25.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

       reply	other threads:[~2022-01-28 18:54 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CANPC24Gqk0NTsztZtE5KADMpr8+PTUoZpB3AaUKi3wh7Lph3Ug@mail.gmail.com>
2022-01-28 18:52 ` Gustav Grusell [this message]
2022-01-28 20:23   ` [FFmpeg-devel] [PATCH v4] avformat/hls: " Gustav Grusell
2022-02-02 16:31     ` Gustav Grusell
2022-02-03 10:20     ` Steven Liu
2022-02-09  5:56       ` Steven Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220128185254.1662873-1-gustav.grusell@gmail.com \
    --to=gustav.grusell@gmail.com \
    --cc=ffmpeg-devel@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git