summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-07-09 12:29:22 +0200
committerwm4 <wm4@nowhere>2020-07-09 12:29:22 +0200
commit06033df715b433d41b1a0855cf7805ff8f66d664 (patch)
tree6ecca1a978736238cc05db57643aea1d95cce1dd
parentadbd28b1dbe256dda82a6154b0ba2cf118c742d5 (diff)
downloadmpv-06033df715b433d41b1a0855cf7805ff8f66d664.tar.bz2
mpv-06033df715b433d41b1a0855cf7805ff8f66d664.tar.xz
demux_lavf: workaround reading gif from unseekable streams
FFmpeg, being the pile of trash as usual, recently broke this. Add our own trash hack to trashily workaround this shit. Fixes: #7893
-rw-r--r--demux/demux_lavf.c19
-rw-r--r--stream/stream.c10
-rw-r--r--stream/stream.h1
3 files changed, 29 insertions, 1 deletions
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 50b9e044e4..e3ebcbfdc6 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -148,6 +148,7 @@ struct format_hack {
bool no_seek : 1;
bool no_pcm_seek : 1;
bool no_seek_on_no_duration : 1;
+ bool readall_on_no_streamseek : 1;
};
#define BLACKLIST(fmt) {fmt, .ignore = true}
@@ -186,6 +187,10 @@ static const struct format_hack format_hacks[] = {
// reset timestamps, which causes all sorts of problems.
{"ogg", .linearize_audio_ts = true, .use_stream_ids = true},
+ // At some point, FFmpeg lost the ability to read gif from unseekable
+ // streams.
+ {"gif", .readall_on_no_streamseek = true},
+
TEXTSUB("aqtitle"), TEXTSUB("jacosub"), TEXTSUB("microdvd"),
TEXTSUB("mpl2"), TEXTSUB("mpsub"), TEXTSUB("pjs"), TEXTSUB("realtext"),
TEXTSUB("sami"), TEXTSUB("srt"), TEXTSUB("stl"), TEXTSUB("subviewer"),
@@ -1020,6 +1025,20 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
return -1;
}
+ if (priv->format_hack.readall_on_no_streamseek && priv->pb &&
+ !priv->pb->seekable)
+ {
+ MP_VERBOSE(demuxer, "Non-seekable demuxer pre-read hack...\n");
+ // Read incremental to avoid unnecessary large buffer sizes.
+ int r = 0;
+ for (int n = 16; n < 29; n++) {
+ r = stream_peek(priv->stream, 1 << n);
+ if (r < (1 << n))
+ break;
+ }
+ MP_VERBOSE(demuxer, "...did read %d bytes.\n", r);
+ }
+
if (avformat_open_input(&avfc, priv->filename, priv->avif, &dopts) < 0) {
MP_ERR(demuxer, "avformat_open_input() failed\n");
av_dict_free(&dopts);
diff --git a/stream/stream.c b/stream/stream.c
index 8361cd8748..3c728eacac 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -611,11 +611,19 @@ int stream_read(stream_t *s, void *mem, int total)
return total;
}
+// Read ahead so that at least forward_size bytes are readable ahead. Returns
+// the actual forward amount available (restricted by EOF or buffer limits).
+int stream_peek(stream_t *s, int forward_size)
+{
+ while (stream_read_more(s, forward_size)) {}
+ return s->buf_end - s->buf_cur;
+}
+
// Like stream_read(), but do not advance the current position. This may resize
// the buffer to satisfy the read request.
int stream_read_peek(stream_t *s, void *buf, int buf_size)
{
- while (stream_read_more(s, buf_size)) {}
+ stream_peek(s, buf_size);
return ring_copy(s, buf, buf_size, s->buf_cur);
}
diff --git a/stream/stream.h b/stream/stream.h
index c127860ceb..2116fdde27 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -212,6 +212,7 @@ bool stream_seek_skip(stream_t *s, int64_t pos);
bool stream_seek(stream_t *s, int64_t pos);
int stream_read(stream_t *s, void *mem, int total);
int stream_read_partial(stream_t *s, void *buf, int buf_size);
+int stream_peek(stream_t *s, int forward_size);
int stream_read_peek(stream_t *s, void *buf, int buf_size);
void stream_drop_buffers(stream_t *s);
int64_t stream_get_size(stream_t *s);