* some minor modification by Philip Gladston
[libav.git] / libav / aviobuf.c
1 /*
2 * Buffered I/O for ffmpeg system
3 * Copyright (c) 2000,2001 Gerard Lantau
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 #include "avformat.h"
20
21 #define IO_BUFFER_SIZE 32768
22
23 int init_put_byte(ByteIOContext *s,
24 unsigned char *buffer,
25 int buffer_size,
26 int write_flag,
27 void *opaque,
28 int (*read_packet)(void *opaque, UINT8 *buf, int buf_size),
29 void (*write_packet)(void *opaque, UINT8 *buf, int buf_size),
30 int (*seek)(void *opaque, offset_t offset, int whence))
31 {
32 s->buffer = buffer;
33 s->buffer_size = buffer_size;
34 s->buf_ptr = buffer;
35 s->write_flag = write_flag;
36 if (!s->write_flag)
37 s->buf_end = buffer;
38 else
39 s->buf_end = buffer + buffer_size;
40 s->opaque = opaque;
41 s->write_packet = write_packet;
42 s->read_packet = read_packet;
43 s->seek = seek;
44 s->pos = 0;
45 s->must_flush = 0;
46 s->eof_reached = 0;
47 s->is_streamed = 0;
48 s->packet_size = 1;
49 return 0;
50 }
51
52
53 static void flush_buffer(ByteIOContext *s)
54 {
55 if (s->buf_ptr > s->buffer) {
56 if (s->write_packet)
57 s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
58 s->pos += s->buf_ptr - s->buffer;
59 }
60 s->buf_ptr = s->buffer;
61 }
62
63 void put_byte(ByteIOContext *s, int b)
64 {
65 *(s->buf_ptr)++ = b;
66 if (s->buf_ptr >= s->buf_end)
67 flush_buffer(s);
68 }
69
70 void put_buffer(ByteIOContext *s, unsigned char *buf, int size)
71 {
72 int len;
73
74 while (size > 0) {
75 len = (s->buf_end - s->buf_ptr);
76 if (len > size)
77 len = size;
78 memcpy(s->buf_ptr, buf, len);
79 s->buf_ptr += len;
80
81 if (s->buf_ptr >= s->buf_end)
82 flush_buffer(s);
83
84 buf += len;
85 size -= len;
86 }
87 }
88
89 void put_flush_packet(ByteIOContext *s)
90 {
91 flush_buffer(s);
92 s->must_flush = 0;
93 }
94
95 offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence)
96 {
97 offset_t offset1;
98
99 if (whence != SEEK_CUR && whence != SEEK_SET)
100 return -EINVAL;
101
102 if (s->write_flag) {
103 if (whence == SEEK_CUR) {
104 offset1 = s->pos + (s->buf_ptr - s->buffer);
105 if (offset == 0)
106 return offset1;
107 offset += offset1;
108 }
109 offset1 = offset - s->pos;
110 if (!s->must_flush &&
111 offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) {
112 /* can do the seek inside the buffer */
113 s->buf_ptr = s->buffer + offset1;
114 } else {
115 if (!s->seek)
116 return -EPIPE;
117 flush_buffer(s);
118 s->must_flush = 1;
119 s->buf_ptr = s->buffer;
120 s->seek(s->opaque, offset, SEEK_SET);
121 s->pos = offset;
122 }
123 } else {
124 if (whence == SEEK_CUR) {
125 offset1 = s->pos - (s->buf_end - s->buffer) + (s->buf_ptr - s->buffer);
126 if (offset == 0)
127 return offset1;
128 offset += offset1;
129 }
130 offset1 = offset - (s->pos - (s->buf_end - s->buffer));
131 if (offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) {
132 /* can do the seek inside the buffer */
133 s->buf_ptr = s->buffer + offset1;
134 } else {
135 if (!s->seek)
136 return -EPIPE;
137 s->buf_ptr = s->buffer;
138 s->buf_end = s->buffer;
139 s->eof_reached = 0;
140 s->seek(s->opaque, offset, SEEK_SET);
141 s->pos = offset;
142 }
143 }
144 return offset;
145 }
146
147 void url_fskip(ByteIOContext *s, offset_t offset)
148 {
149 url_fseek(s, offset, SEEK_CUR);
150 }
151
152 offset_t url_ftell(ByteIOContext *s)
153 {
154 return url_fseek(s, 0, SEEK_CUR);
155 }
156
157 int url_feof(ByteIOContext *s)
158 {
159 return s->eof_reached;
160 }
161
162 void put_le32(ByteIOContext *s, unsigned int val)
163 {
164 put_byte(s, val);
165 put_byte(s, val >> 8);
166 put_byte(s, val >> 16);
167 put_byte(s, val >> 24);
168 }
169
170 void put_be32(ByteIOContext *s, unsigned int val)
171 {
172 put_byte(s, val >> 24);
173 put_byte(s, val >> 16);
174 put_byte(s, val >> 8);
175 put_byte(s, val);
176 }
177
178 void put_le64(ByteIOContext *s, UINT64 val)
179 {
180 put_le32(s, (UINT32)(val & 0xffffffff));
181 put_le32(s, (UINT32)(val >> 32));
182 }
183
184 void put_be64(ByteIOContext *s, UINT64 val)
185 {
186 put_be32(s, (UINT32)(val >> 32));
187 put_be32(s, (UINT32)(val & 0xffffffff));
188 }
189
190 void put_le16(ByteIOContext *s, unsigned int val)
191 {
192 put_byte(s, val);
193 put_byte(s, val >> 8);
194 }
195
196 void put_be16(ByteIOContext *s, unsigned int val)
197 {
198 put_byte(s, val >> 8);
199 put_byte(s, val);
200 }
201
202 void put_tag(ByteIOContext *s, char *tag)
203 {
204 while (*tag) {
205 put_byte(s, *tag++);
206 }
207 }
208
209 /* Input stream */
210
211 static void fill_buffer(ByteIOContext *s)
212 {
213 int len;
214
215 len = s->read_packet(s->opaque, s->buffer, s->buffer_size);
216 s->pos += len;
217 s->buf_ptr = s->buffer;
218 s->buf_end = s->buffer + len;
219 if (len == 0) {
220 s->eof_reached = 1;
221 }
222 }
223
224 int get_byte(ByteIOContext *s)
225 {
226 if (s->buf_ptr < s->buf_end) {
227 return *s->buf_ptr++;
228 } else {
229 fill_buffer(s);
230 if (s->buf_ptr < s->buf_end)
231 return *s->buf_ptr++;
232 else
233 return 0;
234 }
235 }
236
237 int get_buffer(ByteIOContext *s, unsigned char *buf, int size)
238 {
239 int len, size1;
240
241 size1 = size;
242 while (size > 0) {
243 len = s->buf_end - s->buf_ptr;
244 if (len > size)
245 len = size;
246 if (len == 0) {
247 fill_buffer(s);
248 len = s->buf_end - s->buf_ptr;
249 if (len == 0)
250 break;
251 } else {
252 memcpy(buf, s->buf_ptr, len);
253 buf += len;
254 s->buf_ptr += len;
255 size -= len;
256 }
257 }
258 return size1 - size;
259 }
260
261 unsigned int get_le16(ByteIOContext *s)
262 {
263 unsigned int val;
264 val = get_byte(s);
265 val |= get_byte(s) << 8;
266 return val;
267 }
268
269 unsigned int get_le32(ByteIOContext *s)
270 {
271 unsigned int val;
272 val = get_byte(s);
273 val |= get_byte(s) << 8;
274 val |= get_byte(s) << 16;
275 val |= get_byte(s) << 24;
276 return val;
277 }
278
279 UINT64 get_le64(ByteIOContext *s)
280 {
281 UINT64 val;
282 val = (UINT64)get_le32(s);
283 val |= (UINT64)get_le32(s) << 32;
284 return val;
285 }
286
287 unsigned int get_be16(ByteIOContext *s)
288 {
289 unsigned int val;
290 val = get_byte(s) << 8;
291 val |= get_byte(s);
292 return val;
293 }
294
295 unsigned int get_be32(ByteIOContext *s)
296 {
297 unsigned int val;
298 val = get_byte(s) << 24;
299 val |= get_byte(s) << 16;
300 val |= get_byte(s) << 8;
301 val |= get_byte(s);
302 return val;
303 }
304
305 UINT64 get_be64(ByteIOContext *s)
306 {
307 UINT64 val;
308 val = (UINT64)get_be32(s) << 32;
309 val |= (UINT64)get_be32(s);
310 return val;
311 }
312
313 /* link with avio functions */
314
315 void url_write_packet(void *opaque, UINT8 *buf, int buf_size)
316 {
317 URLContext *h = opaque;
318 url_write(h, buf, buf_size);
319 }
320
321 int url_read_packet(void *opaque, UINT8 *buf, int buf_size)
322 {
323 URLContext *h = opaque;
324 return url_read(h, buf, buf_size);
325 }
326
327 int url_seek_packet(void *opaque, INT64 offset, int whence)
328 {
329 URLContext *h = opaque;
330 url_seek(h, offset, whence);
331 return 0;
332 }
333
334 int url_fdopen(ByteIOContext *s, URLContext *h)
335 {
336 UINT8 *buffer;
337 int buffer_size;
338
339 buffer_size = (IO_BUFFER_SIZE / h->packet_size) * h->packet_size;
340 buffer = malloc(buffer_size);
341 if (!buffer)
342 return -ENOMEM;
343
344 if (init_put_byte(s, buffer, buffer_size,
345 (h->flags & URL_WRONLY) != 0, h,
346 url_read_packet, url_write_packet, url_seek_packet) < 0) {
347 free(buffer);
348 return -EIO;
349 }
350 s->is_streamed = h->is_streamed;
351 s->packet_size = h->packet_size;
352 return 0;
353 }
354
355 /* XXX: must be called before any I/O */
356 int url_setbufsize(ByteIOContext *s, int buf_size)
357 {
358 UINT8 *buffer;
359 buffer = malloc(buf_size);
360 if (!buffer)
361 return -ENOMEM;
362
363 free(s->buffer);
364 s->buffer = buffer;
365 s->buffer_size = buf_size;
366 s->buf_ptr = buffer;
367 if (!s->write_flag)
368 s->buf_end = buffer;
369 else
370 s->buf_end = buffer + buf_size;
371 return 0;
372 }
373
374 int url_fopen(ByteIOContext *s, const char *filename, int flags)
375 {
376 URLContext *h;
377 int err;
378
379 err = url_open(&h, filename, flags);
380 if (err < 0)
381 return err;
382 err = url_fdopen(s, h);
383 if (err < 0) {
384 url_close(h);
385 return err;
386 }
387 return 0;
388 }
389
390 int url_fclose(ByteIOContext *s)
391 {
392 URLContext *h = s->opaque;
393
394 free(s->buffer);
395 memset(s, 0, sizeof(ByteIOContext));
396 return url_close(h);
397 }
398
399 URLContext *url_fileno(ByteIOContext *s)
400 {
401 return s->opaque;
402 }
403
404 /* buffer handling */
405 int url_open_buf(ByteIOContext *s, UINT8 *buf, int buf_size, int flags)
406 {
407 return init_put_byte(s, buf, buf_size,
408 (flags & URL_WRONLY) != 0, NULL, NULL, NULL, NULL);
409 }
410
411 /* return the written or read size */
412 int url_close_buf(ByteIOContext *s)
413 {
414 return s->buf_ptr - s->buffer;
415 }