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 FFmpeg.
6  *
7  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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 
34 
36 {
37  return prev ? prev->next : first_protocol;
38 }
39 
40 /** @name Logging context. */
41 /*@{*/
42 static const char *urlcontext_to_name(void *ptr)
43 {
44  URLContext *h = (URLContext *)ptr;
45  if(h->prot) return h->prot->name;
46  else return "NULL";
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 
74 static const AVOption options[] = {{NULL}};
76  .class_name = "URLContext",
77  .item_name = urlcontext_to_name,
78  .option = options,
79  .version = LIBAVUTIL_VERSION_INT,
80  .child_next = urlcontext_child_next,
81  .child_class_next = urlcontext_child_class_next,
82 };
83 /*@}*/
84 
85 
86 const char *avio_enum_protocols(void **opaque, int output)
87 {
88  URLProtocol *p;
89  *opaque = ffurl_protocol_next(*opaque);
90  if (!(p = *opaque)) return NULL;
91  if ((output && p->url_write) || (!output && p->url_read))
92  return p->name;
93  return avio_enum_protocols(opaque, output);
94 }
95 
97 {
98  URLProtocol **p;
99  if (size < sizeof(URLProtocol)) {
101  memcpy(temp, protocol, size);
102  protocol = temp;
103  }
104  p = &first_protocol;
105  while (*p != NULL) p = &(*p)->next;
106  *p = protocol;
107  protocol->next = NULL;
108  return 0;
109 }
110 
111 static int url_alloc_for_protocol (URLContext **puc, struct URLProtocol *up,
112  const char *filename, int flags,
113  const AVIOInterruptCB *int_cb)
114 {
115  URLContext *uc;
116  int err;
117 
118 #if CONFIG_NETWORK
120  return AVERROR(EIO);
121 #endif
122  if ((flags & AVIO_FLAG_READ) && !up->url_read) {
124  "Impossible to open the '%s' protocol for reading\n", up->name);
125  return AVERROR(EIO);
126  }
127  if ((flags & AVIO_FLAG_WRITE) && !up->url_write) {
129  "Impossible to open the '%s' protocol for writing\n", up->name);
130  return AVERROR(EIO);
131  }
132  uc = av_mallocz(sizeof(URLContext) + strlen(filename) + 1);
133  if (!uc) {
134  err = AVERROR(ENOMEM);
135  goto fail;
136  }
138  uc->filename = (char *) &uc[1];
139  strcpy(uc->filename, filename);
140  uc->prot = up;
141  uc->flags = flags;
142  uc->is_streamed = 0; /* default = not streamed */
143  uc->max_packet_size = 0; /* default: stream file */
144  if (up->priv_data_size) {
146  if (up->priv_data_class) {
147  int proto_len= strlen(up->name);
148  char *start = strchr(uc->filename, ',');
149  *(const AVClass**)uc->priv_data = up->priv_data_class;
151  if(!strncmp(up->name, uc->filename, proto_len) && uc->filename + proto_len == start){
152  int ret= 0;
153  char *p= start;
154  char sep= *++p;
155  char *key, *val;
156  p++;
157  while(ret >= 0 && (key= strchr(p, sep)) && p<key && (val = strchr(key+1, sep))){
158  *val= *key= 0;
159  ret= av_opt_set(uc->priv_data, p, key+1, 0);
160  if (ret == AVERROR_OPTION_NOT_FOUND)
161  av_log(uc, AV_LOG_ERROR, "Key '%s' not found.\n", p);
162  *val= *key= sep;
163  p= val+1;
164  }
165  if(ret<0 || p!=key){
166  av_log(uc, AV_LOG_ERROR, "Error parsing options string %s\n", start);
167  av_freep(&uc->priv_data);
168  av_freep(&uc);
169  err = AVERROR(EINVAL);
170  goto fail;
171  }
172  memmove(start, key+1, strlen(key));
173  }
174  }
175  }
176  if (int_cb)
177  uc->interrupt_callback = *int_cb;
178 
179  *puc = uc;
180  return 0;
181  fail:
182  *puc = NULL;
183 #if CONFIG_NETWORK
186 #endif
187  return err;
188 }
189 
191 {
192  int err =
193  uc->prot->url_open2 ? uc->prot->url_open2(uc, uc->filename, uc->flags, options) :
194  uc->prot->url_open(uc, uc->filename, uc->flags);
195  if (err)
196  return err;
197  uc->is_connected = 1;
198  //We must be careful here as ffurl_seek() could be slow, for example for http
199  if( (uc->flags & AVIO_FLAG_WRITE)
200  || !strcmp(uc->prot->name, "file"))
201  if(!uc->is_streamed && ffurl_seek(uc, 0, SEEK_SET) < 0)
202  uc->is_streamed= 1;
203  return 0;
204 }
205 
206 #define URL_SCHEME_CHARS \
207  "abcdefghijklmnopqrstuvwxyz" \
208  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
209  "0123456789+-."
210 
211 int ffurl_alloc(URLContext **puc, const char *filename, int flags,
212  const AVIOInterruptCB *int_cb)
213 {
214  URLProtocol *up = NULL;
215  char proto_str[128], proto_nested[128], *ptr;
216  size_t proto_len = strspn(filename, URL_SCHEME_CHARS);
217 
218  if (!first_protocol) {
219  av_log(NULL, AV_LOG_WARNING, "No URL Protocols are registered. "
220  "Missing call to av_register_all()?\n");
221  }
222 
223  if (filename[proto_len] != ':' &&
224  (filename[proto_len] != ',' || !strchr(filename + proto_len + 1, ':')) ||
225  is_dos_path(filename))
226  strcpy(proto_str, "file");
227  else
228  av_strlcpy(proto_str, filename, FFMIN(proto_len+1, sizeof(proto_str)));
229 
230  if ((ptr = strchr(proto_str, ',')))
231  *ptr = '\0';
232  av_strlcpy(proto_nested, proto_str, sizeof(proto_nested));
233  if ((ptr = strchr(proto_nested, '+')))
234  *ptr = '\0';
235 
236  while (up = ffurl_protocol_next(up)) {
237  if (!strcmp(proto_str, up->name))
238  return url_alloc_for_protocol (puc, up, filename, flags, int_cb);
240  !strcmp(proto_nested, up->name))
241  return url_alloc_for_protocol (puc, up, filename, flags, int_cb);
242  }
243  *puc = NULL;
245 }
246 
247 int ffurl_open(URLContext **puc, const char *filename, int flags,
248  const AVIOInterruptCB *int_cb, AVDictionary **options)
249 {
250  int ret = ffurl_alloc(puc, filename, flags, int_cb);
251  if (ret)
252  return ret;
253  if (options && (*puc)->prot->priv_data_class &&
254  (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0)
255  goto fail;
256  ret = ffurl_connect(*puc, options);
257  if (!ret)
258  return 0;
259 fail:
260  ffurl_close(*puc);
261  *puc = NULL;
262  return ret;
263 }
264 
265 static inline int retry_transfer_wrapper(URLContext *h, unsigned char *buf, int size, int size_min,
266  int (*transfer_func)(URLContext *h, unsigned char *buf, int size))
267 {
268  int ret, len;
269  int fast_retries = 5;
270  int64_t wait_since = 0;
271 
272  len = 0;
273  while (len < size_min) {
274  ret = transfer_func(h, buf+len, size-len);
275  if (ret == AVERROR(EINTR))
276  continue;
277  if (h->flags & AVIO_FLAG_NONBLOCK)
278  return ret;
279  if (ret == AVERROR(EAGAIN)) {
280  ret = 0;
281  if (fast_retries) {
282  fast_retries--;
283  } else {
284  if (h->rw_timeout) {
285  if (!wait_since)
286  wait_since = av_gettime();
287  else if (av_gettime() > wait_since + h->rw_timeout)
288  return AVERROR(EIO);
289  }
290  av_usleep(1000);
291  }
292  } else if (ret < 1)
293  return ret < 0 ? ret : len;
294  if (ret)
295  fast_retries = FFMAX(fast_retries, 2);
296  len += ret;
297  if (len < size && ff_check_interrupt(&h->interrupt_callback))
298  return AVERROR_EXIT;
299  }
300  return len;
301 }
302 
303 int ffurl_read(URLContext *h, unsigned char *buf, int size)
304 {
305  if (!(h->flags & AVIO_FLAG_READ))
306  return AVERROR(EIO);
307  return retry_transfer_wrapper(h, buf, size, 1, h->prot->url_read);
308 }
309 
310 int ffurl_read_complete(URLContext *h, unsigned char *buf, int size)
311 {
312  if (!(h->flags & AVIO_FLAG_READ))
313  return AVERROR(EIO);
314  return retry_transfer_wrapper(h, buf, size, size, h->prot->url_read);
315 }
316 
317 int ffurl_write(URLContext *h, const unsigned char *buf, int size)
318 {
319  if (!(h->flags & AVIO_FLAG_WRITE))
320  return AVERROR(EIO);
321  /* avoid sending too big packets */
322  if (h->max_packet_size && size > h->max_packet_size)
323  return AVERROR(EIO);
324 
325  return retry_transfer_wrapper(h, (unsigned char *)buf, size, size, (void*)h->prot->url_write);
326 }
327 
328 int64_t ffurl_seek(URLContext *h, int64_t pos, int whence)
329 {
330  int64_t ret;
331 
332  if (!h->prot->url_seek)
333  return AVERROR(ENOSYS);
334  ret = h->prot->url_seek(h, pos, whence & ~AVSEEK_FORCE);
335  return ret;
336 }
337 
339 {
340  URLContext *h= *hh;
341  int ret = 0;
342  if (!h) return 0; /* can happen when ffurl_open fails */
343 
344  if (h->is_connected && h->prot->url_close)
345  ret = h->prot->url_close(h);
346 #if CONFIG_NETWORK
349 #endif
350  if (h->prot->priv_data_size) {
351  if (h->prot->priv_data_class)
353  av_freep(&h->priv_data);
354  }
355  av_freep(hh);
356  return ret;
357 }
358 
360 {
361  return ffurl_closep(&h);
362 }
363 
364 
365 int avio_check(const char *url, int flags)
366 {
367  URLContext *h;
368  int ret = ffurl_alloc(&h, url, flags, NULL);
369  if (ret)
370  return ret;
371 
372  if (h->prot->url_check) {
373  ret = h->prot->url_check(h, flags);
374  } else {
375  ret = ffurl_connect(h, NULL);
376  if (ret >= 0)
377  ret = flags;
378  }
379 
380  ffurl_close(h);
381  return ret;
382 }
383 
385 {
386  int64_t pos, size;
387 
388  size= ffurl_seek(h, 0, AVSEEK_SIZE);
389  if(size<0){
390  pos = ffurl_seek(h, 0, SEEK_CUR);
391  if ((size = ffurl_seek(h, -1, SEEK_END)) < 0)
392  return size;
393  size++;
394  ffurl_seek(h, pos, SEEK_SET);
395  }
396  return size;
397 }
398 
400 {
401  if (!h->prot->url_get_file_handle)
402  return -1;
403  return h->prot->url_get_file_handle(h);
404 }
405 
406 int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles)
407 {
408  if (!h->prot->url_get_multi_file_handle) {
409  if (!h->prot->url_get_file_handle)
410  return AVERROR(ENOSYS);
411  *handles = av_malloc(sizeof(**handles));
412  if (!*handles)
413  return AVERROR(ENOMEM);
414  *numhandles = 1;
415  *handles[0] = h->prot->url_get_file_handle(h);
416  return 0;
417  }
418  return h->prot->url_get_multi_file_handle(h, handles, numhandles);
419 }
420 
422 {
423  if (!h->prot->url_shutdown)
424  return AVERROR(EINVAL);
425  return h->prot->url_shutdown(h, flags);
426 }
427 
429 {
430  int ret;
431  if (cb && cb->callback && (ret = cb->callback(cb->opaque)))
432  return ret;
433  return 0;
434 }
Definition: start.py:1
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:205
int ffurl_register_protocol(URLProtocol *protocol, int size)
Register the URLProtocol protocol.
Definition: avio.c:96
int(* url_write)(URLContext *h, const unsigned char *buf, int size)
Definition: url.h:77
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:35
AVOption.
Definition: opt.h:251
int flags
Definition: url.h:90
else temp
Definition: vf_mcdeint.c:148
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:317
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:48
static URLProtocol * first_protocol
Definition: avio.c:33
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
int ffurl_connect(URLContext *uc, AVDictionary **options)
Connect an URLContext that has been allocated by ffurl_alloc.
Definition: avio.c:190
AVIOInterruptCB interrupt_callback
Definition: url.h:50
void av_opt_set_defaults(void *s)
Set the values of all AVOption fields to their default values.
Definition: opt.c:942
int(* url_read)(URLContext *h, unsigned char *buf, int size)
Read data from the protocol.
Definition: url.h:76
#define AVIO_FLAG_READ
read-only
Definition: avio.h:332
int64_t rw_timeout
maximum time to wait for (network) read/write operation completion, in mcs
Definition: url.h:51
struct URLProtocol * prot
Definition: url.h:43
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:333
void ff_network_close(void)
Definition: network.c:173
int(* url_get_file_handle)(URLContext *h)
Definition: url.h:84
int flags
Definition: url.h:46
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:56
static void * urlcontext_child_next(void *obj, void *prev)
Definition: avio.c:49
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:62
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition: avio.c:421
#define URL_SCHEME_CHARS
Definition: avio.c:206
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:198
void * opaque
Definition: avio.h:53
const AVClass * priv_data_class
Definition: url.h:89
struct URLProtocol * next
Definition: url.h:80
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:365
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:55
Public dictionary API.
int ff_network_init(void)
Definition: network.c:126
AVOptions.
miscellaneous OS support macros and functions.
static int url_alloc_for_protocol(URLContext **puc, struct URLProtocol *up, const char *filename, int flags, const AVIOInterruptCB *int_cb)
Definition: avio.c:111
int(* url_shutdown)(URLContext *h, int flags)
Definition: url.h:87
static int retry_transfer_wrapper(URLContext *h, unsigned char *buf, int size, int size_min, int(*transfer_func)(URLContext *h, unsigned char *buf, int size))
Definition: avio.c:265
#define AVERROR_PROTOCOL_NOT_FOUND
Protocol not found.
Definition: error.h:63
int(* url_close)(URLContext *h)
Definition: url.h:79
int(* callback)(void *)
Definition: avio.h:52
Callback for checking whether to abort blocking functions.
Definition: avio.h:51
int ffurl_alloc(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb)
Create a URLContext for accessing to the resource indicated by url, but do not initiate the connectio...
Definition: avio.c:211
int(* url_get_multi_file_handle)(URLContext *h, int **handles, int *numhandles)
Definition: url.h:85
int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles)
Return the file descriptors associated with this URL.
Definition: avio.c:406
const AVIOInterruptCB int_cb
Definition: ffmpeg.c:422
#define URL_PROTOCOL_FLAG_NESTED_SCHEME
Definition: url.h:34
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
#define FFMAX(a, b)
Definition: common.h:56
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:82
static const char * urlcontext_to_name(void *ptr)
Definition: avio.c:42
int size
static const AVOption options[]
Definition: avio.c:74
URLProtocol * ffurl_protocol_next(URLProtocol *prev)
Iterate over all available protocols.
Definition: avio.c:35
#define FFMIN(a, b)
Definition: common.h:58
static const AVClass * urlcontext_child_class_next(const AVClass *prev)
Definition: avio.c:57
ret
Definition: avfilter.c:821
int(* url_check)(URLContext *h, int mask)
Definition: url.h:91
const char * avio_enum_protocols(void **opaque, int output)
Iterate through names of available protocols.
Definition: avio.c:86
int64_t(* url_seek)(URLContext *h, int64_t pos, int whence)
Definition: url.h:78
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:399
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:56
LIBAVUTIL_VERSION_INT
Definition: eval.c:55
int is_connected
Definition: url.h:49
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:338
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
NULL
Definition: eval.c:55
static int is_dos_path(const char *path)
Definition: os_support.h:61
int ff_check_interrupt(AVIOInterruptCB *cb)
Check if the user has requested to interrup a blocking function associated with cb.
Definition: avio.c:428
int av_opt_set_dict(void *obj, AVDictionary **options)
Set all the options from a given dictionary on an object.
Definition: opt.c:1202
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:351
FIXME Range Coding of cb
Definition: snow.txt:367
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
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:384
void * buf
Definition: avisynth_c.h:594
Definition: url.h:41
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:73
Describe the class of an AVClass context structure.
Definition: log.h:50
#define AVSEEK_FORCE
Oring this flag as into the "whence" parameter to a seek function causes it to seek by any means (lik...
Definition: avio.h:230
void * priv_data
Definition: url.h:44
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
const char * name
Definition: url.h:55
const AVClass * av_class
information for av_log().
Definition: url.h:42
static int flags
Definition: cpu.c:23
int ffurl_close(URLContext *h)
Definition: avio.c:359
const AVClass ffurl_context_class
Definition: avio.c:75
Main libavformat public API header.
int(* url_open)(URLContext *h, const char *url, int flags)
Definition: url.h:56
void av_opt_free(void *obj)
Free all string and binary options in obj.
Definition: opt.c:1194
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:328
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
Definition: avio.c:247
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:310
char * filename
specified URL
Definition: url.h:45
these buffered frames must be flushed immediately if a new input produces new output(Example:frame rate-doubling filter:filter_frame must(1) flush the second copy of the previous frame, if it is still there,(2) push the first copy of the incoming frame,(3) keep the second copy for later.) If the input frame is not enough to produce output
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
Definition: avio.h:222
#define AVERROR_OPTION_NOT_FOUND
Option not found.
Definition: error.h:61
int len
int max_packet_size
if non zero, the stream is packetized with this max packet size
Definition: url.h:47
void INT64 start
Definition: avisynth_c.h:594
unbuffered private I/O API
int priv_data_size
Definition: url.h:88
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:252
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:303