]> git.sesse.net Git - ffmpeg/blob - libav/aviobuf.c
removed incomplete seek patch
[ffmpeg] / 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 }