diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c
index 94e39f592f..94cc98cc45 100644
--- a/libavformat/aacdec.c
+++ b/libavformat/aacdec.c
@@ -135,7 +135,7 @@ static int adts_aac_read_header(AVFormatContext *s)
 static int handle_id3(AVFormatContext *s, AVPacket *pkt)
 {
     AVDictionary *metadata = NULL;
-    AVIOContext ioctx;
+    FFIOContext pb;
     ID3v2ExtraMeta *id3v2_extra_meta;
     int ret;
 
@@ -144,8 +144,8 @@ static int handle_id3(AVFormatContext *s, AVPacket *pkt)
         return ret;
     }
 
-    ffio_init_context(&ioctx, pkt->data, pkt->size, 0, NULL, NULL, NULL, NULL);
-    ff_id3v2_read_dict(&ioctx, &metadata, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
+    ffio_init_context(&pb, pkt->data, pkt->size, 0, NULL, NULL, NULL, NULL);
+    ff_id3v2_read_dict(&pb.public, &metadata, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
     if ((ret = ff_id3v2_parse_priv_dict(&metadata, id3v2_extra_meta)) < 0)
         goto error;
 
diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c
index a8a844ce6e..953e7b515c 100644
--- a/libavformat/asfenc.c
+++ b/libavformat/asfenc.c
@@ -236,7 +236,7 @@ typedef struct ASFContext {
     int64_t packet_timestamp_end;
     unsigned int packet_nb_payloads;
     uint8_t packet_buf[PACKET_SIZE_MAX];
-    AVIOContext pb;
+    FFIOContext pb;
     /* only for reading */
     uint64_t data_offset;                ///< beginning of the first data packet
 
@@ -911,7 +911,7 @@ static void put_payload_header(AVFormatContext *s, ASFStream *stream,
                                int m_obj_offset, int payload_len, int flags)
 {
     ASFContext *asf = s->priv_data;
-    AVIOContext *pb = &asf->pb;
+    AVIOContext *const pb = &asf->pb.public;
     int val;
 
     val = stream->num;
@@ -983,7 +983,7 @@ static void put_frame(AVFormatContext *s, ASFStream *stream, AVStream *avst,
 
             put_payload_header(s, stream, timestamp + PREROLL_TIME,
                                m_obj_size, m_obj_offset, payload_len, flags);
-            avio_write(&asf->pb, buf, payload_len);
+            avio_write(&asf->pb.public, buf, payload_len);
 
             if (asf->multi_payloads_present)
                 asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS);
@@ -1125,7 +1125,7 @@ static int asf_write_trailer(AVFormatContext *s)
     int ret;
 
     /* flush the current packet */
-    if (asf->pb.buf_ptr > asf->pb.buffer)
+    if (asf->pb.public.buf_ptr > asf->pb.public.buffer)
         flush_packet(s);
 
     /* write index */
diff --git a/libavformat/av1.c b/libavformat/av1.c
index 5512c4e0f7..de384b8866 100644
--- a/libavformat/av1.c
+++ b/libavformat/av1.c
@@ -86,7 +86,7 @@ int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size)
 int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out,
                            int *size, int *offset)
 {
-    AVIOContext pb;
+    FFIOContext pb;
     uint8_t *buf;
     int len, off, ret;
 
@@ -108,7 +108,7 @@ int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out,
 
     ffio_init_context(&pb, buf, len, 1, NULL, NULL, NULL, NULL);
 
-    ret = av1_filter_obus(&pb, in, *size, NULL);
+    ret = av1_filter_obus(&pb.public, in, *size, NULL);
     av_assert1(ret == len);
 
     memset(buf + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
diff --git a/libavformat/av1dec.c b/libavformat/av1dec.c
index f6c575069e..262fa0a5a0 100644
--- a/libavformat/av1dec.c
+++ b/libavformat/av1dec.c
@@ -135,32 +135,33 @@ static int read_obu(const uint8_t *buf, int size, int64_t *obu_size, int *type)
 
 static int annexb_probe(const AVProbeData *p)
 {
-    AVIOContext pb;
+    FFIOContext ctx;
+    AVIOContext *const pb = &ctx.public;
     int64_t obu_size;
     uint32_t temporal_unit_size, frame_unit_size, obu_unit_size;
     int seq = 0;
     int ret, type, cnt = 0;
 
-    ffio_init_context(&pb, p->buf, p->buf_size, 0,
+    ffio_init_context(&ctx, p->buf, p->buf_size, 0,
                       NULL, NULL, NULL, NULL);
 
-    ret = leb(&pb, &temporal_unit_size);
+    ret = leb(pb, &temporal_unit_size);
     if (ret < 0)
         return 0;
     cnt += ret;
-    ret = leb(&pb, &frame_unit_size);
+    ret = leb(pb, &frame_unit_size);
     if (ret < 0 || ((int64_t)frame_unit_size + ret) > temporal_unit_size)
         return 0;
     cnt += ret;
-    ret = leb(&pb, &obu_unit_size);
+    ret = leb(pb, &obu_unit_size);
     if (ret < 0 || ((int64_t)obu_unit_size + ret) >= frame_unit_size)
         return 0;
     cnt += ret;
 
     frame_unit_size -= obu_unit_size + ret;
 
-    avio_skip(&pb, obu_unit_size);
-    if (pb.eof_reached || pb.error)
+    avio_skip(pb, obu_unit_size);
+    if (pb->eof_reached || pb->error)
         return 0;
 
     // Check that the first OBU is a Temporal Delimiter.
@@ -170,13 +171,13 @@ static int annexb_probe(const AVProbeData *p)
     cnt += obu_unit_size;
 
     do {
-        ret = leb(&pb, &obu_unit_size);
+        ret = leb(pb, &obu_unit_size);
         if (ret < 0 || ((int64_t)obu_unit_size + ret) > frame_unit_size)
             return 0;
         cnt += ret;
 
-        avio_skip(&pb, obu_unit_size);
-        if (pb.eof_reached || pb.error)
+        avio_skip(pb, obu_unit_size);
+        if (pb->eof_reached || pb->error)
             return 0;
 
         ret = read_obu(p->buf + cnt, FFMIN(p->buf_size - cnt, obu_unit_size), &obu_size, &type);
diff --git a/libavformat/avio.h b/libavformat/avio.h
index 0b35409787..a7b56ab667 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -148,9 +148,9 @@ enum AVIODataMarkerType {
 
 /**
  * Bytestream IO Context.
- * New fields can be added to the end with minor version bumps.
- * Removal, reordering and changes to existing fields require a major
- * version bump.
+ * New public fields can be added with minor version bumps.
+ * Removal, reordering and changes to existing public fields require
+ * a major version bump.
  * sizeof(AVIOContext) must not be used outside libav*.
  *
  * @note None of the function pointers in AVIOContext should be called
@@ -237,12 +237,14 @@ typedef struct AVIOContext {
     int64_t (*seek)(void *opaque, int64_t offset, int whence);
     int64_t pos;            /**< position in the file of the current buffer */
     int eof_reached;        /**< true if was unable to read due to error or eof */
+    int error;              /**< contains the error code or 0 if no error happened */
     int write_flag;         /**< true if open for writing */
     int max_packet_size;
+    int min_packet_size;    /**< Try to buffer at least this amount of data
+                                 before flushing it. */
     unsigned long checksum;
     unsigned char *checksum_ptr;
     unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);
-    int error;              /**< contains the error code or 0 if no error happened */
     /**
      * Pause or resume playback for network streaming protocols - e.g. MMS.
      */
@@ -259,12 +261,6 @@ typedef struct AVIOContext {
      */
     int seekable;
 
-    /**
-     * max filesize, used to limit allocations
-     * This field is internal to libavformat and access from outside is not allowed.
-     */
-    int64_t maxsize;
-
     /**
      * avio_read and avio_write should if possible be satisfied directly
      * instead of going through a buffer, and avio_seek will always
@@ -272,37 +268,6 @@ typedef struct AVIOContext {
      */
     int direct;
 
-    /**
-     * Bytes read statistic
-     * This field is internal to libavformat and access from outside is not allowed.
-     */
-    int64_t bytes_read;
-
-    /**
-     * seek statistic
-     * This field is internal to libavformat and access from outside is not allowed.
-     */
-    int seek_count;
-
-    /**
-     * writeout statistic
-     * This field is internal to libavformat and access from outside is not allowed.
-     */
-    int writeout_count;
-
-    /**
-     * Original buffer size
-     * used internally after probing and ensure seekback to reset the buffer size
-     * This field is internal to libavformat and access from outside is not allowed.
-     */
-    int orig_buffer_size;
-
-    /**
-     * Threshold to favor readahead over seek.
-     * This is current internal only, do not use from outside.
-     */
-    int short_seek_threshold;
-
     /**
      * ',' separated list of allowed protocols.
      */
@@ -325,18 +290,6 @@ typedef struct AVIOContext {
      */
     int ignore_boundary_point;
 
-    /**
-     * Internal, not meant to be used from outside of AVIOContext.
-     */
-    enum AVIODataMarkerType current_type;
-    int64_t last_time;
-
-    /**
-     * A callback that is used instead of short_seek_threshold.
-     * This is current internal only, do not use from outside.
-     */
-    int (*short_seek_get)(void *opaque);
-
     int64_t written;
 
     /**
@@ -344,11 +297,6 @@ typedef struct AVIOContext {
      * used keeping track of already written data for a later flush.
      */
     unsigned char *buf_ptr_max;
-
-    /**
-     * Try to buffer at least this amount of data before flushing it
-     */
-    int min_packet_size;
 } AVIOContext;
 
 /**
diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h
index de95b43bdb..b2356529e1 100644
--- a/libavformat/avio_internal.h
+++ b/libavformat/avio_internal.h
@@ -26,7 +26,49 @@
 
 extern const AVClass ff_avio_class;
 
-int ffio_init_context(AVIOContext *s,
+typedef struct FFIOContext {
+    AVIOContext public;
+    /**
+     * A callback that is used instead of short_seek_threshold.
+     */
+    int (*short_seek_get)(void *opaque);
+
+    /**
+     * Threshold to favor readahead over seek.
+     */
+    int short_seek_threshold;
+
+    enum AVIODataMarkerType current_type;
+    int64_t last_time;
+
+    /**
+     * max filesize, used to limit allocations
+     */
+    int64_t maxsize;
+
+    /**
+     * Bytes read statistic
+     */
+    int64_t bytes_read;
+
+    /**
+     * seek statistic
+     */
+    int seek_count;
+
+    /**
+     * writeout statistic
+     */
+    int writeout_count;
+
+    /**
+     * Original buffer size
+     * used after probing to ensure seekback and to reset the buffer size
+     */
+    int orig_buffer_size;
+} FFIOContext;
+
+void ffio_init_context(FFIOContext *s,
                   unsigned char *buffer,
                   int buffer_size,
                   int write_flag,
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 1f0819b328..f04e15f4f1 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -77,7 +77,7 @@ static int url_resetbuf(AVIOContext *s, int flags);
 /** @warning must be called before any I/O */
 static int set_buf_size(AVIOContext *s, int buf_size);
 
-int ffio_init_context(AVIOContext *s,
+void ffio_init_context(FFIOContext *ctx,
                   unsigned char *buffer,
                   int buffer_size,
                   int write_flag,
@@ -86,10 +86,12 @@ int ffio_init_context(AVIOContext *s,
                   int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
                   int64_t (*seek)(void *opaque, int64_t offset, int whence))
 {
-    memset(s, 0, sizeof(AVIOContext));
+    AVIOContext *const s = &ctx->public;
+
+    memset(ctx, 0, sizeof(*ctx));
 
     s->buffer      = buffer;
-    s->orig_buffer_size =
+    ctx->orig_buffer_size =
     s->buffer_size = buffer_size;
     s->buf_ptr     = buffer;
     s->buf_ptr_max = buffer;
@@ -108,7 +110,7 @@ int ffio_init_context(AVIOContext *s,
     s->min_packet_size = 0;
     s->max_packet_size = 0;
     s->update_checksum = NULL;
-    s->short_seek_threshold = SHORT_SEEK_THRESHOLD;
+    ctx->short_seek_threshold = SHORT_SEEK_THRESHOLD;
 
     if (!read_packet && !write_flag) {
         s->pos     = buffer_size;
@@ -119,12 +121,10 @@ int ffio_init_context(AVIOContext *s,
 
     s->write_data_type       = NULL;
     s->ignore_boundary_point = 0;
-    s->current_type          = AVIO_DATA_MARKER_UNKNOWN;
-    s->last_time             = AV_NOPTS_VALUE;
-    s->short_seek_get        = NULL;
+    ctx->current_type        = AVIO_DATA_MARKER_UNKNOWN;
+    ctx->last_time           = AV_NOPTS_VALUE;
+    ctx->short_seek_get      = NULL;
     s->written               = 0;
-
-    return 0;
 }
 
 AVIOContext *avio_alloc_context(
@@ -136,12 +136,12 @@ AVIOContext *avio_alloc_context(
                   int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
                   int64_t (*seek)(void *opaque, int64_t offset, int whence))
 {
-    AVIOContext *s = av_malloc(sizeof(AVIOContext));
+    FFIOContext *s = av_malloc(sizeof(*s));
     if (!s)
         return NULL;
     ffio_init_context(s, buffer, buffer_size, write_flag, opaque,
                   read_packet, write_packet, seek);
-    return s;
+    return &s->public;
 }
 
 void avio_context_free(AVIOContext **ps)
@@ -151,13 +151,14 @@ void avio_context_free(AVIOContext **ps)
 
 static void writeout(AVIOContext *s, const uint8_t *data, int len)
 {
+    FFIOContext *const ctx = (FFIOContext*)s;
     if (!s->error) {
         int ret = 0;
         if (s->write_data_type)
             ret = s->write_data_type(s->opaque, (uint8_t *)data,
                                      len,
-                                     s->current_type,
-                                     s->last_time);
+                                     ctx->current_type,
+                                     ctx->last_time);
         else if (s->write_packet)
             ret = s->write_packet(s->opaque, (uint8_t *)data, len);
         if (ret < 0) {
@@ -167,12 +168,12 @@ static void writeout(AVIOContext *s, const uint8_t *data, int len)
                 s->written = s->pos + len;
         }
     }
-    if (s->current_type == AVIO_DATA_MARKER_SYNC_POINT ||
-        s->current_type == AVIO_DATA_MARKER_BOUNDARY_POINT) {
-        s->current_type = AVIO_DATA_MARKER_UNKNOWN;
+    if (ctx->current_type == AVIO_DATA_MARKER_SYNC_POINT ||
+        ctx->current_type == AVIO_DATA_MARKER_BOUNDARY_POINT) {
+        ctx->current_type = AVIO_DATA_MARKER_UNKNOWN;
     }
-    s->last_time = AV_NOPTS_VALUE;
-    s->writeout_count ++;
+    ctx->last_time = AV_NOPTS_VALUE;
+    ctx->writeout_count++;
     s->pos += len;
 }
 
@@ -244,6 +245,7 @@ void avio_flush(AVIOContext *s)
 
 int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
 {
+    FFIOContext *const ctx = (FFIOContext*)s;
     int64_t offset1;
     int64_t pos;
     int force = whence & AVSEEK_FORCE;
@@ -275,9 +277,9 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
     if (offset < 0)
         return AVERROR(EINVAL);
 
-    short_seek = s->short_seek_threshold;
-    if (s->short_seek_get) {
-        int tmp = s->short_seek_get(s->opaque);
+    short_seek = ctx->short_seek_threshold;
+    if (ctx->short_seek_get) {
+        int tmp = ctx->short_seek_get(s->opaque);
         short_seek = FFMAX(tmp, short_seek);
     }
 
@@ -318,7 +320,7 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
             return AVERROR(EPIPE);
         if ((res = s->seek(s->opaque, offset, SEEK_SET)) < 0)
             return res;
-        s->seek_count ++;
+        ctx->seek_count++;
         if (!s->write_flag)
             s->buf_end = s->buffer;
         s->buf_ptr = s->buf_ptr_max = s->buffer;
@@ -472,6 +474,7 @@ void avio_wb24(AVIOContext *s, unsigned int val)
 
 void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type)
 {
+    FFIOContext *const ctx = (FFIOContext*)s;
     if (type == AVIO_DATA_MARKER_FLUSH_POINT) {
         if (s->buf_ptr - s->buffer >= s->min_packet_size)
             avio_flush(s);
@@ -485,8 +488,8 @@ void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType typ
     // Avoid unnecessary flushes if we are already in non-header/trailer
     // data and setting the type to unknown
     if (type == AVIO_DATA_MARKER_UNKNOWN &&
-        (s->current_type != AVIO_DATA_MARKER_HEADER &&
-         s->current_type != AVIO_DATA_MARKER_TRAILER))
+        (ctx->current_type != AVIO_DATA_MARKER_HEADER &&
+         ctx->current_type != AVIO_DATA_MARKER_TRAILER))
         return;
 
     switch (type) {
@@ -494,7 +497,7 @@ void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType typ
     case AVIO_DATA_MARKER_TRAILER:
         // For header/trailer, ignore a new marker of the same type;
         // consecutive header/trailer markers can be merged.
-        if (type == s->current_type)
+        if (type == ctx->current_type)
             return;
         break;
     }
@@ -502,8 +505,8 @@ void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType typ
     // If we've reached here, we have a new, noteworthy marker.
     // Flush the previous data and mark the start of the new data.
     avio_flush(s);
-    s->current_type = type;
-    s->last_time = time;
+    ctx->current_type = type;
+    ctx->last_time = time;
 }
 
 static int read_packet_wrapper(AVIOContext *s, uint8_t *buf, int size)
@@ -521,6 +524,7 @@ static int read_packet_wrapper(AVIOContext *s, uint8_t *buf, int size)
 
 static void fill_buffer(AVIOContext *s)
 {
+    FFIOContext *const ctx = (FFIOContext *)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 ?
@@ -543,15 +547,16 @@ static void fill_buffer(AVIOContext *s)
     }
 
     /* make buffer smaller in case it ended up large after probing */
-    if (s->read_packet && s->orig_buffer_size && s->buffer_size > s->orig_buffer_size && len >= s->orig_buffer_size) {
+    if (s->read_packet && ctx->orig_buffer_size &&
+        s->buffer_size > ctx->orig_buffer_size  && len >= ctx->orig_buffer_size) {
         if (dst == s->buffer && s->buf_ptr != dst) {
-            int ret = set_buf_size(s, s->orig_buffer_size);
+            int ret = set_buf_size(s, ctx->orig_buffer_size);
             if (ret < 0)
                 av_log(s, AV_LOG_WARNING, "Failed to decrease buffer size\n");
 
             s->checksum_ptr = dst = s->buffer;
         }
-        len = s->orig_buffer_size;
+        len = ctx->orig_buffer_size;
     }
 
     len = read_packet_wrapper(s, dst, len);
@@ -566,7 +571,7 @@ static void fill_buffer(AVIOContext *s)
         s->pos += len;
         s->buf_ptr = dst;
         s->buf_end = dst + len;
-        s->bytes_read += len;
+        ((FFIOContext*)s)->bytes_read += len;
     }
 }
 
@@ -639,7 +644,7 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size)
                     break;
                 } else {
                     s->pos += len;
-                    s->bytes_read += len;
+                    ((FFIOContext*)s)->bytes_read += len;
                     size -= len;
                     buf += len;
                     // reset the buffer
@@ -955,7 +960,7 @@ int ffio_fdopen(AVIOContext **s, URLContext *h)
         if (h->prot->url_read_seek)
             (*s)->seekable |= AVIO_SEEKABLE_TIME;
     }
-    (*s)->short_seek_get = (int (*)(void *))ffurl_get_short_seek;
+    ((FFIOContext*)(*s))->short_seek_get = (int (*)(void *))ffurl_get_short_seek;
     (*s)->av_class = &ff_avio_class;
     return 0;
 fail:
@@ -1019,20 +1024,21 @@ int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
 
 int ffio_limit(AVIOContext *s, int size)
 {
-    if (s->maxsize>= 0) {
+    FFIOContext *const ctx = (FFIOContext*)s;
+    if (ctx->maxsize >= 0) {
         int64_t pos = avio_tell(s);
-        int64_t remaining = s->maxsize - pos;
+        int64_t remaining = ctx->maxsize - pos;
         if (remaining < size) {
             int64_t newsize = avio_size(s);
-            if (!s->maxsize || s->maxsize<newsize)
-                s->maxsize = newsize - !newsize;
-            if (pos > s->maxsize && s->maxsize >= 0)
-                s->maxsize = AVERROR(EIO);
-            if (s->maxsize >= 0)
-                remaining = s->maxsize - pos;
+            if (!ctx->maxsize || ctx->maxsize < newsize)
+                ctx->maxsize = newsize - !newsize;
+            if (pos > ctx->maxsize && ctx->maxsize >= 0)
+                ctx->maxsize = AVERROR(EIO);
+            if (ctx->maxsize >= 0)
+                remaining = ctx->maxsize - pos;
         }
 
-        if (s->maxsize >= 0 && remaining < size && size > 1) {
+        if (ctx->maxsize >= 0 && remaining < size && size > 1) {
             av_log(NULL, remaining ? AV_LOG_ERROR : AV_LOG_DEBUG,
                    "Truncating packet of size %d to %"PRId64"\n",
                    size, remaining + !remaining);
@@ -1051,7 +1057,7 @@ static int set_buf_size(AVIOContext *s, int buf_size)
 
     av_free(s->buffer);
     s->buffer = buffer;
-    s->orig_buffer_size =
+    ((FFIOContext*)s)->orig_buffer_size =
     s->buffer_size = buf_size;
     s->buf_ptr = s->buf_ptr_max = buffer;
     url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);
@@ -1078,7 +1084,7 @@ int ffio_realloc_buf(AVIOContext *s, int buf_size)
         memcpy(buffer, s->write_flag ? s->buffer : s->buf_ptr, data_size);
     av_free(s->buffer);
     s->buffer = buffer;
-    s->orig_buffer_size = buf_size;
+    ((FFIOContext*)s)->orig_buffer_size = buf_size;
     s->buffer_size = buf_size;
     s->buf_ptr = s->write_flag ? (s->buffer + data_size) : s->buffer;
     if (s->write_flag)
@@ -1180,6 +1186,7 @@ int avio_open2(AVIOContext **s, const char *filename, int flags,
 
 int avio_close(AVIOContext *s)
 {
+    FFIOContext *const ctx = (FFIOContext*)s;
     URLContext *h;
 
     if (!s)
@@ -1191,9 +1198,11 @@ int avio_close(AVIOContext *s)
 
     av_freep(&s->buffer);
     if (s->write_flag)
-        av_log(s, AV_LOG_VERBOSE, "Statistics: %d seeks, %d writeouts\n", s->seek_count, s->writeout_count);
+        av_log(s, AV_LOG_VERBOSE, "Statistics: %d seeks, %d writeouts\n",
+               ctx->seek_count, ctx->writeout_count);
     else
-        av_log(s, AV_LOG_VERBOSE, "Statistics: %"PRId64" bytes read, %d seeks\n", s->bytes_read, s->seek_count);
+        av_log(s, AV_LOG_VERBOSE, "Statistics: %"PRId64" bytes read, %d seeks\n",
+               ctx->bytes_read, ctx->seek_count);
     av_opt_free(s);
 
     avio_context_free(&s);
@@ -1427,8 +1436,8 @@ void ffio_reset_dyn_buf(AVIOContext *s)
     DynBuffer *d = s->opaque;
     int max_packet_size = s->max_packet_size;
 
-    ffio_init_context(s, d->io_buffer, d->io_buffer_size, 1, d, NULL,
-                      s->write_packet, s->seek);
+    ffio_init_context((FFIOContext*)s, d->io_buffer, d->io_buffer_size,
+                      1, d, NULL, s->write_packet, s->seek);
     s->max_packet_size = max_packet_size;
     d->pos = d->size = 0;
 }
diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
index 6105ec46d9..0ee2a963d1 100644
--- a/libavformat/dashdec.c
+++ b/libavformat/dashdec.c
@@ -77,7 +77,7 @@ struct timeline {
  */
 struct representation {
     char *url_template;
-    AVIOContext pb;
+    FFIOContext pb;
     AVIOContext *input;
     AVFormatContext *parent;
     AVFormatContext *ctx;
@@ -353,7 +353,7 @@ static void free_representation(struct representation *pls)
     free_fragment(&pls->cur_seg);
     free_fragment(&pls->init_section);
     av_freep(&pls->init_sec_buf);
-    av_freep(&pls->pb.buffer);
+    av_freep(&pls->pb.public.buffer);
     ff_format_io_close(pls->parent, &pls->input);
     if (pls->ctx) {
         pls->ctx->pb = NULL;
@@ -1871,8 +1871,8 @@ static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url,
 static void close_demux_for_component(struct representation *pls)
 {
     /* note: the internal buffer could have changed */
-    av_freep(&pls->pb.buffer);
-    memset(&pls->pb, 0x00, sizeof(AVIOContext));
+    av_freep(&pls->pb.public.buffer);
+    memset(&pls->pb, 0x00, sizeof(pls->pb));
     pls->ctx->pb = NULL;
     avformat_close_input(&pls->ctx);
 }
@@ -1908,7 +1908,7 @@ static int reopen_demux_for_component(AVFormatContext *s, struct representation
     }
     ffio_init_context(&pls->pb, avio_ctx_buffer, INITIAL_BUFFER_SIZE, 0,
                       pls, read_data, NULL, c->is_live ? NULL : seek_data);
-    pls->pb.seekable = 0;
+    pls->pb.public.seekable = 0;
 
     if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0)
         goto fail;
@@ -1917,7 +1917,7 @@ static int reopen_demux_for_component(AVFormatContext *s, struct representation
     pls->ctx->probesize = s->probesize > 0 ? s->probesize : 1024 * 4;
     pls->ctx->max_analyze_duration = s->max_analyze_duration > 0 ? s->max_analyze_duration : 4 * AV_TIME_BASE;
     pls->ctx->interrupt_callback = s->interrupt_callback;
-    ret = av_probe_input_buffer(&pls->pb, &in_fmt, "", NULL, 0, 0);
+    ret = av_probe_input_buffer(&pls->pb.public, &in_fmt, "", NULL, 0, 0);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Error when loading first fragment of playlist\n");
         avformat_free_context(pls->ctx);
@@ -1925,7 +1925,7 @@ static int reopen_demux_for_component(AVFormatContext *s, struct representation
         goto fail;
     }
 
-    pls->ctx->pb = &pls->pb;
+    pls->ctx->pb = &pls->pb.public;
     pls->ctx->io_open  = nested_io_open;
 
     // provide additional information from mpd if available
diff --git a/libavformat/hls.c b/libavformat/hls.c
index 3c1b80f60c..56b440890b 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -92,7 +92,7 @@ enum PlaylistType {
  */
 struct playlist {
     char url[MAX_URL_SIZE];
-    AVIOContext pb;
+    FFIOContext pb;
     uint8_t* read_buffer;
     AVIOContext *input;
     int input_read_done;
@@ -258,7 +258,7 @@ static void free_playlist_list(HLSContext *c)
         ff_id3v2_free_extra_meta(&pls->id3_deferred_extra);
         av_freep(&pls->init_sec_buf);
         av_packet_free(&pls->pkt);
-        av_freep(&pls->pb.buffer);
+        av_freep(&pls->pb.public.buffer);
         ff_format_io_close(c->ctx, &pls->input);
         pls->input_read_done = 0;
         ff_format_io_close(c->ctx, &pls->input_next);
@@ -1222,9 +1222,9 @@ static void intercept_id3(struct playlist *pls, uint8_t *buf,
 
     if (pls->id3_buf) {
         /* Now parse all the ID3 tags */
-        AVIOContext id3ioctx;
+        FFIOContext id3ioctx;
         ffio_init_context(&id3ioctx, pls->id3_buf, id3_buf_pos, 0, NULL, NULL, NULL, NULL);
-        handle_id3(&id3ioctx, pls);
+        handle_id3(&id3ioctx.public, pls);
     }
 
     if (pls->is_id3_timestamped == -1)
@@ -1995,7 +1995,7 @@ static int hls_read_header(AVFormatContext *s)
         pls->ctx->max_analyze_duration = s->max_analyze_duration > 0 ? s->max_analyze_duration : 4 * AV_TIME_BASE;
         pls->ctx->interrupt_callback = s->interrupt_callback;
         url = av_strdup(pls->segments[0]->url);
-        ret = av_probe_input_buffer(&pls->pb, &in_fmt, url, NULL, 0, 0);
+        ret = av_probe_input_buffer(&pls->pb.public, &in_fmt, url, NULL, 0, 0);
         if (ret < 0) {
             /* Free the ctx - it isn't initialized properly at this point,
              * so avformat_close_input shouldn't be called. If
@@ -2008,7 +2008,7 @@ static int hls_read_header(AVFormatContext *s)
             return ret;
         }
         av_free(url);
-        pls->ctx->pb       = &pls->pb;
+        pls->ctx->pb       = &pls->pb.public;
         pls->ctx->io_open  = nested_io_open;
         pls->ctx->flags   |= s->flags & ~AVFMT_FLAG_CUSTOM_IO;
 
@@ -2087,7 +2087,7 @@ static int recheck_discard_flags(AVFormatContext *s, int first)
             pls->needed = 1;
             changed = 1;
             pls->cur_seq_no = select_cur_seq_no(c, pls);
-            pls->pb.eof_reached = 0;
+            pls->pb.public.eof_reached = 0;
             if (c->cur_timestamp != AV_NOPTS_VALUE) {
                 /* catch up */
                 pls->seek_timestamp = c->cur_timestamp;
@@ -2168,7 +2168,7 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt)
                 AVRational tb;
                 ret = av_read_frame(pls->ctx, pls->pkt);
                 if (ret < 0) {
-                    if (!avio_feof(&pls->pb) && ret != AVERROR_EOF)
+                    if (!avio_feof(&pls->pb.public) && ret != AVERROR_EOF)
                         return ret;
                     break;
                 } else {
@@ -2336,16 +2336,17 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
     for (i = 0; i < c->n_playlists; i++) {
         /* Reset reading */
         struct playlist *pls = c->playlists[i];
+        AVIOContext *const pb = &pls->pb.public;
         ff_format_io_close(pls->parent, &pls->input);
         pls->input_read_done = 0;
         ff_format_io_close(pls->parent, &pls->input_next);
         pls->input_next_requested = 0;
         av_packet_unref(pls->pkt);
-        pls->pb.eof_reached = 0;
+        pb->eof_reached = 0;
         /* Clear any buffered data */
-        pls->pb.buf_end = pls->pb.buf_ptr = pls->pb.buffer;
+        pb->buf_end = pb->buf_ptr = pb->buffer;
         /* Reset the pos, to let the mpegts demuxer know we've seeked. */
-        pls->pb.pos = 0;
+        pb->pos = 0;
         /* Flush the packet queue of the subdemuxer. */
         ff_read_frame_flush(pls->ctx);
 
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 96226193c1..0cc2ca32ff 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -827,7 +827,7 @@ static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata,
     int64_t next, end = avio_tell(pb);
     int taghdrlen;
     const char *reason = NULL;
-    AVIOContext pb_local;
+    FFIOContext pb_local;
     AVIOContext *pbx;
     unsigned char *buffer = NULL;
     int buffer_size       = 0;
@@ -999,7 +999,7 @@ static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata,
                 ffio_init_context(&pb_local, buffer, b - buffer, 0, NULL, NULL, NULL,
                                   NULL);
                 tlen = b - buffer;
-                pbx  = &pb_local; // read from sync buffer
+                pbx  = &pb_local.public; // read from sync buffer
             }
 
 #if CONFIG_ZLIB
@@ -1035,7 +1035,7 @@ static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata,
                     }
                     ffio_init_context(&pb_local, uncompressed_buffer, dlen, 0, NULL, NULL, NULL, NULL);
                     tlen = dlen;
-                    pbx = &pb_local; // read from sync buffer
+                    pbx = &pb_local.public; // read from sync buffer
                 }
 #endif
             if (tag[0] == 'T')
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 1977240cf9..6473d97796 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -2350,7 +2350,7 @@ static int matroska_parse_tracks(AVFormatContext *s)
         int extradata_size = 0;
         int extradata_offset = 0;
         uint32_t fourcc = 0;
-        AVIOContext b;
+        FFIOContext b;
         char* key_id_base64 = NULL;
         int bit_depth = -1;
 
@@ -2511,7 +2511,8 @@ static int matroska_parse_tracks(AVFormatContext *s)
             ffio_init_context(&b, track->codec_priv.data,
                               track->codec_priv.size,
                               0, NULL, NULL, NULL, NULL);
-            ret = ff_get_wav_header(s, &b, st->codecpar, track->codec_priv.size, 0);
+            ret = ff_get_wav_header(s, &b.public, st->codecpar,
+                                    track->codec_priv.size, 0);
             if (ret < 0)
                 return ret;
             codec_id         = st->codecpar->codec_id;
@@ -2557,7 +2558,7 @@ static int matroska_parse_tracks(AVFormatContext *s)
                 ffio_init_context(&b, track->codec_priv.data,
                                   track->codec_priv.size,
                                   0, NULL, NULL, NULL, NULL);
-                if (ff_get_qtpalette(codec_id, &b, track->palette)) {
+                if (ff_get_qtpalette(codec_id, &b.public, track->palette)) {
                     bit_depth &= 0x1F;
                     track->has_palette = 1;
                 }
@@ -3587,7 +3588,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf
 {
     uint64_t timecode = AV_NOPTS_VALUE;
     MatroskaTrack *track;
-    AVIOContext pb;
+    FFIOContext pb;
     int res = 0;
     AVStream *st;
     int16_t block_time;
@@ -3598,7 +3599,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf
 
     ffio_init_context(&pb, data, size, 0, NULL, NULL, NULL, NULL);
 
-    if ((n = ebml_read_num(matroska, &pb, 8, &num, 1)) < 0)
+    if ((n = ebml_read_num(matroska, &pb.public, 8, &num, 1)) < 0)
         return n;
     data += n;
     size -= n;
@@ -3656,7 +3657,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf
     }
 
     res = matroska_parse_laces(matroska, &data, size, (flags & 0x06) >> 1,
-                               &pb, lace_size, &laces);
+                               &pb.public, lace_size, &laces);
     if (res < 0) {
         av_log(matroska->ctx, AV_LOG_ERROR, "Error parsing frame sizes.\n");
         return res;
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 899a3388cd..642cebe207 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -839,11 +839,12 @@ static void mkv_write_video_color(AVIOContext *pb, const AVStream *st,
      * a master element with two bytes ID and one byte length field
      * plus another byte to stay clear of the end. */
     uint8_t colour[(2 + 1 + 8) * 18 + (2 + 1) + 1];
-    AVIOContext buf, *dyn_cp = &buf;
+    FFIOContext buf;
+    AVIOContext *const dyn_cp = &buf.public;
     int colorinfo_size;
     const void *side_data;
 
-    ffio_init_context(dyn_cp, colour, sizeof(colour), 1, NULL, NULL, NULL, NULL);
+    ffio_init_context(&buf, colour, sizeof(colour), 1, NULL, NULL, NULL, NULL);
 
     if (par->color_trc != AVCOL_TRC_UNSPECIFIED &&
         par->color_trc < AVCOL_TRC_NB) {
diff --git a/libavformat/mmst.c b/libavformat/mmst.c
index fa6e86ac26..520512490d 100644
--- a/libavformat/mmst.c
+++ b/libavformat/mmst.c
@@ -154,13 +154,13 @@ static int send_command_packet(MMSTContext *mmst)
 
 static int mms_put_utf16(MMSContext *mms, const uint8_t *src)
 {
-    AVIOContext bic;
+    FFIOContext bic;
     int size = mms->write_out_ptr - mms->out_buffer;
     int len;
     ffio_init_context(&bic, mms->write_out_ptr,
             sizeof(mms->out_buffer) - size, 1, NULL, NULL, NULL, NULL);
 
-    len = avio_put_str16le(&bic, src);
+    len = avio_put_str16le(&bic.public, src);
     if (len < 0)
         return len;
     mms->write_out_ptr += len;
diff --git a/libavformat/mov.c b/libavformat/mov.c
index e95d3d2a90..021102f7e4 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -5177,7 +5177,7 @@ static int mov_read_wide(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
 #if CONFIG_ZLIB
-    AVIOContext ctx;
+    FFIOContext ctx;
     uint8_t *cmov_data;
     uint8_t *moov_data; /* uncompressed data */
     long cmov_len, moov_len;
@@ -5211,12 +5211,11 @@ static int mov_read_cmov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     ret = AVERROR_INVALIDDATA;
     if (uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK)
         goto free_and_return;
-    if (ffio_init_context(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0)
-        goto free_and_return;
-    ctx.seekable = AVIO_SEEKABLE_NORMAL;
+    ffio_init_context(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL);
+    ctx.public.seekable = AVIO_SEEKABLE_NORMAL;
     atom.type = MKTAG('m','o','o','v');
     atom.size = moov_len;
-    ret = mov_read_default(c, &ctx, atom);
+    ret = mov_read_default(c, &ctx.public, atom);
 free_and_return:
     av_free(moov_data);
     av_free(cmov_data);
diff --git a/libavformat/mp3dec.c b/libavformat/mp3dec.c
index 0402700445..97b51d0f6a 100644
--- a/libavformat/mp3dec.c
+++ b/libavformat/mp3dec.c
@@ -380,7 +380,7 @@ static int mp3_read_header(AVFormatContext *s)
     // lcm of all mp3 sample rates
     avpriv_set_pts_info(st, 64, 1, 14112000);
 
-    s->pb->maxsize = -1;
+    ((FFIOContext*)s->pb)->maxsize = -1;
     off = avio_tell(s->pb);
 
     if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX))
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index a02965bacf..27b127f7ba 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -1427,7 +1427,7 @@ static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid)
 #define MAX_LEVEL 4
 typedef struct MP4DescrParseContext {
     AVFormatContext *s;
-    AVIOContext pb;
+    FFIOContext pb;
     Mp4Descr *descr;
     Mp4Descr *active_descr;
     int descr_count;
@@ -1440,13 +1440,11 @@ static int init_MP4DescrParseContext(MP4DescrParseContext *d, AVFormatContext *s
                                      const uint8_t *buf, unsigned size,
                                      Mp4Descr *descr, int max_descr_count)
 {
-    int ret;
     if (size > (1 << 30))
         return AVERROR_INVALIDDATA;
 
-    if ((ret = ffio_init_context(&d->pb, (unsigned char *)buf, size, 0,
-                                 NULL, NULL, NULL, NULL)) < 0)
-        return ret;
+    ffio_init_context(&d->pb, (unsigned char *)buf, size,
+                      0, NULL, NULL, NULL, NULL);
 
     d->s               = s;
     d->level           = 0;
@@ -1474,20 +1472,21 @@ static int parse_mp4_descr_arr(MP4DescrParseContext *d, int64_t off, int len)
         int ret = parse_mp4_descr(d, off, len, 0);
         if (ret < 0)
             return ret;
-        update_offsets(&d->pb, &off, &len);
+        update_offsets(&d->pb.public, &off, &len);
     }
     return 0;
 }
 
 static int parse_MP4IODescrTag(MP4DescrParseContext *d, int64_t off, int len)
 {
-    avio_rb16(&d->pb); // ID
-    avio_r8(&d->pb);
-    avio_r8(&d->pb);
-    avio_r8(&d->pb);
-    avio_r8(&d->pb);
-    avio_r8(&d->pb);
-    update_offsets(&d->pb, &off, &len);
+    AVIOContext *const pb = &d->pb.public;
+    avio_rb16(pb); // ID
+    avio_r8(pb);
+    avio_r8(pb);
+    avio_r8(pb);
+    avio_r8(pb);
+    avio_r8(pb);
+    update_offsets(pb, &off, &len);
     return parse_mp4_descr_arr(d, off, len);
 }
 
@@ -1496,9 +1495,9 @@ static int parse_MP4ODescrTag(MP4DescrParseContext *d, int64_t off, int len)
     int id_flags;
     if (len < 2)
         return 0;
-    id_flags = avio_rb16(&d->pb);
+    id_flags = avio_rb16(&d->pb.public);
     if (!(id_flags & 0x0020)) { // URL_Flag
-        update_offsets(&d->pb, &off, &len);
+        update_offsets(&d->pb.public, &off, &len);
         return parse_mp4_descr_arr(d, off, len); // ES_Descriptor[]
     } else {
         return 0;
@@ -1507,19 +1506,20 @@ static int parse_MP4ODescrTag(MP4DescrParseContext *d, int64_t off, int len)
 
 static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len)
 {
+    AVIOContext *const pb = &d->pb.public;
     int es_id = 0;
     int ret   = 0;
 
     if (d->descr_count >= d->max_descr_count)
         return AVERROR_INVALIDDATA;
-    ff_mp4_parse_es_descr(&d->pb, &es_id);
+    ff_mp4_parse_es_descr(pb, &es_id);
     d->active_descr = d->descr + (d->descr_count++);
 
     d->active_descr->es_id = es_id;
-    update_offsets(&d->pb, &off, &len);
+    update_offsets(pb, &off, &len);
     if ((ret = parse_mp4_descr(d, off, len, MP4DecConfigDescrTag)) < 0)
         return ret;
-    update_offsets(&d->pb, &off, &len);
+    update_offsets(pb, &off, &len);
     if (len > 0)
         ret = parse_mp4_descr(d, off, len, MP4SLDescrTag);
     d->active_descr = NULL;
@@ -1536,42 +1536,43 @@ static int parse_MP4DecConfigDescrTag(MP4DescrParseContext *d, int64_t off,
     if (!descr->dec_config_descr)
         return AVERROR(ENOMEM);
     descr->dec_config_descr_len = len;
-    avio_read(&d->pb, descr->dec_config_descr, len);
+    avio_read(&d->pb.public, descr->dec_config_descr, len);
     return 0;
 }
 
 static int parse_MP4SLDescrTag(MP4DescrParseContext *d, int64_t off, int len)
 {
     Mp4Descr *descr = d->active_descr;
+    AVIOContext *const pb = &d->pb.public;
     int predefined;
     if (!descr)
         return AVERROR_INVALIDDATA;
 
 #define R8_CHECK_CLIP_MAX(dst, maxv) do {                       \
-    descr->sl.dst = avio_r8(&d->pb);                            \
+    descr->sl.dst = avio_r8(pb);                                \
     if (descr->sl.dst > maxv) {                                 \
         descr->sl.dst = maxv;                                   \
         return AVERROR_INVALIDDATA;                             \
     }                                                           \
 } while (0)
 
-    predefined = avio_r8(&d->pb);
+    predefined = avio_r8(pb);
     if (!predefined) {
         int lengths;
-        int flags = avio_r8(&d->pb);
+        int flags = avio_r8(pb);
         descr->sl.use_au_start    = !!(flags & 0x80);
         descr->sl.use_au_end      = !!(flags & 0x40);
         descr->sl.use_rand_acc_pt = !!(flags & 0x20);
         descr->sl.use_padding     = !!(flags & 0x08);
         descr->sl.use_timestamps  = !!(flags & 0x04);
         descr->sl.use_idle        = !!(flags & 0x02);
-        descr->sl.timestamp_res   = avio_rb32(&d->pb);
-        avio_rb32(&d->pb);
+        descr->sl.timestamp_res   = avio_rb32(pb);
+        avio_rb32(pb);
         R8_CHECK_CLIP_MAX(timestamp_len, 63);
         R8_CHECK_CLIP_MAX(ocr_len,       63);
         R8_CHECK_CLIP_MAX(au_len,        31);
-        descr->sl.inst_bitrate_len   = avio_r8(&d->pb);
-        lengths                      = avio_rb16(&d->pb);
+        descr->sl.inst_bitrate_len   = avio_r8(pb);
+        lengths                      = avio_rb16(pb);
         descr->sl.degr_prior_len     = lengths >> 12;
         descr->sl.au_seq_num_len     = (lengths >> 7) & 0x1f;
         descr->sl.packet_seq_num_len = (lengths >> 2) & 0x1f;
@@ -1586,10 +1587,11 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
                            int target_tag)
 {
     int tag;
-    int len1 = ff_mp4_read_descr(d->s, &d->pb, &tag);
+    AVIOContext *const pb = &d->pb.public;
+    int len1 = ff_mp4_read_descr(d->s, pb, &tag);
     int ret = 0;
 
-    update_offsets(&d->pb, &off, &len);
+    update_offsets(pb, &off, &len);
     if (len < 0 || len1 > len || len1 <= 0) {
         av_log(d->s, AV_LOG_ERROR,
                "Tag %x length violation new length %d bytes remaining %d\n",
@@ -1631,7 +1633,7 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
 
 done:
     d->level--;
-    avio_seek(&d->pb, off + len1, SEEK_SET);
+    avio_seek(pb, off + len1, SEEK_SET);
     return ret;
 }
 
@@ -1645,7 +1647,7 @@ static int mp4_read_iods(AVFormatContext *s, const uint8_t *buf, unsigned size,
     if (ret < 0)
         return ret;
 
-    ret = parse_mp4_descr(&d, avio_tell(&d.pb), size, MP4IODescrTag);
+    ret = parse_mp4_descr(&d, avio_tell(&d.pb.public), size, MP4IODescrTag);
 
     *descr_count = d.descr_count;
     return ret;
@@ -1661,7 +1663,7 @@ static int mp4_read_od(AVFormatContext *s, const uint8_t *buf, unsigned size,
     if (ret < 0)
         return ret;
 
-    ret = parse_mp4_descr_arr(&d, avio_tell(&d.pb), size);
+    ret = parse_mp4_descr_arr(&d, avio_tell(&d.pb.public), size);
 
     *descr_count = d.descr_count;
     return ret;
@@ -1674,7 +1676,6 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section,
     MpegTSSectionFilter *tssf = &filter->u.section_filter;
     SectionHeader h;
     const uint8_t *p, *p_end;
-    AVIOContext pb;
     int mp4_descr_count = 0;
     Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = { { 0 } };
     int i, pid;
@@ -1698,6 +1699,7 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section,
         for (i = 0; i < mp4_descr_count; i++) {
             PESContext *pes;
             AVStream *st;
+            FFIOContext pb;
             if (ts->pids[pid]->es_id != mp4_descr[i].es_id)
                 continue;
             if (ts->pids[pid]->type != MPEGTS_PES) {
@@ -1714,7 +1716,7 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section,
             ffio_init_context(&pb, mp4_descr[i].dec_config_descr,
                               mp4_descr[i].dec_config_descr_len, 0,
                               NULL, NULL, NULL, NULL);
-            ff_mp4_read_dec_config_descr(s, st, &pb);
+            ff_mp4_read_dec_config_descr(s, st, &pb.public);
             if (st->codecpar->codec_id == AV_CODEC_ID_AAC &&
                 st->codecpar->extradata_size > 0)
                 st->internal->need_parsing = 0;
@@ -1819,11 +1821,11 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
         for (i = 0; i < mp4_descr_count; i++)
             if (mp4_descr[i].dec_config_descr_len &&
                 mp4_descr[i].es_id == desc_es_id) {
-                AVIOContext pb;
+                FFIOContext pb;
                 ffio_init_context(&pb, mp4_descr[i].dec_config_descr,
                                   mp4_descr[i].dec_config_descr_len, 0,
                                   NULL, NULL, NULL, NULL);
-                ff_mp4_read_dec_config_descr(fc, st, &pb);
+                ff_mp4_read_dec_config_descr(fc, st, &pb.public);
                 if (st->codecpar->codec_id == AV_CODEC_ID_AAC &&
                     st->codecpar->extradata_size > 0) {
                     st->internal->need_parsing = 0;
@@ -1841,11 +1843,11 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
              (st->internal->request_probe == 0 && st->codecpar->codec_id == AV_CODEC_ID_NONE) ||
              st->internal->request_probe > 0) &&
             mp4_descr->dec_config_descr_len && mp4_descr->es_id == pid) {
-            AVIOContext pb;
+            FFIOContext pb;
             ffio_init_context(&pb, mp4_descr->dec_config_descr,
                               mp4_descr->dec_config_descr_len, 0,
                               NULL, NULL, NULL, NULL);
-            ff_mp4_read_dec_config_descr(fc, st, &pb);
+            ff_mp4_read_dec_config_descr(fc, st, &pb.public);
             if (st->codecpar->codec_id == AV_CODEC_ID_AAC &&
                 st->codecpar->extradata_size > 0) {
                 st->internal->request_probe = st->internal->need_parsing = 0;
diff --git a/libavformat/mpjpegdec.c b/libavformat/mpjpegdec.c
index 28a24184a2..7c0d6d016c 100644
--- a/libavformat/mpjpegdec.c
+++ b/libavformat/mpjpegdec.c
@@ -113,7 +113,7 @@ static int mpjpeg_read_close(AVFormatContext *s)
 
 static int mpjpeg_read_probe(const AVProbeData *p)
 {
-    AVIOContext pb;
+    FFIOContext pb;
     int ret = 0;
     int size = 0;
 
@@ -122,7 +122,7 @@ static int mpjpeg_read_probe(const AVProbeData *p)
 
     ffio_init_context(&pb, p->buf, p->buf_size, 0, NULL, NULL, NULL, NULL);
 
-    ret = (parse_multipart_header(&pb, &size, "--", NULL) >= 0) ? AVPROBE_SCORE_MAX : 0;
+    ret = (parse_multipart_header(&pb.public, &size, "--", NULL) >= 0) ? AVPROBE_SCORE_MAX : 0;
 
     return ret;
 }
diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c
index aff0ca6b96..4d15a116d3 100644
--- a/libavformat/oggenc.c
+++ b/libavformat/oggenc.c
@@ -275,7 +275,7 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact,
                                         AVChapter **chapters, unsigned int nb_chapters)
 {
     const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
-    AVIOContext pb;
+    FFIOContext pb;
     int64_t size;
     uint8_t *p;
 
@@ -289,9 +289,9 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact,
         return NULL;
 
     ffio_init_context(&pb, p + offset, size - offset, 1, NULL, NULL, NULL, NULL);
-    ff_vorbiscomment_write(&pb, *m, vendor, chapters, nb_chapters);
+    ff_vorbiscomment_write(&pb.public, *m, vendor, chapters, nb_chapters);
     if (framing_bit)
-        avio_w8(&pb, 1);
+        avio_w8(&pb.public, 1);
 
     *header_len = size;
     return p;
diff --git a/libavformat/rdt.c b/libavformat/rdt.c
index da55503ea6..56450403a1 100644
--- a/libavformat/rdt.c
+++ b/libavformat/rdt.c
@@ -131,7 +131,8 @@ ff_rdt_calc_response_and_checksum(char response[41], char chksum[9],
 static int
 rdt_load_mdpr (PayloadContext *rdt, AVStream *st, int rule_nr)
 {
-    AVIOContext pb;
+    FFIOContext pb0;
+    AVIOContext *const pb = &pb0.public;
     unsigned int size;
     uint32_t tag;
 
@@ -151,32 +152,32 @@ rdt_load_mdpr (PayloadContext *rdt, AVStream *st, int rule_nr)
      */
     if (!rdt->mlti_data)
         return -1;
-    ffio_init_context(&pb, rdt->mlti_data, rdt->mlti_data_size, 0,
+    ffio_init_context(&pb0, rdt->mlti_data, rdt->mlti_data_size, 0,
                   NULL, NULL, NULL, NULL);
-    tag = avio_rl32(&pb);
+    tag = avio_rl32(pb);
     if (tag == MKTAG('M', 'L', 'T', 'I')) {
         int num, chunk_nr;
 
         /* read index of MDPR chunk numbers */
-        num = avio_rb16(&pb);
+        num = avio_rb16(pb);
         if (rule_nr < 0 || rule_nr >= num)
             return -1;
-        avio_skip(&pb, rule_nr * 2);
-        chunk_nr = avio_rb16(&pb);
-        avio_skip(&pb, (num - 1 - rule_nr) * 2);
+        avio_skip(pb, rule_nr * 2);
+        chunk_nr = avio_rb16(pb);
+        avio_skip(pb, (num - 1 - rule_nr) * 2);
 
         /* read MDPR chunks */
-        num = avio_rb16(&pb);
+        num = avio_rb16(pb);
         if (chunk_nr >= num)
             return -1;
         while (chunk_nr--)
-            avio_skip(&pb, avio_rb32(&pb));
-        size = avio_rb32(&pb);
+            avio_skip(pb, avio_rb32(pb));
+        size = avio_rb32(pb);
     } else {
         size = rdt->mlti_data_size;
-        avio_seek(&pb, 0, SEEK_SET);
+        avio_seek(pb, 0, SEEK_SET);
     }
-    if (ff_rm_read_mdpr_codecdata(rdt->rmctx, &pb, st, rdt->rmst[st->index], size, NULL) < 0)
+    if (ff_rm_read_mdpr_codecdata(rdt->rmctx, pb, st, rdt->rmst[st->index], size, NULL) < 0)
         return -1;
 
     return 0;
@@ -296,16 +297,16 @@ rdt_parse_packet (AVFormatContext *ctx, PayloadContext *rdt, AVStream *st,
                   const uint8_t *buf, int len, uint16_t rtp_seq, int flags)
 {
     int seq = 1, res;
-    AVIOContext pb;
 
     if (rdt->audio_pkt_cnt == 0) {
+        FFIOContext pb;
         int pos, rmflags;
 
         ffio_init_context(&pb, (uint8_t *)buf, len, 0, NULL, NULL, NULL, NULL);
         rmflags = (flags & RTP_FLAG_KEY) ? 2 : 0;
-        res = ff_rm_parse_packet (rdt->rmctx, &pb, st, rdt->rmst[st->index], len, pkt,
-                                  &seq, rmflags, *timestamp);
-        pos = avio_tell(&pb);
+        res = ff_rm_parse_packet(rdt->rmctx, &pb.public, st, rdt->rmst[st->index],
+                                 len, pkt, &seq, rmflags, *timestamp);
+        pos = avio_tell(&pb.public);
         if (res < 0)
             return res;
         if (res > 0) {
diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c
index 3802a57407..1ff1f3de0f 100644
--- a/libavformat/rtpdec_asf.c
+++ b/libavformat/rtpdec_asf.c
@@ -87,20 +87,20 @@ static int packetizer_read(void *opaque, uint8_t *buf, int buf_size)
     return AVERROR(EAGAIN);
 }
 
-static void init_packetizer(AVIOContext *pb, uint8_t *buf, int len)
+static void init_packetizer(FFIOContext *pb, uint8_t *buf, int len)
 {
     ffio_init_context(pb, buf, len, 0, NULL, packetizer_read, NULL, NULL);
 
     /* this "fills" the buffer with its current content */
-    pb->pos     = len;
-    pb->buf_end = buf + len;
+    pb->public.pos     = len;
+    pb->public.buf_end = buf + len;
 }
 
 int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
 {
     int ret = 0;
     if (av_strstart(p, "pgmpu:data:application/vnd.ms.wms-hdr.asfv1;base64,", &p)) {
-        AVIOContext pb = { 0 };
+        FFIOContext pb;
         RTSPState *rt = s->priv_data;
         AVDictionary *opts = NULL;
         int len = strlen(p) * 6 / 8;
@@ -127,7 +127,7 @@ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
             av_free(buf);
             return AVERROR(ENOMEM);
         }
-        rt->asf_ctx->pb      = &pb;
+        rt->asf_ctx->pb      = &pb.public;
         av_dict_set(&opts, "no_resync_search", "1", 0);
 
         if ((ret = ff_copy_whiteblacklists(rt->asf_ctx, s)) < 0) {
@@ -138,12 +138,12 @@ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
         ret = avformat_open_input(&rt->asf_ctx, "", iformat, &opts);
         av_dict_free(&opts);
         if (ret < 0) {
-            av_free(pb.buffer);
+            av_free(pb.public.buffer);
             return ret;
         }
         av_dict_copy(&s->metadata, rt->asf_ctx->metadata, 0);
-        rt->asf_pb_pos = avio_tell(&pb);
-        av_free(pb.buffer);
+        rt->asf_pb_pos = avio_tell(&pb.public);
+        av_free(pb.public.buffer);
         rt->asf_ctx->pb = NULL;
     }
     return ret;
@@ -178,7 +178,8 @@ static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index,
 }
 
 struct PayloadContext {
-    AVIOContext *pktbuf, pb;
+    FFIOContext pb;
+    AVIOContext *pktbuf;
     uint8_t *buf;
 };
 
@@ -193,7 +194,8 @@ static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf,
                                const uint8_t *buf, int len, uint16_t seq,
                                int flags)
 {
-    AVIOContext *pb = &asf->pb;
+    FFIOContext *const pb0 = &asf->pb;
+    AVIOContext *const pb  = &pb0->public;
     int res, mflags, len_off;
     RTSPState *rt = s->priv_data;
 
@@ -208,7 +210,7 @@ static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf,
 
         av_freep(&asf->buf);
 
-        ffio_init_context(pb, (uint8_t *)buf, len, 0, NULL, NULL, NULL, NULL);
+        ffio_init_context(pb0, (uint8_t *)buf, len, 0, NULL, NULL, NULL, NULL);
 
         while (avio_tell(pb) + 4 < len) {
             int start_off = avio_tell(pb);
@@ -267,7 +269,7 @@ static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf,
             }
         }
 
-        init_packetizer(pb, asf->buf, out_len);
+        init_packetizer(pb0, asf->buf, out_len);
         pb->pos += rt->asf_pb_pos;
         pb->eof_reached = 0;
         rt->asf_ctx->pb = pb;
diff --git a/libavformat/rtpdec_qt.c b/libavformat/rtpdec_qt.c
index 492a1b6715..524608ae00 100644
--- a/libavformat/rtpdec_qt.c
+++ b/libavformat/rtpdec_qt.c
@@ -54,7 +54,8 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
                                uint32_t *timestamp, const uint8_t *buf,
                                int len, uint16_t seq, int flags)
 {
-    AVIOContext pb;
+    FFIOContext pb0;
+    AVIOContext *const pb = &pb0.public;
     GetBitContext gb;
     int packing_scheme, has_payload_desc, has_packet_info, alen,
         has_marker_bit = flags & RTP_FLAG_MARKER,
@@ -82,7 +83,7 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
      * http://developer.apple.com/quicktime/icefloe/dispatch026.html
      */
     init_get_bits(&gb, buf, len << 3);
-    ffio_init_context(&pb, (uint8_t*)buf, len, 0, NULL, NULL, NULL, NULL);
+    ffio_init_context(&pb0, (uint8_t*)buf, len, 0, NULL, NULL, NULL, NULL);
 
     if (len < 4)
         return AVERROR_INVALIDDATA;
@@ -114,22 +115,22 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
         skip_bits(&gb, 12); // reserved
         data_len = get_bits(&gb, 16);
 
-        avio_seek(&pb, pos + 4, SEEK_SET);
-        tag = avio_rl32(&pb);
+        avio_seek(pb, pos + 4, SEEK_SET);
+        tag = avio_rl32(pb);
         if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
                  tag != MKTAG('v','i','d','e')) ||
             (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
                  tag != MKTAG('s','o','u','n')))
             return AVERROR_INVALIDDATA;
-        avpriv_set_pts_info(st, 32, 1, avio_rb32(&pb));
+        avpriv_set_pts_info(st, 32, 1, avio_rb32(pb));
 
         if (pos + data_len > len)
             return AVERROR_INVALIDDATA;
         /* TLVs */
-        while (avio_tell(&pb) + 4 < pos + data_len) {
-            int tlv_len = avio_rb16(&pb);
-            tag = avio_rl16(&pb);
-            if (avio_tell(&pb) + tlv_len > pos + data_len)
+        while (avio_tell(pb) + 4 < pos + data_len) {
+            int tlv_len = avio_rb16(pb);
+            tag = avio_rl16(pb);
+            if (avio_tell(pb) + tlv_len > pos + data_len)
                 return AVERROR_INVALIDDATA;
 
 #define MKTAG16(a,b) MKTAG(a,b,0,0)
@@ -151,7 +152,7 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
                 /* ff_mov_read_stsd_entries updates stream s->nb_streams-1,
                  * so set it temporarily to indicate which stream to update. */
                 s->nb_streams = st->index + 1;
-                ff_mov_read_stsd_entries(mc, &pb, 1);
+                ff_mov_read_stsd_entries(mc, pb, 1);
                 qt->bytes_per_frame = msc->bytes_per_frame;
                 av_free(msc);
                 av_free(mc);
@@ -160,22 +161,22 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
                 break;
             }
             default:
-                avio_skip(&pb, tlv_len);
+                avio_skip(pb, tlv_len);
                 break;
             }
         }
 
         /* 32-bit alignment */
-        avio_skip(&pb, ((avio_tell(&pb) + 3) & ~3) - avio_tell(&pb));
+        avio_skip(pb, ((avio_tell(pb) + 3) & ~3) - avio_tell(pb));
     } else
-        avio_seek(&pb, 4, SEEK_SET);
+        avio_seek(pb, 4, SEEK_SET);
 
     if (has_packet_info) {
         avpriv_request_sample(s, "RTP-X-QT with packet-specific info");
         return AVERROR_PATCHWELCOME;
     }
 
-    alen = len - avio_tell(&pb);
+    alen = len - avio_tell(pb);
     if (alen <= 0)
         return AVERROR_INVALIDDATA;
 
@@ -197,7 +198,7 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
             qt->pkt->size = 0;
             qt->timestamp = *timestamp;
         }
-        memcpy(qt->pkt->data + qt->pkt->size, buf + avio_tell(&pb), alen);
+        memcpy(qt->pkt->data + qt->pkt->size, buf + avio_tell(pb), alen);
         qt->pkt->size += alen;
         if (has_marker_bit) {
             int ret = av_packet_from_data(pkt, qt->pkt->data, qt->pkt->size);
@@ -220,7 +221,7 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
         qt->remaining = (alen / qt->bytes_per_frame) - 1;
         if ((ret = av_new_packet(pkt, qt->bytes_per_frame)) < 0)
             return ret;
-        memcpy(pkt->data, buf + avio_tell(&pb), qt->bytes_per_frame);
+        memcpy(pkt->data, buf + avio_tell(pb), qt->bytes_per_frame);
         pkt->flags = keyframe ? AV_PKT_FLAG_KEY : 0;
         pkt->stream_index = st->index;
         if (qt->remaining > 0) {
@@ -232,7 +233,7 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
             }
             qt->pkt->size = qt->remaining * qt->bytes_per_frame;
             memcpy(qt->pkt->data,
-                   buf + avio_tell(&pb) + qt->bytes_per_frame,
+                   buf + avio_tell(pb) + qt->bytes_per_frame,
                    qt->remaining * qt->bytes_per_frame);
             qt->pkt->flags = pkt->flags;
             return 1;
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 9869e1b72e..a7eb8da2f9 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -2496,7 +2496,7 @@ static int rtp_read_header(AVFormatContext *s)
     int payload_type;
     AVCodecParameters *par = NULL;
     struct sockaddr_storage addr;
-    AVIOContext pb;
+    FFIOContext pb;
     socklen_t addrlen = sizeof(addr);
     RTSPState *rt = s->priv_data;
     const char *p;
@@ -2594,7 +2594,7 @@ static int rtp_read_header(AVFormatContext *s)
     avcodec_parameters_free(&par);
 
     ffio_init_context(&pb, sdp.str, sdp.len, 0, NULL, NULL, NULL, NULL);
-    s->pb = &pb;
+    s->pb = &pb.public;
 
     /* if sdp_read_header() fails then following ff_network_close() cancels out */
     /* ff_network_init() at the start of this function. Otherwise it cancels out */
diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c
index a852b0782b..1ca4836ff6 100644
--- a/libavformat/sapdec.c
+++ b/libavformat/sapdec.c
@@ -35,7 +35,7 @@
 struct SAPState {
     URLContext *ann_fd;
     AVFormatContext *sdp_ctx;
-    AVIOContext sdp_pb;
+    FFIOContext sdp_pb;
     uint16_t hash;
     char *sdp;
     int eof;
@@ -160,7 +160,7 @@ static int sap_read_header(AVFormatContext *s)
         goto fail;
     }
     sap->sdp_ctx->max_delay = s->max_delay;
-    sap->sdp_ctx->pb        = &sap->sdp_pb;
+    sap->sdp_ctx->pb        = &sap->sdp_pb.public;
     sap->sdp_ctx->interrupt_callback = s->interrupt_callback;
 
     if ((ret = ff_copy_whiteblacklists(sap->sdp_ctx, s)) < 0)
diff --git a/libavformat/subtitles.c b/libavformat/subtitles.c
index f80a439bcc..fbf37c0cf1 100644
--- a/libavformat/subtitles.c
+++ b/libavformat/subtitles.c
@@ -51,9 +51,8 @@ void ff_text_init_avio(void *s, FFTextReader *r, AVIOContext *pb)
 
 void ff_text_init_buf(FFTextReader *r, void *buf, size_t size)
 {
-    memset(&r->buf_pb, 0, sizeof(r->buf_pb));
     ffio_init_context(&r->buf_pb, buf, size, 0, NULL, NULL, NULL, NULL);
-    ff_text_init_avio(NULL, r, &r->buf_pb);
+    ff_text_init_avio(NULL, r, &r->buf_pb.public);
 }
 
 int64_t ff_text_pos(FFTextReader *r)
diff --git a/libavformat/subtitles.h b/libavformat/subtitles.h
index 37ca7b19b1..4460efacf3 100644
--- a/libavformat/subtitles.h
+++ b/libavformat/subtitles.h
@@ -25,6 +25,7 @@
 #include <stddef.h>
 #include "avformat.h"
 #include "libavutil/bprint.h"
+#include "avio_internal.h"
 
 enum sub_sort {
     SUB_SORT_TS_POS = 0,    ///< sort by timestamps, then position
@@ -42,7 +43,7 @@ typedef struct {
     AVIOContext *pb;
     unsigned char buf[8];
     int buf_pos, buf_len;
-    AVIOContext buf_pb;
+    FFIOContext buf_pb;
 } FFTextReader;
 
 /**
diff --git a/libavformat/thp.c b/libavformat/thp.c
index 7aad24221b..d5d91a9f23 100644
--- a/libavformat/thp.c
+++ b/libavformat/thp.c
@@ -22,6 +22,7 @@
 #include "libavutil/intreadwrite.h"
 #include "libavutil/intfloat.h"
 #include "avformat.h"
+#include "avio_internal.h"
 #include "internal.h"
 
 typedef struct ThpDemuxContext {
@@ -65,6 +66,7 @@ static int thp_read_header(AVFormatContext *s)
     AVStream *st;
     AVIOContext *pb = s->pb;
     int64_t fsize= avio_size(pb);
+    uint32_t maxsize;
     int i;
 
     /* Read the file header.  */
@@ -79,9 +81,10 @@ static int thp_read_header(AVFormatContext *s)
         return AVERROR_INVALIDDATA;
     thp->framecnt        = avio_rb32(pb);
     thp->first_framesz   = avio_rb32(pb);
-    pb->maxsize          = avio_rb32(pb);
-    if(fsize>0 && (!pb->maxsize || fsize < pb->maxsize))
-        pb->maxsize= fsize;
+    maxsize              = avio_rb32(pb);
+    if (fsize > 0 && (!maxsize || fsize < maxsize))
+        maxsize = fsize;
+    ((FFIOContext*)pb)->maxsize = fsize;
 
     thp->compoff         = avio_rb32(pb);
                            avio_rb32(pb); /* offsetDataOffset.  */
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 8d1b76f590..d2c306a008 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -230,7 +230,7 @@ static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size)
         if (read_size > SANE_CHUNK_SIZE/10) {
             read_size = ffio_limit(s, read_size);
             // If filesize/maxsize is unknown, limit to SANE_CHUNK_SIZE
-            if (s->maxsize < 0)
+            if (((FFIOContext*)s)->maxsize < 0)
                 read_size = FFMIN(read_size, SANE_CHUNK_SIZE);
         }
 
@@ -1972,6 +1972,7 @@ void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance)
     int64_t skip = 0;
     //We could use URLProtocol flags here but as many user applications do not use URLProtocols this would be unreliable
     const char *proto = avio_find_protocol_name(s->url);
+    FFIOContext *ctx;
 
     av_assert0(time_tolerance >= 0);
 
@@ -2012,6 +2013,7 @@ void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance)
     }
 
     pos_delta *= 2;
+    ctx = (FFIOContext*)s->pb;
     /* XXX This could be adjusted depending on protocol*/
     if (s->pb->buffer_size < pos_delta && pos_delta < (1<<24)) {
         av_log(s, AV_LOG_VERBOSE, "Reconfiguring buffers to size %"PRId64"\n", pos_delta);
@@ -2022,11 +2024,11 @@ void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance)
             return;
         }
 
-        s->pb->short_seek_threshold = FFMAX(s->pb->short_seek_threshold, pos_delta/2);
+        ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, pos_delta/2);
     }
 
     if (skip < (1<<23)) {
-        s->pb->short_seek_threshold = FFMAX(s->pb->short_seek_threshold, skip);
+        ctx->short_seek_threshold = FFMAX(ctx->short_seek_threshold, skip);
     }
 }
 
@@ -3553,9 +3555,11 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             max_stream_analyze_duration = 7*AV_TIME_BASE;
     }
 
-    if (ic->pb)
+    if (ic->pb) {
+        FFIOContext *const ctx = (FFIOContext*)ic->pb;
         av_log(ic, AV_LOG_DEBUG, "Before avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d nb_streams:%d\n",
-               avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count, ic->nb_streams);
+               avio_tell(ic->pb), ctx->bytes_read, ctx->seek_count, ic->nb_streams);
+    }
 
     for (i = 0; i < ic->nb_streams; i++) {
         const AVCodec *codec;
@@ -4066,9 +4070,11 @@ find_stream_info_err:
         av_freep(&ic->streams[i]->internal->info);
         av_bsf_free(&ic->streams[i]->internal->extract_extradata.bsf);
     }
-    if (ic->pb)
+    if (ic->pb) {
+        FFIOContext *const ctx = (FFIOContext*)ic->pb;
         av_log(ic, AV_LOG_DEBUG, "After avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d frames:%d\n",
-               avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count, count);
+               avio_tell(ic->pb), ctx->bytes_read, ctx->seek_count, count);
+    }
     return ret;
 
 unref_then_goto_end:
diff --git a/libavformat/vividas.c b/libavformat/vividas.c
index 8d1c1dab29..99e2bfa911 100644
--- a/libavformat/vividas.c
+++ b/libavformat/vividas.c
@@ -283,9 +283,10 @@ static int track_header(VividasDemuxContext *viv, AVFormatContext *s,  uint8_t *
     int64_t off;
     int val_1;
     int num_video;
-    AVIOContext pb0, *pb = &pb0;
+    FFIOContext pb0;
+    AVIOContext *const pb = &pb0.public;
 
-    ffio_init_context(pb, buf, size, 0, NULL, NULL, NULL, NULL);
+    ffio_init_context(&pb0, buf, size, 0, NULL, NULL, NULL, NULL);
 
     ffio_read_varlen(pb); // track_header_len
     avio_r8(pb); // '1'
@@ -436,12 +437,13 @@ static int track_index(VividasDemuxContext *viv, AVFormatContext *s, uint8_t *bu
     int64_t off;
     int64_t poff;
     int maxnp=0;
-    AVIOContext pb0, *pb = &pb0;
+    FFIOContext pb0;
+    AVIOContext *const pb = &pb0.public;
     int i;
     int64_t filesize = avio_size(s->pb);
     uint64_t n_sb_blocks_tmp;
 
-    ffio_init_context(pb, buf, size, 0, NULL, NULL, NULL, NULL);
+    ffio_init_context(&pb0, buf, size, 0, NULL, NULL, NULL, NULL);
 
     ffio_read_varlen(pb); // track_index_len
     avio_r8(pb); // 'c'
