Browse code

avio: add support for passing options to protocols.

Not used anywhere yet, support for passing options from avio_open() will
follow.

Anton Khirnov authored on 2011/11/05 18:04:04
Showing 18 changed files
... ...
@@ -324,14 +324,14 @@ static int open_input(struct variant *var)
324 324
     struct segment *seg = var->segments[var->cur_seq_no - var->start_seq_no];
325 325
     if (seg->key_type == KEY_NONE) {
326 326
         return ffurl_open(&var->input, seg->url, AVIO_FLAG_READ,
327
-                          &var->parent->interrupt_callback);
327
+                          &var->parent->interrupt_callback, NULL);
328 328
     } else if (seg->key_type == KEY_AES_128) {
329 329
         char iv[33], key[33], url[MAX_URL_SIZE];
330 330
         int ret;
331 331
         if (strcmp(seg->key, var->key_url)) {
332 332
             URLContext *uc;
333 333
             if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ,
334
-                           &var->parent->interrupt_callback) == 0) {
334
+                           &var->parent->interrupt_callback, NULL) == 0) {
335 335
                 if (ffurl_read_complete(uc, var->key, sizeof(var->key))
336 336
                     != sizeof(var->key)) {
337 337
                     av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n",
... ...
@@ -356,7 +356,7 @@ static int open_input(struct variant *var)
356 356
             return ret;
357 357
         av_opt_set(var->input->priv_data, "key", key, 0);
358 358
         av_opt_set(var->input->priv_data, "iv", iv, 0);
359
-        if ((ret = ffurl_connect(var->input)) < 0) {
359
+        if ((ret = ffurl_connect(var->input, NULL)) < 0) {
360 360
             ffurl_close(var->input);
361 361
             var->input = NULL;
362 362
             return ret;
... ...
@@ -275,7 +275,7 @@ retry:
275 275
     url = s->segments[s->cur_seq_no - s->start_seq_no]->url,
276 276
     av_log(h, AV_LOG_DEBUG, "opening %s\n", url);
277 277
     ret = ffurl_open(&s->seg_hd, url, AVIO_FLAG_READ,
278
-                     &h->interrupt_callback);
278
+                     &h->interrupt_callback, NULL);
279 279
     if (ret < 0) {
280 280
         if (ff_check_interrupt(&h->interrupt_callback))
281 281
             return AVERROR_EXIT;
... ...
@@ -22,6 +22,7 @@
22 22
 #include <unistd.h>
23 23
 
24 24
 #include "libavutil/avstring.h"
25
+#include "libavutil/dict.h"
25 26
 #include "libavutil/opt.h"
26 27
 #include "os_support.h"
27 28
 #include "avformat.h"
... ...
@@ -45,12 +46,40 @@ static const char *urlcontext_to_name(void *ptr)
45 45
     if(h->prot) return h->prot->name;
46 46
     else        return "NULL";
47 47
 }
48
+
49
+static void *urlcontext_child_next(void *obj, void *prev)
50
+{
51
+    URLContext *h = obj;
52
+    if (!prev && h->priv_data && h->prot->priv_data_class)
53
+        return h->priv_data;
54
+    return NULL;
55
+}
56
+
57
+static const AVClass *urlcontext_child_class_next(const AVClass *prev)
58
+{
59
+    URLProtocol *p = NULL;
60
+
61
+    /* find the protocol that corresponds to prev */
62
+    while (prev && (p = ffurl_protocol_next(p)))
63
+        if (p->priv_data_class == prev)
64
+            break;
65
+
66
+    /* find next protocol with priv options */
67
+    while (p = ffurl_protocol_next(p))
68
+        if (p->priv_data_class)
69
+            return p->priv_data_class;
70
+    return NULL;
71
+
72
+}
73
+
48 74
 static const AVOption options[] = {{NULL}};
49 75
 static const AVClass urlcontext_class = {
50 76
     .class_name     = "URLContext",
51 77
     .item_name      = urlcontext_to_name,
52 78
     .option         = options,
53 79
     .version        = LIBAVUTIL_VERSION_INT,
80
+    .child_next     = urlcontext_child_next,
81
+    .child_class_next = urlcontext_child_class_next,
54 82
 };
55 83
 /*@}*/
56 84
 
... ...
@@ -133,9 +162,13 @@ static int url_alloc_for_protocol (URLContext **puc, struct URLProtocol *up,
133 133
     return err;
134 134
 }
135 135
 
136
-int ffurl_connect(URLContext* uc)
136
+int ffurl_connect(URLContext* uc, AVDictionary **options)
137 137
 {
138
-    int err = uc->prot->url_open(uc, uc->filename, uc->flags);
138
+    int err =
139
+#if !FF_API_OLD_AVIO
140
+        uc->prot->url_open2 ? uc->prot->url_open2(uc, uc->filename, uc->flags, options) :
141
+#endif
142
+        uc->prot->url_open(uc, uc->filename, uc->flags);
139 143
     if (err)
140 144
         return err;
141 145
     uc->is_connected = 1;
... ...
@@ -156,7 +189,7 @@ int url_open_protocol (URLContext **puc, struct URLProtocol *up,
156 156
     ret = url_alloc_for_protocol(puc, up, filename, flags, NULL);
157 157
     if (ret)
158 158
         goto fail;
159
-    ret = ffurl_connect(*puc);
159
+    ret = ffurl_connect(*puc, NULL);
160 160
     if (!ret)
161 161
         return 0;
162 162
  fail:
... ...
@@ -170,11 +203,11 @@ int url_alloc(URLContext **puc, const char *filename, int flags)
170 170
 }
171 171
 int url_connect(URLContext* uc)
172 172
 {
173
-    return ffurl_connect(uc);
173
+    return ffurl_connect(uc, NULL);
174 174
 }
175 175
 int url_open(URLContext **puc, const char *filename, int flags)
176 176
 {
177
-    return ffurl_open(puc, filename, flags, NULL);
177
+    return ffurl_open(puc, filename, flags, NULL, NULL);
178 178
 }
179 179
 int url_read(URLContext *h, unsigned char *buf, int size)
180 180
 {
... ...
@@ -255,14 +288,18 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags,
255 255
 }
256 256
 
257 257
 int ffurl_open(URLContext **puc, const char *filename, int flags,
258
-               const AVIOInterruptCB *int_cb)
258
+               const AVIOInterruptCB *int_cb, AVDictionary **options)
259 259
 {
260 260
     int ret = ffurl_alloc(puc, filename, flags, int_cb);
261 261
     if (ret)
262 262
         return ret;
263
-    ret = ffurl_connect(*puc);
263
+    if (options && (*puc)->prot->priv_data_class &&
264
+        (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0)
265
+        goto fail;
266
+    ret = ffurl_connect(*puc, options);
264 267
     if (!ret)
265 268
         return 0;
269
+fail:
266 270
     ffurl_close(*puc);
267 271
     *puc = NULL;
268 272
     return ret;
... ...
@@ -356,7 +393,7 @@ int ffurl_close(URLContext *h)
356 356
 int url_exist(const char *filename)
357 357
 {
358 358
     URLContext *h;
359
-    if (ffurl_open(&h, filename, AVIO_FLAG_READ, NULL) < 0)
359
+    if (ffurl_open(&h, filename, AVIO_FLAG_READ, NULL, NULL) < 0)
360 360
         return 0;
361 361
     ffurl_close(h);
362 362
     return 1;
... ...
@@ -373,7 +410,7 @@ int avio_check(const char *url, int flags)
373 373
     if (h->prot->url_check) {
374 374
         ret = h->prot->url_check(h, flags);
375 375
     } else {
376
-        ret = ffurl_connect(h);
376
+        ret = ffurl_connect(h, NULL);
377 377
         if (ret >= 0)
378 378
             ret = flags;
379 379
     }
... ...
@@ -932,7 +932,7 @@ int avio_open(AVIOContext **s, const char *filename, int flags)
932 932
     URLContext *h;
933 933
     int err;
934 934
 
935
-    err = ffurl_open(&h, filename, flags, NULL);
935
+    err = ffurl_open(&h, filename, flags, NULL, NULL);
936 936
     if (err < 0)
937 937
         return err;
938 938
     err = ffio_fdopen(s, h);
... ...
@@ -101,7 +101,8 @@ static av_cold int concat_open(URLContext *h, const char *uri, int flags)
101 101
         uri += len + strspn(uri+len, AV_CAT_SEPARATOR);
102 102
 
103 103
         /* creating URLContext */
104
-        if ((err = ffurl_open(&uc, node_uri, flags, &h->interrupt_callback)) < 0)
104
+        if ((err = ffurl_open(&uc, node_uri, flags,
105
+                              &h->interrupt_callback, NULL)) < 0)
105 106
             break;
106 107
 
107 108
         /* creating size */
... ...
@@ -83,7 +83,7 @@ static int crypto_open(URLContext *h, const char *uri, int flags)
83 83
         goto err;
84 84
     }
85 85
     if ((ret = ffurl_open(&c->hd, nested_url, AVIO_FLAG_READ,
86
-                          &h->interrupt_callback)) < 0) {
86
+                          &h->interrupt_callback, NULL)) < 0) {
87 87
         av_log(h, AV_LOG_ERROR, "Unable to open input\n");
88 88
         goto err;
89 89
     }
... ...
@@ -100,7 +100,8 @@ static int gopher_open(URLContext *h, const char *uri, int flags)
100 100
     ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
101 101
 
102 102
     s->hd = NULL;
103
-    err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback);
103
+    err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE,
104
+                     &h->interrupt_callback, NULL);
104 105
     if (err < 0)
105 106
         goto fail;
106 107
 
... ...
@@ -133,7 +133,8 @@ static int http_open_cnx(URLContext *h)
133 133
         port = 80;
134 134
 
135 135
     ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL);
136
-    err = ffurl_open(&hd, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback);
136
+    err = ffurl_open(&hd, buf, AVIO_FLAG_READ_WRITE,
137
+                     &h->interrupt_callback, NULL);
137 138
     if (err < 0)
138 139
         goto fail;
139 140
 
... ...
@@ -65,7 +65,8 @@ static int md5_close(URLContext *h)
65 65
     av_strstart(filename, "md5:", &filename);
66 66
 
67 67
     if (*filename) {
68
-        err = ffurl_open(&out, filename, AVIO_FLAG_WRITE, &h->interrupt_callback);
68
+        err = ffurl_open(&out, filename, AVIO_FLAG_WRITE,
69
+                         &h->interrupt_callback, NULL);
69 70
         if (err)
70 71
             return err;
71 72
         err = ffurl_write(out, buf, i*2+1);
... ...
@@ -249,7 +249,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags)
249 249
              host, port, mmsh->request_seq++);
250 250
     av_opt_set(mms->mms_hd->priv_data, "headers", headers, 0);
251 251
 
252
-    err = ffurl_connect(mms->mms_hd);
252
+    err = ffurl_connect(mms->mms_hd, NULL);
253 253
     if (err) {
254 254
         goto fail;
255 255
     }
... ...
@@ -296,7 +296,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags)
296 296
     av_dlog(NULL, "out_buffer is %s", headers);
297 297
     av_opt_set(mms->mms_hd->priv_data, "headers", headers, 0);
298 298
 
299
-    err = ffurl_connect(mms->mms_hd);
299
+    err = ffurl_connect(mms->mms_hd, NULL);
300 300
     if (err) {
301 301
           goto fail;
302 302
     }
... ...
@@ -524,7 +524,7 @@ static int mms_open(URLContext *h, const char *uri, int flags)
524 524
     // establish tcp connection.
525 525
     ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
526 526
     err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE,
527
-                     &h->interrupt_callback);
527
+                     &h->interrupt_callback, NULL);
528 528
     if (err)
529 529
         goto fail;
530 530
 
... ...
@@ -818,7 +818,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
818 818
     ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
819 819
 
820 820
     if (ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
821
-                   &s->interrupt_callback) < 0) {
821
+                   &s->interrupt_callback, NULL) < 0) {
822 822
         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
823 823
         goto fail;
824 824
     }
... ...
@@ -188,7 +188,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
188 188
     build_udp_url(buf, sizeof(buf),
189 189
                   hostname, rtp_port, local_rtp_port, ttl, max_packet_size,
190 190
                   connect);
191
-    if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback) < 0)
191
+    if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0)
192 192
         goto fail;
193 193
     if (local_rtp_port>=0 && local_rtcp_port<0)
194 194
         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)
196 196
     build_udp_url(buf, sizeof(buf),
197 197
                   hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size,
198 198
                   connect);
199
-    if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback) < 0)
199
+    if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0)
200 200
         goto fail;
201 201
 
202 202
     /* just to ease handle access. XXX: need to suppress direct handle
... ...
@@ -1160,7 +1160,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
1160 1160
                     /* we will use two ports per rtp stream (rtp and rtcp) */
1161 1161
                     j += 2;
1162 1162
                     if (ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE,
1163
-                                   &s->interrupt_callback) == 0)
1163
+                                   &s->interrupt_callback, NULL) == 0)
1164 1164
                         goto rtp_opened;
1165 1165
                 }
1166 1166
             }
... ...
@@ -1308,7 +1308,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
1308 1308
             ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,
1309 1309
                         port, "?ttl=%d", ttl);
1310 1310
             if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
1311
-                           &s->interrupt_callback) < 0) {
1311
+                           &s->interrupt_callback, NULL) < 0) {
1312 1312
                 err = AVERROR_INVALIDDATA;
1313 1313
                 goto fail;
1314 1314
             }
... ...
@@ -1468,7 +1468,7 @@ redirect:
1468 1468
         av_opt_set(rt->rtsp_hd->priv_data, "headers", headers, 0);
1469 1469
 
1470 1470
         /* complete the connection */
1471
-        if (ffurl_connect(rt->rtsp_hd)) {
1471
+        if (ffurl_connect(rt->rtsp_hd, NULL)) {
1472 1472
             err = AVERROR(EIO);
1473 1473
             goto fail;
1474 1474
         }
... ...
@@ -1511,7 +1511,7 @@ redirect:
1511 1511
         ff_http_init_auth_state(rt->rtsp_hd_out, rt->rtsp_hd);
1512 1512
 
1513 1513
         /* complete the connection */
1514
-        if (ffurl_connect(rt->rtsp_hd_out)) {
1514
+        if (ffurl_connect(rt->rtsp_hd_out, NULL)) {
1515 1515
             err = AVERROR(EIO);
1516 1516
             goto fail;
1517 1517
         }
... ...
@@ -1519,7 +1519,7 @@ redirect:
1519 1519
         /* open the tcp connection */
1520 1520
         ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);
1521 1521
         if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
1522
-                       &s->interrupt_callback) < 0) {
1522
+                       &s->interrupt_callback, NULL) < 0) {
1523 1523
             err = AVERROR(EIO);
1524 1524
             goto fail;
1525 1525
         }
... ...
@@ -1868,7 +1868,7 @@ static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap)
1868 1868
                     rtsp_st->sdp_ttl,
1869 1869
                     rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0);
1870 1870
         if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
1871
-                       &s->interrupt_callback) < 0) {
1871
+                       &s->interrupt_callback, NULL) < 0) {
1872 1872
             err = AVERROR_INVALIDDATA;
1873 1873
             goto fail;
1874 1874
         }
... ...
@@ -1933,7 +1933,7 @@ static int rtp_read_header(AVFormatContext *s,
1933 1933
         return AVERROR(EIO);
1934 1934
 
1935 1935
     ret = ffurl_open(&in, s->filename, AVIO_FLAG_READ,
1936
-                     &s->interrupt_callback);
1936
+                     &s->interrupt_callback, NULL);
1937 1937
     if (ret)
1938 1938
         goto fail;
1939 1939
 
... ...
@@ -85,7 +85,8 @@ static int sap_read_header(AVFormatContext *s,
85 85
 
86 86
     ff_url_join(url, sizeof(url), "udp", NULL, host, port, "?localport=%d",
87 87
                 port);
88
-    ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_READ, &s->interrupt_callback);
88
+    ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_READ,
89
+                     &s->interrupt_callback, NULL);
89 90
     if (ret)
90 91
         goto fail;
91 92
 
... ...
@@ -146,7 +146,7 @@ static int sap_write_header(AVFormatContext *s)
146 146
                     "?ttl=%d", ttl);
147 147
         if (!same_port)
148 148
             base_port += 2;
149
-        ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback);
149
+        ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
150 150
         if (ret) {
151 151
             ret = AVERROR(EIO);
152 152
             goto fail;
... ...
@@ -158,7 +158,8 @@ static int sap_write_header(AVFormatContext *s)
158 158
 
159 159
     ff_url_join(url, sizeof(url), "udp", NULL, announce_addr, port,
160 160
                 "?ttl=%d&connect=1", ttl);
161
-    ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback);
161
+    ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_WRITE,
162
+                     &s->interrupt_callback, NULL);
162 163
     if (ret) {
163 164
         ret = AVERROR(EIO);
164 165
         goto fail;
... ...
@@ -123,7 +123,8 @@ static int tls_open(URLContext *h, const char *uri, int flags)
123 123
         freeaddrinfo(ai);
124 124
     }
125 125
 
126
-    ret = ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback);
126
+    ret = ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE,
127
+                     &h->interrupt_callback, NULL);
127 128
     if (ret)
128 129
         goto fail;
129 130
     c->fd = ffurl_get_file_handle(c->tcp);
... ...
@@ -28,6 +28,8 @@
28 28
 #include "avio.h"
29 29
 #include "libavformat/version.h"
30 30
 
31
+#include "libavutil/dict.h"
32
+
31 33
 #if !FF_API_OLD_AVIO
32 34
 #define URL_PROTOCOL_FLAG_NESTED_SCHEME 1 /*< The protocol name can be the first part of a nested protocol scheme */
33 35
 
... ...
@@ -48,6 +50,12 @@ typedef struct URLContext {
48 48
 typedef struct URLProtocol {
49 49
     const char *name;
50 50
     int     (*url_open)( URLContext *h, const char *url, int flags);
51
+    /**
52
+     * This callback is to be used by protocols which open further nested
53
+     * protocols. options are then to be passed to ffurl_open()/ffurl_connect()
54
+     * for those nested protocols.
55
+     */
56
+    int     (*url_open2)(URLContext *h, const char *url, int flags, AVDictionary **options);
51 57
     int     (*url_read)( URLContext *h, unsigned char *buf, int size);
52 58
     int     (*url_write)(URLContext *h, const unsigned char *buf, int size);
53 59
     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,
82 82
 
83 83
 /**
84 84
  * Connect an URLContext that has been allocated by ffurl_alloc
85
+ *
86
+ * @param options  A dictionary filled with options for nested protocols,
87
+ * i.e. it will be passed to url_open2() for protocols implementing it.
88
+ * This parameter will be destroyed and replaced with a dict containing options
89
+ * that were not found. May be NULL.
85 90
  */
86
-int ffurl_connect(URLContext *uc);
91
+int ffurl_connect(URLContext *uc, AVDictionary **options);
87 92
 
88 93
 /**
89 94
  * Create an URLContext for accessing to the resource indicated by
... ...
@@ -95,11 +108,14 @@ int ffurl_connect(URLContext *uc);
95 95
  * is to be opened
96 96
  * @param int_cb interrupt callback to use for the URLContext, may be
97 97
  * NULL
98
+ * @param options  A dictionary filled with protocol-private options. On return
99
+ * this parameter will be destroyed and replaced with a dict containing options
100
+ * that were not found. May be NULL.
98 101
  * @return 0 in case of success, a negative value corresponding to an
99 102
  * AVERROR code in case of failure
100 103
  */
101 104
 int ffurl_open(URLContext **puc, const char *filename, int flags,
102
-               const AVIOInterruptCB *int_cb);
105
+               const AVIOInterruptCB *int_cb, AVDictionary **options);
103 106
 
104 107
 /**
105 108
  * Read up to size bytes from the resource accessed by h, and store