ffmpeg / libavformat / aviobuf.c @ 90ed2776
History | View | Annotate | Download (25 KB)
1 | de6d9b64 | Fabrice Bellard | /*
|
---|---|---|---|
2 | * Buffered I/O for ffmpeg system
|
||
3 | 19720f15 | Fabrice Bellard | * Copyright (c) 2000,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 | #include "libavutil/crc.h" |
||
23 | aa805f94 | Reimar Döffinger | #include "libavutil/intreadwrite.h" |
24 | de6d9b64 | Fabrice Bellard | #include "avformat.h" |
25 | 5c91a675 | Zdenek Kabelac | #include "avio.h" |
26 | ae99313a | Anton Khirnov | #include "avio_internal.h" |
27 | 603e5c0b | Michael Chinen | #include "internal.h" |
28 | abba3dd1 | Fabrice Bellard | #include <stdarg.h> |
29 | de6d9b64 | Fabrice Bellard | |
30 | #define IO_BUFFER_SIZE 32768 |
||
31 | |||
32 | 7939d0ed | Martin Storsjö | /**
|
33 | * Do seeks within this distance ahead of the current buffer by skipping
|
||
34 | * data instead of calling the protocol seek function, for seekable
|
||
35 | * protocols.
|
||
36 | */
|
||
37 | #define SHORT_SEEK_THRESHOLD 4096 |
||
38 | |||
39 | 471fe57e | Anton Khirnov | static void fill_buffer(AVIOContext *s); |
40 | 364cacc7 | Aurelien Jacobs | #if !FF_API_URL_RESETBUF
|
41 | 471fe57e | Anton Khirnov | static int url_resetbuf(AVIOContext *s, int flags); |
42 | 08580cb0 | Benoit Fouet | #endif
|
43 | 398f5d3f | Michael Niedermayer | |
44 | ae99313a | Anton Khirnov | int ffio_init_context(AVIOContext *s,
|
45 | de6d9b64 | Fabrice Bellard | unsigned char *buffer, |
46 | int buffer_size,
|
||
47 | int write_flag,
|
||
48 | void *opaque,
|
||
49 | 0c1a9eda | Zdenek Kabelac | int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), |
50 | 576ae256 | Michael Niedermayer | int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), |
51 | bc5c918e | Diego Biurrun | int64_t (*seek)(void *opaque, int64_t offset, int whence)) |
52 | de6d9b64 | Fabrice Bellard | { |
53 | s->buffer = buffer; |
||
54 | s->buffer_size = buffer_size; |
||
55 | s->buf_ptr = buffer; |
||
56 | s->opaque = opaque; |
||
57 | 9daa4cea | Aurelien Jacobs | url_resetbuf(s, write_flag ? URL_WRONLY : URL_RDONLY); |
58 | de6d9b64 | Fabrice Bellard | s->write_packet = write_packet; |
59 | s->read_packet = read_packet; |
||
60 | s->seek = seek; |
||
61 | s->pos = 0;
|
||
62 | s->must_flush = 0;
|
||
63 | s->eof_reached = 0;
|
||
64 | 576ae256 | Michael Niedermayer | s->error = 0;
|
65 | de6d9b64 | Fabrice Bellard | s->is_streamed = 0;
|
66 | abba3dd1 | Fabrice Bellard | s->max_packet_size = 0;
|
67 | ee9f36a8 | Michael Niedermayer | s->update_checksum= NULL;
|
68 | 942f3bb5 | Michael Niedermayer | if(!read_packet && !write_flag){
|
69 | s->pos = buffer_size; |
||
70 | s->buf_end = s->buffer + buffer_size; |
||
71 | } |
||
72 | e7e4810a | Björn Axelsson | s->read_pause = NULL;
|
73 | s->read_seek = NULL;
|
||
74 | de6d9b64 | Fabrice Bellard | return 0; |
75 | } |
||
76 | 115329f1 | Diego Biurrun | |
77 | ae99313a | Anton Khirnov | #if FF_API_OLD_AVIO
|
78 | int init_put_byte(AVIOContext *s,
|
||
79 | unsigned char *buffer, |
||
80 | int buffer_size,
|
||
81 | int write_flag,
|
||
82 | void *opaque,
|
||
83 | int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), |
||
84 | int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), |
||
85 | int64_t (*seek)(void *opaque, int64_t offset, int whence)) |
||
86 | { |
||
87 | return ffio_init_context(s, buffer, buffer_size, write_flag, opaque,
|
||
88 | read_packet, write_packet, seek); |
||
89 | } |
||
90 | 90ed2776 | Anton Khirnov | AVIOContext *av_alloc_put_byte( |
91 | unsigned char *buffer, |
||
92 | int buffer_size,
|
||
93 | int write_flag,
|
||
94 | void *opaque,
|
||
95 | int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), |
||
96 | int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), |
||
97 | int64_t (*seek)(void *opaque, int64_t offset, int whence)) |
||
98 | { |
||
99 | return avio_alloc_context(buffer, buffer_size, write_flag, opaque,
|
||
100 | read_packet, write_packet, seek); |
||
101 | } |
||
102 | ae99313a | Anton Khirnov | #endif
|
103 | |||
104 | 90ed2776 | Anton Khirnov | AVIOContext *avio_alloc_context( |
105 | 1e0f3468 | Reimar Döffinger | unsigned char *buffer, |
106 | int buffer_size,
|
||
107 | int write_flag,
|
||
108 | void *opaque,
|
||
109 | int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), |
||
110 | int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), |
||
111 | 7f37f568 | Diego Biurrun | int64_t (*seek)(void *opaque, int64_t offset, int whence)) |
112 | { |
||
113 | 471fe57e | Anton Khirnov | AVIOContext *s = av_mallocz(sizeof(AVIOContext));
|
114 | ae99313a | Anton Khirnov | ffio_init_context(s, buffer, buffer_size, write_flag, opaque, |
115 | 1e0f3468 | Reimar Döffinger | read_packet, write_packet, seek); |
116 | return s;
|
||
117 | } |
||
118 | |||
119 | 471fe57e | Anton Khirnov | static void flush_buffer(AVIOContext *s) |
120 | de6d9b64 | Fabrice Bellard | { |
121 | if (s->buf_ptr > s->buffer) {
|
||
122 | 576ae256 | Michael Niedermayer | if (s->write_packet && !s->error){
|
123 | c66f53cf | Martin Storsjö | int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
|
124 | 576ae256 | Michael Niedermayer | if(ret < 0){ |
125 | s->error = ret; |
||
126 | } |
||
127 | } |
||
128 | 465e1dad | Michael Niedermayer | if(s->update_checksum){
|
129 | ee9f36a8 | Michael Niedermayer | s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); |
130 | s->checksum_ptr= s->buffer; |
||
131 | } |
||
132 | de6d9b64 | Fabrice Bellard | s->pos += s->buf_ptr - s->buffer; |
133 | } |
||
134 | s->buf_ptr = s->buffer; |
||
135 | } |
||
136 | |||
137 | 471fe57e | Anton Khirnov | void put_byte(AVIOContext *s, int b) |
138 | de6d9b64 | Fabrice Bellard | { |
139 | *(s->buf_ptr)++ = b; |
||
140 | 115329f1 | Diego Biurrun | if (s->buf_ptr >= s->buf_end)
|
141 | de6d9b64 | Fabrice Bellard | flush_buffer(s); |
142 | } |
||
143 | |||
144 | 471fe57e | Anton Khirnov | void put_nbyte(AVIOContext *s, int b, int count) |
145 | 17ee8f66 | Anssi Hannula | { |
146 | while (count > 0) { |
||
147 | int len = FFMIN(s->buf_end - s->buf_ptr, count);
|
||
148 | memset(s->buf_ptr, b, len); |
||
149 | s->buf_ptr += len; |
||
150 | |||
151 | if (s->buf_ptr >= s->buf_end)
|
||
152 | flush_buffer(s); |
||
153 | |||
154 | count -= len; |
||
155 | } |
||
156 | } |
||
157 | |||
158 | 471fe57e | Anton Khirnov | void put_buffer(AVIOContext *s, const unsigned char *buf, int size) |
159 | de6d9b64 | Fabrice Bellard | { |
160 | while (size > 0) { |
||
161 | 90aa6ace | Reimar Döffinger | int len = FFMIN(s->buf_end - s->buf_ptr, size);
|
162 | de6d9b64 | Fabrice Bellard | memcpy(s->buf_ptr, buf, len); |
163 | s->buf_ptr += len; |
||
164 | |||
165 | 115329f1 | Diego Biurrun | if (s->buf_ptr >= s->buf_end)
|
166 | de6d9b64 | Fabrice Bellard | flush_buffer(s); |
167 | |||
168 | buf += len; |
||
169 | size -= len; |
||
170 | } |
||
171 | } |
||
172 | |||
173 | 471fe57e | Anton Khirnov | void put_flush_packet(AVIOContext *s)
|
174 | de6d9b64 | Fabrice Bellard | { |
175 | flush_buffer(s); |
||
176 | s->must_flush = 0;
|
||
177 | } |
||
178 | |||
179 | 471fe57e | Anton Khirnov | int64_t url_fseek(AVIOContext *s, int64_t offset, int whence)
|
180 | de6d9b64 | Fabrice Bellard | { |
181 | bc5c918e | Diego Biurrun | int64_t offset1; |
182 | int64_t pos; |
||
183 | c6a5e087 | Tomas Härdin | int force = whence & AVSEEK_FORCE;
|
184 | whence &= ~AVSEEK_FORCE; |
||
185 | 899681cd | Björn Axelsson | |
186 | if(!s)
|
||
187 | return AVERROR(EINVAL);
|
||
188 | |||
189 | pos = s->pos - (s->write_flag ? 0 : (s->buf_end - s->buffer));
|
||
190 | de6d9b64 | Fabrice Bellard | |
191 | if (whence != SEEK_CUR && whence != SEEK_SET)
|
||
192 | 8fa36ae0 | François Revol | return AVERROR(EINVAL);
|
193 | 115329f1 | Diego Biurrun | |
194 | f40d1739 | Michael Niedermayer | if (whence == SEEK_CUR) {
|
195 | offset1 = pos + (s->buf_ptr - s->buffer); |
||
196 | if (offset == 0) |
||
197 | return offset1;
|
||
198 | offset += offset1; |
||
199 | } |
||
200 | offset1 = offset - pos; |
||
201 | if (!s->must_flush &&
|
||
202 | b3eab9fb | Baptiste Coudurier | offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) {
|
203 | f40d1739 | Michael Niedermayer | /* can do the seek inside the buffer */
|
204 | s->buf_ptr = s->buffer + offset1; |
||
205 | 7939d0ed | Martin Storsjö | } else if ((s->is_streamed || |
206 | offset1 <= s->buf_end + SHORT_SEEK_THRESHOLD - s->buffer) && |
||
207 | !s->write_flag && offset1 >= 0 &&
|
||
208 | 7a6fe01f | Tomas Härdin | (whence != SEEK_END || force)) { |
209 | 398f5d3f | Michael Niedermayer | while(s->pos < offset && !s->eof_reached)
|
210 | fill_buffer(s); |
||
211 | 5cb4b82a | Baptiste Coudurier | if (s->eof_reached)
|
212 | 8d5e638f | Stefano Sabatini | return AVERROR_EOF;
|
213 | 398f5d3f | Michael Niedermayer | s->buf_ptr = s->buf_end + offset - s->pos; |
214 | f40d1739 | Michael Niedermayer | } else {
|
215 | 9d30e068 | Stefano Sabatini | int64_t res; |
216 | 68fcdbf1 | Ronald S. Bultje | |
217 | b250f9c6 | Aurelien Jacobs | #if CONFIG_MUXERS || CONFIG_NETWORK
|
218 | f40d1739 | Michael Niedermayer | if (s->write_flag) {
|
219 | de6d9b64 | Fabrice Bellard | flush_buffer(s); |
220 | s->must_flush = 1;
|
||
221 | } |
||
222 | b250f9c6 | Aurelien Jacobs | #endif /* CONFIG_MUXERS || CONFIG_NETWORK */ |
223 | 9d30e068 | Stefano Sabatini | if (!s->seek)
|
224 | return AVERROR(EPIPE);
|
||
225 | if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0) |
||
226 | 68fcdbf1 | Ronald S. Bultje | return res;
|
227 | 39a127bf | Baptiste Coudurier | if (!s->write_flag)
|
228 | s->buf_end = s->buffer; |
||
229 | s->buf_ptr = s->buffer; |
||
230 | f40d1739 | Michael Niedermayer | s->pos = offset; |
231 | de6d9b64 | Fabrice Bellard | } |
232 | f40d1739 | Michael Niedermayer | s->eof_reached = 0;
|
233 | de6d9b64 | Fabrice Bellard | return offset;
|
234 | } |
||
235 | |||
236 | 471fe57e | Anton Khirnov | int url_fskip(AVIOContext *s, int64_t offset)
|
237 | de6d9b64 | Fabrice Bellard | { |
238 | d5e9ddeb | Martin Storsjö | int64_t ret = url_fseek(s, offset, SEEK_CUR); |
239 | return ret < 0 ? ret : 0; |
||
240 | de6d9b64 | Fabrice Bellard | } |
241 | |||
242 | 471fe57e | Anton Khirnov | int64_t url_ftell(AVIOContext *s) |
243 | de6d9b64 | Fabrice Bellard | { |
244 | return url_fseek(s, 0, SEEK_CUR); |
||
245 | } |
||
246 | |||
247 | 471fe57e | Anton Khirnov | int64_t url_fsize(AVIOContext *s) |
248 | a965c478 | Aurelien Jacobs | { |
249 | bc5c918e | Diego Biurrun | int64_t size; |
250 | 115329f1 | Diego Biurrun | |
251 | 899681cd | Björn Axelsson | if(!s)
|
252 | return AVERROR(EINVAL);
|
||
253 | |||
254 | a965c478 | Aurelien Jacobs | if (!s->seek)
|
255 | 4c4ef3db | Stefano Sabatini | return AVERROR(ENOSYS);
|
256 | 8e287af0 | Michael Niedermayer | size = s->seek(s->opaque, 0, AVSEEK_SIZE);
|
257 | if(size<0){ |
||
258 | 8f42f523 | Ronald S. Bultje | if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0) |
259 | return size;
|
||
260 | size++; |
||
261 | 1ae2c5f2 | Michael Niedermayer | s->seek(s->opaque, s->pos, SEEK_SET); |
262 | 8e287af0 | Michael Niedermayer | } |
263 | a965c478 | Aurelien Jacobs | return size;
|
264 | } |
||
265 | |||
266 | 471fe57e | Anton Khirnov | int url_feof(AVIOContext *s)
|
267 | de6d9b64 | Fabrice Bellard | { |
268 | 899681cd | Björn Axelsson | if(!s)
|
269 | return 0; |
||
270 | de6d9b64 | Fabrice Bellard | return s->eof_reached;
|
271 | } |
||
272 | |||
273 | 471fe57e | Anton Khirnov | int url_ferror(AVIOContext *s)
|
274 | 576ae256 | Michael Niedermayer | { |
275 | 899681cd | Björn Axelsson | if(!s)
|
276 | return 0; |
||
277 | 576ae256 | Michael Niedermayer | return s->error;
|
278 | } |
||
279 | |||
280 | 471fe57e | Anton Khirnov | void put_le32(AVIOContext *s, unsigned int val) |
281 | de6d9b64 | Fabrice Bellard | { |
282 | put_byte(s, val); |
||
283 | put_byte(s, val >> 8);
|
||
284 | put_byte(s, val >> 16);
|
||
285 | put_byte(s, val >> 24);
|
||
286 | } |
||
287 | |||
288 | 471fe57e | Anton Khirnov | void put_be32(AVIOContext *s, unsigned int val) |
289 | de6d9b64 | Fabrice Bellard | { |
290 | put_byte(s, val >> 24);
|
||
291 | put_byte(s, val >> 16);
|
||
292 | put_byte(s, val >> 8);
|
||
293 | put_byte(s, val); |
||
294 | } |
||
295 | |||
296 | e910a77b | Anton Khirnov | #if FF_API_OLD_AVIO
|
297 | 471fe57e | Anton Khirnov | void put_strz(AVIOContext *s, const char *str) |
298 | 75bdb984 | Philip Gladstone | { |
299 | e910a77b | Anton Khirnov | avio_put_str(s, str); |
300 | } |
||
301 | #endif
|
||
302 | |||
303 | 471fe57e | Anton Khirnov | int avio_put_str(AVIOContext *s, const char *str) |
304 | e910a77b | Anton Khirnov | { |
305 | int len = 1; |
||
306 | if (str) {
|
||
307 | len += strlen(str); |
||
308 | put_buffer(s, (const unsigned char *) str, len); |
||
309 | } else
|
||
310 | 75bdb984 | Philip Gladstone | put_byte(s, 0);
|
311 | e910a77b | Anton Khirnov | return len;
|
312 | 75bdb984 | Philip Gladstone | } |
313 | |||
314 | 471fe57e | Anton Khirnov | int avio_put_str16le(AVIOContext *s, const char *str) |
315 | 6e89b612 | Anton Khirnov | { |
316 | const uint8_t *q = str;
|
||
317 | int ret = 0; |
||
318 | |||
319 | while (*q) {
|
||
320 | uint32_t ch; |
||
321 | uint16_t tmp; |
||
322 | |||
323 | GET_UTF8(ch, *q++, break;)
|
||
324 | PUT_UTF16(ch, tmp, put_le16(s, tmp);ret += 2;)
|
||
325 | } |
||
326 | put_le16(s, 0);
|
||
327 | ret += 2;
|
||
328 | return ret;
|
||
329 | } |
||
330 | |||
331 | 603e5c0b | Michael Chinen | int ff_get_v_length(uint64_t val){
|
332 | int i=1; |
||
333 | |||
334 | while(val>>=7) |
||
335 | i++; |
||
336 | |||
337 | return i;
|
||
338 | } |
||
339 | |||
340 | 471fe57e | Anton Khirnov | void ff_put_v(AVIOContext *bc, uint64_t val){
|
341 | 603e5c0b | Michael Chinen | int i= ff_get_v_length(val);
|
342 | |||
343 | while(--i>0) |
||
344 | put_byte(bc, 128 | (val>>(7*i))); |
||
345 | |||
346 | put_byte(bc, val&127);
|
||
347 | } |
||
348 | |||
349 | 471fe57e | Anton Khirnov | void put_le64(AVIOContext *s, uint64_t val)
|
350 | de6d9b64 | Fabrice Bellard | { |
351 | 0c1a9eda | Zdenek Kabelac | put_le32(s, (uint32_t)(val & 0xffffffff));
|
352 | put_le32(s, (uint32_t)(val >> 32));
|
||
353 | de6d9b64 | Fabrice Bellard | } |
354 | |||
355 | 471fe57e | Anton Khirnov | void put_be64(AVIOContext *s, uint64_t val)
|
356 | de6d9b64 | Fabrice Bellard | { |
357 | 0c1a9eda | Zdenek Kabelac | put_be32(s, (uint32_t)(val >> 32));
|
358 | put_be32(s, (uint32_t)(val & 0xffffffff));
|
||
359 | de6d9b64 | Fabrice Bellard | } |
360 | |||
361 | 471fe57e | Anton Khirnov | void put_le16(AVIOContext *s, unsigned int val) |
362 | de6d9b64 | Fabrice Bellard | { |
363 | put_byte(s, val); |
||
364 | put_byte(s, val >> 8);
|
||
365 | } |
||
366 | |||
367 | 471fe57e | Anton Khirnov | void put_be16(AVIOContext *s, unsigned int val) |
368 | de6d9b64 | Fabrice Bellard | { |
369 | put_byte(s, val >> 8);
|
||
370 | put_byte(s, val); |
||
371 | } |
||
372 | |||
373 | 471fe57e | Anton Khirnov | void put_le24(AVIOContext *s, unsigned int val) |
374 | ea395e8c | Aurelien Jacobs | { |
375 | put_le16(s, val & 0xffff);
|
||
376 | put_byte(s, val >> 16);
|
||
377 | } |
||
378 | |||
379 | 471fe57e | Anton Khirnov | void put_be24(AVIOContext *s, unsigned int val) |
380 | a254c574 | Michael Niedermayer | { |
381 | put_be16(s, val >> 8);
|
||
382 | put_byte(s, val); |
||
383 | } |
||
384 | |||
385 | 471fe57e | Anton Khirnov | void put_tag(AVIOContext *s, const char *tag) |
386 | de6d9b64 | Fabrice Bellard | { |
387 | while (*tag) {
|
||
388 | put_byte(s, *tag++); |
||
389 | } |
||
390 | } |
||
391 | |||
392 | /* Input stream */
|
||
393 | |||
394 | 471fe57e | Anton Khirnov | static void fill_buffer(AVIOContext *s) |
395 | de6d9b64 | Fabrice Bellard | { |
396 | f5edd874 | Jindřich Makovička | uint8_t *dst= !s->max_packet_size && s->buf_end - s->buffer < s->buffer_size ? s->buf_ptr : s->buffer; |
397 | 4589dc5c | Michael Niedermayer | int len= s->buffer_size - (dst - s->buffer);
|
398 | 01d91b9b | Tomas Härdin | int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE;
|
399 | 4589dc5c | Michael Niedermayer | |
400 | abba3dd1 | Fabrice Bellard | /* no need to do anything if EOF already reached */
|
401 | if (s->eof_reached)
|
||
402 | return;
|
||
403 | ee9f36a8 | Michael Niedermayer | |
404 | 4589dc5c | Michael Niedermayer | if(s->update_checksum && dst == s->buffer){
|
405 | 0f0680c5 | Michael Niedermayer | if(s->buf_end > s->checksum_ptr)
|
406 | s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr); |
||
407 | ee9f36a8 | Michael Niedermayer | s->checksum_ptr= s->buffer; |
408 | } |
||
409 | |||
410 | 01d91b9b | Tomas Härdin | /* make buffer smaller in case it ended up large after probing */
|
411 | if (s->buffer_size > max_buffer_size) {
|
||
412 | url_setbufsize(s, max_buffer_size); |
||
413 | |||
414 | s->checksum_ptr = dst = s->buffer; |
||
415 | len = s->buffer_size; |
||
416 | } |
||
417 | |||
418 | 602dd8f6 | Benoit Fouet | if(s->read_packet)
|
419 | c66f53cf | Martin Storsjö | len = s->read_packet(s->opaque, dst, len); |
420 | 4589dc5c | Michael Niedermayer | else
|
421 | len = 0;
|
||
422 | abba3dd1 | Fabrice Bellard | if (len <= 0) { |
423 | /* do not modify buffer if EOF reached so that a seek back can
|
||
424 | be done without rereading data */
|
||
425 | de6d9b64 | Fabrice Bellard | s->eof_reached = 1;
|
426 | 5f097703 | Alex Beregszaszi | if(len<0) |
427 | s->error= len; |
||
428 | abba3dd1 | Fabrice Bellard | } else {
|
429 | s->pos += len; |
||
430 | 4589dc5c | Michael Niedermayer | s->buf_ptr = dst; |
431 | s->buf_end = dst + len; |
||
432 | de6d9b64 | Fabrice Bellard | } |
433 | } |
||
434 | |||
435 | 7f37f568 | Diego Biurrun | unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, |
436 | unsigned int len) |
||
437 | { |
||
438 | 3abe5fbd | Aurelien Jacobs | return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len);
|
439 | 992e78f5 | Baptiste Coudurier | } |
440 | |||
441 | 471fe57e | Anton Khirnov | unsigned long get_checksum(AVIOContext *s) |
442 | 7f37f568 | Diego Biurrun | { |
443 | ee9f36a8 | Michael Niedermayer | s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); |
444 | 465e1dad | Michael Niedermayer | s->update_checksum= NULL;
|
445 | ee9f36a8 | Michael Niedermayer | return s->checksum;
|
446 | } |
||
447 | |||
448 | 471fe57e | Anton Khirnov | void init_checksum(AVIOContext *s,
|
449 | 7f37f568 | Diego Biurrun | unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), |
450 | unsigned long checksum) |
||
451 | { |
||
452 | ee9f36a8 | Michael Niedermayer | s->update_checksum= update_checksum; |
453 | 465e1dad | Michael Niedermayer | if(s->update_checksum){
|
454 | ccb15994 | Michael Niedermayer | s->checksum= checksum; |
455 | 465e1dad | Michael Niedermayer | s->checksum_ptr= s->buf_ptr; |
456 | } |
||
457 | ee9f36a8 | Michael Niedermayer | } |
458 | |||
459 | abba3dd1 | Fabrice Bellard | /* XXX: put an inline version */
|
460 | 471fe57e | Anton Khirnov | int get_byte(AVIOContext *s)
|
461 | de6d9b64 | Fabrice Bellard | { |
462 | 3aa13da9 | Reimar Döffinger | if (s->buf_ptr >= s->buf_end)
|
463 | de6d9b64 | Fabrice Bellard | fill_buffer(s); |
464 | 853a0fcc | Reimar Döffinger | if (s->buf_ptr < s->buf_end)
|
465 | return *s->buf_ptr++;
|
||
466 | return 0; |
||
467 | de6d9b64 | Fabrice Bellard | } |
468 | |||
469 | 471fe57e | Anton Khirnov | int url_fgetc(AVIOContext *s)
|
470 | abba3dd1 | Fabrice Bellard | { |
471 | 3aa13da9 | Reimar Döffinger | if (s->buf_ptr >= s->buf_end)
|
472 | abba3dd1 | Fabrice Bellard | fill_buffer(s); |
473 | 853a0fcc | Reimar Döffinger | if (s->buf_ptr < s->buf_end)
|
474 | return *s->buf_ptr++;
|
||
475 | return URL_EOF;
|
||
476 | abba3dd1 | Fabrice Bellard | } |
477 | |||
478 | 471fe57e | Anton Khirnov | int get_buffer(AVIOContext *s, unsigned char *buf, int size) |
479 | de6d9b64 | Fabrice Bellard | { |
480 | int len, size1;
|
||
481 | |||
482 | size1 = size; |
||
483 | while (size > 0) { |
||
484 | len = s->buf_end - s->buf_ptr; |
||
485 | if (len > size)
|
||
486 | len = size; |
||
487 | if (len == 0) { |
||
488 | 3e2b6358 | Michael Niedermayer | if(size > s->buffer_size && !s->update_checksum){
|
489 | 602dd8f6 | Benoit Fouet | if(s->read_packet)
|
490 | c66f53cf | Martin Storsjö | len = s->read_packet(s->opaque, buf, size); |
491 | 3e2b6358 | Michael Niedermayer | if (len <= 0) { |
492 | /* do not modify buffer if EOF reached so that a seek back can
|
||
493 | be done without rereading data */
|
||
494 | s->eof_reached = 1;
|
||
495 | if(len<0) |
||
496 | s->error= len; |
||
497 | break;
|
||
498 | } else {
|
||
499 | s->pos += len; |
||
500 | size -= len; |
||
501 | buf += len; |
||
502 | s->buf_ptr = s->buffer; |
||
503 | s->buf_end = s->buffer/* + len*/;
|
||
504 | } |
||
505 | }else{
|
||
506 | fill_buffer(s); |
||
507 | len = s->buf_end - s->buf_ptr; |
||
508 | if (len == 0) |
||
509 | break;
|
||
510 | } |
||
511 | de6d9b64 | Fabrice Bellard | } else {
|
512 | memcpy(buf, s->buf_ptr, len); |
||
513 | buf += len; |
||
514 | s->buf_ptr += len; |
||
515 | size -= len; |
||
516 | } |
||
517 | } |
||
518 | 7f7686df | Reimar Döffinger | if (size1 == size) {
|
519 | if (url_ferror(s)) return url_ferror(s); |
||
520 | if (url_feof(s)) return AVERROR_EOF; |
||
521 | } |
||
522 | de6d9b64 | Fabrice Bellard | return size1 - size;
|
523 | } |
||
524 | |||
525 | 471fe57e | Anton Khirnov | int get_partial_buffer(AVIOContext *s, unsigned char *buf, int size) |
526 | e15dec10 | Leon van Stuivenberg | { |
527 | int len;
|
||
528 | 115329f1 | Diego Biurrun | |
529 | 0ecca7a4 | Michael Niedermayer | if(size<0) |
530 | return -1; |
||
531 | e15dec10 | Leon van Stuivenberg | |
532 | len = s->buf_end - s->buf_ptr; |
||
533 | if (len == 0) { |
||
534 | fill_buffer(s); |
||
535 | len = s->buf_end - s->buf_ptr; |
||
536 | } |
||
537 | if (len > size)
|
||
538 | len = size; |
||
539 | memcpy(buf, s->buf_ptr, len); |
||
540 | s->buf_ptr += len; |
||
541 | 7f7686df | Reimar Döffinger | if (!len) {
|
542 | if (url_ferror(s)) return url_ferror(s); |
||
543 | if (url_feof(s)) return AVERROR_EOF; |
||
544 | } |
||
545 | e15dec10 | Leon van Stuivenberg | return len;
|
546 | } |
||
547 | |||
548 | 471fe57e | Anton Khirnov | unsigned int get_le16(AVIOContext *s) |
549 | de6d9b64 | Fabrice Bellard | { |
550 | unsigned int val; |
||
551 | val = get_byte(s); |
||
552 | val |= get_byte(s) << 8;
|
||
553 | return val;
|
||
554 | } |
||
555 | |||
556 | 471fe57e | Anton Khirnov | unsigned int get_le24(AVIOContext *s) |
557 | ea395e8c | Aurelien Jacobs | { |
558 | unsigned int val; |
||
559 | val = get_le16(s); |
||
560 | val |= get_byte(s) << 16;
|
||
561 | return val;
|
||
562 | } |
||
563 | |||
564 | 471fe57e | Anton Khirnov | unsigned int get_le32(AVIOContext *s) |
565 | de6d9b64 | Fabrice Bellard | { |
566 | unsigned int val; |
||
567 | a254c574 | Michael Niedermayer | val = get_le16(s); |
568 | val |= get_le16(s) << 16;
|
||
569 | de6d9b64 | Fabrice Bellard | return val;
|
570 | } |
||
571 | |||
572 | 471fe57e | Anton Khirnov | uint64_t get_le64(AVIOContext *s) |
573 | de6d9b64 | Fabrice Bellard | { |
574 | 0c1a9eda | Zdenek Kabelac | uint64_t val; |
575 | val = (uint64_t)get_le32(s); |
||
576 | val |= (uint64_t)get_le32(s) << 32;
|
||
577 | de6d9b64 | Fabrice Bellard | return val;
|
578 | } |
||
579 | |||
580 | 471fe57e | Anton Khirnov | unsigned int get_be16(AVIOContext *s) |
581 | de6d9b64 | Fabrice Bellard | { |
582 | unsigned int val; |
||
583 | val = get_byte(s) << 8;
|
||
584 | val |= get_byte(s); |
||
585 | return val;
|
||
586 | } |
||
587 | |||
588 | 471fe57e | Anton Khirnov | unsigned int get_be24(AVIOContext *s) |
589 | de6d9b64 | Fabrice Bellard | { |
590 | unsigned int val; |
||
591 | a254c574 | Michael Niedermayer | val = get_be16(s) << 8;
|
592 | de6d9b64 | Fabrice Bellard | val |= get_byte(s); |
593 | return val;
|
||
594 | } |
||
595 | 471fe57e | Anton Khirnov | unsigned int get_be32(AVIOContext *s) |
596 | a254c574 | Michael Niedermayer | { |
597 | unsigned int val; |
||
598 | val = get_be16(s) << 16;
|
||
599 | val |= get_be16(s); |
||
600 | return val;
|
||
601 | } |
||
602 | de6d9b64 | Fabrice Bellard | |
603 | 471fe57e | Anton Khirnov | char *get_strz(AVIOContext *s, char *buf, int maxlen) |
604 | 75bdb984 | Philip Gladstone | { |
605 | int i = 0; |
||
606 | char c;
|
||
607 | |||
608 | while ((c = get_byte(s))) {
|
||
609 | if (i < maxlen-1) |
||
610 | buf[i++] = c; |
||
611 | } |
||
612 | 115329f1 | Diego Biurrun | |
613 | 75bdb984 | Philip Gladstone | buf[i] = 0; /* Ensure null terminated, but may be truncated */ |
614 | |||
615 | return buf;
|
||
616 | } |
||
617 | |||
618 | 471fe57e | Anton Khirnov | int ff_get_line(AVIOContext *s, char *buf, int maxlen) |
619 | 7c892951 | Aurelien Jacobs | { |
620 | int i = 0; |
||
621 | char c;
|
||
622 | |||
623 | do {
|
||
624 | c = get_byte(s); |
||
625 | a43416a5 | Aurelien Jacobs | if (c && i < maxlen-1) |
626 | 7c892951 | Aurelien Jacobs | buf[i++] = c; |
627 | } while (c != '\n' && c); |
||
628 | |||
629 | buf[i] = 0;
|
||
630 | a43416a5 | Aurelien Jacobs | return i;
|
631 | 7c892951 | Aurelien Jacobs | } |
632 | |||
633 | f9d6b13a | Anton Khirnov | #define GET_STR16(type, read) \
|
634 | 471fe57e | Anton Khirnov | int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\ |
635 | f9d6b13a | Anton Khirnov | {\ |
636 | char* q = buf;\
|
||
637 | int ret = 0;\ |
||
638 | while (ret + 1 < maxlen) {\ |
||
639 | uint8_t tmp;\ |
||
640 | uint32_t ch;\ |
||
641 | GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\ |
||
642 | if (!ch)\
|
||
643 | break;\
|
||
644 | PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\ |
||
645 | }\ |
||
646 | *q = 0;\
|
||
647 | return ret;\
|
||
648 | }\ |
||
649 | |||
650 | GET_STR16(le, get_le16) |
||
651 | GET_STR16(be, get_be16) |
||
652 | |||
653 | #undef GET_STR16
|
||
654 | |||
655 | 471fe57e | Anton Khirnov | uint64_t get_be64(AVIOContext *s) |
656 | de6d9b64 | Fabrice Bellard | { |
657 | 0c1a9eda | Zdenek Kabelac | uint64_t val; |
658 | val = (uint64_t)get_be32(s) << 32;
|
||
659 | val |= (uint64_t)get_be32(s); |
||
660 | de6d9b64 | Fabrice Bellard | return val;
|
661 | } |
||
662 | |||
663 | 471fe57e | Anton Khirnov | uint64_t ff_get_v(AVIOContext *bc){ |
664 | 897d3eef | Kostya Shishkov | uint64_t val = 0;
|
665 | int tmp;
|
||
666 | |||
667 | do{
|
||
668 | tmp = get_byte(bc); |
||
669 | val= (val<<7) + (tmp&127); |
||
670 | }while(tmp&128); |
||
671 | return val;
|
||
672 | } |
||
673 | |||
674 | 471fe57e | Anton Khirnov | int url_fdopen(AVIOContext **s, URLContext *h)
|
675 | de6d9b64 | Fabrice Bellard | { |
676 | 0c1a9eda | Zdenek Kabelac | uint8_t *buffer; |
677 | abba3dd1 | Fabrice Bellard | int buffer_size, max_packet_size;
|
678 | de6d9b64 | Fabrice Bellard | |
679 | abba3dd1 | Fabrice Bellard | max_packet_size = url_get_max_packet_size(h); |
680 | if (max_packet_size) {
|
||
681 | buffer_size = max_packet_size; /* no need to bufferize more than one packet */
|
||
682 | } else {
|
||
683 | buffer_size = IO_BUFFER_SIZE; |
||
684 | } |
||
685 | 1ea4f593 | Fabrice Bellard | buffer = av_malloc(buffer_size); |
686 | de6d9b64 | Fabrice Bellard | if (!buffer)
|
687 | 8fa36ae0 | François Revol | return AVERROR(ENOMEM);
|
688 | de6d9b64 | Fabrice Bellard | |
689 | 471fe57e | Anton Khirnov | *s = av_mallocz(sizeof(AVIOContext));
|
690 | 899681cd | Björn Axelsson | if(!*s) {
|
691 | av_free(buffer); |
||
692 | return AVERROR(ENOMEM);
|
||
693 | } |
||
694 | |||
695 | ae99313a | Anton Khirnov | if (ffio_init_context(*s, buffer, buffer_size,
|
696 | ac9fe33d | Gildas Bazin | (h->flags & URL_WRONLY || h->flags & URL_RDWR), h, |
697 | 004050ee | Michael Niedermayer | url_read, url_write, url_seek) < 0) {
|
698 | 1ea4f593 | Fabrice Bellard | av_free(buffer); |
699 | 899681cd | Björn Axelsson | av_freep(s); |
700 | 6f3e0b21 | Panagiotis Issaris | return AVERROR(EIO);
|
701 | de6d9b64 | Fabrice Bellard | } |
702 | 899681cd | Björn Axelsson | (*s)->is_streamed = h->is_streamed; |
703 | (*s)->max_packet_size = max_packet_size; |
||
704 | e7e4810a | Björn Axelsson | if(h->prot) {
|
705 | 502bdf68 | Michael Niedermayer | (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause; |
706 | bc5c918e | Diego Biurrun | (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek; |
707 | e7e4810a | Björn Axelsson | } |
708 | de6d9b64 | Fabrice Bellard | return 0; |
709 | } |
||
710 | |||
711 | 471fe57e | Anton Khirnov | int url_setbufsize(AVIOContext *s, int buf_size) |
712 | de6d9b64 | Fabrice Bellard | { |
713 | 0c1a9eda | Zdenek Kabelac | uint8_t *buffer; |
714 | 1ea4f593 | Fabrice Bellard | buffer = av_malloc(buf_size); |
715 | de6d9b64 | Fabrice Bellard | if (!buffer)
|
716 | 8fa36ae0 | François Revol | return AVERROR(ENOMEM);
|
717 | de6d9b64 | Fabrice Bellard | |
718 | 1ea4f593 | Fabrice Bellard | av_free(s->buffer); |
719 | de6d9b64 | Fabrice Bellard | s->buffer = buffer; |
720 | s->buffer_size = buf_size; |
||
721 | s->buf_ptr = buffer; |
||
722 | 770d9daf | Björn Axelsson | url_resetbuf(s, s->write_flag ? URL_WRONLY : URL_RDONLY); |
723 | return 0; |
||
724 | } |
||
725 | |||
726 | 364cacc7 | Aurelien Jacobs | #if FF_API_URL_RESETBUF
|
727 | 471fe57e | Anton Khirnov | int url_resetbuf(AVIOContext *s, int flags) |
728 | 08580cb0 | Benoit Fouet | #else
|
729 | 471fe57e | Anton Khirnov | static int url_resetbuf(AVIOContext *s, int flags) |
730 | 08580cb0 | Benoit Fouet | #endif
|
731 | 770d9daf | Björn Axelsson | { |
732 | 364cacc7 | Aurelien Jacobs | #if FF_API_URL_RESETBUF
|
733 | 6fa197e2 | Eli Friedman | if (flags & URL_RDWR)
|
734 | 770d9daf | Björn Axelsson | return AVERROR(EINVAL);
|
735 | 08580cb0 | Benoit Fouet | #else
|
736 | assert(flags == URL_WRONLY || flags == URL_RDONLY); |
||
737 | #endif
|
||
738 | 770d9daf | Björn Axelsson | |
739 | if (flags & URL_WRONLY) {
|
||
740 | s->buf_end = s->buffer + s->buffer_size; |
||
741 | s->write_flag = 1;
|
||
742 | } else {
|
||
743 | s->buf_end = s->buffer; |
||
744 | s->write_flag = 0;
|
||
745 | } |
||
746 | de6d9b64 | Fabrice Bellard | return 0; |
747 | } |
||
748 | |||
749 | 471fe57e | Anton Khirnov | int ff_rewind_with_probe_data(AVIOContext *s, unsigned char *buf, int buf_size) |
750 | 01d91b9b | Tomas Härdin | { |
751 | int64_t buffer_start; |
||
752 | int buffer_size;
|
||
753 | 496c645d | Martin Storsjö | int overlap, new_size, alloc_size;
|
754 | 01d91b9b | Tomas Härdin | |
755 | if (s->write_flag)
|
||
756 | return AVERROR(EINVAL);
|
||
757 | |||
758 | buffer_size = s->buf_end - s->buffer; |
||
759 | |||
760 | /* the buffers must touch or overlap */
|
||
761 | if ((buffer_start = s->pos - buffer_size) > buf_size)
|
||
762 | return AVERROR(EINVAL);
|
||
763 | |||
764 | overlap = buf_size - buffer_start; |
||
765 | new_size = buf_size + buffer_size - overlap; |
||
766 | |||
767 | 496c645d | Martin Storsjö | alloc_size = FFMAX(s->buffer_size, new_size); |
768 | if (alloc_size > buf_size)
|
||
769 | if (!(buf = av_realloc(buf, alloc_size)))
|
||
770 | 01d91b9b | Tomas Härdin | return AVERROR(ENOMEM);
|
771 | |||
772 | 496c645d | Martin Storsjö | if (new_size > buf_size) {
|
773 | 01d91b9b | Tomas Härdin | memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap); |
774 | buf_size = new_size; |
||
775 | } |
||
776 | |||
777 | av_free(s->buffer); |
||
778 | s->buf_ptr = s->buffer = buf; |
||
779 | 496c645d | Martin Storsjö | s->buffer_size = alloc_size; |
780 | s->pos = buf_size; |
||
781 | 01d91b9b | Tomas Härdin | s->buf_end = s->buf_ptr + buf_size; |
782 | s->eof_reached = 0;
|
||
783 | s->must_flush = 0;
|
||
784 | |||
785 | return 0; |
||
786 | } |
||
787 | |||
788 | 471fe57e | Anton Khirnov | int url_fopen(AVIOContext **s, const char *filename, int flags) |
789 | de6d9b64 | Fabrice Bellard | { |
790 | URLContext *h; |
||
791 | int err;
|
||
792 | |||
793 | err = url_open(&h, filename, flags); |
||
794 | if (err < 0) |
||
795 | return err;
|
||
796 | err = url_fdopen(s, h); |
||
797 | if (err < 0) { |
||
798 | url_close(h); |
||
799 | return err;
|
||
800 | } |
||
801 | return 0; |
||
802 | } |
||
803 | |||
804 | 471fe57e | Anton Khirnov | int url_fclose(AVIOContext *s)
|
805 | de6d9b64 | Fabrice Bellard | { |
806 | URLContext *h = s->opaque; |
||
807 | 115329f1 | Diego Biurrun | |
808 | 1ea4f593 | Fabrice Bellard | av_free(s->buffer); |
809 | 899681cd | Björn Axelsson | av_free(s); |
810 | de6d9b64 | Fabrice Bellard | return url_close(h);
|
811 | } |
||
812 | |||
813 | 471fe57e | Anton Khirnov | URLContext *url_fileno(AVIOContext *s) |
814 | de6d9b64 | Fabrice Bellard | { |
815 | return s->opaque;
|
||
816 | } |
||
817 | |||
818 | b250f9c6 | Aurelien Jacobs | #if CONFIG_MUXERS
|
819 | 471fe57e | Anton Khirnov | int url_fprintf(AVIOContext *s, const char *fmt, ...) |
820 | abba3dd1 | Fabrice Bellard | { |
821 | va_list ap; |
||
822 | char buf[4096]; |
||
823 | int ret;
|
||
824 | |||
825 | va_start(ap, fmt); |
||
826 | ret = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||
827 | va_end(ap); |
||
828 | put_buffer(s, buf, strlen(buf)); |
||
829 | return ret;
|
||
830 | } |
||
831 | a9e35095 | Diego Biurrun | #endif //CONFIG_MUXERS |
832 | abba3dd1 | Fabrice Bellard | |
833 | 471fe57e | Anton Khirnov | char *url_fgets(AVIOContext *s, char *buf, int buf_size) |
834 | abba3dd1 | Fabrice Bellard | { |
835 | int c;
|
||
836 | char *q;
|
||
837 | |||
838 | c = url_fgetc(s); |
||
839 | if (c == EOF) |
||
840 | return NULL; |
||
841 | q = buf; |
||
842 | for(;;) {
|
||
843 | if (c == EOF || c == '\n') |
||
844 | break;
|
||
845 | if ((q - buf) < buf_size - 1) |
||
846 | *q++ = c; |
||
847 | c = url_fgetc(s); |
||
848 | } |
||
849 | if (buf_size > 0) |
||
850 | *q = '\0';
|
||
851 | return buf;
|
||
852 | } |
||
853 | |||
854 | 471fe57e | Anton Khirnov | int url_fget_max_packet_size(AVIOContext *s)
|
855 | abba3dd1 | Fabrice Bellard | { |
856 | return s->max_packet_size;
|
||
857 | } |
||
858 | |||
859 | 471fe57e | Anton Khirnov | int av_url_read_fpause(AVIOContext *s, int pause) |
860 | e7e4810a | Björn Axelsson | { |
861 | if (!s->read_pause)
|
||
862 | return AVERROR(ENOSYS);
|
||
863 | 502bdf68 | Michael Niedermayer | return s->read_pause(s->opaque, pause);
|
864 | e7e4810a | Björn Axelsson | } |
865 | |||
866 | 471fe57e | Anton Khirnov | int64_t av_url_read_fseek(AVIOContext *s, int stream_index,
|
867 | 7f37f568 | Diego Biurrun | int64_t timestamp, int flags)
|
868 | e7e4810a | Björn Axelsson | { |
869 | URLContext *h = s->opaque; |
||
870 | bc5c918e | Diego Biurrun | int64_t ret; |
871 | e7e4810a | Björn Axelsson | if (!s->read_seek)
|
872 | return AVERROR(ENOSYS);
|
||
873 | ret = s->read_seek(h, stream_index, timestamp, flags); |
||
874 | if(ret >= 0) { |
||
875 | c007c687 | Howard Chu | int64_t pos; |
876 | e7e4810a | Björn Axelsson | s->buf_ptr = s->buf_end; // Flush buffer
|
877 | c007c687 | Howard Chu | pos = s->seek(h, 0, SEEK_CUR);
|
878 | if (pos >= 0) |
||
879 | s->pos = pos; |
||
880 | else if (pos != AVERROR(ENOSYS)) |
||
881 | ret = pos; |
||
882 | e7e4810a | Björn Axelsson | } |
883 | return ret;
|
||
884 | } |
||
885 | |||
886 | 8fa641f8 | Loïc Le Loarer | /* url_open_dyn_buf and url_close_dyn_buf are used in rtp.c to send a response
|
887 | b250f9c6 | Aurelien Jacobs | * back to the server even if CONFIG_MUXERS is false. */
|
888 | #if CONFIG_MUXERS || CONFIG_NETWORK
|
||
889 | de6d9b64 | Fabrice Bellard | /* buffer handling */
|
890 | 471fe57e | Anton Khirnov | int url_open_buf(AVIOContext **s, uint8_t *buf, int buf_size, int flags) |
891 | de6d9b64 | Fabrice Bellard | { |
892 | 899681cd | Björn Axelsson | int ret;
|
893 | 471fe57e | Anton Khirnov | *s = av_mallocz(sizeof(AVIOContext));
|
894 | 899681cd | Björn Axelsson | if(!*s)
|
895 | return AVERROR(ENOMEM);
|
||
896 | ae99313a | Anton Khirnov | ret = ffio_init_context(*s, buf, buf_size, |
897 | 899681cd | Björn Axelsson | (flags & URL_WRONLY || flags & URL_RDWR), |
898 | NULL, NULL, NULL, NULL); |
||
899 | if(ret != 0) |
||
900 | av_freep(s); |
||
901 | return ret;
|
||
902 | de6d9b64 | Fabrice Bellard | } |
903 | |||
904 | 471fe57e | Anton Khirnov | int url_close_buf(AVIOContext *s)
|
905 | de6d9b64 | Fabrice Bellard | { |
906 | abba3dd1 | Fabrice Bellard | put_flush_packet(s); |
907 | de6d9b64 | Fabrice Bellard | return s->buf_ptr - s->buffer;
|
908 | } |
||
909 | abba3dd1 | Fabrice Bellard | |
910 | /* output in a dynamic buffer */
|
||
911 | |||
912 | typedef struct DynBuffer { |
||
913 | int pos, size, allocated_size;
|
||
914 | 0c1a9eda | Zdenek Kabelac | uint8_t *buffer; |
915 | abba3dd1 | Fabrice Bellard | int io_buffer_size;
|
916 | 0c1a9eda | Zdenek Kabelac | uint8_t io_buffer[1];
|
917 | abba3dd1 | Fabrice Bellard | } DynBuffer; |
918 | |||
919 | 576ae256 | Michael Niedermayer | static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size) |
920 | abba3dd1 | Fabrice Bellard | { |
921 | DynBuffer *d = opaque; |
||
922 | 6bc03a69 | Reimar Döffinger | unsigned new_size, new_allocated_size;
|
923 | 115329f1 | Diego Biurrun | |
924 | abba3dd1 | Fabrice Bellard | /* reallocate buffer if needed */
|
925 | new_size = d->pos + buf_size; |
||
926 | new_allocated_size = d->allocated_size; |
||
927 | 568e18b1 | Michael Niedermayer | if(new_size < d->pos || new_size > INT_MAX/2) |
928 | return -1; |
||
929 | abba3dd1 | Fabrice Bellard | while (new_size > new_allocated_size) {
|
930 | if (!new_allocated_size)
|
||
931 | new_allocated_size = new_size; |
||
932 | else
|
||
933 | 115329f1 | Diego Biurrun | new_allocated_size += new_allocated_size / 2 + 1; |
934 | abba3dd1 | Fabrice Bellard | } |
935 | 115329f1 | Diego Biurrun | |
936 | abba3dd1 | Fabrice Bellard | if (new_allocated_size > d->allocated_size) {
|
937 | b88ba823 | Mark Hills | d->buffer = av_realloc(d->buffer, new_allocated_size); |
938 | if(d->buffer == NULL) |
||
939 | 7ce820ef | Reimar Döffinger | return AVERROR(ENOMEM);
|
940 | abba3dd1 | Fabrice Bellard | d->allocated_size = new_allocated_size; |
941 | } |
||
942 | memcpy(d->buffer + d->pos, buf, buf_size); |
||
943 | d->pos = new_size; |
||
944 | if (d->pos > d->size)
|
||
945 | d->size = d->pos; |
||
946 | 576ae256 | Michael Niedermayer | return buf_size;
|
947 | abba3dd1 | Fabrice Bellard | } |
948 | |||
949 | 576ae256 | Michael Niedermayer | static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size) |
950 | abba3dd1 | Fabrice Bellard | { |
951 | unsigned char buf1[4]; |
||
952 | 576ae256 | Michael Niedermayer | int ret;
|
953 | abba3dd1 | Fabrice Bellard | |
954 | /* packetized write: output the header */
|
||
955 | aa805f94 | Reimar Döffinger | AV_WB32(buf1, buf_size); |
956 | 576ae256 | Michael Niedermayer | ret= dyn_buf_write(opaque, buf1, 4);
|
957 | if(ret < 0) |
||
958 | return ret;
|
||
959 | abba3dd1 | Fabrice Bellard | |
960 | /* then the data */
|
||
961 | 576ae256 | Michael Niedermayer | return dyn_buf_write(opaque, buf, buf_size);
|
962 | abba3dd1 | Fabrice Bellard | } |
963 | |||
964 | bc5c918e | Diego Biurrun | static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence) |
965 | abba3dd1 | Fabrice Bellard | { |
966 | DynBuffer *d = opaque; |
||
967 | |||
968 | if (whence == SEEK_CUR)
|
||
969 | offset += d->pos; |
||
970 | else if (whence == SEEK_END) |
||
971 | offset += d->size; |
||
972 | if (offset < 0 || offset > 0x7fffffffLL) |
||
973 | return -1; |
||
974 | d->pos = offset; |
||
975 | return 0; |
||
976 | } |
||
977 | |||
978 | 471fe57e | Anton Khirnov | static int url_open_dyn_buf_internal(AVIOContext **s, int max_packet_size) |
979 | abba3dd1 | Fabrice Bellard | { |
980 | DynBuffer *d; |
||
981 | 2bdaf78c | Reimar Döffinger | int ret;
|
982 | 0c5a43d6 | Reimar Döffinger | unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024; |
983 | 115329f1 | Diego Biurrun | |
984 | 568e18b1 | Michael Niedermayer | if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size) |
985 | return -1; |
||
986 | dc2c2eea | Reimar Döffinger | d = av_mallocz(sizeof(DynBuffer) + io_buffer_size);
|
987 | abba3dd1 | Fabrice Bellard | if (!d)
|
988 | 0e7ceb24 | Reimar Döffinger | return AVERROR(ENOMEM);
|
989 | 471fe57e | Anton Khirnov | *s = av_mallocz(sizeof(AVIOContext));
|
990 | 899681cd | Björn Axelsson | if(!*s) {
|
991 | av_free(d); |
||
992 | return AVERROR(ENOMEM);
|
||
993 | } |
||
994 | abba3dd1 | Fabrice Bellard | d->io_buffer_size = io_buffer_size; |
995 | ae99313a | Anton Khirnov | ret = ffio_init_context(*s, d->io_buffer, io_buffer_size, |
996 | 115329f1 | Diego Biurrun | 1, d, NULL, |
997 | max_packet_size ? dyn_packet_buf_write : dyn_buf_write, |
||
998 | abba3dd1 | Fabrice Bellard | max_packet_size ? NULL : dyn_buf_seek);
|
999 | if (ret == 0) { |
||
1000 | 899681cd | Björn Axelsson | (*s)->max_packet_size = max_packet_size; |
1001 | } else {
|
||
1002 | av_free(d); |
||
1003 | av_freep(s); |
||
1004 | abba3dd1 | Fabrice Bellard | } |
1005 | return ret;
|
||
1006 | } |
||
1007 | |||
1008 | 471fe57e | Anton Khirnov | int url_open_dyn_buf(AVIOContext **s)
|
1009 | abba3dd1 | Fabrice Bellard | { |
1010 | return url_open_dyn_buf_internal(s, 0); |
||
1011 | } |
||
1012 | |||
1013 | 471fe57e | Anton Khirnov | int url_open_dyn_packet_buf(AVIOContext **s, int max_packet_size) |
1014 | abba3dd1 | Fabrice Bellard | { |
1015 | if (max_packet_size <= 0) |
||
1016 | return -1; |
||
1017 | return url_open_dyn_buf_internal(s, max_packet_size);
|
||
1018 | } |
||
1019 | |||
1020 | 471fe57e | Anton Khirnov | int url_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
|
1021 | abba3dd1 | Fabrice Bellard | { |
1022 | DynBuffer *d = s->opaque; |
||
1023 | int size;
|
||
1024 | de1807bb | Josh Allmann | static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0}; |
1025 | int padding = 0; |
||
1026 | |||
1027 | /* don't attempt to pad fixed-size packet buffers */
|
||
1028 | if (!s->max_packet_size) {
|
||
1029 | put_buffer(s, padbuf, sizeof(padbuf));
|
||
1030 | padding = FF_INPUT_BUFFER_PADDING_SIZE; |
||
1031 | } |
||
1032 | abba3dd1 | Fabrice Bellard | |
1033 | put_flush_packet(s); |
||
1034 | |||
1035 | *pbuffer = d->buffer; |
||
1036 | size = d->size; |
||
1037 | av_free(d); |
||
1038 | 899681cd | Björn Axelsson | av_free(s); |
1039 | de1807bb | Josh Allmann | return size - padding;
|
1040 | abba3dd1 | Fabrice Bellard | } |
1041 | 8fa641f8 | Loïc Le Loarer | #endif /* CONFIG_MUXERS || CONFIG_NETWORK */ |