summaryrefslogtreecommitdiffstats
path: root/stream/stream_lavf.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-01-24 18:45:24 +0100
committerwm4 <wm4@nowhere>2013-01-24 18:56:02 +0100
commit8a7b8c3dd6ddb58adb221cfd194c57457a40839c (patch)
tree79d2def8f7d175a2d7281ac4c3285b7baedc0f67 /stream/stream_lavf.c
parent47cec752915a5aa6780b844247b285f5e96536e9 (diff)
downloadmpv-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_lavf.c')
-rw-r--r--stream/stream_lavf.c41
1 files changed, 30 insertions, 11 deletions
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)