ffmpeg / libavformat / aviobuf.c @ a2704c97
History | View | Annotate | Download (26.7 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 | e731b8d8 | 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 | ae628ec1 | Anton Khirnov | static void fill_buffer(AVIOContext *s); |
40 | 364cacc7 | Aurelien Jacobs | #if !FF_API_URL_RESETBUF
|
41 | ae628ec1 | Anton Khirnov | static int url_resetbuf(AVIOContext *s, int flags); |
42 | 08580cb0 | Benoit Fouet | #endif
|
43 | 398f5d3f | Michael Niedermayer | |
44 | e731b8d8 | 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 | e731b8d8 | 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 | 8d9ac969 | 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 | e731b8d8 | Anton Khirnov | #endif
|
103 | |||
104 | 8d9ac969 | 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 | ae628ec1 | Anton Khirnov | AVIOContext *s = av_mallocz(sizeof(AVIOContext));
|
114 | e731b8d8 | 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 | ae628ec1 | 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 | 77eb5504 | Anton Khirnov | void avio_w8(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 | 0ac8e2bf | Anton Khirnov | void ffio_fill(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 | 77eb5504 | Anton Khirnov | void avio_write(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 | ae628ec1 | Anton Khirnov | void put_flush_packet(AVIOContext *s)
|
174 | de6d9b64 | Fabrice Bellard | { |
175 | flush_buffer(s); |
||
176 | s->must_flush = 0;
|
||
177 | } |
||
178 | |||
179 | 6b4aa5da | Anton Khirnov | int64_t avio_seek(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 | 0300db8a | Anton Khirnov | #if FF_API_OLD_AVIO
|
237 | ae628ec1 | Anton Khirnov | int url_fskip(AVIOContext *s, int64_t offset)
|
238 | de6d9b64 | Fabrice Bellard | { |
239 | 6b4aa5da | Anton Khirnov | int64_t ret = avio_seek(s, offset, SEEK_CUR); |
240 | d5e9ddeb | Martin Storsjö | return ret < 0 ? ret : 0; |
241 | de6d9b64 | Fabrice Bellard | } |
242 | |||
243 | ae628ec1 | Anton Khirnov | int64_t url_ftell(AVIOContext *s) |
244 | de6d9b64 | Fabrice Bellard | { |
245 | 6b4aa5da | Anton Khirnov | return avio_seek(s, 0, SEEK_CUR); |
246 | de6d9b64 | Fabrice Bellard | } |
247 | a2704c97 | Anton Khirnov | #endif
|
248 | de6d9b64 | Fabrice Bellard | |
249 | ae628ec1 | Anton Khirnov | int64_t url_fsize(AVIOContext *s) |
250 | a965c478 | Aurelien Jacobs | { |
251 | bc5c918e | Diego Biurrun | int64_t size; |
252 | 115329f1 | Diego Biurrun | |
253 | 899681cd | Björn Axelsson | if(!s)
|
254 | return AVERROR(EINVAL);
|
||
255 | |||
256 | a965c478 | Aurelien Jacobs | if (!s->seek)
|
257 | 4c4ef3db | Stefano Sabatini | return AVERROR(ENOSYS);
|
258 | 8e287af0 | Michael Niedermayer | size = s->seek(s->opaque, 0, AVSEEK_SIZE);
|
259 | if(size<0){ |
||
260 | 8f42f523 | Ronald S. Bultje | if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0) |
261 | return size;
|
||
262 | size++; |
||
263 | 1ae2c5f2 | Michael Niedermayer | s->seek(s->opaque, s->pos, SEEK_SET); |
264 | 8e287af0 | Michael Niedermayer | } |
265 | a965c478 | Aurelien Jacobs | return size;
|
266 | } |
||
267 | |||
268 | ae628ec1 | Anton Khirnov | int url_feof(AVIOContext *s)
|
269 | de6d9b64 | Fabrice Bellard | { |
270 | 899681cd | Björn Axelsson | if(!s)
|
271 | return 0; |
||
272 | de6d9b64 | Fabrice Bellard | return s->eof_reached;
|
273 | } |
||
274 | |||
275 | ae628ec1 | Anton Khirnov | int url_ferror(AVIOContext *s)
|
276 | 576ae256 | Michael Niedermayer | { |
277 | 899681cd | Björn Axelsson | if(!s)
|
278 | return 0; |
||
279 | 576ae256 | Michael Niedermayer | return s->error;
|
280 | } |
||
281 | |||
282 | 77eb5504 | Anton Khirnov | void avio_wl32(AVIOContext *s, unsigned int val) |
283 | de6d9b64 | Fabrice Bellard | { |
284 | 77eb5504 | Anton Khirnov | avio_w8(s, val); |
285 | avio_w8(s, val >> 8);
|
||
286 | avio_w8(s, val >> 16);
|
||
287 | avio_w8(s, val >> 24);
|
||
288 | de6d9b64 | Fabrice Bellard | } |
289 | |||
290 | 77eb5504 | Anton Khirnov | void avio_wb32(AVIOContext *s, unsigned int val) |
291 | de6d9b64 | Fabrice Bellard | { |
292 | 77eb5504 | Anton Khirnov | avio_w8(s, val >> 24);
|
293 | avio_w8(s, val >> 16);
|
||
294 | avio_w8(s, val >> 8);
|
||
295 | avio_w8(s, val); |
||
296 | de6d9b64 | Fabrice Bellard | } |
297 | |||
298 | 4efd5cf3 | Anton Khirnov | #if FF_API_OLD_AVIO
|
299 | ae628ec1 | Anton Khirnov | void put_strz(AVIOContext *s, const char *str) |
300 | 75bdb984 | Philip Gladstone | { |
301 | 4efd5cf3 | Anton Khirnov | avio_put_str(s, str); |
302 | } |
||
303 | b7effd4e | Anton Khirnov | |
304 | #define GET(name, type) \
|
||
305 | type get_be ##name(AVIOContext *s) \ |
||
306 | {\ |
||
307 | return avio_rb ##name(s);\ |
||
308 | }\ |
||
309 | type get_le ##name(AVIOContext *s) \ |
||
310 | {\ |
||
311 | return avio_rl ##name(s);\ |
||
312 | } |
||
313 | |||
314 | GET(16, unsigned int) |
||
315 | GET(24, unsigned int) |
||
316 | GET(32, unsigned int) |
||
317 | GET(64, uint64_t)
|
||
318 | |||
319 | #undef GET
|
||
320 | |||
321 | 77eb5504 | Anton Khirnov | #define PUT(name, type ) \
|
322 | void put_le ##name(AVIOContext *s, type val)\ |
||
323 | {\ |
||
324 | avio_wl ##name(s, val);\ |
||
325 | }\ |
||
326 | void put_be ##name(AVIOContext *s, type val)\ |
||
327 | {\ |
||
328 | avio_wb ##name(s, val);\ |
||
329 | } |
||
330 | |||
331 | PUT(16, unsigned int) |
||
332 | PUT(24, unsigned int) |
||
333 | PUT(32, unsigned int) |
||
334 | PUT(64, uint64_t)
|
||
335 | #undef PUT
|
||
336 | |||
337 | b7effd4e | Anton Khirnov | int get_byte(AVIOContext *s)
|
338 | { |
||
339 | return avio_r8(s);
|
||
340 | } |
||
341 | int get_buffer(AVIOContext *s, unsigned char *buf, int size) |
||
342 | { |
||
343 | return avio_read(s, buf, size);
|
||
344 | } |
||
345 | b3db9cee | Anton Khirnov | int get_partial_buffer(AVIOContext *s, unsigned char *buf, int size) |
346 | { |
||
347 | return ffio_read_partial(s, buf, size);
|
||
348 | } |
||
349 | 77eb5504 | Anton Khirnov | void put_byte(AVIOContext *s, int val) |
350 | { |
||
351 | avio_w8(s, val); |
||
352 | } |
||
353 | void put_buffer(AVIOContext *s, const unsigned char *buf, int size) |
||
354 | { |
||
355 | avio_write(s, buf, size); |
||
356 | } |
||
357 | 0ac8e2bf | Anton Khirnov | void put_nbyte(AVIOContext *s, int b, int count) |
358 | { |
||
359 | ffio_fill(s, b, count); |
||
360 | } |
||
361 | 22a3212e | Anton Khirnov | |
362 | int url_fopen(AVIOContext **s, const char *filename, int flags) |
||
363 | { |
||
364 | return avio_open(s, filename, flags);
|
||
365 | } |
||
366 | int url_fclose(AVIOContext *s)
|
||
367 | { |
||
368 | return avio_close(s);
|
||
369 | } |
||
370 | 6b4aa5da | Anton Khirnov | int64_t url_fseek(AVIOContext *s, int64_t offset, int whence)
|
371 | { |
||
372 | return avio_seek(s, offset, whence);
|
||
373 | } |
||
374 | 4efd5cf3 | Anton Khirnov | #endif
|
375 | |||
376 | ae628ec1 | Anton Khirnov | int avio_put_str(AVIOContext *s, const char *str) |
377 | 4efd5cf3 | Anton Khirnov | { |
378 | int len = 1; |
||
379 | if (str) {
|
||
380 | len += strlen(str); |
||
381 | 77eb5504 | Anton Khirnov | avio_write(s, (const unsigned char *) str, len); |
382 | 4efd5cf3 | Anton Khirnov | } else
|
383 | 77eb5504 | Anton Khirnov | avio_w8(s, 0);
|
384 | 4efd5cf3 | Anton Khirnov | return len;
|
385 | 75bdb984 | Philip Gladstone | } |
386 | |||
387 | ae628ec1 | Anton Khirnov | int avio_put_str16le(AVIOContext *s, const char *str) |
388 | dccbd97d | Anton Khirnov | { |
389 | const uint8_t *q = str;
|
||
390 | int ret = 0; |
||
391 | |||
392 | while (*q) {
|
||
393 | uint32_t ch; |
||
394 | uint16_t tmp; |
||
395 | |||
396 | GET_UTF8(ch, *q++, break;)
|
||
397 | 77eb5504 | Anton Khirnov | PUT_UTF16(ch, tmp, avio_wl16(s, tmp);ret += 2;)
|
398 | dccbd97d | Anton Khirnov | } |
399 | 77eb5504 | Anton Khirnov | avio_wl16(s, 0);
|
400 | dccbd97d | Anton Khirnov | ret += 2;
|
401 | return ret;
|
||
402 | } |
||
403 | |||
404 | 603e5c0b | Michael Chinen | int ff_get_v_length(uint64_t val){
|
405 | int i=1; |
||
406 | |||
407 | while(val>>=7) |
||
408 | i++; |
||
409 | |||
410 | return i;
|
||
411 | } |
||
412 | |||
413 | ae628ec1 | Anton Khirnov | void ff_put_v(AVIOContext *bc, uint64_t val){
|
414 | 603e5c0b | Michael Chinen | int i= ff_get_v_length(val);
|
415 | |||
416 | while(--i>0) |
||
417 | 77eb5504 | Anton Khirnov | avio_w8(bc, 128 | (val>>(7*i))); |
418 | 603e5c0b | Michael Chinen | |
419 | 77eb5504 | Anton Khirnov | avio_w8(bc, val&127);
|
420 | 603e5c0b | Michael Chinen | } |
421 | |||
422 | 77eb5504 | Anton Khirnov | void avio_wl64(AVIOContext *s, uint64_t val)
|
423 | de6d9b64 | Fabrice Bellard | { |
424 | 77eb5504 | Anton Khirnov | avio_wl32(s, (uint32_t)(val & 0xffffffff));
|
425 | avio_wl32(s, (uint32_t)(val >> 32));
|
||
426 | de6d9b64 | Fabrice Bellard | } |
427 | |||
428 | 77eb5504 | Anton Khirnov | void avio_wb64(AVIOContext *s, uint64_t val)
|
429 | de6d9b64 | Fabrice Bellard | { |
430 | 77eb5504 | Anton Khirnov | avio_wb32(s, (uint32_t)(val >> 32));
|
431 | avio_wb32(s, (uint32_t)(val & 0xffffffff));
|
||
432 | de6d9b64 | Fabrice Bellard | } |
433 | |||
434 | 77eb5504 | Anton Khirnov | void avio_wl16(AVIOContext *s, unsigned int val) |
435 | de6d9b64 | Fabrice Bellard | { |
436 | 77eb5504 | Anton Khirnov | avio_w8(s, val); |
437 | avio_w8(s, val >> 8);
|
||
438 | de6d9b64 | Fabrice Bellard | } |
439 | |||
440 | 77eb5504 | Anton Khirnov | void avio_wb16(AVIOContext *s, unsigned int val) |
441 | de6d9b64 | Fabrice Bellard | { |
442 | 77eb5504 | Anton Khirnov | avio_w8(s, val >> 8);
|
443 | avio_w8(s, val); |
||
444 | de6d9b64 | Fabrice Bellard | } |
445 | |||
446 | 77eb5504 | Anton Khirnov | void avio_wl24(AVIOContext *s, unsigned int val) |
447 | ea395e8c | Aurelien Jacobs | { |
448 | 77eb5504 | Anton Khirnov | avio_wl16(s, val & 0xffff);
|
449 | avio_w8(s, val >> 16);
|
||
450 | ea395e8c | Aurelien Jacobs | } |
451 | |||
452 | 77eb5504 | Anton Khirnov | void avio_wb24(AVIOContext *s, unsigned int val) |
453 | a254c574 | Michael Niedermayer | { |
454 | 77eb5504 | Anton Khirnov | avio_wb16(s, val >> 8);
|
455 | avio_w8(s, val); |
||
456 | a254c574 | Michael Niedermayer | } |
457 | |||
458 | 61840b43 | Anton Khirnov | #if FF_API_OLD_AVIO
|
459 | ae628ec1 | Anton Khirnov | void put_tag(AVIOContext *s, const char *tag) |
460 | de6d9b64 | Fabrice Bellard | { |
461 | while (*tag) {
|
||
462 | 77eb5504 | Anton Khirnov | avio_w8(s, *tag++); |
463 | de6d9b64 | Fabrice Bellard | } |
464 | } |
||
465 | 61840b43 | Anton Khirnov | #endif
|
466 | de6d9b64 | Fabrice Bellard | |
467 | /* Input stream */
|
||
468 | |||
469 | ae628ec1 | Anton Khirnov | static void fill_buffer(AVIOContext *s) |
470 | de6d9b64 | Fabrice Bellard | { |
471 | e360ada2 | Martin Storsjö | uint8_t *dst= !s->max_packet_size && s->buf_end - s->buffer < s->buffer_size ? s->buf_end : s->buffer; |
472 | 4589dc5c | Michael Niedermayer | int len= s->buffer_size - (dst - s->buffer);
|
473 | 01d91b9b | Tomas Härdin | int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE;
|
474 | 4589dc5c | Michael Niedermayer | |
475 | abba3dd1 | Fabrice Bellard | /* no need to do anything if EOF already reached */
|
476 | if (s->eof_reached)
|
||
477 | return;
|
||
478 | ee9f36a8 | Michael Niedermayer | |
479 | 4589dc5c | Michael Niedermayer | if(s->update_checksum && dst == s->buffer){
|
480 | 0f0680c5 | Michael Niedermayer | if(s->buf_end > s->checksum_ptr)
|
481 | s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr); |
||
482 | ee9f36a8 | Michael Niedermayer | s->checksum_ptr= s->buffer; |
483 | } |
||
484 | |||
485 | 01d91b9b | Tomas Härdin | /* make buffer smaller in case it ended up large after probing */
|
486 | if (s->buffer_size > max_buffer_size) {
|
||
487 | url_setbufsize(s, max_buffer_size); |
||
488 | |||
489 | s->checksum_ptr = dst = s->buffer; |
||
490 | len = s->buffer_size; |
||
491 | } |
||
492 | |||
493 | 602dd8f6 | Benoit Fouet | if(s->read_packet)
|
494 | c66f53cf | Martin Storsjö | len = s->read_packet(s->opaque, dst, len); |
495 | 4589dc5c | Michael Niedermayer | else
|
496 | len = 0;
|
||
497 | abba3dd1 | Fabrice Bellard | if (len <= 0) { |
498 | /* do not modify buffer if EOF reached so that a seek back can
|
||
499 | be done without rereading data */
|
||
500 | de6d9b64 | Fabrice Bellard | s->eof_reached = 1;
|
501 | 5f097703 | Alex Beregszaszi | if(len<0) |
502 | s->error= len; |
||
503 | abba3dd1 | Fabrice Bellard | } else {
|
504 | s->pos += len; |
||
505 | 4589dc5c | Michael Niedermayer | s->buf_ptr = dst; |
506 | s->buf_end = dst + len; |
||
507 | de6d9b64 | Fabrice Bellard | } |
508 | } |
||
509 | |||
510 | 7f37f568 | Diego Biurrun | unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, |
511 | unsigned int len) |
||
512 | { |
||
513 | 3abe5fbd | Aurelien Jacobs | return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len);
|
514 | 992e78f5 | Baptiste Coudurier | } |
515 | |||
516 | ae628ec1 | Anton Khirnov | unsigned long get_checksum(AVIOContext *s) |
517 | 7f37f568 | Diego Biurrun | { |
518 | ee9f36a8 | Michael Niedermayer | s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr); |
519 | 465e1dad | Michael Niedermayer | s->update_checksum= NULL;
|
520 | ee9f36a8 | Michael Niedermayer | return s->checksum;
|
521 | } |
||
522 | |||
523 | ae628ec1 | Anton Khirnov | void init_checksum(AVIOContext *s,
|
524 | 7f37f568 | Diego Biurrun | unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), |
525 | unsigned long checksum) |
||
526 | { |
||
527 | ee9f36a8 | Michael Niedermayer | s->update_checksum= update_checksum; |
528 | 465e1dad | Michael Niedermayer | if(s->update_checksum){
|
529 | ccb15994 | Michael Niedermayer | s->checksum= checksum; |
530 | 465e1dad | Michael Niedermayer | s->checksum_ptr= s->buf_ptr; |
531 | } |
||
532 | ee9f36a8 | Michael Niedermayer | } |
533 | |||
534 | abba3dd1 | Fabrice Bellard | /* XXX: put an inline version */
|
535 | b7effd4e | Anton Khirnov | int avio_r8(AVIOContext *s)
|
536 | de6d9b64 | Fabrice Bellard | { |
537 | 3aa13da9 | Reimar Döffinger | if (s->buf_ptr >= s->buf_end)
|
538 | de6d9b64 | Fabrice Bellard | fill_buffer(s); |
539 | 853a0fcc | Reimar Döffinger | if (s->buf_ptr < s->buf_end)
|
540 | return *s->buf_ptr++;
|
||
541 | return 0; |
||
542 | de6d9b64 | Fabrice Bellard | } |
543 | |||
544 | ae628ec1 | Anton Khirnov | int url_fgetc(AVIOContext *s)
|
545 | abba3dd1 | Fabrice Bellard | { |
546 | 3aa13da9 | Reimar Döffinger | if (s->buf_ptr >= s->buf_end)
|
547 | abba3dd1 | Fabrice Bellard | fill_buffer(s); |
548 | 853a0fcc | Reimar Döffinger | if (s->buf_ptr < s->buf_end)
|
549 | return *s->buf_ptr++;
|
||
550 | return URL_EOF;
|
||
551 | abba3dd1 | Fabrice Bellard | } |
552 | |||
553 | b7effd4e | Anton Khirnov | int avio_read(AVIOContext *s, unsigned char *buf, int size) |
554 | de6d9b64 | Fabrice Bellard | { |
555 | int len, size1;
|
||
556 | |||
557 | size1 = size; |
||
558 | while (size > 0) { |
||
559 | len = s->buf_end - s->buf_ptr; |
||
560 | if (len > size)
|
||
561 | len = size; |
||
562 | if (len == 0) { |
||
563 | 3e2b6358 | Michael Niedermayer | if(size > s->buffer_size && !s->update_checksum){
|
564 | 602dd8f6 | Benoit Fouet | if(s->read_packet)
|
565 | c66f53cf | Martin Storsjö | len = s->read_packet(s->opaque, buf, size); |
566 | 3e2b6358 | Michael Niedermayer | if (len <= 0) { |
567 | /* do not modify buffer if EOF reached so that a seek back can
|
||
568 | be done without rereading data */
|
||
569 | s->eof_reached = 1;
|
||
570 | if(len<0) |
||
571 | s->error= len; |
||
572 | break;
|
||
573 | } else {
|
||
574 | s->pos += len; |
||
575 | size -= len; |
||
576 | buf += len; |
||
577 | s->buf_ptr = s->buffer; |
||
578 | s->buf_end = s->buffer/* + len*/;
|
||
579 | } |
||
580 | }else{
|
||
581 | fill_buffer(s); |
||
582 | len = s->buf_end - s->buf_ptr; |
||
583 | if (len == 0) |
||
584 | break;
|
||
585 | } |
||
586 | de6d9b64 | Fabrice Bellard | } else {
|
587 | memcpy(buf, s->buf_ptr, len); |
||
588 | buf += len; |
||
589 | s->buf_ptr += len; |
||
590 | size -= len; |
||
591 | } |
||
592 | } |
||
593 | 7f7686df | Reimar Döffinger | if (size1 == size) {
|
594 | if (url_ferror(s)) return url_ferror(s); |
||
595 | if (url_feof(s)) return AVERROR_EOF; |
||
596 | } |
||
597 | de6d9b64 | Fabrice Bellard | return size1 - size;
|
598 | } |
||
599 | |||
600 | b3db9cee | Anton Khirnov | int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size) |
601 | e15dec10 | Leon van Stuivenberg | { |
602 | int len;
|
||
603 | 115329f1 | Diego Biurrun | |
604 | 0ecca7a4 | Michael Niedermayer | if(size<0) |
605 | return -1; |
||
606 | e15dec10 | Leon van Stuivenberg | |
607 | len = s->buf_end - s->buf_ptr; |
||
608 | if (len == 0) { |
||
609 | fill_buffer(s); |
||
610 | len = s->buf_end - s->buf_ptr; |
||
611 | } |
||
612 | if (len > size)
|
||
613 | len = size; |
||
614 | memcpy(buf, s->buf_ptr, len); |
||
615 | s->buf_ptr += len; |
||
616 | 7f7686df | Reimar Döffinger | if (!len) {
|
617 | if (url_ferror(s)) return url_ferror(s); |
||
618 | if (url_feof(s)) return AVERROR_EOF; |
||
619 | } |
||
620 | e15dec10 | Leon van Stuivenberg | return len;
|
621 | } |
||
622 | |||
623 | b7effd4e | Anton Khirnov | unsigned int avio_rl16(AVIOContext *s) |
624 | de6d9b64 | Fabrice Bellard | { |
625 | unsigned int val; |
||
626 | b7effd4e | Anton Khirnov | val = avio_r8(s); |
627 | val |= avio_r8(s) << 8;
|
||
628 | de6d9b64 | Fabrice Bellard | return val;
|
629 | } |
||
630 | |||
631 | b7effd4e | Anton Khirnov | unsigned int avio_rl24(AVIOContext *s) |
632 | ea395e8c | Aurelien Jacobs | { |
633 | unsigned int val; |
||
634 | b7effd4e | Anton Khirnov | val = avio_rl16(s); |
635 | val |= avio_r8(s) << 16;
|
||
636 | ea395e8c | Aurelien Jacobs | return val;
|
637 | } |
||
638 | |||
639 | b7effd4e | Anton Khirnov | unsigned int avio_rl32(AVIOContext *s) |
640 | de6d9b64 | Fabrice Bellard | { |
641 | unsigned int val; |
||
642 | b7effd4e | Anton Khirnov | val = avio_rl16(s); |
643 | val |= avio_rl16(s) << 16;
|
||
644 | de6d9b64 | Fabrice Bellard | return val;
|
645 | } |
||
646 | |||
647 | b7effd4e | Anton Khirnov | uint64_t avio_rl64(AVIOContext *s) |
648 | de6d9b64 | Fabrice Bellard | { |
649 | 0c1a9eda | Zdenek Kabelac | uint64_t val; |
650 | b7effd4e | Anton Khirnov | val = (uint64_t)avio_rl32(s); |
651 | val |= (uint64_t)avio_rl32(s) << 32;
|
||
652 | de6d9b64 | Fabrice Bellard | return val;
|
653 | } |
||
654 | |||
655 | b7effd4e | Anton Khirnov | unsigned int avio_rb16(AVIOContext *s) |
656 | de6d9b64 | Fabrice Bellard | { |
657 | unsigned int val; |
||
658 | b7effd4e | Anton Khirnov | val = avio_r8(s) << 8;
|
659 | val |= avio_r8(s); |
||
660 | de6d9b64 | Fabrice Bellard | return val;
|
661 | } |
||
662 | |||
663 | b7effd4e | Anton Khirnov | unsigned int avio_rb24(AVIOContext *s) |
664 | de6d9b64 | Fabrice Bellard | { |
665 | unsigned int val; |
||
666 | b7effd4e | Anton Khirnov | val = avio_rb16(s) << 8;
|
667 | val |= avio_r8(s); |
||
668 | de6d9b64 | Fabrice Bellard | return val;
|
669 | } |
||
670 | b7effd4e | Anton Khirnov | unsigned int avio_rb32(AVIOContext *s) |
671 | a254c574 | Michael Niedermayer | { |
672 | unsigned int val; |
||
673 | b7effd4e | Anton Khirnov | val = avio_rb16(s) << 16;
|
674 | val |= avio_rb16(s); |
||
675 | a254c574 | Michael Niedermayer | return val;
|
676 | } |
||
677 | de6d9b64 | Fabrice Bellard | |
678 | e16ead07 | Anton Khirnov | #if FF_API_OLD_AVIO
|
679 | ae628ec1 | Anton Khirnov | char *get_strz(AVIOContext *s, char *buf, int maxlen) |
680 | 75bdb984 | Philip Gladstone | { |
681 | e16ead07 | Anton Khirnov | avio_get_str(s, INT_MAX, buf, maxlen); |
682 | 75bdb984 | Philip Gladstone | return buf;
|
683 | } |
||
684 | e16ead07 | Anton Khirnov | #endif
|
685 | 75bdb984 | Philip Gladstone | |
686 | ae628ec1 | Anton Khirnov | int ff_get_line(AVIOContext *s, char *buf, int maxlen) |
687 | 7c892951 | Aurelien Jacobs | { |
688 | int i = 0; |
||
689 | char c;
|
||
690 | |||
691 | do {
|
||
692 | b7effd4e | Anton Khirnov | c = avio_r8(s); |
693 | a43416a5 | Aurelien Jacobs | if (c && i < maxlen-1) |
694 | 7c892951 | Aurelien Jacobs | buf[i++] = c; |
695 | } while (c != '\n' && c); |
||
696 | |||
697 | buf[i] = 0;
|
||
698 | a43416a5 | Aurelien Jacobs | return i;
|
699 | 7c892951 | Aurelien Jacobs | } |
700 | |||
701 | 41d8555f | Reimar Döffinger | int avio_get_str(AVIOContext *s, int maxlen, char *buf, int buflen) |
702 | { |
||
703 | int i;
|
||
704 | |||
705 | // reserve 1 byte for terminating 0
|
||
706 | buflen = FFMIN(buflen - 1, maxlen);
|
||
707 | for (i = 0; i < buflen; i++) |
||
708 | if (!(buf[i] = avio_r8(s)))
|
||
709 | return i + 1; |
||
710 | if (buflen)
|
||
711 | buf[i] = 0;
|
||
712 | for (; i < maxlen; i++)
|
||
713 | if (!avio_r8(s))
|
||
714 | return i + 1; |
||
715 | return maxlen;
|
||
716 | } |
||
717 | |||
718 | 93b78d12 | Anton Khirnov | #define GET_STR16(type, read) \
|
719 | ae628ec1 | Anton Khirnov | int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\ |
720 | 93b78d12 | Anton Khirnov | {\ |
721 | char* q = buf;\
|
||
722 | int ret = 0;\ |
||
723 | while (ret + 1 < maxlen) {\ |
||
724 | uint8_t tmp;\ |
||
725 | uint32_t ch;\ |
||
726 | GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\ |
||
727 | if (!ch)\
|
||
728 | break;\
|
||
729 | PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\ |
||
730 | }\ |
||
731 | *q = 0;\
|
||
732 | return ret;\
|
||
733 | }\ |
||
734 | |||
735 | b7effd4e | Anton Khirnov | GET_STR16(le, avio_rl16) |
736 | GET_STR16(be, avio_rb16) |
||
737 | 93b78d12 | Anton Khirnov | |
738 | #undef GET_STR16
|
||
739 | |||
740 | b7effd4e | Anton Khirnov | uint64_t avio_rb64(AVIOContext *s) |
741 | de6d9b64 | Fabrice Bellard | { |
742 | 0c1a9eda | Zdenek Kabelac | uint64_t val; |
743 | b7effd4e | Anton Khirnov | val = (uint64_t)avio_rb32(s) << 32;
|
744 | val |= (uint64_t)avio_rb32(s); |
||
745 | de6d9b64 | Fabrice Bellard | return val;
|
746 | } |
||
747 | |||
748 | ae628ec1 | Anton Khirnov | uint64_t ff_get_v(AVIOContext *bc){ |
749 | 897d3eef | Kostya Shishkov | uint64_t val = 0;
|
750 | int tmp;
|
||
751 | |||
752 | do{
|
||
753 | b7effd4e | Anton Khirnov | tmp = avio_r8(bc); |
754 | 897d3eef | Kostya Shishkov | val= (val<<7) + (tmp&127); |
755 | }while(tmp&128); |
||
756 | return val;
|
||
757 | } |
||
758 | |||
759 | ae628ec1 | Anton Khirnov | int url_fdopen(AVIOContext **s, URLContext *h)
|
760 | de6d9b64 | Fabrice Bellard | { |
761 | 0c1a9eda | Zdenek Kabelac | uint8_t *buffer; |
762 | abba3dd1 | Fabrice Bellard | int buffer_size, max_packet_size;
|
763 | de6d9b64 | Fabrice Bellard | |
764 | abba3dd1 | Fabrice Bellard | max_packet_size = url_get_max_packet_size(h); |
765 | if (max_packet_size) {
|
||
766 | buffer_size = max_packet_size; /* no need to bufferize more than one packet */
|
||
767 | } else {
|
||
768 | buffer_size = IO_BUFFER_SIZE; |
||
769 | } |
||
770 | 1ea4f593 | Fabrice Bellard | buffer = av_malloc(buffer_size); |
771 | de6d9b64 | Fabrice Bellard | if (!buffer)
|
772 | 8fa36ae0 | François Revol | return AVERROR(ENOMEM);
|
773 | de6d9b64 | Fabrice Bellard | |
774 | ae628ec1 | Anton Khirnov | *s = av_mallocz(sizeof(AVIOContext));
|
775 | 899681cd | Björn Axelsson | if(!*s) {
|
776 | av_free(buffer); |
||
777 | return AVERROR(ENOMEM);
|
||
778 | } |
||
779 | |||
780 | e731b8d8 | Anton Khirnov | if (ffio_init_context(*s, buffer, buffer_size,
|
781 | ac9fe33d | Gildas Bazin | (h->flags & URL_WRONLY || h->flags & URL_RDWR), h, |
782 | 004050ee | Michael Niedermayer | url_read, url_write, url_seek) < 0) {
|
783 | 1ea4f593 | Fabrice Bellard | av_free(buffer); |
784 | 899681cd | Björn Axelsson | av_freep(s); |
785 | 6f3e0b21 | Panagiotis Issaris | return AVERROR(EIO);
|
786 | de6d9b64 | Fabrice Bellard | } |
787 | 899681cd | Björn Axelsson | (*s)->is_streamed = h->is_streamed; |
788 | (*s)->max_packet_size = max_packet_size; |
||
789 | e7e4810a | Björn Axelsson | if(h->prot) {
|
790 | 502bdf68 | Michael Niedermayer | (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause; |
791 | bc5c918e | Diego Biurrun | (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek; |
792 | e7e4810a | Björn Axelsson | } |
793 | de6d9b64 | Fabrice Bellard | return 0; |
794 | } |
||
795 | |||
796 | ae628ec1 | Anton Khirnov | int url_setbufsize(AVIOContext *s, int buf_size) |
797 | de6d9b64 | Fabrice Bellard | { |
798 | 0c1a9eda | Zdenek Kabelac | uint8_t *buffer; |
799 | 1ea4f593 | Fabrice Bellard | buffer = av_malloc(buf_size); |
800 | de6d9b64 | Fabrice Bellard | if (!buffer)
|
801 | 8fa36ae0 | François Revol | return AVERROR(ENOMEM);
|
802 | de6d9b64 | Fabrice Bellard | |
803 | 1ea4f593 | Fabrice Bellard | av_free(s->buffer); |
804 | de6d9b64 | Fabrice Bellard | s->buffer = buffer; |
805 | s->buffer_size = buf_size; |
||
806 | s->buf_ptr = buffer; |
||
807 | 770d9daf | Björn Axelsson | url_resetbuf(s, s->write_flag ? URL_WRONLY : URL_RDONLY); |
808 | return 0; |
||
809 | } |
||
810 | |||
811 | 364cacc7 | Aurelien Jacobs | #if FF_API_URL_RESETBUF
|
812 | ae628ec1 | Anton Khirnov | int url_resetbuf(AVIOContext *s, int flags) |
813 | 08580cb0 | Benoit Fouet | #else
|
814 | ae628ec1 | Anton Khirnov | static int url_resetbuf(AVIOContext *s, int flags) |
815 | 08580cb0 | Benoit Fouet | #endif
|
816 | 770d9daf | Björn Axelsson | { |
817 | 364cacc7 | Aurelien Jacobs | #if FF_API_URL_RESETBUF
|
818 | 6fa197e2 | Eli Friedman | if (flags & URL_RDWR)
|
819 | 770d9daf | Björn Axelsson | return AVERROR(EINVAL);
|
820 | 08580cb0 | Benoit Fouet | #else
|
821 | assert(flags == URL_WRONLY || flags == URL_RDONLY); |
||
822 | #endif
|
||
823 | 770d9daf | Björn Axelsson | |
824 | if (flags & URL_WRONLY) {
|
||
825 | s->buf_end = s->buffer + s->buffer_size; |
||
826 | s->write_flag = 1;
|
||
827 | } else {
|
||
828 | s->buf_end = s->buffer; |
||
829 | s->write_flag = 0;
|
||
830 | } |
||
831 | de6d9b64 | Fabrice Bellard | return 0; |
832 | } |
||
833 | |||
834 | ae628ec1 | Anton Khirnov | int ff_rewind_with_probe_data(AVIOContext *s, unsigned char *buf, int buf_size) |
835 | 01d91b9b | Tomas Härdin | { |
836 | int64_t buffer_start; |
||
837 | int buffer_size;
|
||
838 | 496c645d | Martin Storsjö | int overlap, new_size, alloc_size;
|
839 | 01d91b9b | Tomas Härdin | |
840 | if (s->write_flag)
|
||
841 | return AVERROR(EINVAL);
|
||
842 | |||
843 | buffer_size = s->buf_end - s->buffer; |
||
844 | |||
845 | /* the buffers must touch or overlap */
|
||
846 | if ((buffer_start = s->pos - buffer_size) > buf_size)
|
||
847 | return AVERROR(EINVAL);
|
||
848 | |||
849 | overlap = buf_size - buffer_start; |
||
850 | new_size = buf_size + buffer_size - overlap; |
||
851 | |||
852 | 496c645d | Martin Storsjö | alloc_size = FFMAX(s->buffer_size, new_size); |
853 | if (alloc_size > buf_size)
|
||
854 | if (!(buf = av_realloc(buf, alloc_size)))
|
||
855 | 01d91b9b | Tomas Härdin | return AVERROR(ENOMEM);
|
856 | |||
857 | 496c645d | Martin Storsjö | if (new_size > buf_size) {
|
858 | 01d91b9b | Tomas Härdin | memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap); |
859 | buf_size = new_size; |
||
860 | } |
||
861 | |||
862 | av_free(s->buffer); |
||
863 | s->buf_ptr = s->buffer = buf; |
||
864 | 496c645d | Martin Storsjö | s->buffer_size = alloc_size; |
865 | s->pos = buf_size; |
||
866 | 01d91b9b | Tomas Härdin | s->buf_end = s->buf_ptr + buf_size; |
867 | s->eof_reached = 0;
|
||
868 | s->must_flush = 0;
|
||
869 | |||
870 | return 0; |
||
871 | } |
||
872 | |||
873 | 22a3212e | Anton Khirnov | int avio_open(AVIOContext **s, const char *filename, int flags) |
874 | de6d9b64 | Fabrice Bellard | { |
875 | URLContext *h; |
||
876 | int err;
|
||
877 | |||
878 | err = url_open(&h, filename, flags); |
||
879 | if (err < 0) |
||
880 | return err;
|
||
881 | err = url_fdopen(s, h); |
||
882 | if (err < 0) { |
||
883 | url_close(h); |
||
884 | return err;
|
||
885 | } |
||
886 | return 0; |
||
887 | } |
||
888 | |||
889 | 22a3212e | Anton Khirnov | int avio_close(AVIOContext *s)
|
890 | de6d9b64 | Fabrice Bellard | { |
891 | URLContext *h = s->opaque; |
||
892 | 115329f1 | Diego Biurrun | |
893 | 1ea4f593 | Fabrice Bellard | av_free(s->buffer); |
894 | 899681cd | Björn Axelsson | av_free(s); |
895 | de6d9b64 | Fabrice Bellard | return url_close(h);
|
896 | } |
||
897 | |||
898 | ae628ec1 | Anton Khirnov | URLContext *url_fileno(AVIOContext *s) |
899 | de6d9b64 | Fabrice Bellard | { |
900 | return s->opaque;
|
||
901 | } |
||
902 | |||
903 | b250f9c6 | Aurelien Jacobs | #if CONFIG_MUXERS
|
904 | ae628ec1 | Anton Khirnov | int url_fprintf(AVIOContext *s, const char *fmt, ...) |
905 | abba3dd1 | Fabrice Bellard | { |
906 | va_list ap; |
||
907 | char buf[4096]; |
||
908 | int ret;
|
||
909 | |||
910 | va_start(ap, fmt); |
||
911 | ret = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||
912 | va_end(ap); |
||
913 | 77eb5504 | Anton Khirnov | avio_write(s, buf, strlen(buf)); |
914 | abba3dd1 | Fabrice Bellard | return ret;
|
915 | } |
||
916 | a9e35095 | Diego Biurrun | #endif //CONFIG_MUXERS |
917 | abba3dd1 | Fabrice Bellard | |
918 | ae628ec1 | Anton Khirnov | char *url_fgets(AVIOContext *s, char *buf, int buf_size) |
919 | abba3dd1 | Fabrice Bellard | { |
920 | int c;
|
||
921 | char *q;
|
||
922 | |||
923 | c = url_fgetc(s); |
||
924 | if (c == EOF) |
||
925 | return NULL; |
||
926 | q = buf; |
||
927 | for(;;) {
|
||
928 | if (c == EOF || c == '\n') |
||
929 | break;
|
||
930 | if ((q - buf) < buf_size - 1) |
||
931 | *q++ = c; |
||
932 | c = url_fgetc(s); |
||
933 | } |
||
934 | if (buf_size > 0) |
||
935 | *q = '\0';
|
||
936 | return buf;
|
||
937 | } |
||
938 | |||
939 | ae628ec1 | Anton Khirnov | int url_fget_max_packet_size(AVIOContext *s)
|
940 | abba3dd1 | Fabrice Bellard | { |
941 | return s->max_packet_size;
|
||
942 | } |
||
943 | |||
944 | ae628ec1 | Anton Khirnov | int av_url_read_fpause(AVIOContext *s, int pause) |
945 | e7e4810a | Björn Axelsson | { |
946 | if (!s->read_pause)
|
||
947 | return AVERROR(ENOSYS);
|
||
948 | 502bdf68 | Michael Niedermayer | return s->read_pause(s->opaque, pause);
|
949 | e7e4810a | Björn Axelsson | } |
950 | |||
951 | ae628ec1 | Anton Khirnov | int64_t av_url_read_fseek(AVIOContext *s, int stream_index,
|
952 | 7f37f568 | Diego Biurrun | int64_t timestamp, int flags)
|
953 | e7e4810a | Björn Axelsson | { |
954 | URLContext *h = s->opaque; |
||
955 | bc5c918e | Diego Biurrun | int64_t ret; |
956 | e7e4810a | Björn Axelsson | if (!s->read_seek)
|
957 | return AVERROR(ENOSYS);
|
||
958 | ret = s->read_seek(h, stream_index, timestamp, flags); |
||
959 | if(ret >= 0) { |
||
960 | c007c687 | Howard Chu | int64_t pos; |
961 | e7e4810a | Björn Axelsson | s->buf_ptr = s->buf_end; // Flush buffer
|
962 | c007c687 | Howard Chu | pos = s->seek(h, 0, SEEK_CUR);
|
963 | if (pos >= 0) |
||
964 | s->pos = pos; |
||
965 | else if (pos != AVERROR(ENOSYS)) |
||
966 | ret = pos; |
||
967 | e7e4810a | Björn Axelsson | } |
968 | return ret;
|
||
969 | } |
||
970 | |||
971 | 8fa641f8 | Loïc Le Loarer | /* url_open_dyn_buf and url_close_dyn_buf are used in rtp.c to send a response
|
972 | b250f9c6 | Aurelien Jacobs | * back to the server even if CONFIG_MUXERS is false. */
|
973 | #if CONFIG_MUXERS || CONFIG_NETWORK
|
||
974 | de6d9b64 | Fabrice Bellard | /* buffer handling */
|
975 | ae628ec1 | Anton Khirnov | int url_open_buf(AVIOContext **s, uint8_t *buf, int buf_size, int flags) |
976 | de6d9b64 | Fabrice Bellard | { |
977 | 899681cd | Björn Axelsson | int ret;
|
978 | ae628ec1 | Anton Khirnov | *s = av_mallocz(sizeof(AVIOContext));
|
979 | 899681cd | Björn Axelsson | if(!*s)
|
980 | return AVERROR(ENOMEM);
|
||
981 | e731b8d8 | Anton Khirnov | ret = ffio_init_context(*s, buf, buf_size, |
982 | 899681cd | Björn Axelsson | (flags & URL_WRONLY || flags & URL_RDWR), |
983 | NULL, NULL, NULL, NULL); |
||
984 | if(ret != 0) |
||
985 | av_freep(s); |
||
986 | return ret;
|
||
987 | de6d9b64 | Fabrice Bellard | } |
988 | |||
989 | ae628ec1 | Anton Khirnov | int url_close_buf(AVIOContext *s)
|
990 | de6d9b64 | Fabrice Bellard | { |
991 | abba3dd1 | Fabrice Bellard | put_flush_packet(s); |
992 | de6d9b64 | Fabrice Bellard | return s->buf_ptr - s->buffer;
|
993 | } |
||
994 | abba3dd1 | Fabrice Bellard | |
995 | /* output in a dynamic buffer */
|
||
996 | |||
997 | typedef struct DynBuffer { |
||
998 | int pos, size, allocated_size;
|
||
999 | 0c1a9eda | Zdenek Kabelac | uint8_t *buffer; |
1000 | abba3dd1 | Fabrice Bellard | int io_buffer_size;
|
1001 | 0c1a9eda | Zdenek Kabelac | uint8_t io_buffer[1];
|
1002 | abba3dd1 | Fabrice Bellard | } DynBuffer; |
1003 | |||
1004 | 576ae256 | Michael Niedermayer | static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size) |
1005 | abba3dd1 | Fabrice Bellard | { |
1006 | DynBuffer *d = opaque; |
||
1007 | 6bc03a69 | Reimar Döffinger | unsigned new_size, new_allocated_size;
|
1008 | 115329f1 | Diego Biurrun | |
1009 | abba3dd1 | Fabrice Bellard | /* reallocate buffer if needed */
|
1010 | new_size = d->pos + buf_size; |
||
1011 | new_allocated_size = d->allocated_size; |
||
1012 | 568e18b1 | Michael Niedermayer | if(new_size < d->pos || new_size > INT_MAX/2) |
1013 | return -1; |
||
1014 | abba3dd1 | Fabrice Bellard | while (new_size > new_allocated_size) {
|
1015 | if (!new_allocated_size)
|
||
1016 | new_allocated_size = new_size; |
||
1017 | else
|
||
1018 | 115329f1 | Diego Biurrun | new_allocated_size += new_allocated_size / 2 + 1; |
1019 | abba3dd1 | Fabrice Bellard | } |
1020 | 115329f1 | Diego Biurrun | |
1021 | abba3dd1 | Fabrice Bellard | if (new_allocated_size > d->allocated_size) {
|
1022 | b88ba823 | Mark Hills | d->buffer = av_realloc(d->buffer, new_allocated_size); |
1023 | if(d->buffer == NULL) |
||
1024 | 7ce820ef | Reimar Döffinger | return AVERROR(ENOMEM);
|
1025 | abba3dd1 | Fabrice Bellard | d->allocated_size = new_allocated_size; |
1026 | } |
||
1027 | memcpy(d->buffer + d->pos, buf, buf_size); |
||
1028 | d->pos = new_size; |
||
1029 | if (d->pos > d->size)
|
||
1030 | d->size = d->pos; |
||
1031 | 576ae256 | Michael Niedermayer | return buf_size;
|
1032 | abba3dd1 | Fabrice Bellard | } |
1033 | |||
1034 | 576ae256 | Michael Niedermayer | static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size) |
1035 | abba3dd1 | Fabrice Bellard | { |
1036 | unsigned char buf1[4]; |
||
1037 | 576ae256 | Michael Niedermayer | int ret;
|
1038 | abba3dd1 | Fabrice Bellard | |
1039 | /* packetized write: output the header */
|
||
1040 | aa805f94 | Reimar Döffinger | AV_WB32(buf1, buf_size); |
1041 | 576ae256 | Michael Niedermayer | ret= dyn_buf_write(opaque, buf1, 4);
|
1042 | if(ret < 0) |
||
1043 | return ret;
|
||
1044 | abba3dd1 | Fabrice Bellard | |
1045 | /* then the data */
|
||
1046 | 576ae256 | Michael Niedermayer | return dyn_buf_write(opaque, buf, buf_size);
|
1047 | abba3dd1 | Fabrice Bellard | } |
1048 | |||
1049 | bc5c918e | Diego Biurrun | static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence) |
1050 | abba3dd1 | Fabrice Bellard | { |
1051 | DynBuffer *d = opaque; |
||
1052 | |||
1053 | if (whence == SEEK_CUR)
|
||
1054 | offset += d->pos; |
||
1055 | else if (whence == SEEK_END) |
||
1056 | offset += d->size; |
||
1057 | if (offset < 0 || offset > 0x7fffffffLL) |
||
1058 | return -1; |
||
1059 | d->pos = offset; |
||
1060 | return 0; |
||
1061 | } |
||
1062 | |||
1063 | ae628ec1 | Anton Khirnov | static int url_open_dyn_buf_internal(AVIOContext **s, int max_packet_size) |
1064 | abba3dd1 | Fabrice Bellard | { |
1065 | DynBuffer *d; |
||
1066 | 2bdaf78c | Reimar Döffinger | int ret;
|
1067 | 0c5a43d6 | Reimar Döffinger | unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024; |
1068 | 115329f1 | Diego Biurrun | |
1069 | 568e18b1 | Michael Niedermayer | if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size) |
1070 | return -1; |
||
1071 | dc2c2eea | Reimar Döffinger | d = av_mallocz(sizeof(DynBuffer) + io_buffer_size);
|
1072 | abba3dd1 | Fabrice Bellard | if (!d)
|
1073 | 0e7ceb24 | Reimar Döffinger | return AVERROR(ENOMEM);
|
1074 | ae628ec1 | Anton Khirnov | *s = av_mallocz(sizeof(AVIOContext));
|
1075 | 899681cd | Björn Axelsson | if(!*s) {
|
1076 | av_free(d); |
||
1077 | return AVERROR(ENOMEM);
|
||
1078 | } |
||
1079 | abba3dd1 | Fabrice Bellard | d->io_buffer_size = io_buffer_size; |
1080 | e731b8d8 | Anton Khirnov | ret = ffio_init_context(*s, d->io_buffer, io_buffer_size, |
1081 | 115329f1 | Diego Biurrun | 1, d, NULL, |
1082 | max_packet_size ? dyn_packet_buf_write : dyn_buf_write, |
||
1083 | abba3dd1 | Fabrice Bellard | max_packet_size ? NULL : dyn_buf_seek);
|
1084 | if (ret == 0) { |
||
1085 | 899681cd | Björn Axelsson | (*s)->max_packet_size = max_packet_size; |
1086 | } else {
|
||
1087 | av_free(d); |
||
1088 | av_freep(s); |
||
1089 | abba3dd1 | Fabrice Bellard | } |
1090 | return ret;
|
||
1091 | } |
||
1092 | |||
1093 | ae628ec1 | Anton Khirnov | int url_open_dyn_buf(AVIOContext **s)
|
1094 | abba3dd1 | Fabrice Bellard | { |
1095 | return url_open_dyn_buf_internal(s, 0); |
||
1096 | } |
||
1097 | |||
1098 | ae628ec1 | Anton Khirnov | int url_open_dyn_packet_buf(AVIOContext **s, int max_packet_size) |
1099 | abba3dd1 | Fabrice Bellard | { |
1100 | if (max_packet_size <= 0) |
||
1101 | return -1; |
||
1102 | return url_open_dyn_buf_internal(s, max_packet_size);
|
||
1103 | } |
||
1104 | |||
1105 | ae628ec1 | Anton Khirnov | int url_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
|
1106 | abba3dd1 | Fabrice Bellard | { |
1107 | DynBuffer *d = s->opaque; |
||
1108 | int size;
|
||
1109 | de1807bb | Josh Allmann | static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0}; |
1110 | int padding = 0; |
||
1111 | |||
1112 | /* don't attempt to pad fixed-size packet buffers */
|
||
1113 | if (!s->max_packet_size) {
|
||
1114 | 77eb5504 | Anton Khirnov | avio_write(s, padbuf, sizeof(padbuf));
|
1115 | de1807bb | Josh Allmann | padding = FF_INPUT_BUFFER_PADDING_SIZE; |
1116 | } |
||
1117 | abba3dd1 | Fabrice Bellard | |
1118 | put_flush_packet(s); |
||
1119 | |||
1120 | *pbuffer = d->buffer; |
||
1121 | size = d->size; |
||
1122 | av_free(d); |
||
1123 | 899681cd | Björn Axelsson | av_free(s); |
1124 | de1807bb | Josh Allmann | return size - padding;
|
1125 | abba3dd1 | Fabrice Bellard | } |
1126 | 8fa641f8 | Loïc Le Loarer | #endif /* CONFIG_MUXERS || CONFIG_NETWORK */ |