X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Faviobuf.c;h=bb575ed8a36994fde2d3c8ca6591dd3d815de750;hb=cc8db760616a7ec3bd39b22ca45888c01326db13;hp=8f3e511fc470a46ee753bc4521aeb0cbcbc3553b;hpb=a0b7e289075dccf223b7f407790d8a86fc5d77e8;p=ffmpeg diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 8f3e511fc47..bb575ed8a36 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -40,28 +40,28 @@ */ #define SHORT_SEEK_THRESHOLD 4096 -static void *ffio_url_child_next(void *obj, void *prev) +static void *ff_avio_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) +static const AVClass *ff_avio_child_class_next(const AVClass *prev) { return prev ? NULL : &ffurl_context_class; } -static const AVOption ffio_url_options[] = { +static const AVOption ff_avio_options[] = { { NULL }, }; -const AVClass ffio_url_class = { +const AVClass ff_avio_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, + .option = ff_avio_options, + .child_next = ff_avio_child_next, + .child_class_next = ff_avio_child_class_next, }; static void fill_buffer(AVIOContext *s); @@ -90,7 +90,7 @@ int ffio_init_context(AVIOContext *s, s->must_flush = 0; s->eof_reached = 0; s->error = 0; - s->seekable = AVIO_SEEKABLE_NORMAL; + s->seekable = seek ? AVIO_SEEKABLE_NORMAL : 0; s->max_packet_size = 0; s->update_checksum = NULL; @@ -206,7 +206,7 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence) } offset1 = offset - pos; if (!s->must_flush && - offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) { + offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) { /* can do the seek inside the buffer */ s->buf_ptr = s->buffer + offset1; } else if ((!s->seekable || @@ -284,22 +284,28 @@ int avio_put_str(AVIOContext *s, const char *str) return len; } -int avio_put_str16le(AVIOContext *s, const char *str) -{ - const uint8_t *q = str; - int ret = 0; +#define PUT_STR16(type, write) \ + int avio_put_str16 ## type(AVIOContext * s, const char *str) \ + { \ + const uint8_t *q = str; \ + int ret = 0; \ + \ + while (*q) { \ + uint32_t ch; \ + uint16_t tmp; \ + \ + GET_UTF8(ch, *q++, break; ) \ + PUT_UTF16(ch, tmp, write(s, tmp); ret += 2; ) \ + } \ + write(s, 0); \ + ret += 2; \ + return ret; \ + } - while (*q) { - uint32_t ch; - uint16_t tmp; +PUT_STR16(le, avio_wl16) +PUT_STR16(be, avio_wb16) - GET_UTF8(ch, *q++, break;) - PUT_UTF16(ch, tmp, avio_wl16(s, tmp); ret += 2;) - } - avio_wl16(s, 0); - ret += 2; - return ret; -} +#undef PUT_STR16 int ff_get_v_length(uint64_t val) { @@ -414,6 +420,12 @@ unsigned long ff_crc04C11DB7_update(unsigned long checksum, const uint8_t *buf, return av_crc(av_crc_get_table(AV_CRC_32_IEEE), checksum, buf, len); } +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); +} + unsigned long ffio_get_checksum(AVIOContext *s) { s->checksum = s->update_checksum(s->checksum, s->checksum_ptr, @@ -490,6 +502,26 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size) return size1 - size; } +int ffio_read_size(AVIOContext *s, unsigned char *buf, int size) +{ + int ret = avio_read(s, buf, size); + if (ret != size) + return AVERROR_INVALIDDATA; + return ret; +} + +int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data) +{ + 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); + } +} + int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size) { int len; @@ -506,6 +538,13 @@ int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size) len = s->buf_end - s->buf_ptr; if (len == 0) { + /* 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; fill_buffer(s); len = s->buf_end - s->buf_ptr; } @@ -667,7 +706,9 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) return AVERROR(ENOMEM); *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, h, - ffurl_read, ffurl_write, ffurl_seek); + (int (*)(void *, uint8_t *, int)) ffurl_read, + (int (*)(void *, uint8_t *, int)) ffurl_write, + (int64_t (*)(void *, int64_t, int)) ffurl_seek); if (!*s) { av_free(buffer); return AVERROR(ENOMEM); @@ -678,7 +719,7 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause; (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek; } - (*s)->av_class = &ffio_url_class; + (*s)->av_class = &ff_avio_class; return 0; } @@ -860,9 +901,12 @@ static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size) } if (new_allocated_size > d->allocated_size) { - d->buffer = av_realloc(d->buffer, new_allocated_size); - if(d->buffer == NULL) - return AVERROR(ENOMEM); + int err; + if ((err = av_reallocp(&d->buffer, new_allocated_size)) < 0) { + d->allocated_size = 0; + d->size = 0; + return err; + } d->allocated_size = new_allocated_size; } memcpy(d->buffer + d->pos, buf, buf_size); @@ -937,22 +981,71 @@ int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size) int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer) { - DynBuffer *d = s->opaque; + DynBuffer *d; int size; - static const char padbuf[FF_INPUT_BUFFER_PADDING_SIZE] = {0}; + static const char padbuf[AV_INPUT_BUFFER_PADDING_SIZE] = {0}; int padding = 0; + if (!s) { + *pbuffer = NULL; + return 0; + } + /* don't attempt to pad fixed-size packet buffers */ if (!s->max_packet_size) { avio_write(s, padbuf, sizeof(padbuf)); - padding = FF_INPUT_BUFFER_PADDING_SIZE; + padding = AV_INPUT_BUFFER_PADDING_SIZE; } avio_flush(s); + d = s->opaque; *pbuffer = d->buffer; size = d->size; av_free(d); av_free(s); return size - padding; } + +void ffio_free_dyn_buf(AVIOContext **s) +{ + uint8_t *tmp; + if (!*s) + return; + avio_close_dyn_buf(*s, &tmp); + av_free(tmp); + *s = NULL; +} + +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; +}