From ddffc2fdc351d60ca190b016cccff4acff27823f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 5 Nov 2011 10:04:04 +0100 Subject: [PATCH] avio: add support for passing options to protocols. Not used anywhere yet, support for passing options from avio_open() will follow. --- libavformat/applehttp.c | 6 ++-- libavformat/applehttpproto.c | 2 +- libavformat/avio.c | 55 ++++++++++++++++++++++++++++++------ libavformat/aviobuf.c | 2 +- libavformat/concat.c | 3 +- libavformat/crypto.c | 2 +- libavformat/gopher.c | 3 +- libavformat/http.c | 3 +- libavformat/md5proto.c | 3 +- libavformat/mmsh.c | 4 +-- libavformat/mmst.c | 2 +- libavformat/rtmpproto.c | 2 +- libavformat/rtpproto.c | 4 +-- libavformat/rtsp.c | 14 ++++----- libavformat/sapdec.c | 3 +- libavformat/sapenc.c | 5 ++-- libavformat/tls.c | 3 +- libavformat/url.h | 20 +++++++++++-- 18 files changed, 98 insertions(+), 38 deletions(-) diff --git a/libavformat/applehttp.c b/libavformat/applehttp.c index ae251531e8..74d9f781e3 100644 --- a/libavformat/applehttp.c +++ b/libavformat/applehttp.c @@ -324,14 +324,14 @@ static int open_input(struct variant *var) struct segment *seg = var->segments[var->cur_seq_no - var->start_seq_no]; if (seg->key_type == KEY_NONE) { return ffurl_open(&var->input, seg->url, AVIO_FLAG_READ, - &var->parent->interrupt_callback); + &var->parent->interrupt_callback, NULL); } else if (seg->key_type == KEY_AES_128) { char iv[33], key[33], url[MAX_URL_SIZE]; int ret; if (strcmp(seg->key, var->key_url)) { URLContext *uc; if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ, - &var->parent->interrupt_callback) == 0) { + &var->parent->interrupt_callback, NULL) == 0) { if (ffurl_read_complete(uc, var->key, sizeof(var->key)) != sizeof(var->key)) { av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n", @@ -356,7 +356,7 @@ static int open_input(struct variant *var) return ret; av_opt_set(var->input->priv_data, "key", key, 0); av_opt_set(var->input->priv_data, "iv", iv, 0); - if ((ret = ffurl_connect(var->input)) < 0) { + if ((ret = ffurl_connect(var->input, NULL)) < 0) { ffurl_close(var->input); var->input = NULL; return ret; diff --git a/libavformat/applehttpproto.c b/libavformat/applehttpproto.c index e8d1b495ed..2123423452 100644 --- a/libavformat/applehttpproto.c +++ b/libavformat/applehttpproto.c @@ -275,7 +275,7 @@ retry: url = s->segments[s->cur_seq_no - s->start_seq_no]->url, av_log(h, AV_LOG_DEBUG, "opening %s\n", url); ret = ffurl_open(&s->seg_hd, url, AVIO_FLAG_READ, - &h->interrupt_callback); + &h->interrupt_callback, NULL); if (ret < 0) { if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; diff --git a/libavformat/avio.c b/libavformat/avio.c index 06972cdbdd..330d52cfec 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -22,6 +22,7 @@ #include #include "libavutil/avstring.h" +#include "libavutil/dict.h" #include "libavutil/opt.h" #include "os_support.h" #include "avformat.h" @@ -45,12 +46,40 @@ static const char *urlcontext_to_name(void *ptr) if(h->prot) return h->prot->name; else return "NULL"; } + +static void *urlcontext_child_next(void *obj, void *prev) +{ + URLContext *h = obj; + if (!prev && h->priv_data && h->prot->priv_data_class) + return h->priv_data; + return NULL; +} + +static const AVClass *urlcontext_child_class_next(const AVClass *prev) +{ + URLProtocol *p = NULL; + + /* find the protocol that corresponds to prev */ + while (prev && (p = ffurl_protocol_next(p))) + if (p->priv_data_class == prev) + break; + + /* find next protocol with priv options */ + while (p = ffurl_protocol_next(p)) + if (p->priv_data_class) + return p->priv_data_class; + return NULL; + +} + static const AVOption options[] = {{NULL}}; static const AVClass urlcontext_class = { .class_name = "URLContext", .item_name = urlcontext_to_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .child_next = urlcontext_child_next, + .child_class_next = urlcontext_child_class_next, }; /*@}*/ @@ -133,9 +162,13 @@ static int url_alloc_for_protocol (URLContext **puc, struct URLProtocol *up, return err; } -int ffurl_connect(URLContext* uc) +int ffurl_connect(URLContext* uc, AVDictionary **options) { - int err = uc->prot->url_open(uc, uc->filename, uc->flags); + int err = +#if !FF_API_OLD_AVIO + uc->prot->url_open2 ? uc->prot->url_open2(uc, uc->filename, uc->flags, options) : +#endif + uc->prot->url_open(uc, uc->filename, uc->flags); if (err) return err; uc->is_connected = 1; @@ -156,7 +189,7 @@ int url_open_protocol (URLContext **puc, struct URLProtocol *up, ret = url_alloc_for_protocol(puc, up, filename, flags, NULL); if (ret) goto fail; - ret = ffurl_connect(*puc); + ret = ffurl_connect(*puc, NULL); if (!ret) return 0; fail: @@ -170,11 +203,11 @@ int url_alloc(URLContext **puc, const char *filename, int flags) } int url_connect(URLContext* uc) { - return ffurl_connect(uc); + return ffurl_connect(uc, NULL); } int url_open(URLContext **puc, const char *filename, int flags) { - return ffurl_open(puc, filename, flags, NULL); + return ffurl_open(puc, filename, flags, NULL, NULL); } int url_read(URLContext *h, unsigned char *buf, int size) { @@ -255,14 +288,18 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags, } int ffurl_open(URLContext **puc, const char *filename, int flags, - const AVIOInterruptCB *int_cb) + const AVIOInterruptCB *int_cb, AVDictionary **options) { int ret = ffurl_alloc(puc, filename, flags, int_cb); if (ret) return ret; - ret = ffurl_connect(*puc); + if (options && (*puc)->prot->priv_data_class && + (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0) + goto fail; + ret = ffurl_connect(*puc, options); if (!ret) return 0; +fail: ffurl_close(*puc); *puc = NULL; return ret; @@ -356,7 +393,7 @@ int ffurl_close(URLContext *h) int url_exist(const char *filename) { URLContext *h; - if (ffurl_open(&h, filename, AVIO_FLAG_READ, NULL) < 0) + if (ffurl_open(&h, filename, AVIO_FLAG_READ, NULL, NULL) < 0) return 0; ffurl_close(h); return 1; @@ -373,7 +410,7 @@ int avio_check(const char *url, int flags) if (h->prot->url_check) { ret = h->prot->url_check(h, flags); } else { - ret = ffurl_connect(h); + ret = ffurl_connect(h, NULL); if (ret >= 0) ret = flags; } diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index b2bd6f8dc8..246903baac 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -932,7 +932,7 @@ int avio_open(AVIOContext **s, const char *filename, int flags) URLContext *h; int err; - err = ffurl_open(&h, filename, flags, NULL); + err = ffurl_open(&h, filename, flags, NULL, NULL); if (err < 0) return err; err = ffio_fdopen(s, h); diff --git a/libavformat/concat.c b/libavformat/concat.c index 47f97ef1e7..1501cbcba4 100644 --- a/libavformat/concat.c +++ b/libavformat/concat.c @@ -101,7 +101,8 @@ static av_cold int concat_open(URLContext *h, const char *uri, int flags) uri += len + strspn(uri+len, AV_CAT_SEPARATOR); /* creating URLContext */ - if ((err = ffurl_open(&uc, node_uri, flags, &h->interrupt_callback)) < 0) + if ((err = ffurl_open(&uc, node_uri, flags, + &h->interrupt_callback, NULL)) < 0) break; /* creating size */ diff --git a/libavformat/crypto.c b/libavformat/crypto.c index 5171b1256b..7095360c85 100644 --- a/libavformat/crypto.c +++ b/libavformat/crypto.c @@ -83,7 +83,7 @@ static int crypto_open(URLContext *h, const char *uri, int flags) goto err; } if ((ret = ffurl_open(&c->hd, nested_url, AVIO_FLAG_READ, - &h->interrupt_callback)) < 0) { + &h->interrupt_callback, NULL)) < 0) { av_log(h, AV_LOG_ERROR, "Unable to open input\n"); goto err; } diff --git a/libavformat/gopher.c b/libavformat/gopher.c index afb0aff98d..5f8c320f10 100644 --- a/libavformat/gopher.c +++ b/libavformat/gopher.c @@ -100,7 +100,8 @@ static int gopher_open(URLContext *h, const char *uri, int flags) ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL); s->hd = NULL; - err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback); + err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE, + &h->interrupt_callback, NULL); if (err < 0) goto fail; diff --git a/libavformat/http.c b/libavformat/http.c index dbf384efff..9cc55bd3fc 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -133,7 +133,8 @@ static int http_open_cnx(URLContext *h) port = 80; ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL); - err = ffurl_open(&hd, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback); + err = ffurl_open(&hd, buf, AVIO_FLAG_READ_WRITE, + &h->interrupt_callback, NULL); if (err < 0) goto fail; diff --git a/libavformat/md5proto.c b/libavformat/md5proto.c index f136e805f9..8e61e5be4c 100644 --- a/libavformat/md5proto.c +++ b/libavformat/md5proto.c @@ -65,7 +65,8 @@ static int md5_close(URLContext *h) av_strstart(filename, "md5:", &filename); if (*filename) { - err = ffurl_open(&out, filename, AVIO_FLAG_WRITE, &h->interrupt_callback); + err = ffurl_open(&out, filename, AVIO_FLAG_WRITE, + &h->interrupt_callback, NULL); if (err) return err; err = ffurl_write(out, buf, i*2+1); diff --git a/libavformat/mmsh.c b/libavformat/mmsh.c index 6ea1592d42..50e160f7ba 100644 --- a/libavformat/mmsh.c +++ b/libavformat/mmsh.c @@ -249,7 +249,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) host, port, mmsh->request_seq++); av_opt_set(mms->mms_hd->priv_data, "headers", headers, 0); - err = ffurl_connect(mms->mms_hd); + err = ffurl_connect(mms->mms_hd, NULL); if (err) { goto fail; } @@ -296,7 +296,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) av_dlog(NULL, "out_buffer is %s", headers); av_opt_set(mms->mms_hd->priv_data, "headers", headers, 0); - err = ffurl_connect(mms->mms_hd); + err = ffurl_connect(mms->mms_hd, NULL); if (err) { goto fail; } diff --git a/libavformat/mmst.c b/libavformat/mmst.c index e69d330e1b..7bb4358060 100644 --- a/libavformat/mmst.c +++ b/libavformat/mmst.c @@ -524,7 +524,7 @@ static int mms_open(URLContext *h, const char *uri, int flags) // establish tcp connection. ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL); err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE, - &h->interrupt_callback); + &h->interrupt_callback, NULL); if (err) goto fail; diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 98e6180c92..9d734072ab 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -818,7 +818,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL); if (ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback) < 0) { + &s->interrupt_callback, NULL) < 0) { av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf); goto fail; } diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index ca5007667a..9707bdcec7 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -188,7 +188,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) build_udp_url(buf, sizeof(buf), hostname, rtp_port, local_rtp_port, ttl, max_packet_size, connect); - if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback) < 0) + if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) goto fail; if (local_rtp_port>=0 && local_rtcp_port<0) local_rtcp_port = ff_udp_get_local_port(s->rtp_hd) + 1; @@ -196,7 +196,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) build_udp_url(buf, sizeof(buf), hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size, connect); - if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback) < 0) + if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) goto fail; /* just to ease handle access. XXX: need to suppress direct handle diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index d07cd406ed..d0e9bbf6af 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1160,7 +1160,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, /* we will use two ports per rtp stream (rtp and rtcp) */ j += 2; if (ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback) == 0) + &s->interrupt_callback, NULL) == 0) goto rtp_opened; } } @@ -1308,7 +1308,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, ff_url_join(url, sizeof(url), "rtp", NULL, namebuf, port, "?ttl=%d", ttl); if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback) < 0) { + &s->interrupt_callback, NULL) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1468,7 +1468,7 @@ redirect: av_opt_set(rt->rtsp_hd->priv_data, "headers", headers, 0); /* complete the connection */ - if (ffurl_connect(rt->rtsp_hd)) { + if (ffurl_connect(rt->rtsp_hd, NULL)) { err = AVERROR(EIO); goto fail; } @@ -1511,7 +1511,7 @@ redirect: ff_http_init_auth_state(rt->rtsp_hd_out, rt->rtsp_hd); /* complete the connection */ - if (ffurl_connect(rt->rtsp_hd_out)) { + if (ffurl_connect(rt->rtsp_hd_out, NULL)) { err = AVERROR(EIO); goto fail; } @@ -1519,7 +1519,7 @@ redirect: /* open the tcp connection */ ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL); if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback) < 0) { + &s->interrupt_callback, NULL) < 0) { err = AVERROR(EIO); goto fail; } @@ -1868,7 +1868,7 @@ static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap) rtsp_st->sdp_ttl, rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0); if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback) < 0) { + &s->interrupt_callback, NULL) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1933,7 +1933,7 @@ static int rtp_read_header(AVFormatContext *s, return AVERROR(EIO); ret = ffurl_open(&in, s->filename, AVIO_FLAG_READ, - &s->interrupt_callback); + &s->interrupt_callback, NULL); if (ret) goto fail; diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c index 7b950cd617..6ac7bfd484 100644 --- a/libavformat/sapdec.c +++ b/libavformat/sapdec.c @@ -85,7 +85,8 @@ static int sap_read_header(AVFormatContext *s, ff_url_join(url, sizeof(url), "udp", NULL, host, port, "?localport=%d", port); - ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_READ, &s->interrupt_callback); + ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_READ, + &s->interrupt_callback, NULL); if (ret) goto fail; diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c index ec017909eb..d8ec465afa 100644 --- a/libavformat/sapenc.c +++ b/libavformat/sapenc.c @@ -146,7 +146,7 @@ static int sap_write_header(AVFormatContext *s) "?ttl=%d", ttl); if (!same_port) base_port += 2; - ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback); + ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); if (ret) { ret = AVERROR(EIO); goto fail; @@ -158,7 +158,8 @@ static int sap_write_header(AVFormatContext *s) ff_url_join(url, sizeof(url), "udp", NULL, announce_addr, port, "?ttl=%d&connect=1", ttl); - ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback); + ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_WRITE, + &s->interrupt_callback, NULL); if (ret) { ret = AVERROR(EIO); goto fail; diff --git a/libavformat/tls.c b/libavformat/tls.c index b2ec147adb..33ee782fa8 100644 --- a/libavformat/tls.c +++ b/libavformat/tls.c @@ -123,7 +123,8 @@ static int tls_open(URLContext *h, const char *uri, int flags) freeaddrinfo(ai); } - ret = ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback); + ret = ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE, + &h->interrupt_callback, NULL); if (ret) goto fail; c->fd = ffurl_get_file_handle(c->tcp); diff --git a/libavformat/url.h b/libavformat/url.h index 902539aa64..1f04c8d530 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -28,6 +28,8 @@ #include "avio.h" #include "libavformat/version.h" +#include "libavutil/dict.h" + #if !FF_API_OLD_AVIO #define URL_PROTOCOL_FLAG_NESTED_SCHEME 1 /*< The protocol name can be the first part of a nested protocol scheme */ @@ -48,6 +50,12 @@ typedef struct URLContext { typedef struct URLProtocol { const char *name; int (*url_open)( URLContext *h, const char *url, int flags); + /** + * This callback is to be used by protocols which open further nested + * protocols. options are then to be passed to ffurl_open()/ffurl_connect() + * for those nested protocols. + */ + int (*url_open2)(URLContext *h, const char *url, int flags, AVDictionary **options); int (*url_read)( URLContext *h, unsigned char *buf, int size); int (*url_write)(URLContext *h, const unsigned char *buf, int size); int64_t (*url_seek)( URLContext *h, int64_t pos, int whence); @@ -82,8 +90,13 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags, /** * Connect an URLContext that has been allocated by ffurl_alloc + * + * @param options A dictionary filled with options for nested protocols, + * i.e. it will be passed to url_open2() for protocols implementing it. + * This parameter will be destroyed and replaced with a dict containing options + * that were not found. May be NULL. */ -int ffurl_connect(URLContext *uc); +int ffurl_connect(URLContext *uc, AVDictionary **options); /** * Create an URLContext for accessing to the resource indicated by @@ -95,11 +108,14 @@ int ffurl_connect(URLContext *uc); * is to be opened * @param int_cb interrupt callback to use for the URLContext, may be * NULL + * @param options A dictionary filled with protocol-private options. On return + * this parameter will be destroyed and replaced with a dict containing options + * that were not found. May be NULL. * @return 0 in case of success, a negative value corresponding to an * AVERROR code in case of failure */ int ffurl_open(URLContext **puc, const char *filename, int flags, - const AVIOInterruptCB *int_cb); + const AVIOInterruptCB *int_cb, AVDictionary **options); /** * Read up to size bytes from the resource accessed by h, and store