Coverage Report

Created: 2026-10-28 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavformat/aviobuf.c
Line
Count
Source
1
/*
2
 * buffered I/O
3
 * Copyright (c) 2000,2001 Fabrice Bellard
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
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
20
 */
21
22
#include "libavutil/bprint.h"
23
#include "libavutil/crc.h"
24
#include "libavutil/dict.h"
25
#include "libavutil/intreadwrite.h"
26
#include "libavutil/log.h"
27
#include "libavutil/mem.h"
28
#include "libavutil/opt.h"
29
#include "libavutil/avassert.h"
30
#include "libavcodec/defs.h"
31
#include "avio.h"
32
#include "avio_internal.h"
33
#include "internal.h"
34
#include <stdarg.h>
35
36
0
#define IO_BUFFER_SIZE 32768
37
38
/**
39
 * Do seeks within this distance ahead of the current buffer by skipping
40
 * data instead of calling the protocol seek function, for seekable
41
 * protocols.
42
 */
43
0
#define SHORT_SEEK_THRESHOLD 32768
44
45
static void fill_buffer(AVIOContext *s);
46
static int url_resetbuf(AVIOContext *s, int flags);
47
/** @warning must be called before any I/O */
48
static int set_buf_size(AVIOContext *s, int buf_size);
49
50
void ffio_init_context(FFIOContext *ctx,
51
                  unsigned char *buffer,
52
                  int buffer_size,
53
                  int write_flag,
54
                  void *opaque,
55
                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
56
                  int (*write_packet)(void *opaque, const uint8_t *buf, int buf_size),
57
                  int64_t (*seek)(void *opaque, int64_t offset, int whence))
58
0
{
59
0
    AVIOContext *const s = &ctx->pub;
60
61
0
    memset(ctx, 0, sizeof(*ctx));
62
63
0
    s->buffer      = buffer;
64
0
    ctx->orig_buffer_size =
65
0
    s->buffer_size = buffer_size;
66
0
    s->buf_ptr     = buffer;
67
0
    s->buf_ptr_max = buffer;
68
0
    s->opaque      = opaque;
69
0
    s->direct      = 0;
70
71
0
    url_resetbuf(s, write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
72
73
0
    s->write_packet    = write_packet;
74
0
    s->read_packet     = read_packet;
75
0
    s->seek            = seek;
76
0
    s->pos             = 0;
77
0
    s->eof_reached     = 0;
78
0
    s->error           = 0;
79
0
    s->seekable        = seek ? AVIO_SEEKABLE_NORMAL : 0;
80
0
    s->min_packet_size = 0;
81
0
    s->max_packet_size = 0;
82
0
    s->update_checksum = NULL;
83
0
    ctx->short_seek_threshold = SHORT_SEEK_THRESHOLD;
84
85
0
    if (!read_packet && !write_flag) {
86
0
        s->pos     = buffer_size;
87
0
        s->buf_end = s->buffer + buffer_size;
88
0
    }
89
0
    s->read_pause = NULL;
90
0
    s->read_seek  = NULL;
91
92
0
    s->write_data_type       = NULL;
93
0
    s->ignore_boundary_point = 0;
94
0
    ctx->current_type        = AVIO_DATA_MARKER_UNKNOWN;
95
0
    ctx->last_time           = AV_NOPTS_VALUE;
96
0
    ctx->short_seek_get      = NULL;
97
0
}
98
99
void ffio_init_read_context(FFIOContext *s, const uint8_t *buffer, int buffer_size)
100
0
{
101
0
    ffio_init_context(s, (unsigned char*)buffer, buffer_size, 0, NULL, NULL, NULL, NULL);
102
0
}
103
104
void ffio_init_write_context(FFIOContext *s, uint8_t *buffer, int buffer_size)
105
0
{
106
0
    ffio_init_context(s, buffer, buffer_size, 1, NULL, NULL, NULL, NULL);
107
0
}
108
109
AVIOContext *avio_alloc_context(
110
                  unsigned char *buffer,
111
                  int buffer_size,
112
                  int write_flag,
113
                  void *opaque,
114
                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
115
                  int (*write_packet)(void *opaque, const uint8_t *buf, int buf_size),
116
                  int64_t (*seek)(void *opaque, int64_t offset, int whence))
117
0
{
118
0
    FFIOContext *s = av_malloc(sizeof(*s));
119
0
    if (!s)
120
0
        return NULL;
121
0
    ffio_init_context(s, buffer, buffer_size, write_flag, opaque,
122
0
                  read_packet, write_packet, seek);
123
0
    return &s->pub;
124
0
}
125
126
void avio_context_free(AVIOContext **ps)
127
0
{
128
0
    AVIOContext *s = *ps;
129
0
    if (s) {
130
0
        av_freep(&s->protocol_whitelist);
131
0
        av_freep(&s->protocol_blacklist);
132
0
    }
133
0
    av_freep(ps);
134
0
}
135
136
static void writeout(AVIOContext *s, const uint8_t *data, int len)
137
0
{
138
0
    FFIOContext *const ctx = ffiocontext(s);
139
0
    if (!s->error) {
140
0
        int ret = 0;
141
0
        if (s->write_data_type)
142
0
            ret = s->write_data_type(s->opaque, data,
143
0
                                     len,
144
0
                                     ctx->current_type,
145
0
                                     ctx->last_time);
146
0
        else if (s->write_packet)
147
0
            ret = s->write_packet(s->opaque, data, len);
148
0
        if (ret < 0) {
149
0
            s->error = ret;
150
0
        } else {
151
0
            ctx->bytes_written += len;
152
0
            s->bytes_written = ctx->bytes_written;
153
154
0
            if (s->pos + len > ctx->written_output_size) {
155
0
                ctx->written_output_size = s->pos + len;
156
0
            }
157
0
        }
158
0
    }
159
0
    if (ctx->current_type == AVIO_DATA_MARKER_SYNC_POINT ||
160
0
        ctx->current_type == AVIO_DATA_MARKER_BOUNDARY_POINT) {
161
0
        ctx->current_type = AVIO_DATA_MARKER_UNKNOWN;
162
0
    }
163
0
    ctx->last_time = AV_NOPTS_VALUE;
164
0
    ctx->writeout_count++;
165
0
    s->pos += len;
166
0
}
167
168
static void flush_buffer(AVIOContext *s)
169
0
{
170
0
    s->buf_ptr_max = FFMAX(s->buf_ptr, s->buf_ptr_max);
171
0
    if (s->write_flag && s->buf_ptr_max > s->buffer) {
172
0
        writeout(s, s->buffer, s->buf_ptr_max - s->buffer);
173
0
        if (s->update_checksum) {
174
0
            s->checksum     = s->update_checksum(s->checksum, s->checksum_ptr,
175
0
                                                 s->buf_ptr_max - s->checksum_ptr);
176
0
            s->checksum_ptr = s->buffer;
177
0
        }
178
0
    }
179
0
    s->buf_ptr = s->buf_ptr_max = s->buffer;
180
0
    if (!s->write_flag)
181
0
        s->buf_end = s->buffer;
182
0
}
183
184
void avio_w8(AVIOContext *s, int b)
185
0
{
186
0
    av_assert2(b>=-128 && b<=255);
187
0
    *s->buf_ptr++ = b;
188
0
    if (s->buf_ptr >= s->buf_end)
189
0
        flush_buffer(s);
190
0
}
191
192
void ffio_fill(AVIOContext *s, int b, int64_t count)
193
0
{
194
0
    while (count > 0) {
195
0
        int len = FFMIN(s->buf_end - s->buf_ptr, count);
196
0
        memset(s->buf_ptr, b, len);
197
0
        s->buf_ptr += len;
198
199
0
        if (s->buf_ptr >= s->buf_end)
200
0
            flush_buffer(s);
201
202
0
        count -= len;
203
0
    }
204
0
}
205
206
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
207
0
{
208
0
    if (size <= 0)
209
0
        return;
210
0
    if (s->direct && !s->update_checksum) {
211
0
        avio_flush(s);
212
0
        writeout(s, buf, size);
213
0
        return;
214
0
    }
215
0
    do {
216
0
        int len = FFMIN(s->buf_end - s->buf_ptr, size);
217
0
        memcpy(s->buf_ptr, buf, len);
218
0
        s->buf_ptr += len;
219
220
0
        if (s->buf_ptr >= s->buf_end)
221
0
            flush_buffer(s);
222
223
0
        buf += len;
224
0
        size -= len;
225
0
    } while (size > 0);
226
0
}
227
228
void avio_flush(AVIOContext *s)
229
0
{
230
0
    int seekback = s->write_flag ? FFMIN(0, s->buf_ptr - s->buf_ptr_max) : 0;
231
0
    flush_buffer(s);
232
0
    if (seekback)
233
0
        avio_seek(s, seekback, SEEK_CUR);
234
0
}
235
236
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
237
0
{
238
0
    FFIOContext *const ctx = ffiocontext(s);
239
0
    int64_t offset1;
240
0
    int64_t pos;
241
0
    int buffer_size;
242
0
    int short_seek;
243
0
    whence &= ~AVSEEK_FORCE; // force flag does nothing
244
245
0
    if(!s)
246
0
        return AVERROR(EINVAL);
247
248
0
    if ((whence & AVSEEK_SIZE))
249
0
        return s->seek ? s->seek(s->opaque, offset, AVSEEK_SIZE) : AVERROR(ENOSYS);
250
251
0
    buffer_size = s->buf_end - s->buffer;
252
    // pos is the absolute position that the beginning of s->buffer corresponds to in the file
253
0
    pos = s->pos - (s->write_flag ? 0 : buffer_size);
254
255
0
    if (whence != SEEK_CUR && whence != SEEK_SET)
256
0
        return AVERROR(EINVAL);
257
258
0
    if (whence == SEEK_CUR) {
259
0
        offset1 = pos + (s->buf_ptr - s->buffer);
260
0
        if (offset == 0)
261
0
            return offset1;
262
0
        if (offset > INT64_MAX - offset1)
263
0
            return AVERROR(EINVAL);
264
0
        offset += offset1;
265
0
    }
266
0
    if (offset < 0)
267
0
        return AVERROR(EINVAL);
268
269
0
    short_seek = ctx->short_seek_threshold;
270
0
    if (ctx->short_seek_get) {
271
0
        int tmp = ctx->short_seek_get(s->opaque);
272
0
        short_seek = FFMAX(tmp, short_seek);
273
0
    }
274
275
0
    offset1 = offset - pos; // "offset1" is the relative offset from the beginning of s->buffer
276
0
    s->buf_ptr_max = FFMAX(s->buf_ptr_max, s->buf_ptr);
277
0
    if ((!s->direct || !s->seek) &&
278
0
        offset1 >= 0 && offset1 <= (s->write_flag ? s->buf_ptr_max - s->buffer : buffer_size)) {
279
        /* can do the seek inside the buffer */
280
0
        s->buf_ptr = s->buffer + offset1;
281
0
    } else if ((!(s->seekable & AVIO_SEEKABLE_NORMAL) ||
282
0
               offset1 <= buffer_size + short_seek) &&
283
0
               !s->write_flag && offset1 >= 0 &&
284
0
               (!s->direct || !s->seek)) {
285
0
        while(s->pos < offset && !s->eof_reached)
286
0
            fill_buffer(s);
287
0
        if (s->eof_reached)
288
0
            return AVERROR_EOF;
289
0
        s->buf_ptr = s->buf_end - (s->pos - offset);
290
0
    } else if(!s->write_flag && offset1 < 0 && -offset1 < buffer_size>>1 && s->seek && offset > 0) {
291
0
        int64_t res;
292
293
0
        pos -= FFMIN(buffer_size>>1, pos);
294
0
        if ((res = s->seek(s->opaque, pos, SEEK_SET)) < 0)
295
0
            return res;
296
0
        s->buf_end =
297
0
        s->buf_ptr = s->buffer;
298
0
        s->pos = pos;
299
0
        s->eof_reached = 0;
300
0
        fill_buffer(s);
301
0
        return avio_seek(s, offset, SEEK_SET);
302
0
    } else {
303
0
        int64_t res;
304
0
        if (s->write_flag) {
305
0
            flush_buffer(s);
306
0
        }
307
0
        if (!s->seek)
308
0
            return AVERROR(EPIPE);
309
0
        if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0)
310
0
            return res;
311
0
        ctx->seek_count++;
312
0
        if (!s->write_flag)
313
0
            s->buf_end = s->buffer;
314
0
        s->checksum_ptr = s->buf_ptr = s->buf_ptr_max = s->buffer;
315
0
        s->pos = offset;
316
0
    }
317
0
    s->eof_reached = 0;
318
0
    return offset;
319
0
}
320
321
int64_t avio_skip(AVIOContext *s, int64_t offset)
322
0
{
323
0
    return avio_seek(s, offset, SEEK_CUR);
324
0
}
325
326
int64_t avio_size(AVIOContext *s)
327
0
{
328
0
    FFIOContext *const ctx = ffiocontext(s);
329
0
    int64_t size;
330
331
0
    if (!s)
332
0
        return AVERROR(EINVAL);
333
334
0
    if (ctx->written_output_size)
335
0
        return ctx->written_output_size;
336
337
0
    if (!s->seek)
338
0
        return AVERROR(ENOSYS);
339
0
    size = s->seek(s->opaque, 0, AVSEEK_SIZE);
340
0
    if (size < 0) {
341
0
        if ((size = s->seek(s->opaque, -1, SEEK_END)) < 0)
342
0
            return size;
343
0
        size++;
344
0
        s->seek(s->opaque, s->pos, SEEK_SET);
345
0
    }
346
0
    return size;
347
0
}
348
349
int avio_feof(AVIOContext *s)
350
0
{
351
0
    if(!s)
352
0
        return 0;
353
0
    if(s->eof_reached){
354
0
        s->eof_reached=0;
355
0
        fill_buffer(s);
356
0
    }
357
0
    return s->eof_reached;
358
0
}
359
360
void avio_wl32(AVIOContext *s, unsigned int val)
361
0
{
362
0
    avio_w8(s, (uint8_t) val       );
363
0
    avio_w8(s, (uint8_t)(val >> 8 ));
364
0
    avio_w8(s, (uint8_t)(val >> 16));
365
0
    avio_w8(s,           val >> 24 );
366
0
}
367
368
void avio_wb32(AVIOContext *s, unsigned int val)
369
0
{
370
0
    avio_w8(s,           val >> 24 );
371
0
    avio_w8(s, (uint8_t)(val >> 16));
372
0
    avio_w8(s, (uint8_t)(val >> 8 ));
373
0
    avio_w8(s, (uint8_t) val       );
374
0
}
375
376
int avio_put_str(AVIOContext *s, const char *str)
377
0
{
378
0
    int len = 1;
379
0
    if (str) {
380
0
        len += strlen(str);
381
0
        avio_write(s, (const unsigned char *) str, len);
382
0
    } else
383
0
        avio_w8(s, 0);
384
0
    return len;
385
0
}
386
387
static inline int put_str16(AVIOContext *s, const char *str, const int be)
388
0
{
389
0
    const uint8_t *q = str;
390
0
    int ret = 0;
391
0
    int err = 0;
392
393
0
    while (*q) {
394
0
        uint32_t ch;
395
0
        uint16_t tmp16;
396
397
0
        GET_UTF8(ch, *q++, goto invalid;)
398
0
        PUT_UTF16(ch, tmp16, be ? avio_wb16(s, tmp16) : avio_wl16(s, tmp16);
399
0
                  ret += 2;)
400
0
        continue;
401
0
invalid:
402
0
        av_log(s, AV_LOG_ERROR, "Invalid UTF8 sequence in avio_put_str16%s\n", be ? "be" : "le");
403
0
        err = AVERROR(EINVAL);
404
0
        if (!*(q-1))
405
0
            break;
406
0
    }
407
0
    if (be)
408
0
        avio_wb16(s, 0);
409
0
    else
410
0
        avio_wl16(s, 0);
411
0
    if (err)
412
0
        return err;
413
0
    ret += 2;
414
0
    return ret;
415
0
}
416
417
#define PUT_STR16(type, big_endian)                          \
418
0
int avio_put_str16 ## type(AVIOContext *s, const char *str)  \
419
0
{                                                            \
420
0
return put_str16(s, str, big_endian);                        \
421
0
}
Unexecuted instantiation: avio_put_str16le
Unexecuted instantiation: avio_put_str16be
422
423
PUT_STR16(le, 0)
424
PUT_STR16(be, 1)
425
426
#undef PUT_STR16
427
428
void avio_wl64(AVIOContext *s, uint64_t val)
429
0
{
430
0
    avio_wl32(s, (uint32_t)(val & 0xffffffff));
431
0
    avio_wl32(s, (uint32_t)(val >> 32));
432
0
}
433
434
void avio_wb64(AVIOContext *s, uint64_t val)
435
0
{
436
0
    avio_wb32(s, (uint32_t)(val >> 32));
437
0
    avio_wb32(s, (uint32_t)(val & 0xffffffff));
438
0
}
439
440
void avio_wl16(AVIOContext *s, unsigned int val)
441
0
{
442
0
    avio_w8(s, (uint8_t)val);
443
0
    avio_w8(s, (int)val >> 8);
444
0
}
445
446
void avio_wb16(AVIOContext *s, unsigned int val)
447
0
{
448
0
    avio_w8(s, (int)val >> 8);
449
0
    avio_w8(s, (uint8_t)val);
450
0
}
451
452
void avio_wl24(AVIOContext *s, unsigned int val)
453
0
{
454
0
    avio_wl16(s, val & 0xffff);
455
0
    avio_w8(s, (int)val >> 16);
456
0
}
457
458
void avio_wb24(AVIOContext *s, unsigned int val)
459
0
{
460
0
    avio_wb16(s, (int)val >> 8);
461
0
    avio_w8(s, (uint8_t)val);
462
0
}
463
464
void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type)
465
0
{
466
0
    FFIOContext *const ctx = ffiocontext(s);
467
0
    if (type == AVIO_DATA_MARKER_FLUSH_POINT) {
468
0
        if (s->buf_ptr - s->buffer >= s->min_packet_size)
469
0
            avio_flush(s);
470
0
        return;
471
0
    }
472
0
    if (!s->write_data_type)
473
0
        return;
474
    // If ignoring boundary points, just treat it as unknown
475
0
    if (type == AVIO_DATA_MARKER_BOUNDARY_POINT && s->ignore_boundary_point)
476
0
        type = AVIO_DATA_MARKER_UNKNOWN;
477
    // Avoid unnecessary flushes if we are already in non-header/trailer
478
    // data and setting the type to unknown
479
0
    if (type == AVIO_DATA_MARKER_UNKNOWN &&
480
0
        (ctx->current_type != AVIO_DATA_MARKER_HEADER &&
481
0
         ctx->current_type != AVIO_DATA_MARKER_TRAILER))
482
0
        return;
483
484
0
    switch (type) {
485
0
    case AVIO_DATA_MARKER_HEADER:
486
0
    case AVIO_DATA_MARKER_TRAILER:
487
        // For header/trailer, ignore a new marker of the same type;
488
        // consecutive header/trailer markers can be merged.
489
0
        if (type == ctx->current_type)
490
0
            return;
491
0
        break;
492
0
    }
493
494
    // If we've reached here, we have a new, noteworthy marker.
495
    // Flush the previous data and mark the start of the new data.
496
0
    avio_flush(s);
497
0
    ctx->current_type = type;
498
0
    ctx->last_time = time;
499
0
}
500
501
static int read_packet_wrapper(AVIOContext *s, uint8_t *buf, int size)
502
0
{
503
0
    int ret;
504
505
0
    if (!s->read_packet)
506
0
        return AVERROR(EINVAL);
507
0
    ret = s->read_packet(s->opaque, buf, size);
508
0
    av_assert2(ret || s->max_packet_size);
509
0
    return ret;
510
0
}
511
512
/* Input stream */
513
514
static void fill_buffer(AVIOContext *s)
515
0
{
516
0
    FFIOContext *const ctx = (FFIOContext *)s;
517
0
    int max_buffer_size = s->max_packet_size ?
518
0
                          s->max_packet_size : IO_BUFFER_SIZE;
519
0
    uint8_t *dst        = s->buf_end - s->buffer + max_buffer_size <= s->buffer_size ?
520
0
                          s->buf_end : s->buffer;
521
0
    int len             = s->buffer_size - (dst - s->buffer);
522
523
0
    if (s->error == AVERROR(EAGAIN)) {
524
0
        s->error       = 0;
525
0
        s->eof_reached = 0;
526
0
    }
527
528
    /* can't fill the buffer without read_packet, just set EOF if appropriate */
529
0
    if (!s->read_packet && s->buf_ptr >= s->buf_end)
530
0
        s->eof_reached = 1;
531
532
    /* no need to do anything if EOF already reached */
533
0
    if (s->eof_reached)
534
0
        return;
535
536
0
    if (s->update_checksum && dst == s->buffer) {
537
0
        if (s->buf_end > s->checksum_ptr)
538
0
            s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
539
0
                                             s->buf_end - s->checksum_ptr);
540
0
        s->checksum_ptr = s->buffer;
541
0
    }
542
543
    /* make buffer smaller in case it ended up large after probing */
544
0
    if (s->read_packet && ctx->orig_buffer_size &&
545
0
        s->buffer_size > ctx->orig_buffer_size  && len >= ctx->orig_buffer_size) {
546
0
        if (dst == s->buffer && s->buf_ptr != dst) {
547
0
            int ret = set_buf_size(s, ctx->orig_buffer_size);
548
0
            if (ret < 0)
549
0
                av_log(s, AV_LOG_WARNING, "Failed to decrease buffer size\n");
550
551
0
            s->checksum_ptr = dst = s->buffer;
552
0
        }
553
0
        len = ctx->orig_buffer_size;
554
0
    }
555
556
0
    len = read_packet_wrapper(s, dst, len);
557
0
    if (len == AVERROR_EOF) {
558
        /* do not modify buffer if EOF reached so that a seek back can
559
           be done without rereading data */
560
0
        s->eof_reached = 1;
561
0
    } else if (len < 0) {
562
0
        s->eof_reached = 1;
563
0
        s->error= len;
564
0
    } else {
565
0
        s->pos += len;
566
0
        s->buf_ptr = dst;
567
0
        s->buf_end = dst + len;
568
0
        ffiocontext(s)->bytes_read += len;
569
0
        s->bytes_read = ffiocontext(s)->bytes_read;
570
0
    }
571
0
}
572
573
unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf,
574
                                    unsigned int len)
575
0
{
576
0
    return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len);
577
0
}
578
579
unsigned long ff_crcEDB88320_update(unsigned long checksum, const uint8_t *buf,
580
                                    unsigned int len)
581
0
{
582
0
    return av_crc(av_crc_get_table(AV_CRC_32_IEEE_LE), checksum, buf, len);
583
0
}
584
585
unsigned long ff_crcA001_update(unsigned long checksum, const uint8_t *buf,
586
                                unsigned int len)
587
0
{
588
0
    return av_crc(av_crc_get_table(AV_CRC_16_ANSI_LE), checksum, buf, len);
589
0
}
590
591
unsigned long ffio_get_checksum(AVIOContext *s)
592
0
{
593
0
    s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
594
0
                                     s->buf_ptr - s->checksum_ptr);
595
0
    s->update_checksum = NULL;
596
0
    return s->checksum;
597
0
}
598
599
void ffio_init_checksum(AVIOContext *s,
600
                   unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len),
601
                   unsigned long checksum)
602
0
{
603
0
    s->update_checksum = update_checksum;
604
0
    if (s->update_checksum) {
605
0
        s->checksum     = checksum;
606
0
        s->checksum_ptr = s->buf_ptr;
607
0
    }
608
0
}
609
610
/* XXX: put an inline version */
611
int avio_r8(AVIOContext *s)
612
0
{
613
0
    if (s->buf_ptr >= s->buf_end)
614
0
        fill_buffer(s);
615
0
    if (s->buf_ptr < s->buf_end)
616
0
        return *s->buf_ptr++;
617
0
    return 0;
618
0
}
619
620
int avio_read(AVIOContext *s, unsigned char *buf, int size)
621
0
{
622
0
    int len, size1;
623
624
0
    size1 = size;
625
0
    while (size > 0) {
626
0
        len = FFMIN(s->buf_end - s->buf_ptr, size);
627
0
        if (len == 0 || s->write_flag) {
628
0
            if((s->direct || size > s->buffer_size) && !s->update_checksum && s->read_packet) {
629
                // bypass the buffer and read data directly into buf
630
0
                if (s->error == AVERROR(EAGAIN)) {
631
0
                    s->error       = 0;
632
0
                    s->eof_reached = 0;
633
0
                }
634
0
                len = read_packet_wrapper(s, buf, size);
635
0
                if (len == AVERROR_EOF) {
636
                    /* do not modify buffer if EOF reached so that a seek back can
637
                    be done without rereading data */
638
0
                    s->eof_reached = 1;
639
0
                    break;
640
0
                } else if (len < 0) {
641
0
                    s->eof_reached = 1;
642
0
                    s->error= len;
643
0
                    break;
644
0
                } else {
645
0
                    s->pos += len;
646
0
                    ffiocontext(s)->bytes_read += len;
647
0
                    s->bytes_read = ffiocontext(s)->bytes_read;
648
0
                    size -= len;
649
0
                    buf += len;
650
                    // reset the buffer
651
0
                    s->buf_ptr = s->buffer;
652
0
                    s->buf_end = s->buffer/* + len*/;
653
0
                }
654
0
            } else {
655
0
                fill_buffer(s);
656
0
                len = s->buf_end - s->buf_ptr;
657
0
                if (len == 0)
658
0
                    break;
659
0
            }
660
0
        } else {
661
0
            memcpy(buf, s->buf_ptr, len);
662
0
            buf += len;
663
0
            s->buf_ptr += len;
664
0
            size -= len;
665
0
        }
666
0
    }
667
0
    if (size1 == size) {
668
0
        if (s->error)      return s->error;
669
0
        if (avio_feof(s))  return AVERROR_EOF;
670
0
    }
671
0
    return size1 - size;
672
0
}
673
674
int ffio_read_size(AVIOContext *s, unsigned char *buf, int size)
675
0
{
676
0
    int ret = avio_read(s, buf, size);
677
0
    if (ret == size)
678
0
        return ret;
679
0
    if (ret < 0 && ret != AVERROR_EOF)
680
0
        return ret;
681
0
    return AVERROR_INVALIDDATA;
682
0
}
683
684
int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data)
685
0
{
686
0
    if (s->buf_end - s->buf_ptr >= size && !s->write_flag) {
687
0
        *data = s->buf_ptr;
688
0
        s->buf_ptr += size;
689
0
        return size;
690
0
    } else {
691
0
        *data = buf;
692
0
        return avio_read(s, buf, size);
693
0
    }
694
0
}
695
696
int avio_read_partial(AVIOContext *s, unsigned char *buf, int size)
697
0
{
698
0
    int len;
699
700
0
    if (size < 0)
701
0
        return AVERROR(EINVAL);
702
703
0
    if (s->read_packet && s->write_flag) {
704
0
        len = read_packet_wrapper(s, buf, size);
705
0
        if (len > 0)
706
0
            s->pos += len;
707
0
        return len;
708
0
    }
709
710
0
    len = s->buf_end - s->buf_ptr;
711
0
    if (len == 0) {
712
0
        fill_buffer(s);
713
0
        len = s->buf_end - s->buf_ptr;
714
0
    }
715
0
    if (len > size)
716
0
        len = size;
717
0
    memcpy(buf, s->buf_ptr, len);
718
0
    s->buf_ptr += len;
719
0
    if (!len) {
720
0
        if (s->error)      return s->error;
721
0
        if (avio_feof(s))  return AVERROR_EOF;
722
0
    }
723
0
    return len;
724
0
}
725
726
#define AVIO_READER(name, type, bytes, load, read1, shift1, read2, shift2) \
727
0
type name(AVIOContext *s)                                       \
728
0
{                                                               \
729
0
    type val;                                                   \
730
0
    if (s->buf_end - s->buf_ptr >= bytes) {                     \
731
0
        val = load(s->buf_ptr);                                 \
732
0
        s->buf_ptr += bytes;                                    \
733
0
    } else {                                                    \
734
0
        val  = (type)read1(s) << shift1;                        \
735
0
        val |= (type)read2(s) << shift2;                        \
736
0
    }                                                           \
737
0
    return val;                                                 \
738
0
}
Unexecuted instantiation: avio_rl16
Unexecuted instantiation: avio_rl24
Unexecuted instantiation: avio_rl32
Unexecuted instantiation: avio_rl64
Unexecuted instantiation: avio_rb16
Unexecuted instantiation: avio_rb24
Unexecuted instantiation: avio_rb32
Unexecuted instantiation: avio_rb64
739
740
0
AVIO_READER(avio_rl16, unsigned int, 2, AV_RL16, avio_r8,    0, avio_r8,    8)
741
0
AVIO_READER(avio_rl24, unsigned int, 3, AV_RL24, avio_rl16,  0, avio_r8,   16)
742
0
AVIO_READER(avio_rl32, unsigned int, 4, AV_RL32, avio_rl16,  0, avio_rl16, 16)
743
0
AVIO_READER(avio_rl64, uint64_t,     8, AV_RL64, avio_rl32,  0, avio_rl32, 32)
744
0
AVIO_READER(avio_rb16, unsigned int, 2, AV_RB16, avio_r8,    8, avio_r8,    0)
745
0
AVIO_READER(avio_rb24, unsigned int, 3, AV_RB24, avio_rb16,  8, avio_r8,    0)
746
0
AVIO_READER(avio_rb32, unsigned int, 4, AV_RB32, avio_rb16, 16, avio_rb16,  0)
747
0
AVIO_READER(avio_rb64, uint64_t,     8, AV_RB64, avio_rb32, 32, avio_rb32,  0)
748
int ff_get_line(AVIOContext *s, char *buf, int maxlen)
749
0
{
750
0
    int i = 0;
751
0
    char c;
752
753
0
    do {
754
0
        c = avio_r8(s);
755
0
        if (c && i < maxlen-1)
756
0
            buf[i++] = c;
757
0
    } while (c != '\n' && c != '\r' && c);
758
0
    if (c == '\r' && avio_r8(s) != '\n' && !avio_feof(s))
759
0
        avio_skip(s, -1);
760
761
0
    buf[i] = 0;
762
0
    return i;
763
0
}
764
765
int ff_get_chomp_line(AVIOContext *s, char *buf, int maxlen)
766
0
{
767
0
    int len = ff_get_line(s, buf, maxlen);
768
0
    while (len > 0 && av_isspace(buf[len - 1]))
769
0
        buf[--len] = '\0';
770
0
    return len;
771
0
}
772
773
typedef enum FFBPrintReadStringMode {
774
    FFBPrintReadString = 0,
775
    FFBPrintReadLine   = 1,
776
} FFBPrintReadStringMode;
777
778
static int64_t read_string_to_bprint(AVIOContext *s, AVBPrint *bp,
779
                                     FFBPrintReadStringMode mode,
780
                                     int64_t max_len)
781
0
{
782
0
    int len, end;
783
0
    int64_t read = 0;
784
0
    char tmp[1024];
785
0
    char c;
786
787
0
    if (!max_len)
788
0
        return 0;
789
790
0
    do {
791
0
        len = 0;
792
0
        do {
793
0
            c = avio_r8(s);
794
0
            end = ((mode == FFBPrintReadLine && (c == '\r' || c == '\n')) ||
795
0
                   c == '\0');
796
0
            if (!end)
797
0
                tmp[len++] = c;
798
0
        } while (!end && len < sizeof(tmp) &&
799
0
                 ((max_len < 0) || (read + len < max_len)));
800
0
        av_bprint_append_data(bp, tmp, len);
801
0
        read += len;
802
0
    } while (!end && ((max_len < 0) || (read < max_len)));
803
804
0
    if (mode == FFBPrintReadLine &&
805
0
        c == '\r' && avio_r8(s) != '\n' && !avio_feof(s))
806
0
        avio_skip(s, -1);
807
808
0
    if (!c && s->error)
809
0
        return s->error;
810
811
0
    if (!c && !read && avio_feof(s))
812
0
        return AVERROR_EOF;
813
814
0
    return read;
815
0
}
816
817
static int64_t read_string_to_bprint_overwrite(AVIOContext *s, AVBPrint *bp,
818
                                               FFBPrintReadStringMode mode,
819
                                               int64_t max_len)
820
0
{
821
0
    int64_t ret;
822
823
0
    av_bprint_clear(bp);
824
0
    ret = read_string_to_bprint(s, bp, mode, max_len);
825
0
    if (ret < 0)
826
0
        return ret;
827
828
0
    if (!av_bprint_is_complete(bp))
829
0
        return AVERROR(ENOMEM);
830
831
0
    return bp->len;
832
0
}
833
834
int64_t ff_read_line_to_bprint_overwrite(AVIOContext *s, AVBPrint *bp)
835
0
{
836
0
    return read_string_to_bprint_overwrite(s, bp, FFBPrintReadLine, -1);
837
0
}
838
839
int64_t ff_read_string_to_bprint_overwrite(AVIOContext *s, AVBPrint *bp,
840
                                           int64_t max_len)
841
0
{
842
0
    return read_string_to_bprint_overwrite(s, bp, FFBPrintReadString, max_len);
843
0
}
844
845
int avio_get_str(AVIOContext *s, int maxlen, char *buf, int buflen)
846
0
{
847
0
    int i;
848
849
0
    if (buflen <= 0)
850
0
        return AVERROR(EINVAL);
851
    // reserve 1 byte for terminating 0
852
0
    buflen = FFMIN(buflen - 1, maxlen);
853
0
    for (i = 0; i < buflen; i++)
854
0
        if (!(buf[i] = avio_r8(s)))
855
0
            return i + 1;
856
0
    buf[i] = 0;
857
0
    for (; i < maxlen; i++)
858
0
        if (!avio_r8(s))
859
0
            return i + 1;
860
0
    return maxlen;
861
0
}
862
863
#define GET_STR16(type, read) \
864
0
    int avio_get_str16 ##type(AVIOContext *pb, int maxlen, char *buf, int buflen)\
865
0
{\
866
0
    char* q = buf;\
867
0
    int ret = 0;\
868
0
    if (buflen <= 0) \
869
0
        return AVERROR(EINVAL); \
870
0
    while (ret + 1 < maxlen) {\
871
0
        uint8_t tmp;\
872
0
        uint32_t ch;\
873
0
        GET_UTF16(ch, (ret += 2) <= maxlen ? read(pb) : 0, break;)\
874
0
        if (!ch)\
875
0
            break;\
876
0
        PUT_UTF8(ch, tmp, if (q - buf < buflen - 1) *q++ = tmp;)\
877
0
    }\
878
0
    *q = 0;\
879
0
    return ret;\
880
0
}\
Unexecuted instantiation: avio_get_str16le
Unexecuted instantiation: avio_get_str16be
881
882
GET_STR16(le, avio_rl16)
883
GET_STR16(be, avio_rb16)
884
885
#undef GET_STR16
886
887
0
uint64_t ffio_read_varlen(AVIOContext *bc){
888
0
    uint64_t val = 0;
889
0
    int tmp;
890
891
0
    do{
892
0
        tmp = avio_r8(bc);
893
0
        val= (val<<7) + (tmp&127);
894
0
    }while(tmp&128);
895
0
    return val;
896
0
}
897
898
0
unsigned int ffio_read_leb(AVIOContext *s) {
899
0
    int more, i = 0;
900
0
    unsigned leb = 0;
901
902
0
    do {
903
0
        int byte = avio_r8(s);
904
0
        unsigned bits = byte & 0x7f;
905
0
        more = byte & 0x80;
906
0
        if (i <= 4)
907
0
            leb |= bits << (i * 7);
908
0
        if (++i == 8)
909
0
            break;
910
0
    } while (more);
911
912
0
    return leb;
913
0
}
914
915
void ffio_write_leb(AVIOContext *s, unsigned val)
916
0
{
917
0
    int len;
918
0
    uint8_t byte;
919
920
0
    len = (av_log2(val) + 7) / 7;
921
922
0
    for (int i = 0; i < len; i++) {
923
0
        byte = val >> (7 * i) & 0x7f;
924
0
        if (i < len - 1)
925
0
            byte |= 0x80;
926
927
0
        avio_w8(s, byte);
928
0
    }
929
0
}
930
931
void ffio_write_lines(AVIOContext *s, const unsigned char *buf, int size,
932
                      const unsigned char *ending)
933
0
{
934
0
    int ending_len = ending ? strlen(ending) : 1;
935
0
    if (!ending)
936
0
        ending = "\n";
937
0
    if (size < 0)
938
0
        size = strlen(buf);
939
940
0
    while (size > 0) {
941
0
        size_t len = 0;
942
0
        char last = 0;
943
0
        for (; len < size; len++) {
944
0
            last = buf[len];
945
0
            if (last == '\r' || last == '\n')
946
0
                break;
947
0
        }
948
949
0
        avio_write(s, buf, len);
950
0
        avio_write(s, ending, ending_len);
951
952
0
        buf += len + 1;
953
0
        size -= len + 1;
954
955
0
        if (size > 0 && last == '\r' && buf[0] == '\n') {
956
0
            buf++;
957
0
            size--;
958
0
        }
959
0
    }
960
0
}
961
962
int ffio_copy_url_options(AVIOContext* pb, AVDictionary** avio_opts)
963
0
{
964
0
    const char *opts[] = {
965
0
        "headers", "user_agent", "cookies", "http_proxy", "referer", "rw_timeout", "icy", "prefer_libcurl", NULL };
966
0
    const char **opt = opts;
967
0
    uint8_t *buf = NULL;
968
0
    int ret = 0;
969
970
0
    while (*opt) {
971
0
        if (av_opt_get(pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) {
972
0
            if (buf[0] != '\0') {
973
0
                ret = av_dict_set(avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL);
974
0
                if (ret < 0)
975
0
                    return ret;
976
0
            } else {
977
0
                av_freep(&buf);
978
0
            }
979
0
        }
980
0
        opt++;
981
0
    }
982
983
0
    return ret;
984
0
}
985
986
static void update_checksum(AVIOContext *s)
987
0
{
988
0
    if (s->update_checksum && s->buf_ptr > s->checksum_ptr) {
989
0
        s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
990
0
                                         s->buf_ptr - s->checksum_ptr);
991
0
    }
992
0
}
993
994
int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
995
0
{
996
0
    uint8_t *buffer;
997
0
    int max_buffer_size = s->max_packet_size ?
998
0
                          s->max_packet_size : IO_BUFFER_SIZE;
999
0
    ptrdiff_t filled = s->buf_end - s->buf_ptr;
1000
1001
0
    if (buf_size <= s->buf_end - s->buf_ptr)
1002
0
        return 0;
1003
1004
0
    if (buf_size > INT_MAX - max_buffer_size)
1005
0
        return AVERROR(EINVAL);
1006
1007
0
    buf_size += max_buffer_size - 1;
1008
1009
0
    if (buf_size + s->buf_ptr - s->buffer <= s->buffer_size || s->seekable || !s->read_packet)
1010
0
        return 0;
1011
0
    av_assert0(!s->write_flag);
1012
1013
0
    if (buf_size <= s->buffer_size) {
1014
0
        update_checksum(s);
1015
0
        memmove(s->buffer, s->buf_ptr, filled);
1016
0
    } else {
1017
0
        buffer = av_malloc(buf_size);
1018
0
        if (!buffer)
1019
0
            return AVERROR(ENOMEM);
1020
0
        update_checksum(s);
1021
0
        memcpy(buffer, s->buf_ptr, filled);
1022
0
        av_free(s->buffer);
1023
0
        s->buffer = buffer;
1024
0
        s->buffer_size = buf_size;
1025
0
    }
1026
0
    s->buf_ptr = s->buffer;
1027
0
    s->buf_end = s->buffer + filled;
1028
0
    s->checksum_ptr = s->buffer;
1029
0
    return 0;
1030
0
}
1031
1032
int ffio_limit(AVIOContext *s, int size)
1033
0
{
1034
0
    FFIOContext *const ctx = ffiocontext(s);
1035
0
    if (ctx->maxsize >= 0) {
1036
0
        int64_t pos = avio_tell(s);
1037
0
        int64_t remaining = ctx->maxsize - pos;
1038
0
        if (remaining < size) {
1039
0
            int64_t newsize = avio_size(s);
1040
0
            if (!ctx->maxsize || ctx->maxsize < newsize)
1041
0
                ctx->maxsize = newsize - !newsize;
1042
0
            if (pos > ctx->maxsize && ctx->maxsize >= 0)
1043
0
                ctx->maxsize = AVERROR(EIO);
1044
0
            if (ctx->maxsize >= 0)
1045
0
                remaining = ctx->maxsize - pos;
1046
0
        }
1047
1048
0
        if (ctx->maxsize >= 0 && remaining < size && size > 1) {
1049
0
            av_log(NULL, remaining ? AV_LOG_ERROR : AV_LOG_DEBUG,
1050
0
                   "Truncating packet of size %d to %"PRId64"\n",
1051
0
                   size, remaining + !remaining);
1052
0
            size = remaining + !remaining;
1053
0
        }
1054
0
    }
1055
0
    return size;
1056
0
}
1057
1058
static int set_buf_size(AVIOContext *s, int buf_size)
1059
0
{
1060
0
    uint8_t *buffer;
1061
0
    buffer = av_malloc(buf_size);
1062
0
    if (!buffer)
1063
0
        return AVERROR(ENOMEM);
1064
1065
0
    av_free(s->buffer);
1066
0
    s->buffer = buffer;
1067
0
    ffiocontext(s)->orig_buffer_size =
1068
0
    s->buffer_size = buf_size;
1069
0
    s->buf_ptr = s->buf_ptr_max = buffer;
1070
0
    url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
1071
0
    return 0;
1072
0
}
1073
1074
int ffio_realloc_buf(AVIOContext *s, int buf_size)
1075
0
{
1076
0
    uint8_t *buffer;
1077
0
    int data_size;
1078
1079
0
    if (!s->buffer_size)
1080
0
        return set_buf_size(s, buf_size);
1081
1082
0
    if (buf_size <= s->buffer_size)
1083
0
        return 0;
1084
1085
0
    buffer = av_malloc(buf_size);
1086
0
    if (!buffer)
1087
0
        return AVERROR(ENOMEM);
1088
1089
0
    data_size = s->write_flag ? (s->buf_ptr - s->buffer) : (s->buf_end - s->buf_ptr);
1090
0
    if (data_size > 0)
1091
0
        memcpy(buffer, s->write_flag ? s->buffer : s->buf_ptr, data_size);
1092
0
    av_free(s->buffer);
1093
0
    s->buffer = buffer;
1094
0
    ffiocontext(s)->orig_buffer_size = buf_size;
1095
0
    s->buffer_size = buf_size;
1096
0
    s->buf_ptr = s->write_flag ? (s->buffer + data_size) : s->buffer;
1097
0
    if (s->write_flag)
1098
0
        s->buf_ptr_max = s->buffer + data_size;
1099
1100
0
    s->buf_end = s->write_flag ? (s->buffer + s->buffer_size) : (s->buf_ptr + data_size);
1101
1102
0
    return 0;
1103
0
}
1104
1105
static int url_resetbuf(AVIOContext *s, int flags)
1106
0
{
1107
0
    av_assert1(flags == AVIO_FLAG_WRITE || flags == AVIO_FLAG_READ);
1108
1109
0
    if (flags & AVIO_FLAG_WRITE) {
1110
0
        s->buf_end = s->buffer + s->buffer_size;
1111
0
        s->write_flag = 1;
1112
0
    } else {
1113
0
        s->buf_end = s->buffer;
1114
0
        s->write_flag = 0;
1115
0
    }
1116
0
    return 0;
1117
0
}
1118
1119
int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char **bufp, int buf_size)
1120
0
{
1121
0
    int64_t buffer_start;
1122
0
    int buffer_size;
1123
0
    int overlap, new_size, alloc_size;
1124
0
    uint8_t *buf = *bufp;
1125
1126
0
    if (s->write_flag) {
1127
0
        av_freep(bufp);
1128
0
        return AVERROR(EINVAL);
1129
0
    }
1130
1131
0
    buffer_size = s->buf_end - s->buffer;
1132
1133
    /* the buffers must touch or overlap */
1134
0
    if ((buffer_start = s->pos - buffer_size) > buf_size) {
1135
0
        av_freep(bufp);
1136
0
        return AVERROR(EINVAL);
1137
0
    }
1138
1139
0
    overlap = buf_size - buffer_start;
1140
0
    new_size = buf_size + buffer_size - overlap;
1141
1142
0
    alloc_size = FFMAX(s->buffer_size, new_size);
1143
0
    if (alloc_size > buf_size)
1144
0
        if (!(buf = (*bufp) = av_realloc_f(buf, 1, alloc_size)))
1145
0
            return AVERROR(ENOMEM);
1146
1147
0
    if (new_size > buf_size) {
1148
0
        memcpy(buf + buf_size, s->buffer + overlap, buffer_size - overlap);
1149
0
        buf_size = new_size;
1150
0
    }
1151
1152
0
    av_free(s->buffer);
1153
0
    s->buf_ptr = s->buffer = buf;
1154
0
    s->buffer_size = alloc_size;
1155
0
    s->pos = buf_size;
1156
0
    s->buf_end = s->buf_ptr + buf_size;
1157
0
    s->eof_reached = 0;
1158
1159
0
    return 0;
1160
0
}
1161
1162
int avio_vprintf(AVIOContext *s, const char *fmt, va_list ap)
1163
0
{
1164
0
    AVBPrint bp;
1165
1166
0
    av_bprint_init(&bp, 0, INT_MAX);
1167
0
    av_vbprintf(&bp, fmt, ap);
1168
0
    if (!av_bprint_is_complete(&bp)) {
1169
0
        av_bprint_finalize(&bp, NULL);
1170
0
        s->error = AVERROR(ENOMEM);
1171
0
        return AVERROR(ENOMEM);
1172
0
    }
1173
0
    avio_write(s, bp.str, bp.len);
1174
0
    av_bprint_finalize(&bp, NULL);
1175
0
    return bp.len;
1176
0
}
1177
1178
int avio_printf(AVIOContext *s, const char *fmt, ...)
1179
0
{
1180
0
    va_list ap;
1181
0
    int ret;
1182
1183
0
    va_start(ap, fmt);
1184
0
    ret = avio_vprintf(s, fmt, ap);
1185
0
    va_end(ap);
1186
1187
0
    return ret;
1188
0
}
1189
1190
void avio_print_string_array(AVIOContext *s, const char *const strings[])
1191
0
{
1192
0
    for(; *strings; strings++)
1193
0
        avio_write(s, (const unsigned char *)*strings, strlen(*strings));
1194
0
}
1195
1196
int avio_pause(AVIOContext *s, int pause)
1197
0
{
1198
0
    if (!s->read_pause)
1199
0
        return AVERROR(ENOSYS);
1200
0
    return s->read_pause(s->opaque, pause);
1201
0
}
1202
1203
int64_t avio_seek_time(AVIOContext *s, int stream_index,
1204
                       int64_t timestamp, int flags)
1205
0
{
1206
0
    int64_t ret;
1207
0
    if (!s->read_seek)
1208
0
        return AVERROR(ENOSYS);
1209
0
    ret = s->read_seek(s->opaque, stream_index, timestamp, flags);
1210
0
    if (ret >= 0) {
1211
0
        int64_t pos;
1212
0
        s->buf_ptr = s->buf_end; // Flush buffer
1213
0
        pos = s->seek(s->opaque, 0, SEEK_CUR);
1214
0
        if (pos >= 0)
1215
0
            s->pos = pos;
1216
0
        else if (pos != AVERROR(ENOSYS))
1217
0
            ret = pos;
1218
0
    }
1219
0
    return ret;
1220
0
}
1221
1222
int avio_read_to_bprint(AVIOContext *h, AVBPrint *pb, size_t max_size)
1223
0
{
1224
0
    int ret;
1225
0
    char buf[1024];
1226
0
    while (max_size) {
1227
0
        ret = avio_read(h, buf, FFMIN(max_size, sizeof(buf)));
1228
0
        if (ret == AVERROR_EOF)
1229
0
            return 0;
1230
0
        if (ret <= 0)
1231
0
            return ret;
1232
0
        av_bprint_append_data(pb, buf, ret);
1233
0
        if (!av_bprint_is_complete(pb))
1234
0
            return AVERROR(ENOMEM);
1235
0
        max_size -= ret;
1236
0
    }
1237
0
    return 0;
1238
0
}
1239
1240
/* output in a dynamic buffer */
1241
1242
typedef struct DynBuffer {
1243
    int pos, size, allocated_size;
1244
    uint8_t *buffer;
1245
    int io_buffer_size;
1246
    uint8_t io_buffer[1];
1247
} DynBuffer;
1248
1249
static int dyn_buf_write(void *opaque, const uint8_t *buf, int buf_size)
1250
0
{
1251
0
    DynBuffer *d = opaque;
1252
0
    unsigned new_size;
1253
1254
    /* reallocate buffer if needed */
1255
0
    new_size = (unsigned)d->pos + buf_size;
1256
0
    if (new_size < d->pos || new_size > INT_MAX)
1257
0
        return AVERROR(ERANGE);
1258
0
    if (new_size > d->allocated_size) {
1259
0
        unsigned new_allocated_size = d->allocated_size ? d->allocated_size
1260
0
                                                        : new_size;
1261
0
        int err;
1262
0
        while (new_size > new_allocated_size)
1263
0
            new_allocated_size += new_allocated_size / 2 + 1;
1264
1265
0
        new_allocated_size = FFMIN(new_allocated_size, INT_MAX);
1266
1267
0
        if ((err = av_reallocp(&d->buffer, new_allocated_size)) < 0) {
1268
0
            d->allocated_size = 0;
1269
0
            d->size = 0;
1270
0
            return err;
1271
0
        }
1272
0
        d->allocated_size = new_allocated_size;
1273
0
    }
1274
0
    memcpy(d->buffer + d->pos, buf, buf_size);
1275
0
    d->pos = new_size;
1276
0
    if (d->pos > d->size)
1277
0
        d->size = d->pos;
1278
0
    return buf_size;
1279
0
}
1280
1281
static int dyn_packet_buf_write(void *opaque, const uint8_t *buf, int buf_size)
1282
0
{
1283
0
    unsigned char buf1[4];
1284
0
    int ret;
1285
1286
    /* packetized write: output the header */
1287
0
    AV_WB32(buf1, buf_size);
1288
0
    ret = dyn_buf_write(opaque, buf1, 4);
1289
0
    if (ret < 0)
1290
0
        return ret;
1291
1292
    /* then the data */
1293
0
    return dyn_buf_write(opaque, buf, buf_size);
1294
0
}
1295
1296
static int64_t dyn_buf_seek(void *opaque, int64_t offset, int whence)
1297
0
{
1298
0
    DynBuffer *d = opaque;
1299
1300
0
    if (whence == SEEK_CUR)
1301
0
        offset += d->pos;
1302
0
    else if (whence == SEEK_END)
1303
0
        offset += d->size;
1304
0
    if (offset < 0)
1305
0
        return AVERROR(EINVAL);
1306
0
    if (offset > INT_MAX)
1307
0
        return AVERROR(ERANGE);
1308
0
    d->pos = offset;
1309
0
    return 0;
1310
0
}
1311
1312
static int url_open_dyn_buf_internal(AVIOContext **s, int max_packet_size)
1313
0
{
1314
0
    struct { FFIOContext pb; DynBuffer d; } *ret;
1315
0
    DynBuffer *d;
1316
0
    unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024;
1317
1318
0
    if (sizeof(*ret) + io_buffer_size < io_buffer_size)
1319
0
        return AVERROR(ERANGE);
1320
0
    ret = av_mallocz(sizeof(*ret) + io_buffer_size);
1321
0
    if (!ret)
1322
0
        return AVERROR(ENOMEM);
1323
0
    d = &ret->d;
1324
0
    d->io_buffer_size = io_buffer_size;
1325
0
    ffio_init_context(&ret->pb, d->io_buffer, d->io_buffer_size, 1, d, NULL,
1326
0
                      max_packet_size ? dyn_packet_buf_write : dyn_buf_write,
1327
0
                      max_packet_size ? NULL : dyn_buf_seek);
1328
0
    *s = &ret->pb.pub;
1329
0
    (*s)->max_packet_size = max_packet_size;
1330
0
    return 0;
1331
0
}
1332
1333
int avio_open_dyn_buf(AVIOContext **s)
1334
0
{
1335
0
    return url_open_dyn_buf_internal(s, 0);
1336
0
}
1337
1338
int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
1339
0
{
1340
0
    if (max_packet_size <= 0)
1341
0
        return AVERROR(EINVAL);
1342
0
    return url_open_dyn_buf_internal(s, max_packet_size);
1343
0
}
1344
1345
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
1346
0
{
1347
0
    DynBuffer *d;
1348
1349
0
    if (!s) {
1350
0
        *pbuffer = NULL;
1351
0
        return 0;
1352
0
    }
1353
0
    d = s->opaque;
1354
1355
0
    if (!s->error && !d->size) {
1356
0
        *pbuffer = d->io_buffer;
1357
0
        return FFMAX(s->buf_ptr, s->buf_ptr_max) - s->buffer;
1358
0
    }
1359
1360
0
    avio_flush(s);
1361
1362
0
    *pbuffer = d->buffer;
1363
1364
0
    return d->size;
1365
0
}
1366
1367
void ffio_reset_dyn_buf(AVIOContext *s)
1368
0
{
1369
0
    DynBuffer *d = s->opaque;
1370
0
    int max_packet_size = s->max_packet_size;
1371
1372
0
    ffio_init_context(ffiocontext(s), d->io_buffer, d->io_buffer_size,
1373
0
                      1, d, NULL, s->write_packet, s->seek);
1374
0
    s->max_packet_size = max_packet_size;
1375
0
    d->pos = d->size = 0;
1376
0
}
1377
1378
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
1379
0
{
1380
0
    DynBuffer *d;
1381
0
    int size;
1382
0
    int padding = 0;
1383
1384
0
    if (!s) {
1385
0
        *pbuffer = NULL;
1386
0
        return 0;
1387
0
    }
1388
1389
    /* don't attempt to pad fixed-size packet buffers */
1390
0
    if (!s->max_packet_size) {
1391
0
        ffio_fill(s, 0, AV_INPUT_BUFFER_PADDING_SIZE);
1392
0
        padding = AV_INPUT_BUFFER_PADDING_SIZE;
1393
0
    }
1394
1395
0
    avio_flush(s);
1396
1397
0
    d = s->opaque;
1398
0
    *pbuffer = d->buffer;
1399
0
    size = d->size;
1400
1401
0
    avio_context_free(&s);
1402
1403
0
    return size - padding;
1404
0
}
1405
1406
void ffio_free_dyn_buf(AVIOContext **s)
1407
0
{
1408
0
    DynBuffer *d;
1409
1410
0
    if (!*s)
1411
0
        return;
1412
1413
0
    d = (*s)->opaque;
1414
0
    av_free(d->buffer);
1415
0
    avio_context_free(s);
1416
0
}
1417
1418
static int null_buf_write(void *opaque, const uint8_t *buf, int buf_size)
1419
0
{
1420
0
    DynBuffer *d = opaque;
1421
1422
0
    if ((unsigned)d->pos + (unsigned)buf_size > INT_MAX)
1423
0
        return AVERROR(ERANGE);
1424
0
    d->pos += buf_size;
1425
0
    if (d->pos > d->size)
1426
0
        d->size = d->pos;
1427
0
    return buf_size;
1428
0
}
1429
1430
int ffio_open_null_buf(AVIOContext **s)
1431
0
{
1432
0
    int ret = url_open_dyn_buf_internal(s, 0);
1433
0
    if (ret >= 0) {
1434
0
        AVIOContext *pb = *s;
1435
0
        pb->write_packet = null_buf_write;
1436
0
    }
1437
0
    return ret;
1438
0
}
1439
1440
int ffio_close_null_buf(AVIOContext *s)
1441
0
{
1442
0
    DynBuffer *d = s->opaque;
1443
0
    int size;
1444
1445
0
    avio_flush(s);
1446
1447
0
    size = s->error ? s->error : d->size;
1448
1449
0
    avio_context_free(&s);
1450
1451
0
    return size;
1452
0
}