diff --git a/Sources/BuildScripts/patch/FFmpeg/0001-hls-seek-patch-1.patch b/Sources/BuildScripts/patch/FFmpeg/0001-hls-seek-patch-1.patch new file mode 100644 index 0000000..872056d --- /dev/null +++ b/Sources/BuildScripts/patch/FFmpeg/0001-hls-seek-patch-1.patch @@ -0,0 +1,39 @@ +From 0c14ac8d5f19f22f31ae9505e3db5eb417e8d6e0 Mon Sep 17 00:00:00 2001 +From: llyyr +Date: Sun, 27 Oct 2024 06:52:42 +0530 +Subject: [PATCH 1/2] avformat/hls: always return keyframe if not + AVSEEK_FLAG_ANY + +Co-Authored-by: vectronic +--- + libavformat/hls.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/libavformat/hls.c b/libavformat/hls.c +index 62473a15ddb5..4d02faa9e49a 100644 +--- a/libavformat/hls.c ++++ b/libavformat/hls.c +@@ -2350,8 +2350,10 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) + ts_diff = av_rescale_rnd(pls->pkt->dts, AV_TIME_BASE, + tb.den, AV_ROUND_DOWN) - + pls->seek_timestamp; +- if (ts_diff >= 0 && (pls->seek_flags & AVSEEK_FLAG_ANY || +- pls->pkt->flags & AV_PKT_FLAG_KEY)) { ++ /* If AVSEEK_FLAG_ANY, keep reading until ts_diff >= 0, ++ * otherwise return the first keyframe encountered */ ++ if ((ts_diff >= 0 && (pls->seek_flags & AVSEEK_FLAG_ANY)) || ++ (!(pls->seek_flags & AVSEEK_FLAG_ANY) && (pls->pkt->flags & AV_PKT_FLAG_KEY))) { + pls->seek_timestamp = AV_NOPTS_VALUE; + break; + } +@@ -2502,7 +2504,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, + pb->eof_reached = 0; + /* Clear any buffered data */ + pb->buf_end = pb->buf_ptr = pb->buffer; +- /* Reset the pos, to let the mpegts demuxer know we've seeked. */ ++ /* Reset the pos, to let the mpegts/mov demuxer know we've seeked. */ + pb->pos = 0; + /* Flush the packet queue of the subdemuxer. */ + ff_read_frame_flush(pls->ctx); +-- +2.47.0 \ No newline at end of file diff --git a/Sources/BuildScripts/patch/FFmpeg/0002-hls-seek-patch-2.patch.cpp b/Sources/BuildScripts/patch/FFmpeg/0002-hls-seek-patch-2.patch.cpp new file mode 100644 index 0000000..157df14 --- /dev/null +++ b/Sources/BuildScripts/patch/FFmpeg/0002-hls-seek-patch-2.patch.cpp @@ -0,0 +1,78 @@ +From 07045b8245cfc5822005c716db8a84b710579787 Mon Sep 17 00:00:00 2001 +From: llyyr +Date: Sun, 27 Oct 2024 06:44:51 +0530 +Subject: [PATCH 2/2] avformat/mov: handle stream position resets + +If the stream position has been reset, clear fragment index, the index +entries and the current sample and search for the next root. + +Co-Authored-by: vectronic +--- + libavformat/mov.c | 37 +++++++++++++++++++++++++++++++++---- + 1 file changed, 33 insertions(+), 4 deletions(-) + +diff --git a/libavformat/mov.c b/libavformat/mov.c +index 8c3329b81596..78540bec1d11 100644 +--- a/libavformat/mov.c ++++ b/libavformat/mov.c +@@ -10612,15 +10612,15 @@ static int mov_switch_root(AVFormatContext *s, int64_t target, int index) + + if (index >= 0 && index < mov->frag_index.nb_items) + target = mov->frag_index.item[index].moof_offset; +- if (avio_seek(s->pb, target, SEEK_SET) != target) { ++ if (target >= 0 && avio_seek(s->pb, target, SEEK_SET) != target) { + av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target); + return AVERROR_INVALIDDATA; + } + + mov->next_root_atom = 0; +- if (index < 0 || index >= mov->frag_index.nb_items) ++ if ((index < 0 && target >= 0) || index >= mov->frag_index.nb_items) + index = search_frag_moof_offset(&mov->frag_index, target); +- if (index < mov->frag_index.nb_items && ++ if (index >= 0 && index < mov->frag_index.nb_items && + mov->frag_index.item[index].moof_offset == target) { + if (index + 1 < mov->frag_index.nb_items) + mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset; +@@ -10751,9 +10751,38 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) + AVIndexEntry *sample; + AVStream *st = NULL; + int64_t current_index; +- int ret; ++ int ret, i; + mov->fc = s; + retry: ++ if (s->pb->pos == 0) { ++ // Discard current fragment index ++ if (mov->frag_index.allocated_size > 0) { ++ av_freep(&mov->frag_index.item); ++ mov->frag_index.nb_items = 0; ++ mov->frag_index.allocated_size = 0; ++ mov->frag_index.current = -1; ++ mov->frag_index.complete = 0; ++ } ++ ++ for (i = 0; i < s->nb_streams; i++) { ++ AVStream *avst = s->streams[i]; ++ FFStream *sti = ffstream(avst); ++ MOVStreamContext *msc = avst->priv_data; ++ ++ // Clear current sample ++ mov_current_sample_set(msc, 0); ++ ++ // Discard current index entries ++ if (sti->index_entries_allocated_size > 0) { ++ av_freep(&sti->index_entries); ++ sti->index_entries_allocated_size = 0; ++ sti->nb_index_entries = 0; ++ } ++ } ++ ++ if ((ret = mov_switch_root(s, -1, -1)) < 0) ++ return ret; ++ } + sample = mov_find_next_sample(s, &st); + if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) { + if (!mov->next_root_atom) +-- +2.47.0 \ No newline at end of file