Statistics
| Branch: | Revision:

ffmpeg / libavformat / aviobuf.c @ 9870a7bd

History | View | Annotate | Download (18.7 KB)

1 de6d9b64 Fabrice Bellard
/*
2
 * Buffered I/O for ffmpeg system
3 19720f15 Fabrice Bellard
 * Copyright (c) 2000,2001 Fabrice Bellard
4 de6d9b64 Fabrice Bellard
 *
5 19720f15 Fabrice Bellard
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9 de6d9b64 Fabrice Bellard
 *
10 19720f15 Fabrice Bellard
 * This library is distributed in the hope that it will be useful,
11 de6d9b64 Fabrice Bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 19720f15 Fabrice Bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14 de6d9b64 Fabrice Bellard
 *
15 19720f15 Fabrice Bellard
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17 5509bffa Diego Biurrun
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 de6d9b64 Fabrice Bellard
 */
19
#include "avformat.h"
20 5c91a675 Zdenek Kabelac
#include "avio.h"
21 abba3dd1 Fabrice Bellard
#include <stdarg.h>
22 de6d9b64 Fabrice Bellard
23
#define IO_BUFFER_SIZE 32768
24
25
int init_put_byte(ByteIOContext *s,
26
                  unsigned char *buffer,
27
                  int buffer_size,
28
                  int write_flag,
29
                  void *opaque,
30 0c1a9eda Zdenek Kabelac
                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
31 576ae256 Michael Niedermayer
                  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
32 536ffa59 Wolfram Gloger
                  offset_t (*seek)(void *opaque, offset_t offset, int whence))
33 de6d9b64 Fabrice Bellard
{
34
    s->buffer = buffer;
35
    s->buffer_size = buffer_size;
36
    s->buf_ptr = buffer;
37
    s->write_flag = write_flag;
38 115329f1 Diego Biurrun
    if (!s->write_flag)
39 de6d9b64 Fabrice Bellard
        s->buf_end = buffer;
40
    else
41
        s->buf_end = buffer + buffer_size;
42
    s->opaque = opaque;
43
    s->write_packet = write_packet;
44
    s->read_packet = read_packet;
45
    s->seek = seek;
46
    s->pos = 0;
47
    s->must_flush = 0;
48
    s->eof_reached = 0;
49 576ae256 Michael Niedermayer
    s->error = 0;
50 de6d9b64 Fabrice Bellard
    s->is_streamed = 0;
51 abba3dd1 Fabrice Bellard
    s->max_packet_size = 0;
52 ee9f36a8 Michael Niedermayer
    s->update_checksum= NULL;
53 de6d9b64 Fabrice Bellard
    return 0;
54
}
55 115329f1 Diego Biurrun
56 de6d9b64 Fabrice Bellard
static void flush_buffer(ByteIOContext *s)
57
{
58
    if (s->buf_ptr > s->buffer) {
59 576ae256 Michael Niedermayer
        if (s->write_packet && !s->error){
60
            int ret= s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
61
            if(ret < 0){
62
                s->error = ret;
63
            }
64
        }
65 465e1dad Michael Niedermayer
        if(s->update_checksum){
66 ee9f36a8 Michael Niedermayer
            s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
67
            s->checksum_ptr= s->buffer;
68
        }
69 de6d9b64 Fabrice Bellard
        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 115329f1 Diego Biurrun
    if (s->buf_ptr >= s->buf_end)
78 de6d9b64 Fabrice Bellard
        flush_buffer(s);
79
}
80
81 75bdb984 Philip Gladstone
void put_buffer(ByteIOContext *s, const unsigned char *buf, int size)
82 de6d9b64 Fabrice Bellard
{
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 115329f1 Diego Biurrun
        if (s->buf_ptr >= s->buf_end)
93 de6d9b64 Fabrice Bellard
            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 115329f1 Diego Biurrun
113 a9e35095 Diego Biurrun
#ifdef CONFIG_MUXERS
114 de6d9b64 Fabrice Bellard
    if (s->write_flag) {
115
        if (whence == SEEK_CUR) {
116 4606ac8d Zdenek Kabelac
            offset1 = s->pos + (s->buf_ptr - s->buffer);
117 de6d9b64 Fabrice Bellard
            if (offset == 0)
118
                return offset1;
119
            offset += offset1;
120
        }
121
        offset1 = offset - s->pos;
122 115329f1 Diego Biurrun
        if (!s->must_flush &&
123 de6d9b64 Fabrice Bellard
            offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) {
124
            /* can do the seek inside the buffer */
125
            s->buf_ptr = s->buffer + offset1;
126
        } else {
127
            if (!s->seek)
128
                return -EPIPE;
129
            flush_buffer(s);
130
            s->must_flush = 1;
131
            s->buf_ptr = s->buffer;
132
            s->seek(s->opaque, offset, SEEK_SET);
133
            s->pos = offset;
134
        }
135 115329f1 Diego Biurrun
    } else
136 a9e35095 Diego Biurrun
#endif //CONFIG_MUXERS
137 764ef400 Mike Melanson
    {
138 de6d9b64 Fabrice Bellard
        if (whence == SEEK_CUR) {
139
            offset1 = s->pos - (s->buf_end - s->buffer) + (s->buf_ptr - s->buffer);
140
            if (offset == 0)
141
                return offset1;
142
            offset += offset1;
143
        }
144
        offset1 = offset - (s->pos - (s->buf_end - s->buffer));
145
        if (offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) {
146
            /* can do the seek inside the buffer */
147
            s->buf_ptr = s->buffer + offset1;
148
        } else {
149
            if (!s->seek)
150
                return -EPIPE;
151
            s->buf_ptr = s->buffer;
152
            s->buf_end = s->buffer;
153 53e2f9ca Michael Niedermayer
            if (s->seek(s->opaque, offset, SEEK_SET) == (offset_t)-EPIPE)
154
                return -EPIPE;
155 de6d9b64 Fabrice Bellard
            s->pos = offset;
156
        }
157 abba3dd1 Fabrice Bellard
        s->eof_reached = 0;
158 de6d9b64 Fabrice Bellard
    }
159
    return offset;
160
}
161
162
void url_fskip(ByteIOContext *s, offset_t offset)
163
{
164
    url_fseek(s, offset, SEEK_CUR);
165
}
166
167
offset_t url_ftell(ByteIOContext *s)
168
{
169
    return url_fseek(s, 0, SEEK_CUR);
170
}
171
172 a965c478 Aurelien Jacobs
offset_t url_fsize(ByteIOContext *s)
173
{
174
    offset_t size;
175 115329f1 Diego Biurrun
176 a965c478 Aurelien Jacobs
    if (!s->seek)
177
        return -EPIPE;
178
    size = s->seek(s->opaque, -1, SEEK_END) + 1;
179
    s->seek(s->opaque, s->pos, SEEK_SET);
180
    return size;
181
}
182
183 de6d9b64 Fabrice Bellard
int url_feof(ByteIOContext *s)
184
{
185
    return s->eof_reached;
186
}
187
188 576ae256 Michael Niedermayer
int url_ferror(ByteIOContext *s)
189
{
190
    return s->error;
191
}
192
193 04f46ced Gildas Bazin
#if defined(CONFIG_MUXERS) || defined(CONFIG_PROTOCOLS)
194 de6d9b64 Fabrice Bellard
void put_le32(ByteIOContext *s, unsigned int val)
195
{
196
    put_byte(s, val);
197
    put_byte(s, val >> 8);
198
    put_byte(s, val >> 16);
199
    put_byte(s, val >> 24);
200
}
201
202
void put_be32(ByteIOContext *s, unsigned int val)
203
{
204
    put_byte(s, val >> 24);
205
    put_byte(s, val >> 16);
206
    put_byte(s, val >> 8);
207
    put_byte(s, val);
208
}
209
210 3b4b29dc Fabrice Bellard
void put_strz(ByteIOContext *s, const char *str)
211 75bdb984 Philip Gladstone
{
212
    if (str)
213
        put_buffer(s, (const unsigned char *) str, strlen(str) + 1);
214
    else
215
        put_byte(s, 0);
216
}
217
218 0c1a9eda Zdenek Kabelac
void put_le64(ByteIOContext *s, uint64_t val)
219 de6d9b64 Fabrice Bellard
{
220 0c1a9eda Zdenek Kabelac
    put_le32(s, (uint32_t)(val & 0xffffffff));
221
    put_le32(s, (uint32_t)(val >> 32));
222 de6d9b64 Fabrice Bellard
}
223
224 0c1a9eda Zdenek Kabelac
void put_be64(ByteIOContext *s, uint64_t val)
225 de6d9b64 Fabrice Bellard
{
226 0c1a9eda Zdenek Kabelac
    put_be32(s, (uint32_t)(val >> 32));
227
    put_be32(s, (uint32_t)(val & 0xffffffff));
228 de6d9b64 Fabrice Bellard
}
229
230
void put_le16(ByteIOContext *s, unsigned int val)
231
{
232
    put_byte(s, val);
233
    put_byte(s, val >> 8);
234
}
235
236
void put_be16(ByteIOContext *s, unsigned int val)
237
{
238
    put_byte(s, val >> 8);
239
    put_byte(s, val);
240
}
241
242 a254c574 Michael Niedermayer
void put_be24(ByteIOContext *s, unsigned int val)
243
{
244
    put_be16(s, val >> 8);
245
    put_byte(s, val);
246
}
247
248 0570bf06 Zdenek Kabelac
void put_tag(ByteIOContext *s, const char *tag)
249 de6d9b64 Fabrice Bellard
{
250
    while (*tag) {
251
        put_byte(s, *tag++);
252
    }
253
}
254 04f46ced Gildas Bazin
#endif //CONFIG_MUXERS || CONFIG_PROTOCOLS
255 de6d9b64 Fabrice Bellard
256
/* Input stream */
257
258
static void fill_buffer(ByteIOContext *s)
259
{
260
    int len;
261
262 abba3dd1 Fabrice Bellard
    /* no need to do anything if EOF already reached */
263
    if (s->eof_reached)
264
        return;
265 ee9f36a8 Michael Niedermayer
266 465e1dad Michael Niedermayer
    if(s->update_checksum){
267 0f0680c5 Michael Niedermayer
        if(s->buf_end > s->checksum_ptr)
268
            s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr);
269 ee9f36a8 Michael Niedermayer
        s->checksum_ptr= s->buffer;
270
    }
271
272 de6d9b64 Fabrice Bellard
    len = s->read_packet(s->opaque, s->buffer, s->buffer_size);
273 abba3dd1 Fabrice Bellard
    if (len <= 0) {
274
        /* do not modify buffer if EOF reached so that a seek back can
275
           be done without rereading data */
276 de6d9b64 Fabrice Bellard
        s->eof_reached = 1;
277 576ae256 Michael Niedermayer
    if(len<0)
278
        s->error= len;
279 abba3dd1 Fabrice Bellard
    } else {
280
        s->pos += len;
281
        s->buf_ptr = s->buffer;
282
        s->buf_end = s->buffer + len;
283 de6d9b64 Fabrice Bellard
    }
284
}
285
286 ee9f36a8 Michael Niedermayer
unsigned long get_checksum(ByteIOContext *s){
287
    s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
288 465e1dad Michael Niedermayer
    s->update_checksum= NULL;
289 ee9f36a8 Michael Niedermayer
    return s->checksum;
290
}
291
292
void init_checksum(ByteIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum){
293
    s->update_checksum= update_checksum;
294 465e1dad Michael Niedermayer
    if(s->update_checksum){
295
        s->checksum= s->update_checksum(checksum, NULL, 0);
296
        s->checksum_ptr= s->buf_ptr;
297
    }
298 ee9f36a8 Michael Niedermayer
}
299
300 abba3dd1 Fabrice Bellard
/* NOTE: return 0 if EOF, so you cannot use it if EOF handling is
301
   necessary */
302
/* XXX: put an inline version */
303 de6d9b64 Fabrice Bellard
int get_byte(ByteIOContext *s)
304
{
305
    if (s->buf_ptr < s->buf_end) {
306
        return *s->buf_ptr++;
307
    } else {
308
        fill_buffer(s);
309
        if (s->buf_ptr < s->buf_end)
310
            return *s->buf_ptr++;
311
        else
312
            return 0;
313
    }
314
}
315
316 abba3dd1 Fabrice Bellard
/* NOTE: return URL_EOF (-1) if EOF */
317
int url_fgetc(ByteIOContext *s)
318
{
319
    if (s->buf_ptr < s->buf_end) {
320
        return *s->buf_ptr++;
321
    } else {
322
        fill_buffer(s);
323
        if (s->buf_ptr < s->buf_end)
324
            return *s->buf_ptr++;
325
        else
326
            return URL_EOF;
327
    }
328
}
329
330 de6d9b64 Fabrice Bellard
int get_buffer(ByteIOContext *s, unsigned char *buf, int size)
331
{
332
    int len, size1;
333
334
    size1 = size;
335
    while (size > 0) {
336
        len = s->buf_end - s->buf_ptr;
337
        if (len > size)
338
            len = size;
339
        if (len == 0) {
340 3e2b6358 Michael Niedermayer
            if(size > s->buffer_size && !s->update_checksum){
341
                len = s->read_packet(s->opaque, buf, size);
342
                if (len <= 0) {
343
                    /* do not modify buffer if EOF reached so that a seek back can
344
                    be done without rereading data */
345
                    s->eof_reached = 1;
346
                    if(len<0)
347
                        s->error= len;
348
                    break;
349
                } else {
350
                    s->pos += len;
351
                    size -= len;
352
                    buf += len;
353
                    s->buf_ptr = s->buffer;
354
                    s->buf_end = s->buffer/* + len*/;
355
                }
356
            }else{
357
                fill_buffer(s);
358
                len = s->buf_end - s->buf_ptr;
359
                if (len == 0)
360
                    break;
361
            }
362 de6d9b64 Fabrice Bellard
        } else {
363
            memcpy(buf, s->buf_ptr, len);
364
            buf += len;
365
            s->buf_ptr += len;
366
            size -= len;
367
        }
368
    }
369
    return size1 - size;
370
}
371
372 e15dec10 Leon van Stuivenberg
int get_partial_buffer(ByteIOContext *s, unsigned char *buf, int size)
373
{
374
    int len;
375 115329f1 Diego Biurrun
376 0ecca7a4 Michael Niedermayer
    if(size<0)
377
        return -1;
378 e15dec10 Leon van Stuivenberg
379
    len = s->buf_end - s->buf_ptr;
380
    if (len == 0) {
381
        fill_buffer(s);
382
        len = s->buf_end - s->buf_ptr;
383
    }
384
    if (len > size)
385
        len = size;
386
    memcpy(buf, s->buf_ptr, len);
387
    s->buf_ptr += len;
388
    return len;
389
}
390
391 de6d9b64 Fabrice Bellard
unsigned int get_le16(ByteIOContext *s)
392
{
393
    unsigned int val;
394
    val = get_byte(s);
395
    val |= get_byte(s) << 8;
396
    return val;
397
}
398
399
unsigned int get_le32(ByteIOContext *s)
400
{
401
    unsigned int val;
402 a254c574 Michael Niedermayer
    val = get_le16(s);
403
    val |= get_le16(s) << 16;
404 de6d9b64 Fabrice Bellard
    return val;
405
}
406
407 0c1a9eda Zdenek Kabelac
uint64_t get_le64(ByteIOContext *s)
408 de6d9b64 Fabrice Bellard
{
409 0c1a9eda Zdenek Kabelac
    uint64_t val;
410
    val = (uint64_t)get_le32(s);
411
    val |= (uint64_t)get_le32(s) << 32;
412 de6d9b64 Fabrice Bellard
    return val;
413
}
414
415
unsigned int get_be16(ByteIOContext *s)
416
{
417
    unsigned int val;
418
    val = get_byte(s) << 8;
419
    val |= get_byte(s);
420
    return val;
421
}
422
423 a254c574 Michael Niedermayer
unsigned int get_be24(ByteIOContext *s)
424 de6d9b64 Fabrice Bellard
{
425
    unsigned int val;
426 a254c574 Michael Niedermayer
    val = get_be16(s) << 8;
427 de6d9b64 Fabrice Bellard
    val |= get_byte(s);
428
    return val;
429
}
430 a254c574 Michael Niedermayer
unsigned int get_be32(ByteIOContext *s)
431
{
432
    unsigned int val;
433
    val = get_be16(s) << 16;
434
    val |= get_be16(s);
435
    return val;
436
}
437 de6d9b64 Fabrice Bellard
438 3b4b29dc Fabrice Bellard
char *get_strz(ByteIOContext *s, char *buf, int maxlen)
439 75bdb984 Philip Gladstone
{
440
    int i = 0;
441
    char c;
442
443
    while ((c = get_byte(s))) {
444
        if (i < maxlen-1)
445
            buf[i++] = c;
446
    }
447 115329f1 Diego Biurrun
448 75bdb984 Philip Gladstone
    buf[i] = 0; /* Ensure null terminated, but may be truncated */
449
450
    return buf;
451
}
452
453 0c1a9eda Zdenek Kabelac
uint64_t get_be64(ByteIOContext *s)
454 de6d9b64 Fabrice Bellard
{
455 0c1a9eda Zdenek Kabelac
    uint64_t val;
456
    val = (uint64_t)get_be32(s) << 32;
457
    val |= (uint64_t)get_be32(s);
458 de6d9b64 Fabrice Bellard
    return val;
459
}
460
461
/* link with avio functions */
462
463 a9e35095 Diego Biurrun
#ifdef CONFIG_MUXERS
464 576ae256 Michael Niedermayer
static int url_write_packet(void *opaque, uint8_t *buf, int buf_size)
465 de6d9b64 Fabrice Bellard
{
466
    URLContext *h = opaque;
467 576ae256 Michael Niedermayer
    return url_write(h, buf, buf_size);
468 de6d9b64 Fabrice Bellard
}
469 764ef400 Mike Melanson
#else
470 bb270c08 Diego Biurrun
#define         url_write_packet NULL
471 a9e35095 Diego Biurrun
#endif //CONFIG_MUXERS
472 de6d9b64 Fabrice Bellard
473 0c1a9eda Zdenek Kabelac
static int url_read_packet(void *opaque, uint8_t *buf, int buf_size)
474 de6d9b64 Fabrice Bellard
{
475
    URLContext *h = opaque;
476
    return url_read(h, buf, buf_size);
477
}
478
479 536ffa59 Wolfram Gloger
static offset_t url_seek_packet(void *opaque, offset_t offset, int whence)
480 de6d9b64 Fabrice Bellard
{
481
    URLContext *h = opaque;
482 53e2f9ca Michael Niedermayer
    return url_seek(h, offset, whence);
483
    //return 0;
484 de6d9b64 Fabrice Bellard
}
485
486
int url_fdopen(ByteIOContext *s, URLContext *h)
487
{
488 0c1a9eda Zdenek Kabelac
    uint8_t *buffer;
489 abba3dd1 Fabrice Bellard
    int buffer_size, max_packet_size;
490 de6d9b64 Fabrice Bellard
491 115329f1 Diego Biurrun
492 abba3dd1 Fabrice Bellard
    max_packet_size = url_get_max_packet_size(h);
493
    if (max_packet_size) {
494
        buffer_size = max_packet_size; /* no need to bufferize more than one packet */
495
    } else {
496
        buffer_size = IO_BUFFER_SIZE;
497
    }
498 1ea4f593 Fabrice Bellard
    buffer = av_malloc(buffer_size);
499 de6d9b64 Fabrice Bellard
    if (!buffer)
500
        return -ENOMEM;
501
502 115329f1 Diego Biurrun
    if (init_put_byte(s, buffer, buffer_size,
503 ac9fe33d Gildas Bazin
                      (h->flags & URL_WRONLY || h->flags & URL_RDWR), h,
504 de6d9b64 Fabrice Bellard
                      url_read_packet, url_write_packet, url_seek_packet) < 0) {
505 1ea4f593 Fabrice Bellard
        av_free(buffer);
506 0bd586c5 Mike Melanson
        return AVERROR_IO;
507 de6d9b64 Fabrice Bellard
    }
508
    s->is_streamed = h->is_streamed;
509 abba3dd1 Fabrice Bellard
    s->max_packet_size = max_packet_size;
510 de6d9b64 Fabrice Bellard
    return 0;
511
}
512
513
/* XXX: must be called before any I/O */
514
int url_setbufsize(ByteIOContext *s, int buf_size)
515
{
516 0c1a9eda Zdenek Kabelac
    uint8_t *buffer;
517 1ea4f593 Fabrice Bellard
    buffer = av_malloc(buf_size);
518 de6d9b64 Fabrice Bellard
    if (!buffer)
519
        return -ENOMEM;
520
521 1ea4f593 Fabrice Bellard
    av_free(s->buffer);
522 de6d9b64 Fabrice Bellard
    s->buffer = buffer;
523
    s->buffer_size = buf_size;
524
    s->buf_ptr = buffer;
525 115329f1 Diego Biurrun
    if (!s->write_flag)
526 de6d9b64 Fabrice Bellard
        s->buf_end = buffer;
527
    else
528
        s->buf_end = buffer + buf_size;
529
    return 0;
530
}
531
532 abba3dd1 Fabrice Bellard
/* NOTE: when opened as read/write, the buffers are only used for
533
   reading */
534 de6d9b64 Fabrice Bellard
int url_fopen(ByteIOContext *s, const char *filename, int flags)
535
{
536
    URLContext *h;
537
    int err;
538
539
    err = url_open(&h, filename, flags);
540
    if (err < 0)
541
        return err;
542
    err = url_fdopen(s, h);
543
    if (err < 0) {
544
        url_close(h);
545
        return err;
546
    }
547
    return 0;
548
}
549
550
int url_fclose(ByteIOContext *s)
551
{
552
    URLContext *h = s->opaque;
553 115329f1 Diego Biurrun
554 1ea4f593 Fabrice Bellard
    av_free(s->buffer);
555 de6d9b64 Fabrice Bellard
    memset(s, 0, sizeof(ByteIOContext));
556
    return url_close(h);
557
}
558
559
URLContext *url_fileno(ByteIOContext *s)
560
{
561
    return s->opaque;
562
}
563
564 a9e35095 Diego Biurrun
#ifdef CONFIG_MUXERS
565 abba3dd1 Fabrice Bellard
/* XXX: currently size is limited */
566
int url_fprintf(ByteIOContext *s, const char *fmt, ...)
567
{
568
    va_list ap;
569
    char buf[4096];
570
    int ret;
571
572
    va_start(ap, fmt);
573
    ret = vsnprintf(buf, sizeof(buf), fmt, ap);
574
    va_end(ap);
575
    put_buffer(s, buf, strlen(buf));
576
    return ret;
577
}
578 a9e35095 Diego Biurrun
#endif //CONFIG_MUXERS
579 abba3dd1 Fabrice Bellard
580
/* note: unlike fgets, the EOL character is not returned and a whole
581
   line is parsed. return NULL if first char read was EOF */
582
char *url_fgets(ByteIOContext *s, char *buf, int buf_size)
583
{
584
    int c;
585
    char *q;
586
587
    c = url_fgetc(s);
588
    if (c == EOF)
589
        return NULL;
590
    q = buf;
591
    for(;;) {
592
        if (c == EOF || c == '\n')
593
            break;
594
        if ((q - buf) < buf_size - 1)
595
            *q++ = c;
596
        c = url_fgetc(s);
597
    }
598
    if (buf_size > 0)
599
        *q = '\0';
600
    return buf;
601
}
602
603 115329f1 Diego Biurrun
/*
604 abba3dd1 Fabrice Bellard
 * Return the maximum packet size associated to packetized buffered file
605
 * handle. If the file is not packetized (stream like http or file on
606
 * disk), then 0 is returned.
607 115329f1 Diego Biurrun
 *
608 abba3dd1 Fabrice Bellard
 * @param h buffered file handle
609
 * @return maximum packet size in bytes
610
 */
611
int url_fget_max_packet_size(ByteIOContext *s)
612
{
613
    return s->max_packet_size;
614
}
615
616 a9e35095 Diego Biurrun
#ifdef CONFIG_MUXERS
617 de6d9b64 Fabrice Bellard
/* buffer handling */
618 0c1a9eda Zdenek Kabelac
int url_open_buf(ByteIOContext *s, uint8_t *buf, int buf_size, int flags)
619 de6d9b64 Fabrice Bellard
{
620 115329f1 Diego Biurrun
    return init_put_byte(s, buf, buf_size,
621 ac9fe33d Gildas Bazin
                         (flags & URL_WRONLY || flags & URL_RDWR),
622
                         NULL, NULL, NULL, NULL);
623 de6d9b64 Fabrice Bellard
}
624
625
/* return the written or read size */
626
int url_close_buf(ByteIOContext *s)
627
{
628 abba3dd1 Fabrice Bellard
    put_flush_packet(s);
629 de6d9b64 Fabrice Bellard
    return s->buf_ptr - s->buffer;
630
}
631 abba3dd1 Fabrice Bellard
632
/* output in a dynamic buffer */
633
634
typedef struct DynBuffer {
635
    int pos, size, allocated_size;
636 0c1a9eda Zdenek Kabelac
    uint8_t *buffer;
637 abba3dd1 Fabrice Bellard
    int io_buffer_size;
638 0c1a9eda Zdenek Kabelac
    uint8_t io_buffer[1];
639 abba3dd1 Fabrice Bellard
} DynBuffer;
640
641 576ae256 Michael Niedermayer
static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size)
642 abba3dd1 Fabrice Bellard
{
643
    DynBuffer *d = opaque;
644
    int new_size, new_allocated_size;
645 115329f1 Diego Biurrun
646 abba3dd1 Fabrice Bellard
    /* reallocate buffer if needed */
647
    new_size = d->pos + buf_size;
648
    new_allocated_size = d->allocated_size;
649 568e18b1 Michael Niedermayer
    if(new_size < d->pos || new_size > INT_MAX/2)
650
        return -1;
651 abba3dd1 Fabrice Bellard
    while (new_size > new_allocated_size) {
652
        if (!new_allocated_size)
653
            new_allocated_size = new_size;
654
        else
655 115329f1 Diego Biurrun
            new_allocated_size += new_allocated_size / 2 + 1;
656 abba3dd1 Fabrice Bellard
    }
657 115329f1 Diego Biurrun
658 abba3dd1 Fabrice Bellard
    if (new_allocated_size > d->allocated_size) {
659 b88ba823 Mark Hills
        d->buffer = av_realloc(d->buffer, new_allocated_size);
660
        if(d->buffer == NULL)
661 576ae256 Michael Niedermayer
             return -1234;
662 abba3dd1 Fabrice Bellard
        d->allocated_size = new_allocated_size;
663
    }
664
    memcpy(d->buffer + d->pos, buf, buf_size);
665
    d->pos = new_size;
666
    if (d->pos > d->size)
667
        d->size = d->pos;
668 576ae256 Michael Niedermayer
    return buf_size;
669 abba3dd1 Fabrice Bellard
}
670
671 576ae256 Michael Niedermayer
static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size)
672 abba3dd1 Fabrice Bellard
{
673
    unsigned char buf1[4];
674 576ae256 Michael Niedermayer
    int ret;
675 abba3dd1 Fabrice Bellard
676
    /* packetized write: output the header */
677
    buf1[0] = (buf_size >> 24);
678
    buf1[1] = (buf_size >> 16);
679
    buf1[2] = (buf_size >> 8);
680
    buf1[3] = (buf_size);
681 576ae256 Michael Niedermayer
    ret= dyn_buf_write(opaque, buf1, 4);
682
    if(ret < 0)
683
        return ret;
684 abba3dd1 Fabrice Bellard
685
    /* then the data */
686 576ae256 Michael Niedermayer
    return dyn_buf_write(opaque, buf, buf_size);
687 abba3dd1 Fabrice Bellard
}
688
689 536ffa59 Wolfram Gloger
static offset_t dyn_buf_seek(void *opaque, offset_t offset, int whence)
690 abba3dd1 Fabrice Bellard
{
691
    DynBuffer *d = opaque;
692
693
    if (whence == SEEK_CUR)
694
        offset += d->pos;
695
    else if (whence == SEEK_END)
696
        offset += d->size;
697
    if (offset < 0 || offset > 0x7fffffffLL)
698
        return -1;
699
    d->pos = offset;
700
    return 0;
701
}
702
703
static int url_open_dyn_buf_internal(ByteIOContext *s, int max_packet_size)
704
{
705
    DynBuffer *d;
706
    int io_buffer_size, ret;
707 115329f1 Diego Biurrun
708
    if (max_packet_size)
709 abba3dd1 Fabrice Bellard
        io_buffer_size = max_packet_size;
710
    else
711
        io_buffer_size = 1024;
712 115329f1 Diego Biurrun
713 568e18b1 Michael Niedermayer
    if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size)
714
        return -1;
715 abba3dd1 Fabrice Bellard
    d = av_malloc(sizeof(DynBuffer) + io_buffer_size);
716
    if (!d)
717
        return -1;
718
    d->io_buffer_size = io_buffer_size;
719
    d->buffer = NULL;
720
    d->pos = 0;
721
    d->size = 0;
722
    d->allocated_size = 0;
723 115329f1 Diego Biurrun
    ret = init_put_byte(s, d->io_buffer, io_buffer_size,
724
                        1, d, NULL,
725
                        max_packet_size ? dyn_packet_buf_write : dyn_buf_write,
726 abba3dd1 Fabrice Bellard
                        max_packet_size ? NULL : dyn_buf_seek);
727
    if (ret == 0) {
728
        s->max_packet_size = max_packet_size;
729
    }
730
    return ret;
731
}
732
733
/*
734
 * Open a write only memory stream.
735 115329f1 Diego Biurrun
 *
736 abba3dd1 Fabrice Bellard
 * @param s new IO context
737
 * @return zero if no error.
738
 */
739
int url_open_dyn_buf(ByteIOContext *s)
740
{
741
    return url_open_dyn_buf_internal(s, 0);
742
}
743
744
/*
745
 * Open a write only packetized memory stream with a maximum packet
746
 * size of 'max_packet_size'.  The stream is stored in a memory buffer
747
 * with a big endian 4 byte header giving the packet size in bytes.
748 115329f1 Diego Biurrun
 *
749 abba3dd1 Fabrice Bellard
 * @param s new IO context
750 115329f1 Diego Biurrun
 * @param max_packet_size maximum packet size (must be > 0)
751 abba3dd1 Fabrice Bellard
 * @return zero if no error.
752
 */
753
int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size)
754
{
755
    if (max_packet_size <= 0)
756
        return -1;
757
    return url_open_dyn_buf_internal(s, max_packet_size);
758
}
759
760 115329f1 Diego Biurrun
/*
761 abba3dd1 Fabrice Bellard
 * Return the written size and a pointer to the buffer. The buffer
762 115329f1 Diego Biurrun
 *  must be freed with av_free().
763 abba3dd1 Fabrice Bellard
 * @param s IO context
764
 * @param pointer to a byte buffer
765
 * @return the length of the byte buffer
766
 */
767 0c1a9eda Zdenek Kabelac
int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer)
768 abba3dd1 Fabrice Bellard
{
769
    DynBuffer *d = s->opaque;
770
    int size;
771
772
    put_flush_packet(s);
773
774
    *pbuffer = d->buffer;
775
    size = d->size;
776
    av_free(d);
777
    return size;
778
}
779 a9e35095 Diego Biurrun
#endif //CONFIG_MUXERS