* some minor modification by Philip Gladston
[libav.git] / libav / aviobuf.c
CommitLineData
de6d9b64
FB
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 */
de6d9b64
FB
19#include "avformat.h"
20
21#define IO_BUFFER_SIZE 32768
22
23int 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
53static 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
63void 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
70void 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
89void put_flush_packet(ByteIOContext *s)
90{
91 flush_buffer(s);
92 s->must_flush = 0;
93}
94
95offset_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) {
4606ac8d 104 offset1 = s->pos + (s->buf_ptr - s->buffer);
de6d9b64
FB
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
147void url_fskip(ByteIOContext *s, offset_t offset)
148{
149 url_fseek(s, offset, SEEK_CUR);
150}
151
152offset_t url_ftell(ByteIOContext *s)
153{
154 return url_fseek(s, 0, SEEK_CUR);
155}
156
157int url_feof(ByteIOContext *s)
158{
159 return s->eof_reached;
160}
161
162void 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
170void 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
8be1c656 178void put_le64(ByteIOContext *s, UINT64 val)
de6d9b64 179{
8be1c656
FB
180 put_le32(s, (UINT32)(val & 0xffffffff));
181 put_le32(s, (UINT32)(val >> 32));
de6d9b64
FB
182}
183
8be1c656 184void put_be64(ByteIOContext *s, UINT64 val)
de6d9b64 185{
8be1c656
FB
186 put_be32(s, (UINT32)(val >> 32));
187 put_be32(s, (UINT32)(val & 0xffffffff));
de6d9b64
FB
188}
189
190void put_le16(ByteIOContext *s, unsigned int val)
191{
192 put_byte(s, val);
193 put_byte(s, val >> 8);
194}
195
196void put_be16(ByteIOContext *s, unsigned int val)
197{
198 put_byte(s, val >> 8);
199 put_byte(s, val);
200}
201
202void put_tag(ByteIOContext *s, char *tag)
203{
204 while (*tag) {
205 put_byte(s, *tag++);
206 }
207}
208
209/* Input stream */
210
211static 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
224int 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
237int 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
261unsigned 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
269unsigned 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
8be1c656 279UINT64 get_le64(ByteIOContext *s)
de6d9b64
FB
280{
281 UINT64 val;
282 val = (UINT64)get_le32(s);
283 val |= (UINT64)get_le32(s) << 32;
284 return val;
285}
286
287unsigned 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
295unsigned 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
8be1c656 305UINT64 get_be64(ByteIOContext *s)
de6d9b64
FB
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
315void url_write_packet(void *opaque, UINT8 *buf, int buf_size)
316{
317 URLContext *h = opaque;
318 url_write(h, buf, buf_size);
319}
320
321int 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
8be1c656 327int url_seek_packet(void *opaque, INT64 offset, int whence)
de6d9b64
FB
328{
329 URLContext *h = opaque;
330 url_seek(h, offset, whence);
331 return 0;
332}
333
334int 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 */
356int 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
374int 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
390int 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
399URLContext *url_fileno(ByteIOContext *s)
400{
401 return s->opaque;
402}
403
404/* buffer handling */
405int 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 */
412int url_close_buf(ByteIOContext *s)
413{
414 return s->buf_ptr - s->buffer;
415}