aboutsummaryrefslogtreecommitdiffhomepage
path: root/stream
diff options
context:
space:
mode:
authorGravatar wm4 <wm4@nowhere>2018-01-04 15:20:19 +0100
committerGravatar Kevin Mitchell <kevmitch@gmail.com>2018-01-04 18:33:18 -0800
commit185e63a3e2a84fe4d006054960481460072a8243 (patch)
treea320b4df574926e0254749a445006e9d9b798e65 /stream
parentcf411a9489b825f5b5587414431a694dc743da82 (diff)
stream: use native libavformat reconnection feature
Remove our own hacky reconnection code, and use libavformat's feature for that. It's disabled by default, and until recently it did not work too well. This has been fixed in recent ffmpeg git master[1], so there's no reason to keep our own code. [1] FFmpeg/FFmpeg@8a108bdea06fac43af9f44b6d2538f357451167a We set "reconnect_delay_max" to 7, which limits the maximum time it waits. Since libavformat doubles the wait time on each reconnect attempt (starting with 1), and stops trying to reconnect once the wait time is over the reconnect_delay_max value, this allows for 4 reconnection attempts which should add to 11 seconds maximum wait time. The default is 120, which seems too high for normal playback use. (The user can still override these parameters with --stream-lavf-o.)
Diffstat (limited to 'stream')
-rw-r--r--stream/cache.c1
-rw-r--r--stream/stream.c35
-rw-r--r--stream/stream.h1
-rw-r--r--stream/stream_lavf.c30
4 files changed, 3 insertions, 64 deletions
diff --git a/stream/cache.c b/stream/cache.c
index d91ae73b05..10e1bd7ce7 100644
--- a/stream/cache.c
+++ b/stream/cache.c
@@ -504,7 +504,6 @@ static bool control_needs_flush(int stream_ctrl)
case STREAM_CTRL_AVSEEK:
case STREAM_CTRL_SET_ANGLE:
case STREAM_CTRL_SET_CURRENT_TITLE:
- case STREAM_CTRL_RECONNECT:
case STREAM_CTRL_DVB_SET_CHANNEL:
case STREAM_CTRL_DVB_SET_CHANNEL_NAME:
case STREAM_CTRL_DVB_STEP_CHANNEL:
diff --git a/stream/stream.c b/stream/stream.c
index dba30d5df2..255e583de2 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -336,32 +336,6 @@ stream_t *open_output_stream(const char *filename, struct mpv_global *global)
return stream_create(filename, STREAM_WRITE, NULL, global);
}
-static bool stream_reconnect(stream_t *s)
-{
- if (!s->streaming || s->caching || !s->seekable || !s->cancel)
- return false;
-
- double sleep_secs = 0;
- for (int retry = 0; retry < 6; retry++) {
- if (mp_cancel_wait(s->cancel, sleep_secs))
- break;
-
- int r = stream_control(s, STREAM_CTRL_RECONNECT, NULL);
- if (r == STREAM_UNSUPPORTED)
- break;
- if (r == STREAM_OK) {
- MP_WARN(s, "Reconnected successfully.\n");
- return true;
- }
-
- MP_WARN(s, "Connection lost! Attempting to reconnect (%d)...\n", retry + 1);
-
- sleep_secs = MPMAX(sleep_secs, 0.1);
- sleep_secs = MPMIN(sleep_secs * 4, 10.0);
- }
- return false;
-}
-
// Read function bypassing the local stream buffer. This will not write into
// s->buffer, but into buf[0..len] instead.
// Returns 0 on error or EOF, and length of bytes read on success.
@@ -374,15 +348,6 @@ static int stream_read_unbuffered(stream_t *s, void *buf, int len)
if (s->fill_buffer && !mp_cancel_test(s->cancel))
res = s->fill_buffer(s, buf, len);
if (res <= 0) {
- // just in case this is an error e.g. due to network
- // timeout reset and retry
- // do not retry if this looks like proper eof
- int64_t size = stream_get_size(s);
- if (!s->eof && s->pos != size && stream_reconnect(s)) {
- s->eof = 1; // make sure EOF is set to ensure no endless recursion
- return stream_read_unbuffered(s, buf, len);
- }
-
s->eof = 1;
return 0;
}
diff --git a/stream/stream.h b/stream/stream.h
index ba2b0ca2af..3ce74ecd15 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -64,7 +64,6 @@ enum stream_ctrl {
STREAM_CTRL_GET_BASE_FILENAME,
// Certain network protocols
- STREAM_CTRL_RECONNECT,
STREAM_CTRL_AVSEEK,
STREAM_CTRL_HAS_AVSEEK,
STREAM_CTRL_GET_METADATA,
diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c
index 2230247f28..82d9b3a392 100644
--- a/stream/stream_lavf.c
+++ b/stream/stream_lavf.c
@@ -77,8 +77,6 @@ static struct mp_tags *read_icy(stream_t *stream);
static int fill_buffer(stream_t *s, char *buffer, int max_len)
{
AVIOContext *avio = s->priv;
- if (!avio)
- return -1;
#if LIBAVFORMAT_VERSION_MICRO >= 100 && LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 81, 100)
int r = avio_read_partial(avio, buffer, max_len);
#else
@@ -90,8 +88,6 @@ 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)
@@ -102,8 +98,6 @@ 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;
if (avio_seek(avio, newpos, SEEK_SET) < 0) {
return 0;
}
@@ -125,8 +119,6 @@ static void close_f(stream_t *stream)
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;
switch(cmd) {
case STREAM_CTRL_GET_SIZE:
@@ -175,25 +167,6 @@ static int control(stream_t *s, int cmd, void *arg)
break;
return 1;
}
- case STREAM_CTRL_RECONNECT: {
- if (avio && avio->write_flag)
- break; // don't bother with this
- // avio supports reconneting for http (as private avio option), but it
- // seems somewhat broken and drops part of the stream if the first
- // reconnect does not work. emulate it.
- close_f(s);
- s->priv = NULL;
- int res = open_f(s);
- if (res == STREAM_OK) {
- if (!seek(s, s->pos)) {
- MP_WARN(s, "Reconnecting failed.\n");
- close_f(s);
- s->priv = NULL;
- return STREAM_UNSUPPORTED;
- }
- }
- return res;
- }
}
return STREAM_UNSUPPORTED;
}
@@ -313,6 +286,9 @@ static int open_f(stream_t *stream)
filename = talloc_asprintf(temp, "mmsh://%.*s", BSTR_P(b_filename));
}
+ av_dict_set(&dict, "reconnect", "1", 0);
+ av_dict_set(&dict, "reconnect_delay_max", "7", 0);
+
mp_setup_av_network_options(&dict, stream->global, stream->log);
AVIOInterruptCB cb = {