ffmpeg / libavformat / avio.c @ f1d2b572
History | View | Annotate | Download (6.66 KB)
1 | de6d9b64 | Fabrice Bellard | /*
|
---|---|---|---|
2 | * Unbuffered io for ffmpeg system
|
||
3 | 19720f15 | Fabrice Bellard | * Copyright (c) 2001 Fabrice Bellard
|
4 | de6d9b64 | Fabrice Bellard | *
|
5 | b78e7197 | Diego Biurrun | * This file is part of FFmpeg.
|
6 | *
|
||
7 | * FFmpeg is free software; you can redistribute it and/or
|
||
8 | 19720f15 | Fabrice Bellard | * modify it under the terms of the GNU Lesser General Public
|
9 | * License as published by the Free Software Foundation; either
|
||
10 | b78e7197 | Diego Biurrun | * version 2.1 of the License, or (at your option) any later version.
|
11 | de6d9b64 | Fabrice Bellard | *
|
12 | b78e7197 | Diego Biurrun | * FFmpeg is distributed in the hope that it will be useful,
|
13 | de6d9b64 | Fabrice Bellard | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | 19720f15 | Fabrice Bellard | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 | * Lesser General Public License for more details.
|
||
16 | de6d9b64 | Fabrice Bellard | *
|
17 | 19720f15 | Fabrice Bellard | * You should have received a copy of the GNU Lesser General Public
|
18 | b78e7197 | Diego Biurrun | * License along with FFmpeg; if not, write to the Free Software
|
19 | 5509bffa | Diego Biurrun | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
20 | de6d9b64 | Fabrice Bellard | */
|
21 | 245976da | Diego Biurrun | |
22 | f1d2b572 | Reimar Döffinger | /* needed for usleep() */
|
23 | #define _XOPEN_SOURCE 600 |
||
24 | #include <unistd.h> |
||
25 | 245976da | Diego Biurrun | #include "libavutil/avstring.h" |
26 | #include "libavcodec/opt.h" |
||
27 | bc574408 | Ramiro Polla | #include "os_support.h" |
28 | de6d9b64 | Fabrice Bellard | #include "avformat.h" |
29 | 5acef35f | Björn Axelsson | |
30 | #if LIBAVFORMAT_VERSION_MAJOR >= 53 |
||
31 | /** @name Logging context. */
|
||
32 | /*@{*/
|
||
33 | static const char *urlcontext_to_name(void *ptr) |
||
34 | { |
||
35 | URLContext *h = (URLContext *)ptr; |
||
36 | if(h->prot) return h->prot->name; |
||
37 | else return "NULL"; |
||
38 | } |
||
39 | static const AVOption options[] = {{NULL}}; |
||
40 | static const AVClass urlcontext_class = |
||
41 | { "URLContext", urlcontext_to_name, options };
|
||
42 | /*@}*/
|
||
43 | #endif
|
||
44 | de6d9b64 | Fabrice Bellard | |
45 | 019ac05a | Fabrice Bellard | static int default_interrupt_cb(void); |
46 | |||
47 | de6d9b64 | Fabrice Bellard | URLProtocol *first_protocol = NULL;
|
48 | 019ac05a | Fabrice Bellard | URLInterruptCB *url_interrupt_cb = default_interrupt_cb; |
49 | de6d9b64 | Fabrice Bellard | |
50 | 84be6e72 | Michael Niedermayer | URLProtocol *av_protocol_next(URLProtocol *p) |
51 | { |
||
52 | if(p) return p->next; |
||
53 | else return first_protocol; |
||
54 | } |
||
55 | |||
56 | 65c40e4e | Stefano Sabatini | int av_register_protocol(URLProtocol *protocol)
|
57 | de6d9b64 | Fabrice Bellard | { |
58 | URLProtocol **p; |
||
59 | p = &first_protocol; |
||
60 | while (*p != NULL) p = &(*p)->next; |
||
61 | *p = protocol; |
||
62 | protocol->next = NULL;
|
||
63 | return 0; |
||
64 | } |
||
65 | |||
66 | 65c40e4e | Stefano Sabatini | #if LIBAVFORMAT_VERSION_MAJOR < 53 |
67 | int register_protocol(URLProtocol *protocol)
|
||
68 | { |
||
69 | return av_register_protocol(protocol);
|
||
70 | } |
||
71 | #endif
|
||
72 | |||
73 | ba99cfc2 | Ronald S. Bultje | int url_open_protocol (URLContext **puc, struct URLProtocol *up, |
74 | const char *filename, int flags) |
||
75 | de6d9b64 | Fabrice Bellard | { |
76 | URLContext *uc; |
||
77 | int err;
|
||
78 | |||
79 | 62181004 | Ronald S. Bultje | uc = av_malloc(sizeof(URLContext) + strlen(filename) + 1); |
80 | 8a9488b5 | Fabrice Bellard | if (!uc) {
|
81 | 8fa36ae0 | François Revol | err = AVERROR(ENOMEM); |
82 | 8a9488b5 | Fabrice Bellard | goto fail;
|
83 | } |
||
84 | 5acef35f | Björn Axelsson | #if LIBAVFORMAT_VERSION_MAJOR >= 53 |
85 | uc->av_class = &urlcontext_class; |
||
86 | #endif
|
||
87 | 62181004 | Ronald S. Bultje | uc->filename = (char *) &uc[1]; |
88 | f746a046 | Fabrice Bellard | strcpy(uc->filename, filename); |
89 | de6d9b64 | Fabrice Bellard | uc->prot = up; |
90 | uc->flags = flags; |
||
91 | uc->is_streamed = 0; /* default = not streamed */ |
||
92 | 8a9488b5 | Fabrice Bellard | uc->max_packet_size = 0; /* default: stream file */ |
93 | de6d9b64 | Fabrice Bellard | err = up->url_open(uc, filename, flags); |
94 | if (err < 0) { |
||
95 | 1ea4f593 | Fabrice Bellard | av_free(uc); |
96 | de6d9b64 | Fabrice Bellard | *puc = NULL;
|
97 | return err;
|
||
98 | } |
||
99 | abbae514 | Michael Niedermayer | |
100 | 48fdb66c | Måns Rullgård | //We must be careful here as url_seek() could be slow, for example for http
|
101 | abbae514 | Michael Niedermayer | if( (flags & (URL_WRONLY | URL_RDWR))
|
102 | ba99cfc2 | Ronald S. Bultje | || !strcmp(up->name, "file"))
|
103 | abbae514 | Michael Niedermayer | if(!uc->is_streamed && url_seek(uc, 0, SEEK_SET) < 0) |
104 | uc->is_streamed= 1;
|
||
105 | de6d9b64 | Fabrice Bellard | *puc = uc; |
106 | return 0; |
||
107 | 8a9488b5 | Fabrice Bellard | fail:
|
108 | *puc = NULL;
|
||
109 | return err;
|
||
110 | de6d9b64 | Fabrice Bellard | } |
111 | |||
112 | ba99cfc2 | Ronald S. Bultje | int url_open(URLContext **puc, const char *filename, int flags) |
113 | { |
||
114 | URLProtocol *up; |
||
115 | const char *p; |
||
116 | char proto_str[128], *q; |
||
117 | |||
118 | p = filename; |
||
119 | q = proto_str; |
||
120 | while (*p != '\0' && *p != ':') { |
||
121 | /* protocols can only contain alphabetic chars */
|
||
122 | if (!isalpha(*p))
|
||
123 | goto file_proto;
|
||
124 | if ((q - proto_str) < sizeof(proto_str) - 1) |
||
125 | *q++ = *p; |
||
126 | p++; |
||
127 | } |
||
128 | /* if the protocol has length 1, we consider it is a dos drive */
|
||
129 | bc574408 | Ramiro Polla | if (*p == '\0' || is_dos_path(filename)) { |
130 | ba99cfc2 | Ronald S. Bultje | file_proto:
|
131 | strcpy(proto_str, "file");
|
||
132 | } else {
|
||
133 | *q = '\0';
|
||
134 | } |
||
135 | |||
136 | up = first_protocol; |
||
137 | while (up != NULL) { |
||
138 | if (!strcmp(proto_str, up->name))
|
||
139 | return url_open_protocol (puc, up, filename, flags);
|
||
140 | up = up->next; |
||
141 | } |
||
142 | *puc = NULL;
|
||
143 | return AVERROR(ENOENT);
|
||
144 | } |
||
145 | |||
146 | de6d9b64 | Fabrice Bellard | int url_read(URLContext *h, unsigned char *buf, int size) |
147 | { |
||
148 | int ret;
|
||
149 | if (h->flags & URL_WRONLY)
|
||
150 | 6f3e0b21 | Panagiotis Issaris | return AVERROR(EIO);
|
151 | de6d9b64 | Fabrice Bellard | ret = h->prot->url_read(h, buf, size); |
152 | return ret;
|
||
153 | } |
||
154 | |||
155 | 0e848977 | Kostya Shishkov | int url_read_complete(URLContext *h, unsigned char *buf, int size) |
156 | { |
||
157 | int ret, len;
|
||
158 | f1d2b572 | Reimar Döffinger | int fast_retries = 5; |
159 | 0e848977 | Kostya Shishkov | |
160 | len = 0;
|
||
161 | while (len < size) {
|
||
162 | ret = url_read(h, buf+len, size-len); |
||
163 | ddb901b7 | Reimar Döffinger | if (ret == AVERROR(EAGAIN)) {
|
164 | ret = 0;
|
||
165 | f1d2b572 | Reimar Döffinger | if (fast_retries)
|
166 | fast_retries--; |
||
167 | else
|
||
168 | usleep(1000);
|
||
169 | ddb901b7 | Reimar Döffinger | } else if (ret < 1) |
170 | return ret < 0 ? ret : len; |
||
171 | f1d2b572 | Reimar Döffinger | if (ret)
|
172 | fast_retries = FFMAX(fast_retries, 2);
|
||
173 | 0e848977 | Kostya Shishkov | len += ret; |
174 | } |
||
175 | return len;
|
||
176 | } |
||
177 | |||
178 | de6d9b64 | Fabrice Bellard | int url_write(URLContext *h, unsigned char *buf, int size) |
179 | { |
||
180 | int ret;
|
||
181 | 8a9488b5 | Fabrice Bellard | if (!(h->flags & (URL_WRONLY | URL_RDWR)))
|
182 | 6f3e0b21 | Panagiotis Issaris | return AVERROR(EIO);
|
183 | 8a9488b5 | Fabrice Bellard | /* avoid sending too big packets */
|
184 | if (h->max_packet_size && size > h->max_packet_size)
|
||
185 | 6f3e0b21 | Panagiotis Issaris | return AVERROR(EIO);
|
186 | de6d9b64 | Fabrice Bellard | ret = h->prot->url_write(h, buf, size); |
187 | return ret;
|
||
188 | } |
||
189 | |||
190 | bc5c918e | Diego Biurrun | int64_t url_seek(URLContext *h, int64_t pos, int whence)
|
191 | de6d9b64 | Fabrice Bellard | { |
192 | bc5c918e | Diego Biurrun | int64_t ret; |
193 | de6d9b64 | Fabrice Bellard | |
194 | if (!h->prot->url_seek)
|
||
195 | 8fa36ae0 | François Revol | return AVERROR(EPIPE);
|
196 | de6d9b64 | Fabrice Bellard | ret = h->prot->url_seek(h, pos, whence); |
197 | return ret;
|
||
198 | } |
||
199 | |||
200 | int url_close(URLContext *h)
|
||
201 | { |
||
202 | 7a813b36 | Alex Beregszaszi | int ret = 0; |
203 | 346db900 | Thorsten Jordan | if (!h) return 0; /* can happen when url_open fails */ |
204 | de6d9b64 | Fabrice Bellard | |
205 | 7a813b36 | Alex Beregszaszi | if (h->prot->url_close)
|
206 | ret = h->prot->url_close(h); |
||
207 | 1ea4f593 | Fabrice Bellard | av_free(h); |
208 | de6d9b64 | Fabrice Bellard | return ret;
|
209 | } |
||
210 | |||
211 | int url_exist(const char *filename) |
||
212 | { |
||
213 | URLContext *h; |
||
214 | if (url_open(&h, filename, URL_RDONLY) < 0) |
||
215 | return 0; |
||
216 | url_close(h); |
||
217 | return 1; |
||
218 | } |
||
219 | |||
220 | bc5c918e | Diego Biurrun | int64_t url_filesize(URLContext *h) |
221 | de6d9b64 | Fabrice Bellard | { |
222 | bc5c918e | Diego Biurrun | int64_t pos, size; |
223 | 115329f1 | Diego Biurrun | |
224 | 8e287af0 | Michael Niedermayer | size= url_seek(h, 0, AVSEEK_SIZE);
|
225 | if(size<0){ |
||
226 | 1ae2c5f2 | Michael Niedermayer | pos = url_seek(h, 0, SEEK_CUR);
|
227 | eabbae73 | Ronald S. Bultje | if ((size = url_seek(h, -1, SEEK_END)) < 0) |
228 | return size;
|
||
229 | size++; |
||
230 | 1ae2c5f2 | Michael Niedermayer | url_seek(h, pos, SEEK_SET); |
231 | 8e287af0 | Michael Niedermayer | } |
232 | de6d9b64 | Fabrice Bellard | return size;
|
233 | } |
||
234 | 8a9488b5 | Fabrice Bellard | |
235 | f0a80394 | Ronald S. Bultje | int url_get_file_handle(URLContext *h)
|
236 | { |
||
237 | if (!h->prot->url_get_file_handle)
|
||
238 | return -1; |
||
239 | return h->prot->url_get_file_handle(h);
|
||
240 | } |
||
241 | |||
242 | 8a9488b5 | Fabrice Bellard | int url_get_max_packet_size(URLContext *h)
|
243 | { |
||
244 | return h->max_packet_size;
|
||
245 | } |
||
246 | f746a046 | Fabrice Bellard | |
247 | void url_get_filename(URLContext *h, char *buf, int buf_size) |
||
248 | { |
||
249 | 75e61b0e | Måns Rullgård | av_strlcpy(buf, h->filename, buf_size); |
250 | f746a046 | Fabrice Bellard | } |
251 | 019ac05a | Fabrice Bellard | |
252 | |||
253 | static int default_interrupt_cb(void) |
||
254 | { |
||
255 | return 0; |
||
256 | } |
||
257 | |||
258 | void url_set_interrupt_cb(URLInterruptCB *interrupt_cb)
|
||
259 | { |
||
260 | if (!interrupt_cb)
|
||
261 | interrupt_cb = default_interrupt_cb; |
||
262 | url_interrupt_cb = interrupt_cb; |
||
263 | } |
||
264 | 536333a0 | Björn Axelsson | |
265 | 502bdf68 | Michael Niedermayer | int av_url_read_pause(URLContext *h, int pause) |
266 | 536333a0 | Björn Axelsson | { |
267 | if (!h->prot->url_read_pause)
|
||
268 | return AVERROR(ENOSYS);
|
||
269 | 502bdf68 | Michael Niedermayer | return h->prot->url_read_pause(h, pause);
|
270 | 536333a0 | Björn Axelsson | } |
271 | |||
272 | bc5c918e | Diego Biurrun | int64_t av_url_read_seek(URLContext *h, |
273 | 536333a0 | Björn Axelsson | int stream_index, int64_t timestamp, int flags) |
274 | { |
||
275 | if (!h->prot->url_read_seek)
|
||
276 | return AVERROR(ENOSYS);
|
||
277 | return h->prot->url_read_seek(h, stream_index, timestamp, flags);
|
||
278 | } |