Commit | Line | Data |
---|---|---|
de6d9b64 FB |
1 | /* |
2 | * Buffered I/O for ffmpeg system | |
19720f15 | 3 | * Copyright (c) 2000,2001 Fabrice Bellard |
de6d9b64 | 4 | * |
b78e7197 DB |
5 | * This file is part of FFmpeg. |
6 | * | |
7 | * FFmpeg is free software; you can redistribute it and/or | |
19720f15 FB |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either | |
b78e7197 | 10 | * version 2.1 of the License, or (at your option) any later version. |
de6d9b64 | 11 | * |
b78e7197 | 12 | * FFmpeg is distributed in the hope that it will be useful, |
de6d9b64 | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19720f15 FB |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. | |
de6d9b64 | 16 | * |
19720f15 | 17 | * You should have received a copy of the GNU Lesser General Public |
b78e7197 | 18 | * License along with FFmpeg; if not, write to the Free Software |
5509bffa | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
de6d9b64 | 20 | */ |
de6d9b64 | 21 | #include "avformat.h" |
5c91a675 | 22 | #include "avio.h" |
992e78f5 | 23 | #include "crc.h" |
abba3dd1 | 24 | #include <stdarg.h> |
de6d9b64 FB |
25 | |
26 | #define IO_BUFFER_SIZE 32768 | |
27 | ||
398f5d3f MN |
28 | static void fill_buffer(ByteIOContext *s); |
29 | ||
de6d9b64 FB |
30 | int init_put_byte(ByteIOContext *s, |
31 | unsigned char *buffer, | |
32 | int buffer_size, | |
33 | int write_flag, | |
34 | void *opaque, | |
0c1a9eda | 35 | int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), |
576ae256 | 36 | int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), |
536ffa59 | 37 | offset_t (*seek)(void *opaque, offset_t offset, int whence)) |
de6d9b64 FB |
38 | { |
39 | s->buffer = buffer; | |
40 | s->buffer_size = buffer_size; | |
41 | s->buf_ptr = buffer; | |
770d9daf | 42 | url_resetbuf(s, write_flag ? URL_WRONLY : URL_RDONLY); |
de6d9b64 FB |
43 | s->opaque = opaque; |
44 | s->write_packet = write_packet; | |
45 | s->read_packet = read_packet; | |
46 | s->seek = seek; | |
47 | s->pos = 0; | |
48 | s->must_flush = 0; | |
49 | s->eof_reached = 0; | |
576ae256 | 50 | s->error = 0; |
de6d9b64 | 51 | s->is_streamed = 0; |
abba3dd1 | 52 | s->max_packet_size = 0; |
ee9f36a8 | 53 | s->update_checksum= NULL; |
942f3bb5 MN |
54 | if(!read_packet && !write_flag){ |
55 | s->pos = buffer_size; | |
56 | s->buf_end = s->buffer + buffer_size; | |
57 | } | |
de6d9b64 FB |
58 | return 0; |
59 | } | |
115329f1 | 60 | |
de6d9b64 FB |
61 | static void flush_buffer(ByteIOContext *s) |
62 | { | |
63 | if (s->buf_ptr > s->buffer) { | |
576ae256 MN |
64 | if (s->write_packet && !s->error){ |
65 | int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer); | |
66 | if(ret < 0){ | |
67 | s->error = ret; | |
68 | } | |
69 | } | |
465e1dad | 70 | if(s->update_checksum){ |
ee9f36a8 MN |
71 | s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); |
72 | s->checksum_ptr= s->buffer; | |
73 | } | |
de6d9b64 FB |
74 | s->pos += s->buf_ptr - s->buffer; |
75 | } | |
76 | s->buf_ptr = s->buffer; | |
77 | } | |
78 | ||
79 | void put_byte(ByteIOContext *s, int b) | |
80 | { | |
81 | *(s->buf_ptr)++ = b; | |
115329f1 | 82 | if (s->buf_ptr >= s->buf_end) |
de6d9b64 FB |
83 | flush_buffer(s); |
84 | } | |
85 | ||
75bdb984 | 86 | void put_buffer(ByteIOContext *s, const unsigned char *buf, int size) |
de6d9b64 FB |
87 | { |
88 | int len; | |
89 | ||
90 | while (size > 0) { | |
91 | len = (s->buf_end - s->buf_ptr); | |
92 | if (len > size) | |
93 | len = size; | |
94 | memcpy(s->buf_ptr, buf, len); | |
95 | s->buf_ptr += len; | |
96 | ||
115329f1 | 97 | if (s->buf_ptr >= s->buf_end) |
de6d9b64 FB |
98 | flush_buffer(s); |
99 | ||
100 | buf += len; | |
101 | size -= len; | |
102 | } | |
103 | } | |
104 | ||
105 | void put_flush_packet(ByteIOContext *s) | |
106 | { | |
107 | flush_buffer(s); | |
108 | s->must_flush = 0; | |
109 | } | |
110 | ||
111 | offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence) | |
112 | { | |
113 | offset_t offset1; | |
f40d1739 | 114 | offset_t pos= s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer)); |
de6d9b64 FB |
115 | |
116 | if (whence != SEEK_CUR && whence != SEEK_SET) | |
8fa36ae0 | 117 | return AVERROR(EINVAL); |
115329f1 | 118 | |
f40d1739 MN |
119 | if (whence == SEEK_CUR) { |
120 | offset1 = pos + (s->buf_ptr - s->buffer); | |
121 | if (offset == 0) | |
122 | return offset1; | |
123 | offset += offset1; | |
124 | } | |
125 | offset1 = offset - pos; | |
126 | if (!s->must_flush && | |
127 | offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) { | |
128 | /* can do the seek inside the buffer */ | |
129 | s->buf_ptr = s->buffer + offset1; | |
398f5d3f MN |
130 | } else if(s->is_streamed && !s->write_flag && |
131 | offset1 >= 0 && offset1 < (s->buf_end - s->buffer) + (1<<16)){ | |
132 | while(s->pos < offset && !s->eof_reached) | |
133 | fill_buffer(s); | |
134 | s->buf_ptr = s->buf_end + offset - s->pos; | |
f40d1739 | 135 | } else { |
8fa36ae0 | 136 | offset_t res = AVERROR(EPIPE); |
68fcdbf1 | 137 | |
8fa641f8 | 138 | #if defined(CONFIG_MUXERS) || defined(CONFIG_NETWORK) |
f40d1739 | 139 | if (s->write_flag) { |
de6d9b64 FB |
140 | flush_buffer(s); |
141 | s->must_flush = 1; | |
f40d1739 | 142 | } else |
8fa641f8 | 143 | #endif /* defined(CONFIG_MUXERS) || defined(CONFIG_NETWORK) */ |
f40d1739 | 144 | { |
de6d9b64 | 145 | s->buf_end = s->buffer; |
de6d9b64 | 146 | } |
f40d1739 | 147 | s->buf_ptr = s->buffer; |
68fcdbf1 RB |
148 | if (!s->seek || (res = s->seek(s->opaque, offset, SEEK_SET)) < 0) |
149 | return res; | |
f40d1739 | 150 | s->pos = offset; |
de6d9b64 | 151 | } |
f40d1739 | 152 | s->eof_reached = 0; |
de6d9b64 FB |
153 | return offset; |
154 | } | |
155 | ||
156 | void url_fskip(ByteIOContext *s, offset_t offset) | |
157 | { | |
158 | url_fseek(s, offset, SEEK_CUR); | |
159 | } | |
160 | ||
161 | offset_t url_ftell(ByteIOContext *s) | |
162 | { | |
163 | return url_fseek(s, 0, SEEK_CUR); | |
164 | } | |
165 | ||
a965c478 AJ |
166 | offset_t url_fsize(ByteIOContext *s) |
167 | { | |
168 | offset_t size; | |
115329f1 | 169 | |
a965c478 | 170 | if (!s->seek) |
8fa36ae0 | 171 | return AVERROR(EPIPE); |
8e287af0 MN |
172 | size = s->seek(s->opaque, 0, AVSEEK_SIZE); |
173 | if(size<0){ | |
8f42f523 RB |
174 | if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0) |
175 | return size; | |
176 | size++; | |
1ae2c5f2 | 177 | s->seek(s->opaque, s->pos, SEEK_SET); |
8e287af0 | 178 | } |
a965c478 AJ |
179 | return size; |
180 | } | |
181 | ||
de6d9b64 FB |
182 | int url_feof(ByteIOContext *s) |
183 | { | |
184 | return s->eof_reached; | |
185 | } | |
186 | ||
576ae256 MN |
187 | int url_ferror(ByteIOContext *s) |
188 | { | |
189 | return s->error; | |
190 | } | |
191 | ||
de6d9b64 FB |
192 | void put_le32(ByteIOContext *s, unsigned int val) |
193 | { | |
194 | put_byte(s, val); | |
195 | put_byte(s, val >> 8); | |
196 | put_byte(s, val >> 16); | |
197 | put_byte(s, val >> 24); | |
198 | } | |
199 | ||
200 | void put_be32(ByteIOContext *s, unsigned int val) | |
201 | { | |
202 | put_byte(s, val >> 24); | |
203 | put_byte(s, val >> 16); | |
204 | put_byte(s, val >> 8); | |
205 | put_byte(s, val); | |
206 | } | |
207 | ||
3b4b29dc | 208 | void put_strz(ByteIOContext *s, const char *str) |
75bdb984 PG |
209 | { |
210 | if (str) | |
211 | put_buffer(s, (const unsigned char *) str, strlen(str) + 1); | |
212 | else | |
213 | put_byte(s, 0); | |
214 | } | |
215 | ||
0c1a9eda | 216 | void put_le64(ByteIOContext *s, uint64_t val) |
de6d9b64 | 217 | { |
0c1a9eda ZK |
218 | put_le32(s, (uint32_t)(val & 0xffffffff)); |
219 | put_le32(s, (uint32_t)(val >> 32)); | |
de6d9b64 FB |
220 | } |
221 | ||
0c1a9eda | 222 | void put_be64(ByteIOContext *s, uint64_t val) |
de6d9b64 | 223 | { |
0c1a9eda ZK |
224 | put_be32(s, (uint32_t)(val >> 32)); |
225 | put_be32(s, (uint32_t)(val & 0xffffffff)); | |
de6d9b64 FB |
226 | } |
227 | ||
228 | void put_le16(ByteIOContext *s, unsigned int val) | |
229 | { | |
230 | put_byte(s, val); | |
231 | put_byte(s, val >> 8); | |
232 | } | |
233 | ||
234 | void put_be16(ByteIOContext *s, unsigned int val) | |
235 | { | |
236 | put_byte(s, val >> 8); | |
237 | put_byte(s, val); | |
238 | } | |
239 | ||
ea395e8c AJ |
240 | void put_le24(ByteIOContext *s, unsigned int val) |
241 | { | |
242 | put_le16(s, val & 0xffff); | |
243 | put_byte(s, val >> 16); | |
244 | } | |
245 | ||
a254c574 MN |
246 | void put_be24(ByteIOContext *s, unsigned int val) |
247 | { | |
248 | put_be16(s, val >> 8); | |
249 | put_byte(s, val); | |
250 | } | |
251 | ||
0570bf06 | 252 | void put_tag(ByteIOContext *s, const char *tag) |
de6d9b64 FB |
253 | { |
254 | while (*tag) { | |
255 | put_byte(s, *tag++); | |
256 | } | |
257 | } | |
258 | ||
259 | /* Input stream */ | |
260 | ||
261 | static void fill_buffer(ByteIOContext *s) | |
262 | { | |
602dd8f6 | 263 | int len=0; |
de6d9b64 | 264 | |
abba3dd1 FB |
265 | /* no need to do anything if EOF already reached */ |
266 | if (s->eof_reached) | |
267 | return; | |
ee9f36a8 | 268 | |
465e1dad | 269 | if(s->update_checksum){ |
0f0680c5 MN |
270 | if(s->buf_end > s->checksum_ptr) |
271 | s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr); | |
ee9f36a8 MN |
272 | s->checksum_ptr= s->buffer; |
273 | } | |
274 | ||
602dd8f6 | 275 | if(s->read_packet) |
2d89f334 | 276 | len = s->read_packet(s->opaque, s->buffer, s->buffer_size); |
abba3dd1 FB |
277 | if (len <= 0) { |
278 | /* do not modify buffer if EOF reached so that a seek back can | |
279 | be done without rereading data */ | |
de6d9b64 | 280 | s->eof_reached = 1; |
5f097703 AB |
281 | if(len<0) |
282 | s->error= len; | |
abba3dd1 FB |
283 | } else { |
284 | s->pos += len; | |
285 | s->buf_ptr = s->buffer; | |
286 | s->buf_end = s->buffer + len; | |
de6d9b64 FB |
287 | } |
288 | } | |
289 | ||
992e78f5 BC |
290 | unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, unsigned int len){ |
291 | return av_crc(av_crc04C11DB7, checksum, buf, len); | |
292 | } | |
293 | ||
ee9f36a8 MN |
294 | unsigned long get_checksum(ByteIOContext *s){ |
295 | s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); | |
465e1dad | 296 | s->update_checksum= NULL; |
ee9f36a8 MN |
297 | return s->checksum; |
298 | } | |
299 | ||
300 | void init_checksum(ByteIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum){ | |
301 | s->update_checksum= update_checksum; | |
465e1dad | 302 | if(s->update_checksum){ |
ccb15994 | 303 | s->checksum= checksum; |
465e1dad MN |
304 | s->checksum_ptr= s->buf_ptr; |
305 | } | |
ee9f36a8 MN |
306 | } |
307 | ||
abba3dd1 | 308 | /* XXX: put an inline version */ |
de6d9b64 FB |
309 | int get_byte(ByteIOContext *s) |
310 | { | |
311 | if (s->buf_ptr < s->buf_end) { | |
312 | return *s->buf_ptr++; | |
313 | } else { | |
314 | fill_buffer(s); | |
315 | if (s->buf_ptr < s->buf_end) | |
316 | return *s->buf_ptr++; | |
317 | else | |
318 | return 0; | |
319 | } | |
320 | } | |
321 | ||
abba3dd1 FB |
322 | int url_fgetc(ByteIOContext *s) |
323 | { | |
324 | if (s->buf_ptr < s->buf_end) { | |
325 | return *s->buf_ptr++; | |
326 | } else { | |
327 | fill_buffer(s); | |
328 | if (s->buf_ptr < s->buf_end) | |
329 | return *s->buf_ptr++; | |
330 | else | |
331 | return URL_EOF; | |
332 | } | |
333 | } | |
334 | ||
de6d9b64 FB |
335 | int get_buffer(ByteIOContext *s, unsigned char *buf, int size) |
336 | { | |
337 | int len, size1; | |
338 | ||
339 | size1 = size; | |
340 | while (size > 0) { | |
341 | len = s->buf_end - s->buf_ptr; | |
342 | if (len > size) | |
343 | len = size; | |
344 | if (len == 0) { | |
3e2b6358 | 345 | if(size > s->buffer_size && !s->update_checksum){ |
602dd8f6 | 346 | if(s->read_packet) |
2d89f334 | 347 | len = s->read_packet(s->opaque, buf, size); |
3e2b6358 MN |
348 | if (len <= 0) { |
349 | /* do not modify buffer if EOF reached so that a seek back can | |
350 | be done without rereading data */ | |
351 | s->eof_reached = 1; | |
352 | if(len<0) | |
353 | s->error= len; | |
354 | break; | |
355 | } else { | |
356 | s->pos += len; | |
357 | size -= len; | |
358 | buf += len; | |
359 | s->buf_ptr = s->buffer; | |
360 | s->buf_end = s->buffer/* + len*/; | |
361 | } | |
362 | }else{ | |
363 | fill_buffer(s); | |
364 | len = s->buf_end - s->buf_ptr; | |
365 | if (len == 0) | |
366 | break; | |
367 | } | |
de6d9b64 FB |
368 | } else { |
369 | memcpy(buf, s->buf_ptr, len); | |
370 | buf += len; | |
371 | s->buf_ptr += len; | |
372 | size -= len; | |
373 | } | |
374 | } | |
375 | return size1 - size; | |
376 | } | |
377 | ||
e15dec10 LS |
378 | int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size) |
379 | { | |
380 | int len; | |
115329f1 | 381 | |
0ecca7a4 MN |
382 | if(size<0) |
383 | return -1; | |
e15dec10 LS |
384 | |
385 | len = s->buf_end - s->buf_ptr; | |
386 | if (len == 0) { | |
387 | fill_buffer(s); | |
388 | len = s->buf_end - s->buf_ptr; | |
389 | } | |
390 | if (len > size) | |
391 | len = size; | |
392 | memcpy(buf, s->buf_ptr, len); | |
393 | s->buf_ptr += len; | |
394 | return len; | |
395 | } | |
396 | ||
de6d9b64 FB |
397 | unsigned int get_le16(ByteIOContext *s) |
398 | { | |
399 | unsigned int val; | |
400 | val = get_byte(s); | |
401 | val |= get_byte(s) << 8; | |
402 | return val; | |
403 | } | |
404 | ||
ea395e8c AJ |
405 | unsigned int get_le24(ByteIOContext *s) |
406 | { | |
407 | unsigned int val; | |
408 | val = get_le16(s); | |
409 | val |= get_byte(s) << 16; | |
410 | return val; | |
411 | } | |
412 | ||
de6d9b64 FB |
413 | unsigned int get_le32(ByteIOContext *s) |
414 | { | |
415 | unsigned int val; | |
a254c574 MN |
416 | val = get_le16(s); |
417 | val |= get_le16(s) << 16; | |
de6d9b64 FB |
418 | return val; |
419 | } | |
420 | ||
0c1a9eda | 421 | uint64_t get_le64(ByteIOContext *s) |
de6d9b64 | 422 | { |
0c1a9eda ZK |
423 | uint64_t val; |
424 | val = (uint64_t)get_le32(s); | |
425 | val |= (uint64_t)get_le32(s) << 32; | |
de6d9b64 FB |
426 | return val; |
427 | } | |
428 | ||
429 | unsigned int get_be16(ByteIOContext *s) | |
430 | { | |
431 | unsigned int val; | |
432 | val = get_byte(s) << 8; | |
433 | val |= get_byte(s); | |
434 | return val; | |
435 | } | |
436 | ||
a254c574 | 437 | unsigned int get_be24(ByteIOContext *s) |
de6d9b64 FB |
438 | { |
439 | unsigned int val; | |
a254c574 | 440 | val = get_be16(s) << 8; |
de6d9b64 FB |
441 | val |= get_byte(s); |
442 | return val; | |
443 | } | |
a254c574 MN |
444 | unsigned int get_be32(ByteIOContext *s) |
445 | { | |
446 | unsigned int val; | |
447 | val = get_be16(s) << 16; | |
448 | val |= get_be16(s); | |
449 | return val; | |
450 | } | |
de6d9b64 | 451 | |
3b4b29dc | 452 | char *get_strz(ByteIOContext *s, char *buf, int maxlen) |
75bdb984 PG |
453 | { |
454 | int i = 0; | |
455 | char c; | |
456 | ||
457 | while ((c = get_byte(s))) { | |
458 | if (i < maxlen-1) | |
459 | buf[i++] = c; | |
460 | } | |
115329f1 | 461 | |
75bdb984 PG |
462 | buf[i] = 0; /* Ensure null terminated, but may be truncated */ |
463 | ||
464 | return buf; | |
465 | } | |
466 | ||
0c1a9eda | 467 | uint64_t get_be64(ByteIOContext *s) |
de6d9b64 | 468 | { |
0c1a9eda ZK |
469 | uint64_t val; |
470 | val = (uint64_t)get_be32(s) << 32; | |
471 | val |= (uint64_t)get_be32(s); | |
de6d9b64 FB |
472 | return val; |
473 | } | |
474 | ||
7798b42d | 475 | uint64_t ff_get_v(ByteIOContext *bc){ |
897d3eef KS |
476 | uint64_t val = 0; |
477 | int tmp; | |
478 | ||
479 | do{ | |
480 | tmp = get_byte(bc); | |
481 | val= (val<<7) + (tmp&127); | |
482 | }while(tmp&128); | |
483 | return val; | |
484 | } | |
485 | ||
de6d9b64 FB |
486 | /* link with avio functions */ |
487 | ||
a9e35095 | 488 | #ifdef CONFIG_MUXERS |
576ae256 | 489 | static int url_write_packet(void *opaque, uint8_t *buf, int buf_size) |
de6d9b64 FB |
490 | { |
491 | URLContext *h = opaque; | |
576ae256 | 492 | return url_write(h, buf, buf_size); |
de6d9b64 | 493 | } |
764ef400 | 494 | #else |
bb270c08 | 495 | #define url_write_packet NULL |
a9e35095 | 496 | #endif //CONFIG_MUXERS |
de6d9b64 | 497 | |
0c1a9eda | 498 | static int url_read_packet(void *opaque, uint8_t *buf, int buf_size) |
de6d9b64 FB |
499 | { |
500 | URLContext *h = opaque; | |
501 | return url_read(h, buf, buf_size); | |
502 | } | |
503 | ||
536ffa59 | 504 | static offset_t url_seek_packet(void *opaque, offset_t offset, int whence) |
de6d9b64 FB |
505 | { |
506 | URLContext *h = opaque; | |
53e2f9ca MN |
507 | return url_seek(h, offset, whence); |
508 | //return 0; | |
de6d9b64 FB |
509 | } |
510 | ||
511 | int url_fdopen(ByteIOContext *s, URLContext *h) | |
512 | { | |
0c1a9eda | 513 | uint8_t *buffer; |
abba3dd1 | 514 | int buffer_size, max_packet_size; |
de6d9b64 | 515 | |
115329f1 | 516 | |
abba3dd1 FB |
517 | max_packet_size = url_get_max_packet_size(h); |
518 | if (max_packet_size) { | |
519 | buffer_size = max_packet_size; /* no need to bufferize more than one packet */ | |
520 | } else { | |
521 | buffer_size = IO_BUFFER_SIZE; | |
522 | } | |
1ea4f593 | 523 | buffer = av_malloc(buffer_size); |
de6d9b64 | 524 | if (!buffer) |
8fa36ae0 | 525 | return AVERROR(ENOMEM); |
de6d9b64 | 526 | |
115329f1 | 527 | if (init_put_byte(s, buffer, buffer_size, |
ac9fe33d | 528 | (h->flags & URL_WRONLY || h->flags & URL_RDWR), h, |
de6d9b64 | 529 | url_read_packet, url_write_packet, url_seek_packet) < 0) { |
1ea4f593 | 530 | av_free(buffer); |
6f3e0b21 | 531 | return AVERROR(EIO); |
de6d9b64 FB |
532 | } |
533 | s->is_streamed = h->is_streamed; | |
abba3dd1 | 534 | s->max_packet_size = max_packet_size; |
de6d9b64 FB |
535 | return 0; |
536 | } | |
537 | ||
de6d9b64 FB |
538 | int url_setbufsize(ByteIOContext *s, int buf_size) |
539 | { | |
0c1a9eda | 540 | uint8_t *buffer; |
1ea4f593 | 541 | buffer = av_malloc(buf_size); |
de6d9b64 | 542 | if (!buffer) |
8fa36ae0 | 543 | return AVERROR(ENOMEM); |
de6d9b64 | 544 | |
1ea4f593 | 545 | av_free(s->buffer); |
de6d9b64 FB |
546 | s->buffer = buffer; |
547 | s->buffer_size = buf_size; | |
548 | s->buf_ptr = buffer; | |
770d9daf BA |
549 | url_resetbuf(s, s->write_flag ? URL_WRONLY : URL_RDONLY); |
550 | return 0; | |
551 | } | |
552 | ||
553 | int url_resetbuf(ByteIOContext *s, int flags) | |
554 | { | |
555 | URLContext *h = s->opaque; | |
556 | if ((flags & URL_RDWR) || (h && h->flags != flags && !h->flags & URL_RDWR)) | |
557 | return AVERROR(EINVAL); | |
558 | ||
559 | if (flags & URL_WRONLY) { | |
560 | s->buf_end = s->buffer + s->buffer_size; | |
561 | s->write_flag = 1; | |
562 | } else { | |
563 | s->buf_end = s->buffer; | |
564 | s->write_flag = 0; | |
565 | } | |
de6d9b64 FB |
566 | return 0; |
567 | } | |
568 | ||
569 | int url_fopen(ByteIOContext *s, const char *filename, int flags) | |
570 | { | |
571 | URLContext *h; | |
572 | int err; | |
573 | ||
574 | err = url_open(&h, filename, flags); | |
575 | if (err < 0) | |
576 | return err; | |
577 | err = url_fdopen(s, h); | |
578 | if (err < 0) { | |
579 | url_close(h); | |
580 | return err; | |
581 | } | |
582 | return 0; | |
583 | } | |
584 | ||
585 | int url_fclose(ByteIOContext *s) | |
586 | { | |
587 | URLContext *h = s->opaque; | |
115329f1 | 588 | |
1ea4f593 | 589 | av_free(s->buffer); |
de6d9b64 FB |
590 | memset(s, 0, sizeof(ByteIOContext)); |
591 | return url_close(h); | |
592 | } | |
593 | ||
594 | URLContext *url_fileno(ByteIOContext *s) | |
595 | { | |
596 | return s->opaque; | |
597 | } | |
598 | ||
a9e35095 | 599 | #ifdef CONFIG_MUXERS |
abba3dd1 FB |
600 | int url_fprintf(ByteIOContext *s, const char *fmt, ...) |
601 | { | |
602 | va_list ap; | |
603 | char buf[4096]; | |
604 | int ret; | |
605 | ||
606 | va_start(ap, fmt); | |
607 | ret = vsnprintf(buf, sizeof(buf), fmt, ap); | |
608 | va_end(ap); | |
609 | put_buffer(s, buf, strlen(buf)); | |
610 | return ret; | |
611 | } | |
a9e35095 | 612 | #endif //CONFIG_MUXERS |
abba3dd1 | 613 | |
abba3dd1 FB |
614 | char *url_fgets(ByteIOContext *s, char *buf, int buf_size) |
615 | { | |
616 | int c; | |
617 | char *q; | |
618 | ||
619 | c = url_fgetc(s); | |
620 | if (c == EOF) | |
621 | return NULL; | |
622 | q = buf; | |
623 | for(;;) { | |
624 | if (c == EOF || c == '\n') | |
625 | break; | |
626 | if ((q - buf) < buf_size - 1) | |
627 | *q++ = c; | |
628 | c = url_fgetc(s); | |
629 | } | |
630 | if (buf_size > 0) | |
631 | *q = '\0'; | |
632 | return buf; | |
633 | } | |
634 | ||
abba3dd1 FB |
635 | int url_fget_max_packet_size(ByteIOContext *s) |
636 | { | |
637 | return s->max_packet_size; | |
638 | } | |
639 | ||
8fa641f8 LLL |
640 | /* url_open_dyn_buf and url_close_dyn_buf are used in rtp.c to send a response |
641 | * back to the server even if CONFIG_MUXERS is not set. */ | |
642 | #if defined(CONFIG_MUXERS) || defined(CONFIG_NETWORK) | |
de6d9b64 | 643 | /* buffer handling */ |
0c1a9eda | 644 | int url_open_buf(ByteIOContext *s, uint8_t *buf, int buf_size, int flags) |
de6d9b64 | 645 | { |
115329f1 | 646 | return init_put_byte(s, buf, buf_size, |
ac9fe33d GB |
647 | (flags & URL_WRONLY || flags & URL_RDWR), |
648 | NULL, NULL, NULL, NULL); | |
de6d9b64 FB |
649 | } |
650 | ||
de6d9b64 FB |
651 | int url_close_buf(ByteIOContext *s) |
652 | { | |
abba3dd1 | 653 | put_flush_packet(s); |
de6d9b64 FB |
654 | return s->buf_ptr - s->buffer; |
655 | } | |
abba3dd1 FB |
656 | |
657 | /* output in a dynamic buffer */ | |
658 | ||
659 | typedef struct DynBuffer { | |
660 | int pos, size, allocated_size; | |
0c1a9eda | 661 | uint8_t *buffer; |
abba3dd1 | 662 | int io_buffer_size; |
0c1a9eda | 663 | uint8_t io_buffer[1]; |
abba3dd1 FB |
664 | } DynBuffer; |
665 | ||
576ae256 | 666 | static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size) |
abba3dd1 FB |
667 | { |
668 | DynBuffer *d = opaque; | |
669 | int new_size, new_allocated_size; | |
115329f1 | 670 | |
abba3dd1 FB |
671 | /* reallocate buffer if needed */ |
672 | new_size = d->pos + buf_size; | |
673 | new_allocated_size = d->allocated_size; | |
568e18b1 MN |
674 | if(new_size < d->pos || new_size > INT_MAX/2) |
675 | return -1; | |
abba3dd1 FB |
676 | while (new_size > new_allocated_size) { |
677 | if (!new_allocated_size) | |
678 | new_allocated_size = new_size; | |
679 | else | |
115329f1 | 680 | new_allocated_size += new_allocated_size / 2 + 1; |
abba3dd1 | 681 | } |
115329f1 | 682 | |
abba3dd1 | 683 | if (new_allocated_size > d->allocated_size) { |
b88ba823 MH |
684 | d->buffer = av_realloc(d->buffer, new_allocated_size); |
685 | if(d->buffer == NULL) | |
576ae256 | 686 | return -1234; |
abba3dd1 FB |
687 | d->allocated_size = new_allocated_size; |
688 | } | |
689 | memcpy(d->buffer + d->pos, buf, buf_size); | |
690 | d->pos = new_size; | |
691 | if (d->pos > d->size) | |
692 | d->size = d->pos; | |
576ae256 | 693 | return buf_size; |
abba3dd1 FB |
694 | } |
695 | ||
576ae256 | 696 | static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size) |
abba3dd1 FB |
697 | { |
698 | unsigned char buf1[4]; | |
576ae256 | 699 | int ret; |
abba3dd1 FB |
700 | |
701 | /* packetized write: output the header */ | |
702 | buf1[0] = (buf_size >> 24); | |
703 | buf1[1] = (buf_size >> 16); | |
704 | buf1[2] = (buf_size >> 8); | |
705 | buf1[3] = (buf_size); | |
576ae256 MN |
706 | ret= dyn_buf_write(opaque, buf1, 4); |
707 | if(ret < 0) | |
708 | return ret; | |
abba3dd1 FB |
709 | |
710 | /* then the data */ | |
576ae256 | 711 | return dyn_buf_write(opaque, buf, buf_size); |
abba3dd1 FB |
712 | } |
713 | ||
536ffa59 | 714 | static offset_t dyn_buf_seek(void *opaque, offset_t offset, int whence) |
abba3dd1 FB |
715 | { |
716 | DynBuffer *d = opaque; | |
717 | ||
718 | if (whence == SEEK_CUR) | |
719 | offset += d->pos; | |
720 | else if (whence == SEEK_END) | |
721 | offset += d->size; | |
722 | if (offset < 0 || offset > 0x7fffffffLL) | |
723 | return -1; | |
724 | d->pos = offset; | |
725 | return 0; | |
726 | } | |
727 | ||
728 | static int url_open_dyn_buf_internal(ByteIOContext *s, int max_packet_size) | |
729 | { | |
730 | DynBuffer *d; | |
731 | int io_buffer_size, ret; | |
115329f1 DB |
732 | |
733 | if (max_packet_size) | |
abba3dd1 FB |
734 | io_buffer_size = max_packet_size; |
735 | else | |
736 | io_buffer_size = 1024; | |
115329f1 | 737 | |
568e18b1 MN |
738 | if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size) |
739 | return -1; | |
abba3dd1 FB |
740 | d = av_malloc(sizeof(DynBuffer) + io_buffer_size); |
741 | if (!d) | |
742 | return -1; | |
743 | d->io_buffer_size = io_buffer_size; | |
744 | d->buffer = NULL; | |
745 | d->pos = 0; | |
746 | d->size = 0; | |
747 | d->allocated_size = 0; | |
115329f1 DB |
748 | ret = init_put_byte(s, d->io_buffer, io_buffer_size, |
749 | 1, d, NULL, | |
750 | max_packet_size ? dyn_packet_buf_write : dyn_buf_write, | |
abba3dd1 FB |
751 | max_packet_size ? NULL : dyn_buf_seek); |
752 | if (ret == 0) { | |
753 | s->max_packet_size = max_packet_size; | |
754 | } | |
755 | return ret; | |
756 | } | |
757 | ||
abba3dd1 FB |
758 | int url_open_dyn_buf(ByteIOContext *s) |
759 | { | |
760 | return url_open_dyn_buf_internal(s, 0); | |
761 | } | |
762 | ||
abba3dd1 FB |
763 | int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size) |
764 | { | |
765 | if (max_packet_size <= 0) | |
766 | return -1; | |
767 | return url_open_dyn_buf_internal(s, max_packet_size); | |
768 | } | |
769 | ||
0c1a9eda | 770 | int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer) |
abba3dd1 FB |
771 | { |
772 | DynBuffer *d = s->opaque; | |
773 | int size; | |
774 | ||
775 | put_flush_packet(s); | |
776 | ||
777 | *pbuffer = d->buffer; | |
778 | size = d->size; | |
779 | av_free(d); | |
780 | return size; | |
781 | } | |
8fa641f8 | 782 | #endif /* CONFIG_MUXERS || CONFIG_NETWORK */ |