summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
Diffstat (limited to 'stream')
-rw-r--r--stream/stream.c29
-rw-r--r--stream/stream.h1
-rw-r--r--stream/stream_lavf.c41
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)