mirror of
https://github.com/mpv-player/mpv
synced 2024-12-23 23:32:26 +00:00
stream_lavf: fix determining seekability
demux_lavf.c forces seek to being determined as supported if STREAM_CTRL_HAS_AVSEEK is returned as success. But it always succeeds with current FFmpeg versions. (Seems like Libav commit cae448cf broke this in early 2016.) Now we can't determine via private API whether the underlying protocol supports read_seek anymore. The affected protocols (mostly rtmp) also set seekable=0, meaning they signal they're not seekable, even though read_seek would work. (My guess is that this can't be fixed because even though seekable is in theory a combination of elaborate flags [of which only 1 is defined, AVIO_SEEKABLE_NORMAL], a seekable!=0 always means it's byte-seekable in some way.) So the FFmpeg API is being garbage _again_, and all what we can do is determining this via protocol name and a whitelist. Should fix the behavior reported in #1701.
This commit is contained in:
parent
41002c46f5
commit
0f110ad0e2
@ -141,10 +141,30 @@ static int control(stream_t *s, int cmd, void *arg)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case STREAM_CTRL_HAS_AVSEEK:
|
||||
if (avio->read_seek)
|
||||
case STREAM_CTRL_HAS_AVSEEK: {
|
||||
// Starting at some point, read_seek is always available, and runtime
|
||||
// behavior decides whether it exists or not. FFmpeg's API doesn't
|
||||
// return anything helpful to determine seekability upfront, so here's
|
||||
// a hardcoded whitelist. Not our fault.
|
||||
// In addition we also have to jump through ridiculous hoops just to
|
||||
// get the fucking protocol name.
|
||||
const char *proto = NULL;
|
||||
if (avio->av_class && avio->av_class->child_next) {
|
||||
// This usually yields the URLContext (why does it even exist?),
|
||||
// which holds the name of the actual protocol implementation.
|
||||
void *child = avio->av_class->child_next(avio, NULL);
|
||||
AVClass *cl = *(AVClass **)child;
|
||||
if (cl && cl->item_name)
|
||||
proto = cl->item_name(child);
|
||||
}
|
||||
static const char *const has_read_seek[] = {
|
||||
"rtmp", "rtmpt", "rtmpe", "rtmpte", "rtmps", "rtmpts", "mmsh", 0};
|
||||
for (int n = 0; has_read_seek[n]; n++) {
|
||||
if (avio->read_seek && proto && strcmp(proto, has_read_seek[n]) == 0)
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case STREAM_CTRL_GET_METADATA: {
|
||||
*(struct mp_tags **)arg = read_icy(s);
|
||||
if (!*(struct mp_tags **)arg)
|
||||
|
Loading…
Reference in New Issue
Block a user