avformat/http: support auto reconnect

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Zhang Rui 2015-03-12 11:39:55 +08:00 committed by Michael Niedermayer
parent 3727cd5416
commit 3f375950f3
1 changed files with 27 additions and 5 deletions

View File

@ -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 },
{ 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 (read_ret < 0 && s->reconnect && !h->is_streamed && s->filesize > 0 && s->off < s->filesize) {
av_log(h, AV_LOG_INFO, "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_ERROR, "Failed to reconnect at %"PRId64".\n", s->off);
return read_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;