[FFmpeg-cvslog] urlprotocol: receive a list of protocols from the caller

Anton Khirnov git at videolan.org
Thu Mar 3 17:51:18 CET 2016


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Fri Feb 19 18:02:45 2016 +0100| [8c0ceafb0f25da077ff23e394667119f031574fd] | committer: Anton Khirnov

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.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=8c0ceafb0f25da077ff23e394667119f031574fd
---

 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 a9a399a..668e5ea 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 18c3945..20bef66 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 de48f7b..ecdf5df 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 e9dd474..a364dc0 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 fc4fbe5..afa2b7d 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 9f46c48..b01cef0 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 6886e15..4830390 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 22adbed..7823837 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 42b64b2..07c085a 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 bdbf678..4c1ed05 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 7013389..aeddf0f 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 c35ebe9..75fc128 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 2577df9..4806872 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 f745c37..9ed3d0f 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 5f31d97..50b8d24 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 4beb275..1a545c7 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 b9357c1..0226dac 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 8ccf147..c6f4d52 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 f09222d..9fafd6b 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 89f7f99..54eb0be 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 e1b0a63..cfb1f8f 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 4dcbad3..2c64f45 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 eee3fc3..a2a1ffe 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 4550219..482658b 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



More information about the ffmpeg-cvslog mailing list