aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat/http.c
diff options
context:
space:
mode:
authorwm4 <nfxjfg@googlemail.com>2018-01-02 17:05:03 +0100
committerwm4 <nfxjfg@googlemail.com>2018-01-04 15:07:55 +0100
commit8a108bdea06fac43af9f44b6d2538f357451167a (patch)
tree24428bb98451621940eb507a2b10173fe741a202 /libavformat/http.c
parent89bbf5c7ec18a3dff2e2505883a662d182ca6c3a (diff)
downloadffmpeg-8a108bdea06fac43af9f44b6d2538f357451167a.tar.gz
http: block while waiting for reconnecting
It makes no sense to return an error after the first reconnect, and then somehow resume the next time it's called. Usually this will lead to demuxer errors. Make reconnecting block instead, until it has either successfully reconnected, or given up. Also make the wait reasonably interruptible. Since there is no mechanism for this in the API, polling is the best we can do. This behaves roughly the same as other interruptible network functions in libavformat. (The original code would work if it returned AVERROR(EAGAIN) or so, which would make retry_transfer_wrapper() repeat the read call. But I think having an explicit loop for this is better anyway.) I also snuck in a fix for reconnect_at_eof. It has to check for AVERROR_EOF, not 0.
Diffstat (limited to 'libavformat/http.c')
-rw-r--r--libavformat/http.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/libavformat/http.c b/libavformat/http.c
index 8f7e56de54..5eff87f8bb 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -117,7 +117,6 @@ typedef struct HTTPContext {
int reconnect;
int reconnect_at_eof;
int reconnect_streamed;
- int reconnect_delay;
int reconnect_delay_max;
int listen;
char *resource;
@@ -1433,6 +1432,7 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size)
HTTPContext *s = h->priv_data;
int err, new_location, read_ret;
int64_t seek_ret;
+ int reconnect_delay = 0;
if (!s->hd)
return AVERROR_EOF;
@@ -1448,25 +1448,26 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size)
return http_buf_read_compressed(h, buf, size);
#endif /* CONFIG_ZLIB */
read_ret = http_buf_read(h, buf, size);
- if ( (read_ret < 0 && s->reconnect && (!h->is_streamed || s->reconnect_streamed) && s->filesize > 0 && s->off < s->filesize)
- || (read_ret == 0 && s->reconnect_at_eof && (!h->is_streamed || s->reconnect_streamed))) {
+ while ((read_ret < 0 && s->reconnect && (!h->is_streamed || s->reconnect_streamed) && s->filesize > 0 && s->off < s->filesize)
+ || (read_ret == AVERROR_EOF && s->reconnect_at_eof && (!h->is_streamed || s->reconnect_streamed))) {
uint64_t target = h->is_streamed ? 0 : s->off;
- if (s->reconnect_delay > s->reconnect_delay_max)
+ if (reconnect_delay > s->reconnect_delay_max)
return AVERROR(EIO);
av_log(h, AV_LOG_INFO, "Will reconnect at %"PRIu64" error=%s.\n", s->off, av_err2str(read_ret));
- av_usleep(1000U*1000*s->reconnect_delay);
- s->reconnect_delay = 1 + 2*s->reconnect_delay;
+ err = ff_network_sleep_interruptible(1000U*1000*reconnect_delay, &h->interrupt_callback);
+ if (err != AVERROR(ETIMEDOUT))
+ return err;
+ reconnect_delay = 1 + 2*reconnect_delay;
seek_ret = http_seek_internal(h, target, SEEK_SET, 1);
- if (seek_ret != target) {
+ if (seek_ret >= 0 && seek_ret != target) {
av_log(h, AV_LOG_ERROR, "Failed to reconnect at %"PRIu64".\n", target);
return read_ret;
}
read_ret = http_buf_read(h, buf, size);
- } else
- s->reconnect_delay = 0;
+ }
return read_ret;
}