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".
next parent 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