From 8c0ceafb0f25da077ff23e394667119f031574fd Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 19 Feb 2016 18:02:45 +0100 Subject: [PATCH] urlprotocol: receive a list of protocols from the caller This way, the decisions about which protocols are available for use in any given situations can be delegated to the caller. --- libavformat/avio.c | 42 ++++++++++++++++++++------------ libavformat/aviobuf.c | 20 +++++++++++++-- libavformat/concat.c | 2 +- libavformat/crypto.c | 2 +- libavformat/gopher.c | 2 +- libavformat/hlsproto.c | 2 +- libavformat/http.c | 4 +-- libavformat/icecast.c | 3 ++- libavformat/md5proto.c | 3 ++- libavformat/mmsh.c | 4 +-- libavformat/mmst.c | 2 +- libavformat/rtmpcrypt.c | 2 +- libavformat/rtmphttp.c | 2 +- libavformat/rtmpproto.c | 4 +-- libavformat/rtpproto.c | 6 +++-- libavformat/rtsp.c | 33 +++++++++++++++++++------ libavformat/rtsp.h | 2 ++ libavformat/rtspdec.c | 10 ++++++-- libavformat/sapdec.c | 11 ++++++++- libavformat/sapenc.c | 15 ++++++++++-- libavformat/smoothstreamingenc.c | 24 +++++++++++++++--- libavformat/srtpproto.c | 3 ++- libavformat/tls.c | 2 +- libavformat/url.h | 16 ++++++++++-- 24 files changed, 162 insertions(+), 54 deletions(-) diff --git a/libavformat/avio.c b/libavformat/avio.c index a9a399af93..668e5eab87 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -62,7 +62,8 @@ const AVClass ffurl_context_class = { static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up, const char *filename, int flags, - const AVIOInterruptCB *int_cb) + const AVIOInterruptCB *int_cb, + const URLProtocol **protocols) { URLContext *uc; int err; @@ -83,6 +84,7 @@ static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up, uc->flags = flags; uc->is_streamed = 0; /* default = not streamed */ uc->max_packet_size = 0; /* default: stream file */ + uc->protocols = protocols; if (up->priv_data_size) { uc->priv_data = av_mallocz(up->priv_data_size); if (!uc->priv_data) { @@ -136,9 +138,9 @@ int ffurl_connect(URLContext *uc, AVDictionary **options) "0123456789+-." int ffurl_alloc(URLContext **puc, const char *filename, int flags, - const AVIOInterruptCB *int_cb) + const AVIOInterruptCB *int_cb, + const URLProtocol **protocols) { - const URLProtocol **protocols; char proto_str[128], proto_nested[128], *ptr; size_t proto_len = strspn(filename, URL_SCHEME_CHARS); int i; @@ -153,27 +155,25 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags, if ((ptr = strchr(proto_nested, '+'))) *ptr = '\0'; - protocols = ffurl_get_protocols(NULL, NULL); for (i = 0; protocols[i]; i++) { const URLProtocol *up = protocols[i]; - if (!strcmp(proto_str, up->name)) { - av_freep(&protocols); - return url_alloc_for_protocol(puc, up, filename, flags, int_cb); - } + if (!strcmp(proto_str, up->name)) + return url_alloc_for_protocol(puc, up, filename, flags, int_cb, + protocols); if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME && - !strcmp(proto_nested, up->name)) { - av_freep(&protocols); - return url_alloc_for_protocol(puc, up, filename, flags, int_cb); - } + !strcmp(proto_nested, up->name)) + return url_alloc_for_protocol(puc, up, filename, flags, int_cb, + protocols); } *puc = NULL; return AVERROR_PROTOCOL_NOT_FOUND; } int ffurl_open(URLContext **puc, const char *filename, int flags, - const AVIOInterruptCB *int_cb, AVDictionary **options) + const AVIOInterruptCB *int_cb, AVDictionary **options, + const URLProtocol **protocols) { - int ret = ffurl_alloc(puc, filename, flags, int_cb); + int ret = ffurl_alloc(puc, filename, flags, int_cb, protocols); if (ret) return ret; if (options && (*puc)->prot->priv_data_class && @@ -281,10 +281,19 @@ int ffurl_close(URLContext *h) int avio_check(const char *url, int flags) { + const URLProtocol **protocols; URLContext *h; - int ret = ffurl_alloc(&h, url, flags, NULL); - if (ret) + int ret; + + protocols = ffurl_get_protocols(NULL, NULL); + if (!protocols) + return AVERROR(ENOMEM); + + ret = ffurl_alloc(&h, url, flags, NULL, protocols); + if (ret) { + av_freep(&protocols); return ret; + } if (h->prot->url_check) { ret = h->prot->url_check(h, flags); @@ -295,6 +304,7 @@ int avio_check(const char *url, int flags) } ffurl_close(h); + av_freep(&protocols); return ret; } diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 18c3945c30..20bef66029 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -42,6 +42,7 @@ typedef struct AVIOInternal { URLContext *h; + const URLProtocol **protocols; } AVIOInternal; static void *ff_avio_child_next(void *obj, void *prev) @@ -846,17 +847,31 @@ int avio_open(AVIOContext **s, const char *filename, int flags) int avio_open2(AVIOContext **s, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options) { + AVIOInternal *internal; + const URLProtocol **protocols; URLContext *h; int err; - err = ffurl_open(&h, filename, flags, int_cb, options); - if (err < 0) + protocols = ffurl_get_protocols(NULL, NULL); + if (!protocols) + return AVERROR(ENOMEM); + + err = ffurl_open(&h, filename, flags, int_cb, options, protocols); + if (err < 0) { + av_freep(&protocols); return err; + } + err = ffio_fdopen(s, h); if (err < 0) { ffurl_close(h); + av_freep(&protocols); return err; } + + internal = (*s)->opaque; + internal->protocols = protocols; + return 0; } @@ -872,6 +887,7 @@ int avio_close(AVIOContext *s) internal = s->opaque; h = internal->h; + av_freep(&internal->protocols); av_freep(&s->opaque); av_freep(&s->buffer); av_free(s); diff --git a/libavformat/concat.c b/libavformat/concat.c index de48f7b55f..ecdf5dfeb7 100644 --- a/libavformat/concat.c +++ b/libavformat/concat.c @@ -95,7 +95,7 @@ static av_cold int concat_open(URLContext *h, const char *uri, int flags) /* creating URLContext */ if ((err = ffurl_open(&uc, node_uri, flags, - &h->interrupt_callback, NULL)) < 0) + &h->interrupt_callback, NULL, h->protocols)) < 0) break; /* creating size */ diff --git a/libavformat/crypto.c b/libavformat/crypto.c index e9dd474448..a364dc0af5 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, NULL)) < 0) { + &h->interrupt_callback, NULL, h->protocols)) < 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 fc4fbe51e4..afa2b7d68b 100644 --- a/libavformat/gopher.c +++ b/libavformat/gopher.c @@ -94,7 +94,7 @@ static int gopher_open(URLContext *h, const char *uri, int flags) s->hd = NULL; err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE, - &h->interrupt_callback, NULL); + &h->interrupt_callback, NULL, h->protocols); if (err < 0) goto fail; diff --git a/libavformat/hlsproto.c b/libavformat/hlsproto.c index 9f46c4885d..b01cef0008 100644 --- a/libavformat/hlsproto.c +++ b/libavformat/hlsproto.c @@ -304,7 +304,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, NULL); + &h->interrupt_callback, NULL, h->protocols); if (ret < 0) { if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; diff --git a/libavformat/http.c b/libavformat/http.c index 6886e151a1..48303908b5 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -181,7 +181,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) if (!s->hd) { err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE, - &h->interrupt_callback, options); + &h->interrupt_callback, options, h->protocols); if (err < 0) return err; } @@ -1079,7 +1079,7 @@ static int http_proxy_open(URLContext *h, const char *uri, int flags) NULL); redo: ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE, - &h->interrupt_callback, NULL); + &h->interrupt_callback, NULL, h->protocols); if (ret < 0) return ret; diff --git a/libavformat/icecast.c b/libavformat/icecast.c index 22adbed562..78238378b7 100644 --- a/libavformat/icecast.c +++ b/libavformat/icecast.c @@ -176,7 +176,8 @@ static int icecast_open(URLContext *h, const char *uri, int flags) // Build new URI for passing to http protocol ff_url_join(h_url, sizeof(h_url), "http", auth, host, port, "%s", path); // Finally open http proto handler - ret = ffurl_open(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL, &opt_dict); + ret = ffurl_open(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL, &opt_dict, + h->protocols); cleanup: // Free variables diff --git a/libavformat/md5proto.c b/libavformat/md5proto.c index 42b64b2e4b..07c085a561 100644 --- a/libavformat/md5proto.c +++ b/libavformat/md5proto.c @@ -70,7 +70,8 @@ static int md5_close(URLContext *h) if (*filename) { err = ffurl_open(&out, filename, AVIO_FLAG_WRITE, - &h->interrupt_callback, NULL); + &h->interrupt_callback, NULL, + h->protocols); if (err) return err; err = ffurl_write(out, buf, i*2+1); diff --git a/libavformat/mmsh.c b/libavformat/mmsh.c index bdbf67820a..4c1ed05b24 100644 --- a/libavformat/mmsh.c +++ b/libavformat/mmsh.c @@ -230,7 +230,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, "%s", path); if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ, - &h->interrupt_callback) < 0) { + &h->interrupt_callback, h->protocols) < 0) { return AVERROR(EIO); } @@ -259,7 +259,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) ffurl_close(mms->mms_hd); memset(headers, 0, sizeof(headers)); if ((err = ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ, - &h->interrupt_callback)) < 0) { + &h->interrupt_callback, h->protocols)) < 0) { goto fail; } stream_selection = av_mallocz(mms->stream_num * 19 + 1); diff --git a/libavformat/mmst.c b/libavformat/mmst.c index 7013389870..aeddf0fd1d 100644 --- a/libavformat/mmst.c +++ b/libavformat/mmst.c @@ -520,7 +520,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, NULL); + &h->interrupt_callback, NULL, h->protocols); if (err) goto fail; diff --git a/libavformat/rtmpcrypt.c b/libavformat/rtmpcrypt.c index c35ebe9a62..75fc1283c5 100644 --- a/libavformat/rtmpcrypt.c +++ b/libavformat/rtmpcrypt.c @@ -265,7 +265,7 @@ static int rtmpe_open(URLContext *h, const char *uri, int flags) /* open the tcp or ffrtmphttp connection */ if ((ret = ffurl_open(&rt->stream, url, AVIO_FLAG_READ_WRITE, - &h->interrupt_callback, NULL)) < 0) { + &h->interrupt_callback, NULL, h->protocols)) < 0) { rtmpe_close(h); return ret; } diff --git a/libavformat/rtmphttp.c b/libavformat/rtmphttp.c index 2577df95fd..4806872493 100644 --- a/libavformat/rtmphttp.c +++ b/libavformat/rtmphttp.c @@ -208,7 +208,7 @@ static int rtmp_http_open(URLContext *h, const char *uri, int flags) } /* alloc the http context */ - if ((ret = ffurl_alloc(&rt->stream, url, AVIO_FLAG_READ_WRITE, NULL)) < 0) + if ((ret = ffurl_alloc(&rt->stream, url, AVIO_FLAG_READ_WRITE, NULL, h->protocols)) < 0) goto fail; /* set options */ diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index f745c37606..9ed3d0f436 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -1119,7 +1119,7 @@ static int rtmp_calc_swfhash(URLContext *s) /* Get the SWF player file. */ if ((ret = ffurl_open(&stream, rt->swfverify, AVIO_FLAG_READ, - &s->interrupt_callback, NULL)) < 0) { + &s->interrupt_callback, NULL, s->protocols)) < 0) { av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify); goto fail; } @@ -2641,7 +2641,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) reconnect: if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, &opts)) < 0) { + &s->interrupt_callback, &opts, s->protocols)) < 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 5f31d97a38..50b8d249ce 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -368,14 +368,16 @@ static int rtp_open(URLContext *h, const char *uri, int flags) build_udp_url(s, buf, sizeof(buf), hostname, rtp_port, s->local_rtpport, sources, block); - if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) + if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL, + h->protocols) < 0) goto fail; if (s->local_rtpport >= 0 && s->local_rtcpport < 0) s->local_rtcpport = ff_udp_get_local_port(s->rtp_hd) + 1; build_udp_url(s, buf, sizeof(buf), hostname, s->rtcp_port, s->local_rtcpport, sources, block); - if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) + if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL, + h->protocols) < 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 4beb275158..1a545c78d6 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -777,6 +777,7 @@ void ff_rtsp_close_streams(AVFormatContext *s) } if (CONFIG_RTPDEC && rt->ts) ff_mpegts_parse_close(rt->ts); + av_freep(&rt->protocols); av_free(rt->p); av_free(rt->recvbuf); } @@ -1465,7 +1466,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; err = ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, &opts); + &s->interrupt_callback, &opts, rt->protocols); av_dict_free(&opts); @@ -1609,7 +1610,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, ff_url_join(url, sizeof(url), "rtp", NULL, namebuf, port, "%s", optbuf); if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL) < 0) { + &s->interrupt_callback, NULL, rt->protocols) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1666,6 +1667,12 @@ int ff_rtsp_connect(AVFormatContext *s) if (!ff_network_init()) return AVERROR(EIO); + if (!rt->protocols) { + rt->protocols = ffurl_get_protocols(NULL, NULL); + if (!rt->protocols) + return AVERROR(ENOMEM); + } + if (s->max_delay < 0) /* Not set by the caller */ s->max_delay = s->iformat ? DEFAULT_REORDERING_DELAY : 0; @@ -1729,7 +1736,7 @@ redirect: /* GET requests */ if (ffurl_alloc(&rt->rtsp_hd, httpname, AVIO_FLAG_READ, - &s->interrupt_callback) < 0) { + &s->interrupt_callback, rt->protocols) < 0) { err = AVERROR(EIO); goto fail; } @@ -1751,7 +1758,7 @@ redirect: /* POST requests */ if (ffurl_alloc(&rt->rtsp_hd_out, httpname, AVIO_FLAG_WRITE, - &s->interrupt_callback) < 0 ) { + &s->interrupt_callback, rt->protocols) < 0 ) { err = AVERROR(EIO); goto fail; } @@ -1796,7 +1803,7 @@ redirect: ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL, host, port, NULL); if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL) < 0) { + &s->interrupt_callback, NULL, rt->protocols) < 0) { err = AVERROR(EIO); goto fail; } @@ -2244,6 +2251,12 @@ static int sdp_read_header(AVFormatContext *s) if (!ff_network_init()) return AVERROR(EIO); + if (!rt->protocols) { + rt->protocols = ffurl_get_protocols(NULL, NULL); + if (!rt->protocols) + return AVERROR(ENOMEM); + } + if (s->max_delay < 0) /* Not set by the caller */ s->max_delay = DEFAULT_REORDERING_DELAY; if (rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO) @@ -2296,7 +2309,7 @@ static int sdp_read_header(AVFormatContext *s) rtsp_st->nb_exclude_source_addrs, rtsp_st->exclude_source_addrs); err = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, &opts); + &s->interrupt_callback, &opts, rt->protocols); av_dict_free(&opts); @@ -2365,8 +2378,14 @@ static int rtp_read_header(AVFormatContext *s) if (!ff_network_init()) return AVERROR(EIO); + if (!rt->protocols) { + rt->protocols = ffurl_get_protocols(NULL, NULL); + if (!rt->protocols) + return AVERROR(ENOMEM); + } + ret = ffurl_open(&in, s->filename, AVIO_FLAG_READ, - &s->interrupt_callback, NULL); + &s->interrupt_callback, NULL, rt->protocols); if (ret) goto fail; diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index b9357c1b6f..0226dac0f1 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -398,6 +398,8 @@ typedef struct RTSPState { char default_lang[4]; int buffer_size; + + const URLProtocol **protocols; } RTSPState; #define RTSP_FLAG_FILTER_SRC 0x1 /**< Filter incoming UDP packets - diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 8ccf147699..c6f4d521e4 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -295,7 +295,7 @@ static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl) ff_url_join(url, sizeof(url), "rtp", NULL, host, localport, NULL); av_log(s, AV_LOG_TRACE, "Opening: %s", url); ret = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, &opts); + &s->interrupt_callback, &opts, rt->protocols); av_dict_free(&opts); if (ret) localport += 2; @@ -639,6 +639,12 @@ static int rtsp_listen(AVFormatContext *s) int ret; enum RTSPMethod methodcode; + if (!rt->protocols) { + rt->protocols = ffurl_get_protocols(NULL, NULL); + if (!rt->protocols) + return AVERROR(ENOMEM); + } + /* extract hostname and port */ av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host), &port, path, sizeof(path), s->filename); @@ -660,7 +666,7 @@ static int rtsp_listen(AVFormatContext *s) "?listen&listen_timeout=%d", rt->initial_timeout * 1000); if (ret = ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL)) { + &s->interrupt_callback, NULL, rt->protocols)) { av_log(s, AV_LOG_ERROR, "Unable to open RTSP for listening\n"); return ret; } diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c index f09222df3c..9fafd6bffe 100644 --- a/libavformat/sapdec.c +++ b/libavformat/sapdec.c @@ -39,6 +39,8 @@ struct SAPState { uint16_t hash; char *sdp; int eof; + + const URLProtocol **protocols; }; static int sap_probe(AVProbeData *p) @@ -55,6 +57,7 @@ static int sap_read_close(AVFormatContext *s) avformat_close_input(&sap->sdp_ctx); if (sap->ann_fd) ffurl_close(sap->ann_fd); + av_freep(&sap->protocols); av_freep(&sap->sdp); ff_network_close(); return 0; @@ -82,10 +85,16 @@ static int sap_read_header(AVFormatContext *s) av_strlcpy(host, "224.2.127.254", sizeof(host)); } + sap->protocols = ffurl_get_protocols(NULL, NULL); + if (!sap->protocols) { + ret = AVERROR(ENOMEM); + goto fail; + } + 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, NULL); + &s->interrupt_callback, NULL, sap->protocols); if (ret) goto fail; diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c index 89f7f99ecc..54eb0bec38 100644 --- a/libavformat/sapenc.c +++ b/libavformat/sapenc.c @@ -37,6 +37,8 @@ struct SAPState { int ann_size; URLContext *ann_fd; int64_t last_time; + + const URLProtocol **protocols; }; static int sap_write_close(AVFormatContext *s) @@ -59,6 +61,8 @@ static int sap_write_close(AVFormatContext *s) ffurl_write(sap->ann_fd, sap->ann, sap->ann_size); } + av_freep(&sap->protocols); + av_freep(&sap->ann); if (sap->ann_fd) ffurl_close(sap->ann_fd); @@ -134,6 +138,12 @@ static int sap_write_header(AVFormatContext *s) freeaddrinfo(ai); } + sap->protocols = ffurl_get_protocols(NULL, NULL); + if (!sap->protocols) { + ret = AVERROR(ENOMEM); + goto fail; + } + contexts = av_mallocz(sizeof(AVFormatContext*) * s->nb_streams); if (!contexts) { ret = AVERROR(ENOMEM); @@ -148,7 +158,8 @@ 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, NULL); + ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, + sap->protocols); if (ret) { ret = AVERROR(EIO); goto fail; @@ -167,7 +178,7 @@ 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, NULL); + &s->interrupt_callback, NULL, sap->protocols); if (ret) { ret = AVERROR(EIO); goto fail; diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c index e1b0a63949..cfb1f8f1c9 100644 --- a/libavformat/smoothstreamingenc.c +++ b/libavformat/smoothstreamingenc.c @@ -64,6 +64,8 @@ typedef struct OutputStream { char *private_str; int packet_size; int audio_tag; + + const URLProtocol **protocols; } OutputStream; typedef struct SmoothStreamingContext { @@ -76,6 +78,8 @@ typedef struct SmoothStreamingContext { OutputStream *streams; int has_video, has_audio; int nb_fragments; + + const URLProtocol **protocols; } SmoothStreamingContext; static int ism_write(void *opaque, uint8_t *buf, int buf_size) @@ -121,7 +125,8 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence) AVDictionary *opts = NULL; os->tail_out = os->out; av_dict_set(&opts, "truncate", "0", 0); - ret = ffurl_open(&os->out, frag->file, AVIO_FLAG_WRITE, &os->ctx->interrupt_callback, &opts); + ret = ffurl_open(&os->out, frag->file, AVIO_FLAG_WRITE, &os->ctx->interrupt_callback, &opts, + os->protocols); av_dict_free(&opts); if (ret < 0) { os->out = os->tail_out; @@ -129,7 +134,8 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence) return ret; } av_dict_set(&opts, "truncate", "0", 0); - ffurl_open(&os->out2, frag->infofile, AVIO_FLAG_WRITE, &os->ctx->interrupt_callback, &opts); + ffurl_open(&os->out2, frag->infofile, AVIO_FLAG_WRITE, &os->ctx->interrupt_callback, &opts, + os->protocols); av_dict_free(&opts); ffurl_seek(os->out, offset - frag->start_pos, SEEK_SET); if (os->out2) @@ -168,6 +174,9 @@ static void ism_free(AVFormatContext *s) { SmoothStreamingContext *c = s->priv_data; int i, j; + + av_freep(&c->protocols); + if (!c->streams) return; for (i = 0; i < s->nb_streams; i++) { @@ -303,6 +312,12 @@ static int ism_write_header(AVFormatContext *s) goto fail; } + c->protocols = ffurl_get_protocols(NULL, NULL); + if (!c->protocols) { + ret = AVERROR(ENOMEM); + goto fail; + } + c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams); if (!c->streams) { ret = AVERROR(ENOMEM); @@ -327,6 +342,8 @@ static int ism_write_header(AVFormatContext *s) goto fail; } + os->protocols = c->protocols; + ctx = avformat_alloc_context(); if (!ctx) { ret = AVERROR(ENOMEM); @@ -523,7 +540,8 @@ static int ism_flush(AVFormatContext *s, int final) continue; snprintf(filename, sizeof(filename), "%s/temp", os->dirname); - ret = ffurl_open(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); + ret = ffurl_open(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, + c->protocols); if (ret < 0) break; os->cur_start_pos = os->tail_pos; diff --git a/libavformat/srtpproto.c b/libavformat/srtpproto.c index 4dcbad3aaa..2c64f451aa 100644 --- a/libavformat/srtpproto.c +++ b/libavformat/srtpproto.c @@ -80,7 +80,8 @@ static int srtp_open(URLContext *h, const char *uri, int flags) av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port, path, sizeof(path), uri); ff_url_join(buf, sizeof(buf), "rtp", NULL, hostname, rtp_port, "%s", path); - if ((ret = ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL)) < 0) + if ((ret = ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL, + h->protocols)) < 0) goto fail; h->max_packet_size = FFMIN(s->rtp_hd->max_packet_size, diff --git a/libavformat/tls.c b/libavformat/tls.c index eee3fc3d7d..a2a1ffe36d 100644 --- a/libavformat/tls.c +++ b/libavformat/tls.c @@ -76,5 +76,5 @@ int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV } return ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE, - &parent->interrupt_callback, options); + &parent->interrupt_callback, options, parent->protocols); } diff --git a/libavformat/url.h b/libavformat/url.h index 455021964e..482658b7fe 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -38,6 +38,10 @@ extern const AVClass ffurl_context_class; typedef struct URLContext { const AVClass *av_class; /**< information for av_log(). Set by url_open(). */ const struct URLProtocol *prot; + /** + * A NULL-terminated list of protocols usable by the child contexts. + */ + const struct URLProtocol **protocols; void *priv_data; char *filename; /**< specified URL */ int flags; @@ -96,11 +100,15 @@ typedef struct URLProtocol { * is to be opened * @param int_cb interrupt callback to use for the URLContext, may be * NULL + * @param protocols a NULL-terminate list of protocols available for use by + * this context and its children. The caller must ensure this + * list remains valid until the context is closed. * @return 0 in case of success, a negative value corresponding to an * AVERROR code in case of failure */ int ffurl_alloc(URLContext **puc, const char *filename, int flags, - const AVIOInterruptCB *int_cb); + const AVIOInterruptCB *int_cb, + const URLProtocol **protocols); /** * Connect an URLContext that has been allocated by ffurl_alloc @@ -125,11 +133,15 @@ int ffurl_connect(URLContext *uc, AVDictionary **options); * @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. + * @param protocols a NULL-terminate list of protocols available for use by + * this context and its children. The caller must ensure this + * list remains valid until the context is closed. * @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, AVDictionary **options); + const AVIOInterruptCB *int_cb, AVDictionary **options, + const URLProtocol **protocols); /** * Read up to size bytes from the resource accessed by h, and store