On Fri, 6 Mar 2015 18:19:14 +0800 Zhang Rui <bbcal...@gmail.com> wrote:
> --- > libavformat/http.c | 32 +++++++++++++++++++++++++++----- > 1 file changed, 27 insertions(+), 5 deletions(-) > > diff --git a/libavformat/http.c b/libavformat/http.c > index 55dcb6e..9d44f3b 100644 > --- a/libavformat/http.c > +++ b/libavformat/http.c > @@ -93,6 +93,7 @@ typedef struct HTTPContext { > AVDictionary *chained_options; > int send_expect_100; > char *method; > + int reconnect; > } HTTPContext; > > #define OFFSET(x) offsetof(HTTPContext, x) > @@ -123,6 +124,7 @@ static const AVOption options[] = { > { "offset", "initial byte offset", OFFSET(off), AV_OPT_TYPE_INT64, { > .i64 = 0 }, 0, INT64_MAX, D }, > { "end_offset", "try to limit the request to bytes preceding this > offset", OFFSET(end_off), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, D }, > { "method", "Override the HTTP method", OFFSET(method), > AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, > + { "reconnect", "auto reconnect after disconnect before EOF", > OFFSET(reconnect), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D }, The default of this setting is probably worth a discussion. > { NULL } > }; > > @@ -908,10 +910,12 @@ static int http_buf_read_compressed(URLContext *h, > uint8_t *buf, int size) > } > #endif /* CONFIG_ZLIB */ > > +static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, > int force_reconnect); > + > static int http_read_stream(URLContext *h, uint8_t *buf, int size) > { > HTTPContext *s = h->priv_data; > - int err, new_location; > + int err, new_location, read_ret, seek_ret; > > if (!s->hd) > return AVERROR_EOF; > @@ -945,7 +949,19 @@ static int http_read_stream(URLContext *h, uint8_t *buf, > int size) > if (s->compressed) > return http_buf_read_compressed(h, buf, size); > #endif /* CONFIG_ZLIB */ > - return http_buf_read(h, buf, size); > + read_ret = http_buf_read(h, buf, size); > + if (s->reconnect && s->filesize > 0 && s->off < s->filesize && read_ret > < 0) { Maybe it should check is_streamed (seekability) too? > + av_log(h, AV_LOG_WARNING, "Will reconnect at %"PRId64".\n", s->off); > + seek_ret = http_seek_internal(h, s->off, SEEK_SET, 1); > + if (seek_ret != s->off) { > + av_log(h, AV_LOG_WARNING, "Failed to reconnect at %"PRId64".\n", > s->off); > + return read_ret; Not sure if it should return read_ret or seek_ret... > + } > + > + read_ret = http_buf_read(h, buf, size); > + } > + > + return read_ret; > } > > // Like http_read_stream(), but no short reads. > @@ -1104,7 +1120,7 @@ static int http_close(URLContext *h) > return ret; > } > > -static int64_t http_seek(URLContext *h, int64_t off, int whence) > +static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, > int force_reconnect) > { > HTTPContext *s = h->priv_data; > URLContext *old_hd = s->hd; > @@ -1115,8 +1131,9 @@ static int64_t http_seek(URLContext *h, int64_t off, > int whence) > > if (whence == AVSEEK_SIZE) > return s->filesize; > - else if ((whence == SEEK_CUR && off == 0) || > - (whence == SEEK_SET && off == s->off)) > + else if (!force_reconnect && > + ((whence == SEEK_CUR && off == 0) || > + (whence == SEEK_SET && off == s->off))) > return s->off; > else if ((s->filesize == -1 && whence == SEEK_END) || h->is_streamed) > return AVERROR(ENOSYS); > @@ -1151,6 +1168,11 @@ static int64_t http_seek(URLContext *h, int64_t off, > int whence) > return off; > } > > +static int64_t http_seek(URLContext *h, int64_t off, int whence) > +{ > + return http_seek_internal(h, off, whence, 0); > +} > + > static int http_get_file_handle(URLContext *h) > { > HTTPContext *s = h->priv_data; In generals looks sane to me. _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel