aviobuf.c 28.6 KB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
1
/*
2
 * buffered I/O
3
 * Copyright (c) 2000,2001 Fabrice Bellard
Fabrice Bellard's avatar
Fabrice Bellard committed
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
Fabrice Bellard committed
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Fabrice Bellard's avatar
Fabrice Bellard committed
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Fabrice Bellard's avatar
Fabrice Bellard committed
20
 */
21

22
#include "libavutil/bprint.h"
23
#include "libavutil/crc.h"
24
#include "libavutil/dict.h"
25
#include "libavutil/intreadwrite.h"
26 27
#include "libavutil/log.h"
#include "libavutil/opt.h"
28
#include "libavutil/avassert.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
29
#include "avformat.h"
30
#include "avio.h"
31
#include "avio_internal.h"
32
#include "internal.h"
33
#include "url.h"
34
#include <stdarg.h>
Fabrice Bellard's avatar
Fabrice Bellard committed
35 36 37

#define IO_BUFFER_SIZE 32768

38 39 40 41 42 43 44
/**
 * Do seeks within this distance ahead of the current buffer by skipping
 * data instead of calling the protocol seek function, for seekable
 * protocols.
 */
#define SHORT_SEEK_THRESHOLD 4096

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
static void *ffio_url_child_next(void *obj, void *prev)
{
    AVIOContext *s = obj;
    return prev ? NULL : s->opaque;
}

static const AVClass *ffio_url_child_class_next(const AVClass *prev)
{
    return prev ? NULL : &ffurl_context_class;
}

static const AVOption ffio_url_options[] = {
    { NULL },
};

const AVClass ffio_url_class = {
    .class_name = "AVIOContext",
    .item_name  = av_default_item_name,
    .version    = LIBAVUTIL_VERSION_INT,
    .option     = ffio_url_options,
    .child_next = ffio_url_child_next,
    .child_class_next = ffio_url_child_class_next,
};
68

69 70
static void fill_buffer(AVIOContext *s);
static int url_resetbuf(AVIOContext *s, int flags);
71

72
int ffio_init_context(AVIOContext *s,
Fabrice Bellard's avatar
Fabrice Bellard committed
73 74 75 76
                  unsigned char *buffer,
                  int buffer_size,
                  int write_flag,
                  void *opaque,
77
                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
78
                  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
79
                  int64_t (*seek)(void *opaque, int64_t offset, int whence))
Fabrice Bellard's avatar
Fabrice Bellard committed
80
{
81
    s->buffer      = buffer;
82
    s->orig_buffer_size =
Fabrice Bellard's avatar
Fabrice Bellard committed
83
    s->buffer_size = buffer_size;
84 85
    s->buf_ptr     = buffer;
    s->opaque      = opaque;
86
    s->direct      = 0;
87

88
    url_resetbuf(s, write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
89 90 91 92 93 94 95 96

    s->write_packet    = write_packet;
    s->read_packet     = read_packet;
    s->seek            = seek;
    s->pos             = 0;
    s->must_flush      = 0;
    s->eof_reached     = 0;
    s->error           = 0;
97
    s->seekable        = seek ? AVIO_SEEKABLE_NORMAL : 0;
98
    s->max_packet_size = 0;
99 100 101 102
    s->update_checksum = NULL;

    if (!read_packet && !write_flag) {
        s->pos     = buffer_size;
103 104
        s->buf_end = s->buffer + buffer_size;
    }
105 106
    s->read_pause = NULL;
    s->read_seek  = NULL;
107

Fabrice Bellard's avatar
Fabrice Bellard committed
108 109
    return 0;
}
110

111
AVIOContext *avio_alloc_context(
112 113 114 115 116 117
                  unsigned char *buffer,
                  int buffer_size,
                  int write_flag,
                  void *opaque,
                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
                  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
Diego Biurrun's avatar
Diego Biurrun committed
118 119
                  int64_t (*seek)(void *opaque, int64_t offset, int whence))
{
120
    AVIOContext *s = av_mallocz(sizeof(AVIOContext));
121 122
    if (!s)
        return NULL;
123
    ffio_init_context(s, buffer, buffer_size, write_flag, opaque,
124 125 126 127
                  read_packet, write_packet, seek);
    return s;
}

128 129
static void writeout(AVIOContext *s, const uint8_t *data, int len)
{
130 131 132
    if (s->write_packet && !s->error) {
        int ret = s->write_packet(s->opaque, (uint8_t *)data, len);
        if (ret < 0) {
133 134 135
            s->error = ret;
        }
    }
136
    s->writeout_count ++;
137 138 139
    s->pos += len;
}

140
static void flush_buffer(AVIOContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
141
{
142
    if (s->write_flag && s->buf_ptr > s->buffer) {
143
        writeout(s, s->buffer, s->buf_ptr - s->buffer);
144 145 146 147
        if (s->update_checksum) {
            s->checksum     = s->update_checksum(s->checksum, s->checksum_ptr,
                                                 s->buf_ptr - s->checksum_ptr);
            s->checksum_ptr = s->buffer;
148
        }
Fabrice Bellard's avatar
Fabrice Bellard committed
149 150
    }
    s->buf_ptr = s->buffer;
151 152
    if (!s->write_flag)
        s->buf_end = s->buffer;
Fabrice Bellard's avatar
Fabrice Bellard committed
153 154
}

155
void avio_w8(AVIOContext *s, int b)
Fabrice Bellard's avatar
Fabrice Bellard committed
156
{
157
    av_assert2(b>=-128 && b<=255);
158
    *s->buf_ptr++ = b;
159
    if (s->buf_ptr >= s->buf_end)
Fabrice Bellard's avatar
Fabrice Bellard committed
160 161 162
        flush_buffer(s);
}

163
void ffio_fill(AVIOContext *s, int b, int count)
164 165 166 167 168 169 170 171 172 173 174 175 176
{
    while (count > 0) {
        int len = FFMIN(s->buf_end - s->buf_ptr, count);
        memset(s->buf_ptr, b, len);
        s->buf_ptr += len;

        if (s->buf_ptr >= s->buf_end)
            flush_buffer(s);

        count -= len;
    }
}

177
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Fabrice Bellard's avatar
Fabrice Bellard committed
178
{
179 180 181 182 183
    if (s->direct && !s->update_checksum) {
        avio_flush(s);
        writeout(s, buf, size);
        return;
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
184
    while (size > 0) {
185
        int len = FFMIN(s->buf_end - s->buf_ptr, size);
Fabrice Bellard's avatar
Fabrice Bellard committed
186 187 188
        memcpy(s->buf_ptr, buf, len);
        s->buf_ptr += len;

189
        if (s->buf_ptr >= s->buf_end)
Fabrice Bellard's avatar
Fabrice Bellard committed
190 191 192 193 194 195 196
            flush_buffer(s);

        buf += len;
        size -= len;
    }
}

197
void avio_flush(AVIOContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
198 199 200 201 202
{
    flush_buffer(s);
    s->must_flush = 0;
}

203
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
Fabrice Bellard's avatar
Fabrice Bellard committed
204
{
205 206
    int64_t offset1;
    int64_t pos;
207
    int force = whence & AVSEEK_FORCE;
208
    int buffer_size;
209
    whence &= ~AVSEEK_FORCE;
210 211 212 213

    if(!s)
        return AVERROR(EINVAL);

214 215
    buffer_size = s->buf_end - s->buffer;
    pos = s->pos - (s->write_flag ? 0 : buffer_size);
Fabrice Bellard's avatar
Fabrice Bellard committed
216 217

    if (whence != SEEK_CUR && whence != SEEK_SET)
218
        return AVERROR(EINVAL);
219

220 221 222 223 224 225
    if (whence == SEEK_CUR) {
        offset1 = pos + (s->buf_ptr - s->buffer);
        if (offset == 0)
            return offset1;
        offset += offset1;
    }
226 227 228
    if (offset < 0)
        return AVERROR(EINVAL);

229
    offset1 = offset - pos;
230
    if (!s->must_flush && (!s->direct || !s->seek) &&
231
        offset1 >= 0 && offset1 <= buffer_size - s->write_flag) {
232 233
        /* can do the seek inside the buffer */
        s->buf_ptr = s->buffer + offset1;
234
    } else if ((!s->seekable ||
235 236
               offset1 <= s->buf_end + SHORT_SEEK_THRESHOLD - s->buffer) &&
               !s->write_flag && offset1 >= 0 &&
237
               (!s->direct || !s->seek) &&
238
              (whence != SEEK_END || force)) {
239 240
        while(s->pos < offset && !s->eof_reached)
            fill_buffer(s);
241
        if (s->eof_reached)
242
            return AVERROR_EOF;
243
        s->buf_ptr = s->buf_end + offset - s->pos;
244
    } else if(!s->write_flag && offset1 < 0 && -offset1 < buffer_size>>1 && s->seek && offset > 0) {
245
        int64_t res;
246

247 248 249 250 251 252 253 254 255 256 257
        pos -= FFMIN(buffer_size>>1, pos);
        if ((res = s->seek(s->opaque, pos, SEEK_SET)) < 0)
            return res;
        s->buf_end =
        s->buf_ptr = s->buffer;
        s->pos = pos;
        s->eof_reached = 0;
        fill_buffer(s);
        return avio_seek(s, offset, SEEK_SET | force);
    } else {
        int64_t res;
258
        if (s->write_flag) {
Fabrice Bellard's avatar
Fabrice Bellard committed
259 260 261
            flush_buffer(s);
            s->must_flush = 1;
        }
262 263 264
        if (!s->seek)
            return AVERROR(EPIPE);
        if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0)
265
            return res;
266
        s->seek_count ++;
267 268 269
        if (!s->write_flag)
            s->buf_end = s->buffer;
        s->buf_ptr = s->buffer;
270
        s->pos = offset;
Fabrice Bellard's avatar
Fabrice Bellard committed
271
    }
272
    s->eof_reached = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
273 274 275
    return offset;
}

Michael Niedermayer's avatar
Michael Niedermayer committed
276 277 278 279 280
int64_t avio_skip(AVIOContext *s, int64_t offset)
{
    return avio_seek(s, offset, SEEK_CUR);
}

281
int64_t avio_size(AVIOContext *s)
282
{
283
    int64_t size;
284

285
    if (!s)
286 287
        return AVERROR(EINVAL);

288
    if (!s->seek)
289
        return AVERROR(ENOSYS);
290
    size = s->seek(s->opaque, 0, AVSEEK_SIZE);
291
    if (size < 0) {
292 293 294
        if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0)
            return size;
        size++;
295
        s->seek(s->opaque, s->pos, SEEK_SET);
296
    }
297 298 299
    return size;
}

300
int avio_feof(AVIOContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
301
{
302 303
    if(!s)
        return 0;
304 305 306 307
    if(s->eof_reached){
        s->eof_reached=0;
        fill_buffer(s);
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
308 309 310
    return s->eof_reached;
}

311 312 313 314 315 316 317
#if FF_API_URL_FEOF
int url_feof(AVIOContext *s)
{
    return avio_feof(s);
}
#endif

318
void avio_wl32(AVIOContext *s, unsigned int val)
Fabrice Bellard's avatar
Fabrice Bellard committed
319
{
320 321 322 323
    avio_w8(s, (uint8_t) val       );
    avio_w8(s, (uint8_t)(val >> 8 ));
    avio_w8(s, (uint8_t)(val >> 16));
    avio_w8(s,           val >> 24 );
Fabrice Bellard's avatar
Fabrice Bellard committed
324 325
}

326
void avio_wb32(AVIOContext *s, unsigned int val)
Fabrice Bellard's avatar
Fabrice Bellard committed
327
{
328 329 330 331
    avio_w8(s,           val >> 24 );
    avio_w8(s, (uint8_t)(val >> 16));
    avio_w8(s, (uint8_t)(val >> 8 ));
    avio_w8(s, (uint8_t) val       );
Fabrice Bellard's avatar
Fabrice Bellard committed
332 333
}

334
int avio_put_str(AVIOContext *s, const char *str)
335 336 337 338
{
    int len = 1;
    if (str) {
        len += strlen(str);
339
        avio_write(s, (const unsigned char *) str, len);
340
    } else
341
        avio_w8(s, 0);
342
    return len;
343 344
}

345
int avio_put_str16le(AVIOContext *s, const char *str)
346 347 348
{
    const uint8_t *q = str;
    int ret = 0;
349
    int err = 0;
350 351 352 353 354

    while (*q) {
        uint32_t ch;
        uint16_t tmp;

355
        GET_UTF8(ch, *q++, goto invalid;)
356
        PUT_UTF16(ch, tmp, avio_wl16(s, tmp); ret += 2;)
357 358 359
        continue;
invalid:
        av_log(s, AV_LOG_ERROR, "Invaid UTF8 sequence in avio_put_str16le\n");
360
        err = AVERROR(EINVAL);
361
    }
362
    avio_wl16(s, 0);
363 364
    if (err)
        return err;
365 366 367 368
    ret += 2;
    return ret;
}

369 370 371
int ff_get_v_length(uint64_t val)
{
    int i = 1;
372

373
    while (val >>= 7)
374 375 376 377 378
        i++;

    return i;
}

379 380 381
void ff_put_v(AVIOContext *bc, uint64_t val)
{
    int i = ff_get_v_length(val);
382

383
    while (--i > 0)
384
        avio_w8(bc, 128 | (uint8_t)(val >> (7*i)));
385

386
    avio_w8(bc, val & 127);
387 388
}

389
void avio_wl64(AVIOContext *s, uint64_t val)
Fabrice Bellard's avatar
Fabrice Bellard committed
390
{
391 392
    avio_wl32(s, (uint32_t)(val & 0xffffffff));
    avio_wl32(s, (uint32_t)(val >> 32));
Fabrice Bellard's avatar
Fabrice Bellard committed
393 394
}

395
void avio_wb64(AVIOContext *s, uint64_t val)
Fabrice Bellard's avatar
Fabrice Bellard committed
396
{
397 398
    avio_wb32(s, (uint32_t)(val >> 32));
    avio_wb32(s, (uint32_t)(val & 0xffffffff));
Fabrice Bellard's avatar
Fabrice Bellard committed
399 400
}

401
void avio_wl16(AVIOContext *s, unsigned int val)
Fabrice Bellard's avatar
Fabrice Bellard committed
402
{
403 404
    avio_w8(s, (uint8_t)val);
    avio_w8(s, (int)val >> 8);
Fabrice Bellard's avatar
Fabrice Bellard committed
405 406
}

407
void avio_wb16(AVIOContext *s, unsigned int val)
Fabrice Bellard's avatar
Fabrice Bellard committed
408
{
409 410
    avio_w8(s, (int)val >> 8);
    avio_w8(s, (uint8_t)val);
Fabrice Bellard's avatar
Fabrice Bellard committed
411 412
}

413
void avio_wl24(AVIOContext *s, unsigned int val)
414
{
415
    avio_wl16(s, val & 0xffff);
416
    avio_w8(s, (int)val >> 16);
417 418
}

419
void avio_wb24(AVIOContext *s, unsigned int val)
420
{
421 422
    avio_wb16(s, (int)val >> 8);
    avio_w8(s, (uint8_t)val);
423 424
}

Fabrice Bellard's avatar
Fabrice Bellard committed
425 426
/* Input stream */

427
static void fill_buffer(AVIOContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
428
{
429 430
    int max_buffer_size = s->max_packet_size ?
                          s->max_packet_size : IO_BUFFER_SIZE;
431 432 433
    uint8_t *dst        = s->buf_end - s->buffer + max_buffer_size < s->buffer_size ?
                          s->buf_end : s->buffer;
    int len             = s->buffer_size - (dst - s->buffer);
434

435
    /* can't fill the buffer without read_packet, just set EOF if appropriate */
436 437 438
    if (!s->read_packet && s->buf_ptr >= s->buf_end)
        s->eof_reached = 1;

439 440 441
    /* no need to do anything if EOF already reached */
    if (s->eof_reached)
        return;
442

443 444 445 446 447
    if (s->update_checksum && dst == s->buffer) {
        if (s->buf_end > s->checksum_ptr)
            s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
                                             s->buf_end - s->checksum_ptr);
        s->checksum_ptr = s->buffer;
448 449
    }

450
    /* make buffer smaller in case it ended up large after probing */
451
    if (s->read_packet && s->orig_buffer_size && s->buffer_size > s->orig_buffer_size) {
452
        if (dst == s->buffer) {
453
            ffio_set_buf_size(s, s->orig_buffer_size);
454

455 456
            s->checksum_ptr = dst = s->buffer;
        }
457 458
        av_assert0(len >= s->orig_buffer_size);
        len = s->orig_buffer_size;
459 460
    }

461
    if (s->read_packet)
462
        len = s->read_packet(s->opaque, dst, len);
463 464
    else
        len = 0;
465 466 467
    if (len <= 0) {
        /* do not modify buffer if EOF reached so that a seek back can
           be done without rereading data */
Fabrice Bellard's avatar
Fabrice Bellard committed
468
        s->eof_reached = 1;
469 470
        if (len < 0)
            s->error = len;
471 472
    } else {
        s->pos += len;
473 474
        s->buf_ptr = dst;
        s->buf_end = dst + len;
475
        s->bytes_read += len;
Fabrice Bellard's avatar
Fabrice Bellard committed
476 477 478
    }
}

Diego Biurrun's avatar
Diego Biurrun committed
479 480 481
unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
                                    unsigned int len)
{
Aurelien Jacobs's avatar
Aurelien Jacobs committed
482
    return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len);
483 484
}

485 486 487 488 489 490
unsigned long ff_crcA001_update(unsigned long checksum, const uint8_t *buf,
                                unsigned int len)
{
    return av_crc(av_crc_get_table(AV_CRC_16_ANSI_LE), checksum, buf, len);
}

491
unsigned long ffio_get_checksum(AVIOContext *s)
Diego Biurrun's avatar
Diego Biurrun committed
492
{
493 494 495
    s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
                                     s->buf_ptr - s->checksum_ptr);
    s->update_checksum = NULL;
496 497 498
    return s->checksum;
}

499
void ffio_init_checksum(AVIOContext *s,
Diego Biurrun's avatar
Diego Biurrun committed
500 501 502
                   unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len),
                   unsigned long checksum)
{
503 504 505 506
    s->update_checksum = update_checksum;
    if (s->update_checksum) {
        s->checksum     = checksum;
        s->checksum_ptr = s->buf_ptr;
507
    }
508 509
}

510
/* XXX: put an inline version */
511
int avio_r8(AVIOContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
512
{
513
    if (s->buf_ptr >= s->buf_end)
Fabrice Bellard's avatar
Fabrice Bellard committed
514
        fill_buffer(s);
515 516 517
    if (s->buf_ptr < s->buf_end)
        return *s->buf_ptr++;
    return 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
518 519
}

520
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Fabrice Bellard's avatar
Fabrice Bellard committed
521 522 523 524 525 526 527 528
{
    int len, size1;

    size1 = size;
    while (size > 0) {
        len = s->buf_end - s->buf_ptr;
        if (len > size)
            len = size;
529
        if (len == 0 || s->write_flag) {
530
            if((s->direct || size > s->buffer_size) && !s->update_checksum){
531
                if(s->read_packet)
532
                    len = s->read_packet(s->opaque, buf, size);
533 534 535 536 537 538 539 540 541
                if (len <= 0) {
                    /* do not modify buffer if EOF reached so that a seek back can
                    be done without rereading data */
                    s->eof_reached = 1;
                    if(len<0)
                        s->error= len;
                    break;
                } else {
                    s->pos += len;
542
                    s->bytes_read += len;
543 544 545 546 547
                    size -= len;
                    buf += len;
                    s->buf_ptr = s->buffer;
                    s->buf_end = s->buffer/* + len*/;
                }
548
            } else {
549 550 551 552 553
                fill_buffer(s);
                len = s->buf_end - s->buf_ptr;
                if (len == 0)
                    break;
            }
Fabrice Bellard's avatar
Fabrice Bellard committed
554 555 556 557 558 559 560
        } else {
            memcpy(buf, s->buf_ptr, len);
            buf += len;
            s->buf_ptr += len;
            size -= len;
        }
    }
561
    if (size1 == size) {
562
        if (s->error)      return s->error;
563
        if (avio_feof(s))  return AVERROR_EOF;
564
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
565 566 567
    return size1 - size;
}

568
int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data)
569 570 571 572 573 574 575 576 577 578 579
{
    if (s->buf_end - s->buf_ptr >= size && !s->write_flag) {
        *data = s->buf_ptr;
        s->buf_ptr += size;
        return size;
    } else {
        *data = buf;
        return avio_read(s, buf, size);
    }
}

580
int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size)
581 582
{
    int len;
583

584
    if (size < 0)
585
        return -1;
586

587 588 589 590 591 592 593
    if (s->read_packet && s->write_flag) {
        len = s->read_packet(s->opaque, buf, size);
        if (len > 0)
            s->pos += len;
        return len;
    }

594 595
    len = s->buf_end - s->buf_ptr;
    if (len == 0) {
596 597 598 599 600 601 602
        /* Reset the buf_end pointer to the start of the buffer, to make sure
         * the fill_buffer call tries to read as much data as fits into the
         * full buffer, instead of just what space is left after buf_end.
         * This avoids returning partial packets at the end of the buffer,
         * for packet based inputs.
         */
        s->buf_end = s->buf_ptr = s->buffer;
603 604 605 606 607 608 609
        fill_buffer(s);
        len = s->buf_end - s->buf_ptr;
    }
    if (len > size)
        len = size;
    memcpy(buf, s->buf_ptr, len);
    s->buf_ptr += len;
610
    if (!len) {
611
        if (s->error)      return s->error;
612
        if (avio_feof(s))  return AVERROR_EOF;
613
    }
614 615 616
    return len;
}

617
unsigned int avio_rl16(AVIOContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
618 619
{
    unsigned int val;
620 621
    val = avio_r8(s);
    val |= avio_r8(s) << 8;
Fabrice Bellard's avatar
Fabrice Bellard committed
622 623 624
    return val;
}

625
unsigned int avio_rl24(AVIOContext *s)
626 627
{
    unsigned int val;
628 629
    val = avio_rl16(s);
    val |= avio_r8(s) << 16;
630 631 632
    return val;
}

633
unsigned int avio_rl32(AVIOContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
634 635
{
    unsigned int val;
636 637
    val = avio_rl16(s);
    val |= avio_rl16(s) << 16;
Fabrice Bellard's avatar
Fabrice Bellard committed
638 639 640
    return val;
}

641
uint64_t avio_rl64(AVIOContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
642
{
643
    uint64_t val;
644 645
    val = (uint64_t)avio_rl32(s);
    val |= (uint64_t)avio_rl32(s) << 32;
Fabrice Bellard's avatar
Fabrice Bellard committed
646 647 648
    return val;
}

649
unsigned int avio_rb16(AVIOContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
650 651
{
    unsigned int val;
652 653
    val = avio_r8(s) << 8;
    val |= avio_r8(s);
Fabrice Bellard's avatar
Fabrice Bellard committed
654 655 656
    return val;
}

657
unsigned int avio_rb24(AVIOContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
658 659
{
    unsigned int val;
660 661
    val = avio_rb16(s) << 8;
    val |= avio_r8(s);
Fabrice Bellard's avatar
Fabrice Bellard committed
662 663
    return val;
}
664
unsigned int avio_rb32(AVIOContext *s)
665 666
{
    unsigned int val;
667 668
    val = avio_rb16(s) << 16;
    val |= avio_rb16(s);
669 670
    return val;
}
Fabrice Bellard's avatar
Fabrice Bellard committed
671

672
int ff_get_line(AVIOContext *s, char *buf, int maxlen)
673 674 675 676 677
{
    int i = 0;
    char c;

    do {
678
        c = avio_r8(s);
679
        if (c && i < maxlen-1)
680
            buf[i++] = c;
681
    } while (c != '\n' && c != '\r' && c);
682
    if (c == '\r' && avio_r8(s) != '\n' && !avio_feof(s))
683
        avio_skip(s, -1);
684 685

    buf[i] = 0;
686
    return i;
687 688
}

689 690 691 692
int avio_get_str(AVIOContext *s, int maxlen, char *buf, int buflen)
{
    int i;

693 694
    if (buflen <= 0)
        return AVERROR(EINVAL);
695 696 697 698 699
    // reserve 1 byte for terminating 0
    buflen = FFMIN(buflen - 1, maxlen);
    for (i = 0; i < buflen; i++)
        if (!(buf[i] = avio_r8(s)))
            return i + 1;
700
    buf[i] = 0;
701 702 703 704 705 706
    for (; i < maxlen; i++)
        if (!avio_r8(s))
            return i + 1;
    return maxlen;
}

707
#define GET_STR16(type, read) \
708
    int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\
709 710 711
{\
    char* q = buf;\
    int ret = 0;\
712 713
    if (buflen <= 0) \
        return AVERROR(EINVAL); \
714 715 716 717 718 719 720 721 722 723 724 725
    while (ret + 1 < maxlen) {\
        uint8_t tmp;\
        uint32_t ch;\
        GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\
        if (!ch)\
            break;\
        PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\
    }\
    *q = 0;\
    return ret;\
}\

726 727
GET_STR16(le, avio_rl16)
GET_STR16(be, avio_rb16)
728 729 730

#undef GET_STR16

731
uint64_t avio_rb64(AVIOContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
732
{
733
    uint64_t val;
734 735
    val = (uint64_t)avio_rb32(s) << 32;
    val |= (uint64_t)avio_rb32(s);
Fabrice Bellard's avatar
Fabrice Bellard committed
736 737 738
    return val;
}

739
uint64_t ffio_read_varlen(AVIOContext *bc){
740 741 742 743
    uint64_t val = 0;
    int tmp;

    do{
744
        tmp = avio_r8(bc);
745 746 747 748 749
        val= (val<<7) + (tmp&127);
    }while(tmp&128);
    return val;
}

750
int ffio_fdopen(AVIOContext **s, URLContext *h)
Fabrice Bellard's avatar
Fabrice Bellard committed
751
{
752
    uint8_t *buffer;
753
    int buffer_size, max_packet_size;
Fabrice Bellard's avatar
Fabrice Bellard committed
754

755
    max_packet_size = h->max_packet_size;
756 757 758 759 760
    if (max_packet_size) {
        buffer_size = max_packet_size; /* no need to bufferize more than one packet */
    } else {
        buffer_size = IO_BUFFER_SIZE;
    }
761
    buffer = av_malloc(buffer_size);
Fabrice Bellard's avatar
Fabrice Bellard committed
762
    if (!buffer)
763
        return AVERROR(ENOMEM);
Fabrice Bellard's avatar
Fabrice Bellard committed
764

765
    *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, h,
766
                            (void*)ffurl_read, (void*)ffurl_write, (void*)ffurl_seek);
767
    if (!*s) {
768 769 770
        av_free(buffer);
        return AVERROR(ENOMEM);
    }
771
    (*s)->direct = h->flags & AVIO_FLAG_DIRECT;
772
    (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL;
773
    (*s)->max_packet_size = max_packet_size;
774
    if(h->prot) {
775
        (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause;
776
        (*s)->read_seek  = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek;
777
    }
778
    (*s)->av_class = &ffio_url_class;
Fabrice Bellard's avatar
Fabrice Bellard committed
779 780 781
    return 0;
}

782
int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
783 784 785 786
{
    uint8_t *buffer;
    int max_buffer_size = s->max_packet_size ?
                          s->max_packet_size : IO_BUFFER_SIZE;
787
    int filled = s->buf_end - s->buffer;
788 789 790

    buf_size += s->buf_ptr - s->buffer + max_buffer_size;

791
    if (buf_size < filled || s->seekable)
792 793 794 795 796 797 798
        return 0;
    av_assert0(!s->write_flag);

    buffer = av_malloc(buf_size);
    if (!buffer)
        return AVERROR(ENOMEM);

799
    memcpy(buffer, s->buffer, filled);
800 801 802 803 804 805 806 807
    av_free(s->buffer);
    s->buf_ptr = buffer + (s->buf_ptr - s->buffer);
    s->buf_end = buffer + (s->buf_end - s->buffer);
    s->buffer = buffer;
    s->buffer_size = buf_size;
    return 0;
}

808
int ffio_set_buf_size(AVIOContext *s, int buf_size)
Fabrice Bellard's avatar
Fabrice Bellard committed
809
{
810
    uint8_t *buffer;
811
    buffer = av_malloc(buf_size);
Fabrice Bellard's avatar
Fabrice Bellard committed
812
    if (!buffer)
813
        return AVERROR(ENOMEM);
Fabrice Bellard's avatar
Fabrice Bellard committed
814

815
    av_free(s->buffer);
Fabrice Bellard's avatar
Fabrice Bellard committed
816
    s->buffer = buffer;
817
    s->orig_buffer_size =
Fabrice Bellard's avatar
Fabrice Bellard committed
818 819
    s->buffer_size = buf_size;
    s->buf_ptr = buffer;
820
    url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
821 822 823
    return 0;
}

824
static int url_resetbuf(AVIOContext *s, int flags)
825
{
826
    av_assert1(flags == AVIO_FLAG_WRITE || flags == AVIO_FLAG_READ);
827

828
    if (flags & AVIO_FLAG_WRITE) {
829 830 831 832 833 834
        s->buf_end = s->buffer + s->buffer_size;
        s->write_flag = 1;
    } else {
        s->buf_end = s->buffer;
        s->write_flag = 0;
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
835 836 837
    return 0;
}

838
int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char **bufp, int buf_size)
839 840 841
{
    int64_t buffer_start;
    int buffer_size;
842
    int overlap, new_size, alloc_size;
843
    uint8_t *buf = *bufp;
844

845 846
    if (s->write_flag) {
        av_freep(bufp);
847
        return AVERROR(EINVAL);
848
    }
849 850 851 852

    buffer_size = s->buf_end - s->buffer;

    /* the buffers must touch or overlap */
853 854
    if ((buffer_start = s->pos - buffer_size) > buf_size) {
        av_freep(bufp);
855
        return AVERROR(EINVAL);
856
    }
857 858 859 860

    overlap = buf_size - buffer_start;
    new_size = buf_size + buffer_size - overlap;

861 862
    alloc_size = FFMAX(s->buffer_size, new_size);
    if (alloc_size > buf_size)
863
        if (!(buf = (*bufp) = av_realloc_f(buf, 1, alloc_size)))
864 865
            return AVERROR(ENOMEM);

866
    if (new_size > buf_size) {
867 868 869 870 871 872
        memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap);
        buf_size = new_size;
    }

    av_free(s->buffer);
    s->buf_ptr = s->buffer = buf;
873 874
    s->buffer_size = alloc_size;
    s->pos = buf_size;
875 876 877 878 879 880 881
    s->buf_end = s->buf_ptr + buf_size;
    s->eof_reached = 0;
    s->must_flush = 0;

    return 0;
}

882
int avio_open(AVIOContext **s, const char *filename, int flags)
883 884 885 886 887 888
{
    return avio_open2(s, filename, flags, NULL, NULL);
}

int avio_open2(AVIOContext **s, const char *filename, int flags,
               const AVIOInterruptCB *int_cb, AVDictionary **options)
Fabrice Bellard's avatar
Fabrice Bellard committed
889 890 891 892
{
    URLContext *h;
    int err;

893
    err = ffurl_open(&h, filename, flags, int_cb, options);
Fabrice Bellard's avatar
Fabrice Bellard committed
894 895
    if (err < 0)
        return err;
896
    err = ffio_fdopen(s, h);
Fabrice Bellard's avatar
Fabrice Bellard committed
897
    if (err < 0) {
898
        ffurl_close(h);
Fabrice Bellard's avatar
Fabrice Bellard committed
899 900 901 902 903
        return err;
    }
    return 0;
}

904
int avio_close(AVIOContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
905
{
906 907 908 909
    URLContext *h;

    if (!s)
        return 0;
910

911
    avio_flush(s);
912
    h = s->opaque;
913
    av_freep(&s->buffer);
914 915 916
    if (s->write_flag)
        av_log(s, AV_LOG_DEBUG, "Statistics: %d seeks, %d writeouts\n", s->seek_count, s->writeout_count);
    else
917
        av_log(s, AV_LOG_DEBUG, "Statistics: %"PRId64" bytes read, %d seeks\n", s->bytes_read, s->seek_count);
918
    av_free(s);
919
    return ffurl_close(h);
Fabrice Bellard's avatar
Fabrice Bellard committed
920 921
}

922 923 924 925 926 927 928
int avio_closep(AVIOContext **s)
{
    int ret = avio_close(*s);
    *s = NULL;
    return ret;
}

929
int avio_printf(AVIOContext *s, const char *fmt, ...)
930 931 932 933 934 935 936 937
{
    va_list ap;
    char buf[4096];
    int ret;

    va_start(ap, fmt);
    ret = vsnprintf(buf, sizeof(buf), fmt, ap);
    va_end(ap);
938
    avio_write(s, buf, strlen(buf));
939 940 941
    return ret;
}

942
int avio_pause(AVIOContext *s, int pause)
943 944 945
{
    if (!s->read_pause)
        return AVERROR(ENOSYS);
946
    return s->read_pause(s->opaque, pause);
947 948
}

949
int64_t avio_seek_time(AVIOContext *s, int stream_index,
950
                       int64_t timestamp, int flags)
951 952
{
    URLContext *h = s->opaque;
953
    int64_t ret;
954 955 956
    if (!s->read_seek)
        return AVERROR(ENOSYS);
    ret = s->read_seek(h, stream_index, timestamp, flags);
957
    if (ret >= 0) {
958
        int64_t pos;
959
        s->buf_ptr = s->buf_end; // Flush buffer
960 961 962 963 964
        pos = s->seek(h, 0, SEEK_CUR);
        if (pos >= 0)
            s->pos = pos;
        else if (pos != AVERROR(ENOSYS))
            ret = pos;
965 966 967 968
    }
    return ret;
}

969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
int avio_read_to_bprint(AVIOContext *h, AVBPrint *pb, size_t max_size)
{
    int ret;
    char buf[1024];
    while (max_size) {
        ret = avio_read(h, buf, FFMIN(max_size, sizeof(buf)));
        if (ret == AVERROR_EOF)
            return 0;
        if (ret <= 0)
            return ret;
        av_bprint_append_data(pb, buf, ret);
        if (!av_bprint_is_complete(pb))
            return AVERROR(ENOMEM);
        max_size -= ret;
    }
    return 0;
}

987 988 989 990
/* output in a dynamic buffer */

typedef struct DynBuffer {
    int pos, size, allocated_size;
991
    uint8_t *buffer;
992
    int io_buffer_size;
993
    uint8_t io_buffer[1];
994 995
} DynBuffer;

996
static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size)
997 998
{
    DynBuffer *d = opaque;
999
    unsigned new_size, new_allocated_size;
1000

1001 1002 1003
    /* reallocate buffer if needed */
    new_size = d->pos + buf_size;
    new_allocated_size = d->allocated_size;
1004
    if (new_size < d->pos || new_size > INT_MAX/2)
1005
        return -1;
1006 1007 1008 1009
    while (new_size > new_allocated_size) {
        if (!new_allocated_size)
            new_allocated_size = new_size;
        else
1010
            new_allocated_size += new_allocated_size / 2 + 1;
1011
    }
1012

1013
    if (new_allocated_size > d->allocated_size) {
1014
        int err;
1015 1016 1017
        if ((err = av_reallocp(&d->buffer, new_allocated_size)) < 0) {
            d->allocated_size = 0;
            d->size = 0;
1018
            return err;
1019
        }
1020 1021 1022 1023 1024 1025
        d->allocated_size = new_allocated_size;
    }
    memcpy(d->buffer + d->pos, buf, buf_size);
    d->pos = new_size;
    if (d->pos > d->size)
        d->size = d->pos;
1026
    return buf_size;
1027 1028
}

1029
static int dyn_packet_buf_write(void *opaque, uint8_t *buf, int buf_size)
1030 1031
{
    unsigned char buf1[4];
1032
    int ret;
1033 1034

    /* packetized write: output the header */
1035
    AV_WB32(buf1, buf_size);
1036 1037
    ret = dyn_buf_write(opaque, buf1, 4);
    if (ret < 0)
1038
        return ret;
1039 1040

    /* then the data */
1041
    return dyn_buf_write(opaque, buf, buf_size);
1042 1043
}

1044
static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence)
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
{
    DynBuffer *d = opaque;

    if (whence == SEEK_CUR)
        offset += d->pos;
    else if (whence == SEEK_END)
        offset += d->size;
    if (offset < 0 || offset > 0x7fffffffLL)
        return -1;
    d->pos = offset;
    return 0;
}

1058
static int url_open_dyn_buf_internal(AVIOContext **s, int max_packet_size)
1059 1060
{
    DynBuffer *d;
1061
    unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024;
1062

1063
    if (sizeof(DynBuffer) + io_buffer_size < io_buffer_size)
1064
        return -1;
1065
    d = av_mallocz(sizeof(DynBuffer) + io_buffer_size);
1066
    if (!d)
1067
        return AVERROR(ENOMEM);
1068 1069 1070 1071
    d->io_buffer_size = io_buffer_size;
    *s = avio_alloc_context(d->io_buffer, d->io_buffer_size, 1, d, NULL,
                            max_packet_size ? dyn_packet_buf_write : dyn_buf_write,
                            max_packet_size ? NULL : dyn_buf_seek);
1072 1073 1074 1075
    if(!*s) {
        av_free(d);
        return AVERROR(ENOMEM);
    }
1076 1077
    (*s)->max_packet_size = max_packet_size;
    return 0;
1078 1079
}

1080
int avio_open_dyn_buf(AVIOContext **s)
1081 1082 1083 1084
{
    return url_open_dyn_buf_internal(s, 0);
}

1085
int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
1086 1087 1088 1089 1090 1091
{
    if (max_packet_size <= 0)
        return -1;
    return url_open_dyn_buf_internal(s, max_packet_size);
}

1092
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
1093
{
1094
    DynBuffer *d;
1095
    int size;
1096 1097 1098
    static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0};
    int padding = 0;

1099 1100 1101 1102 1103
    if (!s) {
        *pbuffer = NULL;
        return 0;
    }

1104 1105
    /* don't attempt to pad fixed-size packet buffers */
    if (!s->max_packet_size) {
1106
        avio_write(s, padbuf, sizeof(padbuf));
1107 1108
        padding = FF_INPUT_BUFFER_PADDING_SIZE;
    }
1109

1110
    avio_flush(s);
1111

1112
    d = s->opaque;
1113 1114 1115
    *pbuffer = d->buffer;
    size = d->size;
    av_free(d);
1116
    av_free(s);
1117
    return size - padding;
1118
}
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151

static int null_buf_write(void *opaque, uint8_t *buf, int buf_size)
{
    DynBuffer *d = opaque;

    d->pos += buf_size;
    if (d->pos > d->size)
        d->size = d->pos;
    return buf_size;
}

int ffio_open_null_buf(AVIOContext **s)
{
    int ret = url_open_dyn_buf_internal(s, 0);
    if (ret >= 0) {
        AVIOContext *pb = *s;
        pb->write_packet = null_buf_write;
    }
    return ret;
}

int ffio_close_null_buf(AVIOContext *s)
{
    DynBuffer *d = s->opaque;
    int size;

    avio_flush(s);

    size = d->size;
    av_free(d);
    av_free(s);
    return size;
}