diff options
author | wm4 <wm4@nowhere> | 2013-01-24 18:45:24 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-01-24 18:56:02 +0100 |
commit | 8a7b8c3dd6ddb58adb221cfd194c57457a40839c (patch) | |
tree | 79d2def8f7d175a2d7281ac4c3285b7baedc0f67 /stream/stream.c | |
parent | 47cec752915a5aa6780b844247b285f5e96536e9 (diff) | |
download | mpv-8a7b8c3dd6ddb58adb221cfd194c57457a40839c.tar.bz2 mpv-8a7b8c3dd6ddb58adb221cfd194c57457a40839c.tar.xz |
stream: fix reconnecting on broken network connections
This didn't work properly for HTTP with libavformat. The builtin HTTP
implementation reconnects automatically on its own, while libavformat
doesn't. Fix this by adding explicit reconnection support to
stream_lavf.c, which simply destroys and recreates the AVIO context.
It mostly works, though sometimes it mysteriously fails, spamming crap
all over the terminal and feeding broken data to the decoders. This is
probably due to itneractions with the cache. Also, reconnecting to
unseekable HTTP streams will make it read the entire stream until the
previous playback position is reached again.
It's not known whether this change makes behavior with "strange"
protocols like RTP better or worse.
Diffstat (limited to 'stream/stream.c')
-rw-r--r-- | stream/stream.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/stream/stream.c b/stream/stream.c index 9dd190055a..d0bd0b58d6 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -286,21 +286,30 @@ static int stream_reconnect(stream_t *s) { #define MAX_RECONNECT_RETRIES 5 #define RECONNECT_SLEEP_MS 1000 - int retry = 0; + if (!s->streaming) + return 0; int64_t pos = s->pos; - // Seeking is used as a hack to make network streams - // reopen the connection, ideally they would implement - // e.g. a STREAM_CTRL_RECONNECT to do this - do { - if (retry >= MAX_RECONNECT_RETRIES) - return 0; + for (int retry = 0; retry < MAX_RECONNECT_RETRIES; retry++) { + mp_msg(MSGT_STREAM, MSGL_WARN, + "Connection lost! Attempting to reconnect...\n"); + if (retry) usec_sleep(RECONNECT_SLEEP_MS * 1000); - retry++; + s->eof = 1; stream_reset(s); - } while (stream_seek_internal(s, pos) >= 0 || s->pos != pos); // seek failed - return 1; + + // Some streams (internal http.c) don't support STREAM_CTRL_RECONNECT, + // but do it when trying to seek. + if (s->control) { + if (s->control(s, STREAM_CTRL_RECONNECT, NULL) == STREAM_ERROR) + continue; + } + + if (stream_seek_internal(s, pos) < 0 && s->pos == pos) + return 1; + } + return 0; } int stream_read_internal(stream_t *s, void *buf, int len) |