Libav
avio.c
Go to the documentation of this file.
1 /*
2  * unbuffered I/O
3  * Copyright (c) 2001 Fabrice Bellard
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "libavutil/avstring.h"
23 #include "libavutil/dict.h"
24 #include "libavutil/opt.h"
25 #include "libavutil/time.h"
26 #include "os_support.h"
27 #include "avformat.h"
28 #if CONFIG_NETWORK
29 #include "network.h"
30 #endif
31 #include "url.h"
32 
35 static const char *urlcontext_to_name(void *ptr)
36 {
37  URLContext *h = (URLContext *)ptr;
38  if (h->prot)
39  return h->prot->name;
40  else
41  return "NULL";
42 }
43 
44 static void *urlcontext_child_next(void *obj, void *prev)
45 {
46  URLContext *h = obj;
47  if (!prev && h->priv_data && h->prot->priv_data_class)
48  return h->priv_data;
49  return NULL;
50 }
51 
52 static const AVOption options[] = {
53  { "rw_timeout", "Timeout for IO operations (in microseconds)", offsetof(URLContext, rw_timeout), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_DECODING_PARAM },
54  { NULL }
55 };
57  .class_name = "URLContext",
58  .item_name = urlcontext_to_name,
59  .option = options,
60  .version = LIBAVUTIL_VERSION_INT,
61  .child_next = urlcontext_child_next,
62  .child_class_next = ff_urlcontext_child_class_next,
63 };
66 static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up,
67  const char *filename, int flags,
68  const AVIOInterruptCB *int_cb,
69  const URLProtocol **protocols)
70 {
71  URLContext *uc;
72  int err;
73 
74 #if CONFIG_NETWORK
76  return AVERROR(EIO);
77 #endif
78  uc = av_mallocz(sizeof(URLContext) + strlen(filename) + 1);
79  if (!uc) {
80  err = AVERROR(ENOMEM);
81  goto fail;
82  }
84  uc->filename = (char *)&uc[1];
85  strcpy(uc->filename, filename);
86  uc->prot = up;
87  uc->flags = flags;
88  uc->is_streamed = 0; /* default = not streamed */
89  uc->max_packet_size = 0; /* default: stream file */
90  uc->protocols = protocols;
91  if (up->priv_data_size) {
93  if (!uc->priv_data) {
94  err = AVERROR(ENOMEM);
95  goto fail;
96  }
97  if (up->priv_data_class) {
98  *(const AVClass **)uc->priv_data = up->priv_data_class;
100  }
101  }
102  if (int_cb)
103  uc->interrupt_callback = *int_cb;
104 
105  *puc = uc;
106  return 0;
107 fail:
108  *puc = NULL;
109  if (uc)
110  av_freep(&uc->priv_data);
111  av_freep(&uc);
112 #if CONFIG_NETWORK
115 #endif
116  return err;
117 }
118 
120 {
121  int err =
122  uc->prot->url_open2 ? uc->prot->url_open2(uc,
123  uc->filename,
124  uc->flags,
125  options) :
126  uc->prot->url_open(uc, uc->filename, uc->flags);
127  if (err)
128  return err;
129  uc->is_connected = 1;
130  /* We must be careful here as ffurl_seek() could be slow,
131  * for example for http */
132  if ((uc->flags & AVIO_FLAG_WRITE) || !strcmp(uc->prot->name, "file"))
133  if (!uc->is_streamed && ffurl_seek(uc, 0, SEEK_SET) < 0)
134  uc->is_streamed = 1;
135  return 0;
136 }
137 
138 #define URL_SCHEME_CHARS \
139  "abcdefghijklmnopqrstuvwxyz" \
140  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
141  "0123456789+-."
142 
143 int ffurl_alloc(URLContext **puc, const char *filename, int flags,
144  const AVIOInterruptCB *int_cb,
145  const URLProtocol **protocols)
146 {
147  char proto_str[128], proto_nested[128], *ptr;
148  size_t proto_len = strspn(filename, URL_SCHEME_CHARS);
149  int i;
150 
151  if (filename[proto_len] != ':' || is_dos_path(filename))
152  strcpy(proto_str, "file");
153  else
154  av_strlcpy(proto_str, filename,
155  FFMIN(proto_len + 1, sizeof(proto_str)));
156 
157  av_strlcpy(proto_nested, proto_str, sizeof(proto_nested));
158  if ((ptr = strchr(proto_nested, '+')))
159  *ptr = '\0';
160 
161  for (i = 0; protocols[i]; i++) {
162  const URLProtocol *up = protocols[i];
163  if (!strcmp(proto_str, up->name))
164  return url_alloc_for_protocol(puc, up, filename, flags, int_cb,
165  protocols);
167  !strcmp(proto_nested, up->name))
168  return url_alloc_for_protocol(puc, up, filename, flags, int_cb,
169  protocols);
170  }
171  *puc = NULL;
173 }
174 
175 int ffurl_open(URLContext **puc, const char *filename, int flags,
176  const AVIOInterruptCB *int_cb, AVDictionary **options,
177  const URLProtocol **protocols,
178  URLContext *parent)
179 {
180  int ret = ffurl_alloc(puc, filename, flags, int_cb, protocols);
181  if (ret)
182  return ret;
183  if (parent)
184  av_opt_copy(*puc, parent);
185  if (options &&
186  (ret = av_opt_set_dict(*puc, options)) < 0)
187  goto fail;
188  if (options && (*puc)->prot->priv_data_class &&
189  (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0)
190  goto fail;
191  ret = ffurl_connect(*puc, options);
192  if (!ret)
193  return 0;
194 fail:
195  ffurl_close(*puc);
196  *puc = NULL;
197  return ret;
198 }
199 
200 static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
201  int size, int size_min,
202  int (*transfer_func)(URLContext *h,
203  uint8_t *buf,
204  int size))
205 {
206  int ret, len;
207  int fast_retries = 5;
208  int64_t wait_since = 0;
209 
210  len = 0;
211  while (len < size_min) {
212  ret = transfer_func(h, buf + len, size - len);
213  if (ret == AVERROR(EINTR))
214  continue;
215  if (h->flags & AVIO_FLAG_NONBLOCK)
216  return ret;
217  if (ret == AVERROR(EAGAIN)) {
218  ret = 0;
219  if (fast_retries) {
220  fast_retries--;
221  } else {
222  if (h->rw_timeout) {
223  if (!wait_since)
224  wait_since = av_gettime_relative();
225  else if (av_gettime_relative() > wait_since + h->rw_timeout)
226  return AVERROR(EIO);
227  }
228  av_usleep(1000);
229  }
230  } else if (ret < 1)
231  return (ret < 0 && ret != AVERROR_EOF) ? ret : len;
232  if (ret) {
233  fast_retries = FFMAX(fast_retries, 2);
234  wait_since = 0;
235  }
236  len += ret;
238  return AVERROR_EXIT;
239  }
240  return len;
241 }
242 
243 int ffurl_read(URLContext *h, unsigned char *buf, int size)
244 {
245  if (!(h->flags & AVIO_FLAG_READ))
246  return AVERROR(EIO);
247  return retry_transfer_wrapper(h, buf, size, 1, h->prot->url_read);
248 }
249 
250 int ffurl_read_complete(URLContext *h, unsigned char *buf, int size)
251 {
252  if (!(h->flags & AVIO_FLAG_READ))
253  return AVERROR(EIO);
254  return retry_transfer_wrapper(h, buf, size, size, h->prot->url_read);
255 }
256 
257 int ffurl_write(URLContext *h, const unsigned char *buf, int size)
258 {
259  if (!(h->flags & AVIO_FLAG_WRITE))
260  return AVERROR(EIO);
261  /* avoid sending too big packets */
262  if (h->max_packet_size && size > h->max_packet_size)
263  return AVERROR(EIO);
264 
265  return retry_transfer_wrapper(h, buf, size, size,
266  (int (*)(struct URLContext *, uint8_t *, int))
267  h->prot->url_write);
268 }
269 
270 int64_t ffurl_seek(URLContext *h, int64_t pos, int whence)
271 {
272  int64_t ret;
273 
274  if (!h->prot->url_seek)
275  return AVERROR(ENOSYS);
276  ret = h->prot->url_seek(h, pos, whence & ~AVSEEK_FORCE);
277  return ret;
278 }
279 
281 {
282  int ret = 0;
283  if (!h)
284  return 0; /* can happen when ffurl_open fails */
285 
286  if (h->is_connected && h->prot->url_close)
287  ret = h->prot->url_close(h);
288 #if CONFIG_NETWORK
291 #endif
292  if (h->prot->priv_data_size) {
293  if (h->prot->priv_data_class)
295  av_free(h->priv_data);
296  }
297  av_free(h);
298  return ret;
299 }
300 
301 int avio_check(const char *url, int flags)
302 {
303  const URLProtocol **protocols;
304  URLContext *h;
305  int ret;
306 
307  protocols = ffurl_get_protocols(NULL, NULL);
308  if (!protocols)
309  return AVERROR(ENOMEM);
310 
311  ret = ffurl_alloc(&h, url, flags, NULL, protocols);
312  if (ret) {
313  av_freep(&protocols);
314  return ret;
315  }
316 
317  if (h->prot->url_check) {
318  ret = h->prot->url_check(h, flags);
319  } else {
320  ret = ffurl_connect(h, NULL);
321  if (ret >= 0)
322  ret = flags;
323  }
324 
325  ffurl_close(h);
326  av_freep(&protocols);
327  return ret;
328 }
329 
331 {
332  int64_t pos, size;
333 
334  size = ffurl_seek(h, 0, AVSEEK_SIZE);
335  if (size < 0) {
336  pos = ffurl_seek(h, 0, SEEK_CUR);
337  if ((size = ffurl_seek(h, -1, SEEK_END)) < 0)
338  return size;
339  size++;
340  ffurl_seek(h, pos, SEEK_SET);
341  }
342  return size;
343 }
344 
346 {
347  if (!h->prot->url_get_file_handle)
348  return -1;
349  return h->prot->url_get_file_handle(h);
350 }
351 
352 int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles)
353 {
354  if (!h->prot->url_get_multi_file_handle) {
355  if (!h->prot->url_get_file_handle)
356  return AVERROR(ENOSYS);
357  *handles = av_malloc(sizeof(**handles));
358  if (!*handles)
359  return AVERROR(ENOMEM);
360  *numhandles = 1;
361  *handles[0] = h->prot->url_get_file_handle(h);
362  return 0;
363  }
364  return h->prot->url_get_multi_file_handle(h, handles, numhandles);
365 }
366 
368 {
369  if (!h->prot->url_shutdown)
370  return AVERROR(EINVAL);
371  return h->prot->url_shutdown(h, flags);
372 }
373 
375 {
376  int ret;
377  if (cb && cb->callback && (ret = cb->callback(cb->opaque)))
378  return ret;
379  return 0;
380 }
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:62
int(* url_write)(URLContext *h, const unsigned char *buf, int size)
Definition: url.h:78
int size
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:34
AVOption.
Definition: opt.h:234
int flags
Definition: url.h:90
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: avio.c:257
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:49
int ffurl_connect(URLContext *uc, AVDictionary **options)
Connect an URLContext that has been allocated by ffurl_alloc.
Definition: avio.c:119
AVIOInterruptCB interrupt_callback
Definition: url.h:51
void av_opt_set_defaults(void *s)
Set the values of all AVOption fields to their default values.
Definition: opt.c:599
int(* url_read)(URLContext *h, unsigned char *buf, int size)
Read data from the protocol.
Definition: url.h:77
#define AVIO_FLAG_READ
read-only
Definition: avio.h:368
int64_t rw_timeout
maximum time to wait for (network) read/write operation completion, in microseconds ...
Definition: url.h:52
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:369
void ff_network_close(void)
Definition: network.c:77
int(* url_get_file_handle)(URLContext *h)
Definition: url.h:84
int flags
Definition: url.h:47
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:68
static void * urlcontext_child_next(void *obj, void *prev)
Definition: avio.c:44
int(* url_open2)(URLContext *h, const char *url, int flags, AVDictionary **options)
This callback is to be used by protocols which open further nested protocols.
Definition: url.h:63
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition: avio.c:367
#define URL_SCHEME_CHARS
Definition: avio.c:138
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:202
void * opaque
Definition: avio.h:53
const AVClass * priv_data_class
Definition: url.h:89
int avio_check(const char *url, int flags)
Return AVIO_FLAG_* access flags corresponding to the access permissions of the resource in url...
Definition: avio.c:301
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:39
int av_opt_copy(void *dst, const void *src)
Copy options from src object into dest object.
Definition: opt.c:838
Public dictionary API.
uint8_t
int ff_network_init(void)
Definition: network.c:50
AVOptions.
miscellaneous OS support macros and functions.
int(* url_shutdown)(URLContext *h, int flags)
Definition: url.h:87
#define AVERROR_PROTOCOL_NOT_FOUND
Protocol not found.
Definition: error.h:58
const AVClass * ff_urlcontext_child_class_next(const AVClass *prev)
Definition: protocols.c:63
static int flags
Definition: log.c:50
#define AVERROR_EOF
End of file.
Definition: error.h:51
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const URLProtocol **protocols, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
Definition: avio.c:175
int(* url_close)(URLContext *h)
Definition: url.h:80
int(* callback)(void *)
Definition: avio.h:52
#define AV_OPT_FLAG_ENCODING_PARAM
a generic parameter which can be set by the user for muxing or encoding
Definition: opt.h:264
Callback for checking whether to abort blocking functions.
Definition: avio.h:51
int(* url_get_multi_file_handle)(URLContext *h, int **handles, int *numhandles)
Definition: url.h:85
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:190
int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles)
Return the file descriptors associated with this URL.
Definition: avio.c:352
#define AVERROR(e)
Definition: error.h:43
#define URL_PROTOCOL_FLAG_NESTED_SCHEME
Definition: url.h:33
int ffurl_alloc(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, const URLProtocol **protocols)
Create a URLContext for accessing to the resource indicated by url, but do not initiate the connectio...
Definition: avio.c:143
#define FFMAX(a, b)
Definition: common.h:64
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:81
#define fail()
Definition: checkasm.h:80
static const char * urlcontext_to_name(void *ptr)
Definition: avio.c:35
static const AVOption options[]
Definition: avio.c:52
static int retry_transfer_wrapper(URLContext *h, uint8_t *buf, int size, int size_min, int(*transfer_func)(URLContext *h, uint8_t *buf, int size))
Definition: avio.c:200
const AVIOInterruptCB int_cb
Definition: avconv.c:140
#define FFMIN(a, b)
Definition: common.h:66
int(* url_check)(URLContext *h, int mask)
Definition: url.h:91
int64_t(* url_seek)(URLContext *h, int64_t pos, int whence)
Definition: url.h:79
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:345
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:52
LIBAVUTIL_VERSION_INT
Definition: eval.c:55
int is_connected
Definition: url.h:50
NULL
Definition: eval.c:55
static int is_dos_path(const char *path)
Definition: os_support.h:53
int ff_check_interrupt(AVIOInterruptCB *cb)
Check if the user has requested to interrupt a blocking function associated with cb.
Definition: avio.c:374
int av_opt_set_dict(void *obj, AVDictionary **options)
Definition: opt.c:735
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:387
int64_t ffurl_size(URLContext *h)
Return the filesize of the resource accessed by h, AVERROR(ENOSYS) if the operation is not supported ...
Definition: avio.c:330
Definition: url.h:38
Describe the class of an AVClass context structure.
Definition: log.h:34
#define AVSEEK_FORCE
Passing this flag as the "whence" parameter to a seek function causes it to seek by any means (like r...
Definition: avio.h:274
void * priv_data
Definition: url.h:45
#define AV_OPT_FLAG_DECODING_PARAM
a generic parameter which can be set by the user for demuxing or decoding
Definition: opt.h:265
static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up, const char *filename, int flags, const AVIOInterruptCB *int_cb, const URLProtocol **protocols)
Definition: avio.c:66
const char * name
Definition: url.h:56
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
Definition: time.c:57
const AVClass * av_class
information for av_log().
Definition: url.h:39
int ffurl_close(URLContext *h)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:280
const AVClass ffurl_context_class
Definition: avio.c:56
const struct URLProtocol ** protocols
A NULL-terminated list of protocols usable by the child contexts.
Definition: url.h:44
Main libavformat public API header.
int(* url_open)(URLContext *h, const char *url, int flags)
Definition: url.h:57
void av_opt_free(void *obj)
Free all allocated objects in obj.
Definition: opt.c:715
int64_t ffurl_seek(URLContext *h, int64_t pos, int whence)
Change the position that will be used by the next read/write operation on the resource accessed by h...
Definition: avio.c:270
const struct URLProtocol * prot
Definition: url.h:40
int ffurl_read_complete(URLContext *h, unsigned char *buf, int size)
Read as many bytes as possible (up to size), calling the read function multiple times if necessary...
Definition: avio.c:250
char * filename
specified URL
Definition: url.h:46
#define AVSEEK_SIZE
ORing this as the "whence" parameter to a seek function causes it to return the filesize without seek...
Definition: avio.h:266
int len
int max_packet_size
if non zero, the stream is packetized with this max packet size
Definition: url.h:48
unbuffered private I/O API
int priv_data_size
Definition: url.h:88
const URLProtocol ** ffurl_get_protocols(const char *whitelist, const char *blacklist)
Construct a list of protocols matching a given whitelist and/or blacklist.
Definition: protocols.c:98
int ffurl_read(URLContext *h, unsigned char *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf...
Definition: avio.c:243
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:211