diff --git a/libavformat/avformat.h b/libavformat/avformat.h index b2bac97818..f8dff367ea 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -22,7 +22,7 @@ #define AVFORMAT_AVFORMAT_H #define LIBAVFORMAT_VERSION_MAJOR 52 -#define LIBAVFORMAT_VERSION_MINOR 69 +#define LIBAVFORMAT_VERSION_MINOR 70 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavformat/avio.c b/libavformat/avio.c index 3371b40c4d..240289d686 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -94,7 +94,7 @@ int register_protocol(URLProtocol *protocol) } #endif -int url_open_protocol (URLContext **puc, struct URLProtocol *up, +static int url_alloc_for_protocol (URLContext **puc, struct URLProtocol *up, const char *filename, int flags) { URLContext *uc; @@ -118,17 +118,7 @@ int url_open_protocol (URLContext **puc, struct URLProtocol *up, uc->flags = flags; uc->is_streamed = 0; /* default = not streamed */ uc->max_packet_size = 0; /* default: stream file */ - err = up->url_open(uc, filename, flags); - if (err < 0) { - av_free(uc); - goto fail; - } - //We must be careful here as url_seek() could be slow, for example for http - if( (flags & (URL_WRONLY | URL_RDWR)) - || !strcmp(up->name, "file")) - if(!uc->is_streamed && url_seek(uc, 0, SEEK_SET) < 0) - uc->is_streamed= 1; *puc = uc; return 0; fail: @@ -139,7 +129,38 @@ int url_open_protocol (URLContext **puc, struct URLProtocol *up, return err; } -int url_open(URLContext **puc, const char *filename, int flags) +int url_connect(URLContext* uc) +{ + int err = uc->prot->url_open(uc, uc->filename, uc->flags); + if (err) + return err; + uc->is_connected = 1; + //We must be careful here as url_seek() could be slow, for example for http + if( (uc->flags & (URL_WRONLY | URL_RDWR)) + || !strcmp(uc->prot->name, "file")) + if(!uc->is_streamed && url_seek(uc, 0, SEEK_SET) < 0) + uc->is_streamed= 1; + return 0; +} + +int url_open_protocol (URLContext **puc, struct URLProtocol *up, + const char *filename, int flags) +{ + int ret; + + ret = url_alloc_for_protocol(puc, up, filename, flags); + if (ret) + goto fail; + ret = url_connect(*puc); + if (!ret) + return 0; + fail: + url_close(*puc); + *puc = NULL; + return ret; +} + +int url_alloc(URLContext **puc, const char *filename, int flags) { URLProtocol *up; const char *p; @@ -166,13 +187,27 @@ int url_open(URLContext **puc, const char *filename, int flags) up = first_protocol; while (up != NULL) { if (!strcmp(proto_str, up->name)) - return url_open_protocol (puc, up, filename, flags); + return url_alloc_for_protocol (puc, up, filename, flags); up = up->next; } *puc = NULL; return AVERROR(ENOENT); } +int url_open(URLContext **puc, const char *filename, int flags) +{ + int ret = url_alloc(puc, filename, flags); + if (ret) + return ret; + ret = url_connect(*puc); + if (!ret) + return 0; + fail: + url_close(*puc); + *puc = NULL; + return ret; +} + int url_read(URLContext *h, unsigned char *buf, int size) { int ret; @@ -232,7 +267,7 @@ int url_close(URLContext *h) int ret = 0; if (!h) return 0; /* can happen when url_open fails */ - if (h->prot->url_close) + if (h->is_connected && h->prot->url_close) ret = h->prot->url_close(h); #if CONFIG_NETWORK ff_network_close(); diff --git a/libavformat/avio.h b/libavformat/avio.h index 7aefe1a1c4..752f6e2cba 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -51,6 +51,7 @@ typedef struct URLContext { int max_packet_size; /**< if non zero, the stream is packetized with this max packet size */ void *priv_data; char *filename; /**< specified URL */ + int is_connected; } URLContext; typedef struct URLPollEntry { @@ -79,6 +80,24 @@ typedef int URLInterruptCB(void); int url_open_protocol (URLContext **puc, struct URLProtocol *up, const char *url, int flags); +/** + * Creates an URLContext for accessing to the resource indicated by + * url, but doesn't initiate the connection yet. + * + * @param puc pointer to the location where, in case of success, the + * function puts the pointer to the created URLContext + * @param flags flags which control how the resource indicated by url + * is to be opened + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int url_alloc(URLContext **h, const char *url, int flags); + +/** + * Connect an URLContext that has been allocated by url_alloc + */ +int url_connect(URLContext *h); + /** * Creates an URLContext for accessing to the resource indicated by * url, and opens it.