Message ID | 20171230170726.10824-1-nfxjfg@googlemail.com |
---|---|
State | Superseded |
Headers | show |
Am 30.12.2017 um 18:07 schrieb wm4: > It makes no sense to return an error after the first reconnect, and then > somehow resume the next time it's called. > > Also make the wait reasonably interruptible. Since there is no mechanism > for this in the API, polling is the best we can do. (Some effort could > be put into making the wait more accurate, since the av_usleep() will > not wait exactly 1000 microseconds, and the error will add up.) > > (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.) > --- > libavformat/http.c | 22 +++++++++++++--------- > 1 file changed, 13 insertions(+), 9 deletions(-) > > diff --git a/libavformat/http.c b/libavformat/http.c > index a376f1a488..2957648d61 100644 > --- a/libavformat/http.c > +++ b/libavformat/http.c > @@ -1443,25 +1443,29 @@ 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) > + while ( (read_ret < 0 && s->reconnect && (!h->is_streamed || s->reconnect_streamed) && s->filesize > 0 && s->off < s->filesize) nit: could just get rid of the extra whitespace here and it will be perfectly aligned with the next line. > || (read_ret == 0 && s->reconnect_at_eof && (!h->is_streamed || s->reconnect_streamed))) { > + unsigned int wait = 0; > uint64_t target = h->is_streamed ? 0 : s->off; > > if (s->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); > + for (wait = 0; wait < 1000U*s->reconnect_delay; wait++) { > + if (ff_check_interrupt(&h->interrupt_callback)) > + return AVERROR(EIO); > + av_usleep(1000); > + } > s->reconnect_delay = 1 + 2*s->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 AVERROR(EIO); > + } else > + read_ret = http_buf_read(h, buf, size); > + } > + s->reconnect_delay = 0; > > return read_ret; > } > looks reasonable to me, but it's not my code and I don't have any experience with it.
diff --git a/libavformat/http.c b/libavformat/http.c index a376f1a488..2957648d61 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -1443,25 +1443,29 @@ 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) + while ( (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))) { + unsigned int wait = 0; uint64_t target = h->is_streamed ? 0 : s->off; if (s->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); + for (wait = 0; wait < 1000U*s->reconnect_delay; wait++) { + if (ff_check_interrupt(&h->interrupt_callback)) + return AVERROR(EIO); + av_usleep(1000); + } s->reconnect_delay = 1 + 2*s->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 AVERROR(EIO); + } else + read_ret = http_buf_read(h, buf, size); + } + s->reconnect_delay = 0; return read_ret; }