return prev ? NULL : s->opaque;
}
+#if FF_API_CHILD_CLASS_NEXT
static const AVClass *ff_avio_child_class_next(const AVClass *prev)
{
return prev ? NULL : &ffurl_context_class;
}
+#endif
+
+static const AVClass *child_class_iterate(void **iter)
+{
+ const AVClass *c = *iter ? NULL : &ffurl_context_class;
+ *iter = (void*)(uintptr_t)c;
+ return c;
+}
#define OFFSET(x) offsetof(AVIOContext,x)
#define E AV_OPT_FLAG_ENCODING_PARAM
.version = LIBAVUTIL_VERSION_INT,
.option = ff_avio_options,
.child_next = ff_avio_child_next,
+#if FF_API_CHILD_CLASS_NEXT
.child_class_next = ff_avio_child_class_next,
+#endif
+ .child_class_iterate = child_class_iterate,
};
static void fill_buffer(AVIOContext *s);
{
int max_buffer_size = s->max_packet_size ?
s->max_packet_size : IO_BUFFER_SIZE;
- uint8_t *dst = s->buf_end - s->buffer + max_buffer_size < s->buffer_size ?
+ 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);
int len;
if (size < 0)
- return -1;
+ return AVERROR(EINVAL);
if (s->read_packet && s->write_flag) {
len = read_packet_wrapper(s, buf, size);
return NULL;
}
+static void update_checksum(AVIOContext *s)
+{
+ if (s->update_checksum && s->buf_ptr > s->checksum_ptr) {
+ s->checksum = s->update_checksum(s->checksum, s->checksum_ptr,
+ s->buf_ptr - s->checksum_ptr);
+ }
+}
+
int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
{
uint8_t *buffer;
int max_buffer_size = s->max_packet_size ?
s->max_packet_size : IO_BUFFER_SIZE;
- int filled = s->buf_end - s->buffer;
- ptrdiff_t checksum_ptr_offset = s->checksum_ptr ? s->checksum_ptr - s->buffer : -1;
+ ptrdiff_t filled = s->buf_end - s->buf_ptr;
+
+ if (buf_size <= s->buf_end - s->buf_ptr)
+ return 0;
- buf_size += s->buf_ptr - s->buffer + max_buffer_size;
+ buf_size += max_buffer_size - 1;
- if (buf_size < filled || s->seekable || !s->read_packet)
+ if (buf_size + s->buf_ptr - s->buffer <= s->buffer_size || s->seekable || !s->read_packet)
return 0;
av_assert0(!s->write_flag);
- buffer = av_malloc(buf_size);
- if (!buffer)
- return AVERROR(ENOMEM);
-
- memcpy(buffer, s->buffer, filled);
- 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;
- if (checksum_ptr_offset >= 0)
- s->checksum_ptr = s->buffer + checksum_ptr_offset;
+ if (buf_size <= s->buffer_size) {
+ update_checksum(s);
+ memmove(s->buffer, s->buf_ptr, filled);
+ } else {
+ buffer = av_malloc(buf_size);
+ if (!buffer)
+ return AVERROR(ENOMEM);
+ update_checksum(s);
+ memcpy(buffer, s->buf_ptr, filled);
+ av_free(s->buffer);
+ s->buffer = buffer;
+ s->buffer_size = buf_size;
+ }
+ s->buf_ptr = s->buffer;
+ s->buf_end = s->buffer + filled;
+ s->checksum_ptr = s->buffer;
return 0;
}
static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size)
{
DynBuffer *d = opaque;
- unsigned new_size, new_allocated_size;
+ unsigned new_size;
/* reallocate buffer if needed */
- new_size = d->pos + buf_size;
- new_allocated_size = d->allocated_size;
- if (new_size < d->pos || new_size > INT_MAX/2)
- return -1;
- while (new_size > new_allocated_size) {
- if (!new_allocated_size)
- new_allocated_size = new_size;
- else
+ new_size = (unsigned)d->pos + buf_size;
+ if (new_size < d->pos || new_size > INT_MAX)
+ return AVERROR(ERANGE);
+ if (new_size > d->allocated_size) {
+ unsigned new_allocated_size = d->allocated_size ? d->allocated_size
+ : new_size;
+ int err;
+ while (new_size > new_allocated_size)
new_allocated_size += new_allocated_size / 2 + 1;
- }
- if (new_allocated_size > d->allocated_size) {
- int err;
+ new_allocated_size = FFMIN(new_allocated_size, INT_MAX);
+
if ((err = av_reallocp(&d->buffer, new_allocated_size)) < 0) {
d->allocated_size = 0;
d->size = 0;
offset += d->pos;
else if (whence == SEEK_END)
offset += d->size;
- if (offset < 0 || offset > 0x7fffffffLL)
- return -1;
+ if (offset < 0)
+ return AVERROR(EINVAL);
+ if (offset > INT_MAX)
+ return AVERROR(ERANGE);
d->pos = offset;
return 0;
}
unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024;
if (sizeof(DynBuffer) + io_buffer_size < io_buffer_size)
- return -1;
+ return AVERROR(ERANGE);
d = av_mallocz(sizeof(DynBuffer) + io_buffer_size);
if (!d)
return AVERROR(ENOMEM);
int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
{
if (max_packet_size <= 0)
- return -1;
+ return AVERROR(EINVAL);
return url_open_dyn_buf_internal(s, max_packet_size);
}
{
DynBuffer *d;
- if (!s || s->error) {
+ if (!s) {
*pbuffer = NULL;
return 0;
}
d = s->opaque;
- if (!d->size) {
+ if (!s->error && !d->size) {
*pbuffer = d->io_buffer;
return FFMAX(s->buf_ptr, s->buf_ptr_max) - s->buffer;
}