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