Open nihaals opened 11 months ago
This is a feature request for ffmpeg. The same issue can be reproduced with ffplay where it'll try to download all the segments sequentially even if you seek way ahead of the current pts but still fail to continue anyway.
- Notice MPV crashes
This shouldn't and doesn't happen, in my case mpv and ffplay continuously download the file until they reach the end but the playback never resumes. Looking at the logs, it seems to be the case for you too.
[ 51.911][v][lavf] EOF reached.
[ 51.911][v][vf] filter input EOF
[ 51.911][v][vf] filter output EOF
[ 51.911][v][cplayer] video EOF reached
[ 51.911][d][cplayer] video EOF (status=4)
[ 51.911][v][af] filter input EOF
[ 51.911][v][af] filter output EOF
[ 51.911][v][cplayer] audio filter EOF
[ 51.911][d][cplayer] video EOF (status=4)
[ 51.911][v][cplayer] audio ready (and EOF)
[ 51.911][d][cplayer] video EOF (status=4)
[ 51.911][v][cplayer] starting audio playback
[ 51.911][v][cplayer] audio draining
[ 51.911][v][cplayer] playback restart complete @ -9223372036854775808.000000, audio=draining, video=eof
[ 51.911][v][cplayer] audio EOF reached
[ 51.911][d][cplayer] video EOF (status=4)
[ 51.911][v][cplayer] EOF code: 1
mpv reaches EOF so it exits, that's not a crash.
Quick question. Has this been reported upstream?
I searched their bug tracker but haven't found a ticket that resembles this one.
I haven't had a chance to so there might not be a ffmpeg issue yet.
It's an open defect with fmp4 handling. https://trac.ffmpeg.org/ticket/7359 https://ffmpeg.org/pipermail/ffmpeg-devel/2020-April/261343.html There's a patch from 2020 but it hasn't been merged.
Ping the patch or resubmit it to the ML
is it any way to fix it?
is it any way to fix it?
Yes, ping the patch above and try to get it merged into ffmpeg
is it any way to fix it?
Yes, ping the patch above and try to get it merged into ffmpeg
for what ffmpeg version this patch? I have errors when I apply it
You did something wrong because it applies with no conflicts on ffmpeg master
Sorry, you're right that it doesn't compile even if it does apply, because it's accessing items that aren't part of the public AVStream anymore. I rebased the patches
From 0c14ac8d5f19f22f31ae9505e3db5eb417e8d6e0 Mon Sep 17 00:00:00 2001
From: llyyr <llyyr.public@gmail.com>
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 <hello.vectronic@gmail.com>
---
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
From 07045b8245cfc5822005c716db8a84b710579787 Mon Sep 17 00:00:00 2001
From: llyyr <llyyr.public@gmail.com>
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 <hello.vectronic@gmail.com>
---
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
Looks like fixed by https://github.com/FFmpeg/FFmpeg/commit/380a518c439d4e5e3cf17b97e4a06259e8048f99
Thank you for the patch. I had just finished personally developing my HLS track generator for my music player and I couldn't understand why, when seeking faster than mpv's cache, mpv would skip the music.
With this patch I can say that the problem has disappeared and mpv now loads segments properly.
However, I have a question - for now I'm patching ffmpeg myself and then recompiling mpv with my version.
Around when can I be sure that the majority of mpv versions will definitely include the patch?
I'm not at all familiar with the release cycles of mpv and ffmpeg. ^^
mpv doesn't publish any binaries, so ask wherever you're getting your binaries from
Important Information
Provide following Information:
0.37.0
13.6.2
Reproduction steps
Try to reproduce your issue with --no-config first. If it isn't reproducible with --no-config try to first find out which option or script causes your issue.
Describe the reproduction steps as precise as possible. It's very likely that the bug you experience wasn't reproduced by the developer because the workflow differs from your own.
mpv --no-config "https://framatube.org/static/streaming-playlists/hls/66fcff64-d8f9-49c1-8deb-011b115786de/73451ad8-d30e-4beb-aa92-3dba23ba07c8-720.m3u8"
Expected behavior
Video plays
Actual behavior
Video freezes and errors are logged:
MPV then crashes
Log file
mpv.log
Sample files
https://framatube.org/static/streaming-playlists/hls/66fcff64-d8f9-49c1-8deb-011b115786de/73451ad8-d30e-4beb-aa92-3dba23ba07c8-720.m3u8
Extra context
The example video is from #10029 as I'm not able to share the video I found the issue with, but it doesn't seem to be a duplicate of that issue. Based on experiments, this seems to only happen with playlists that use byte ranges on a single MP4 file. This might be caused by the boundaries not being in ideal places but I don't know much about how MP4 files work. VLC can play these streams as expected but prints errors like
mp4: Fragment sequence discontinuity detected 677 != 0
. It looks like VLC might download the previous chunk to get the data it needs to play the actual timestamp skipped to but I'm unsure.