diff options
Diffstat (limited to 'stream')
-rw-r--r-- | stream/stream_lavf.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c index bd4e629136..67681d3c43 100644 --- a/stream/stream_lavf.c +++ b/stream/stream_lavf.c @@ -141,10 +141,30 @@ static int control(stream_t *s, int cmd, void *arg) } break; } - case STREAM_CTRL_HAS_AVSEEK: - if (avio->read_seek) - return 1; + 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) |