diff options
Diffstat (limited to 'stream')
-rw-r--r-- | stream/stream.c | 29 | ||||
-rw-r--r-- | stream/stream.h | 1 | ||||
-rw-r--r-- | stream/stream_lavf.c | 41 |
3 files changed, 50 insertions, 21 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) diff --git a/stream/stream.h b/stream/stream.h index 4beefc91bd..746667c564 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -101,6 +101,7 @@ #define STREAM_CTRL_GET_CACHE_SIZE 15 #define STREAM_CTRL_GET_CACHE_FILL 16 #define STREAM_CTRL_GET_CACHE_IDLE 17 +#define STREAM_CTRL_RECONNECT 18 struct stream_lang_req { int type; // STREAM_AUDIO, STREAM_SUB diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c index d652bf27a8..2fa7764d44 100644 --- a/stream/stream_lavf.c +++ b/stream/stream_lavf.c @@ -30,9 +30,13 @@ #include "network.h" #include "cookies.h" +static int open_f(stream_t *stream, int mode, void *opts, int *file_format); + static int fill_buffer(stream_t *s, char *buffer, int max_len) { AVIOContext *avio = s->priv; + if (!avio) + return -1; int r = avio_read(avio, buffer, max_len); return (r <= 0) ? -1 : r; } @@ -40,6 +44,8 @@ static int fill_buffer(stream_t *s, char *buffer, int max_len) static int write_buffer(stream_t *s, char *buffer, int len) { AVIOContext *avio = s->priv; + if (!avio) + return -1; avio_write(avio, buffer, len); avio_flush(avio); if (avio->error) @@ -50,6 +56,8 @@ static int write_buffer(stream_t *s, char *buffer, int len) static int seek(stream_t *s, int64_t newpos) { AVIOContext *avio = s->priv; + if (!avio) + return -1; s->pos = newpos; if (avio_seek(avio, s->pos, SEEK_SET) < 0) { s->eof = 1; @@ -58,9 +66,23 @@ static int seek(stream_t *s, int64_t newpos) return 1; } +static void close_f(stream_t *stream) +{ + AVIOContext *avio = stream->priv; + /* NOTE: As of 2011 write streams must be manually flushed before close. + * Currently write_buffer() always flushes them after writing. + * avio_close() could return an error, but we have no way to return that + * with the current stream API. + */ + if (avio) + avio_close(avio); +} + static int control(stream_t *s, int cmd, void *arg) { AVIOContext *avio = s->priv; + if (!avio && cmd != STREAM_CTRL_RECONNECT) + return -1; int64_t size, ts; double pts; switch(cmd) { @@ -78,21 +100,18 @@ static int control(stream_t *s, int cmd, void *arg) if (ts >= 0) return 1; break; + case STREAM_CTRL_RECONNECT: { + if (avio && avio->write_flag) + break; // don't bother with this + // avio doesn't seem to support this - emulate it by reopening + close_f(s); + s->priv = NULL; + return open_f(s, STREAM_READ, NULL, &(int) {0}); + } } return STREAM_UNSUPPORTED; } -static void close_f(stream_t *stream) -{ - AVIOContext *avio = stream->priv; - /* NOTE: As of 2011 write streams must be manually flushed before close. - * Currently write_buffer() always flushes them after writing. - * avio_close() could return an error, but we have no way to return that - * with the current stream API. - */ - avio_close(avio); -} - static const char * const prefix[] = { "lavf://", "ffmpeg://" }; static int open_f(stream_t *stream, int mode, void *opts, int *file_format) |