added CONFIG_AC3, CONFIG_MPGLIB, CONFIG_DECODERS and CONFIG_ENCODERS (Arpi: don't...
[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 <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
34 int 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
64 static 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
74 void 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
81 void 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
100 void put_flush_packet(ByteIOContext *s)
101 {
102 flush_buffer(s);
103 s->must_flush = 0;
104 }
105
106 offset_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
158 void url_fskip(ByteIOContext *s, offset_t offset)
159 {
160 url_fseek(s, offset, SEEK_CUR);
161 }
162
163 offset_t url_ftell(ByteIOContext *s)
164 {
165 return url_fseek(s, 0, SEEK_CUR);
166 }
167
168 int url_feof(ByteIOContext *s)
169 {
170 return s->eof_reached;
171 }
172
173 void 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
181 void 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
189 void put_le64(ByteIOContext *s, unsigned long long val)
190 {
191 put_le32(s, val & 0xffffffff);
192 put_le32(s, val >> 32);
193 }
194
195 void put_be64(ByteIOContext *s, unsigned long long val)
196 {
197 put_be32(s, val >> 32);
198 put_be32(s, val & 0xffffffff);
199 }
200
201 void put_le16(ByteIOContext *s, unsigned int val)
202 {
203 put_byte(s, val);
204 put_byte(s, val >> 8);
205 }
206
207 void put_be16(ByteIOContext *s, unsigned int val)
208 {
209 put_byte(s, val >> 8);
210 put_byte(s, val);
211 }
212
213 void put_tag(ByteIOContext *s, char *tag)
214 {
215 while (*tag) {
216 put_byte(s, *tag++);
217 }
218 }
219
220 /* Input stream */
221
222 static 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
235 int 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
248 int 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
272 unsigned 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
280 unsigned 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
290 unsigned 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
298 unsigned 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
306 unsigned 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
316 unsigned 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
326 void url_write_packet(void *opaque, UINT8 *buf, int buf_size)
327 {
328 URLContext *h = opaque;
329 url_write(h, buf, buf_size);
330 }
331
332 int 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
338 int 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
345 int 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 */
367 int 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
385 int 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
401 int 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
410 URLContext *url_fileno(ByteIOContext *s)
411 {
412 return s->opaque;
413 }
414
415 /* buffer handling */
416 int 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 */
423 int url_close_buf(ByteIOContext *s)
424 {
425 return s->buf_ptr - s->buffer;
426 }