diff mbox series

[FFmpeg-devel,5/9] avformat/avio: Move internal AVIOContext fields to avio_internal.h

Message ID AM7PR03MB666022017ABBD64D49AA30918FF29@AM7PR03MB6660.eurprd03.prod.outlook.com
State Superseded
Headers show
Series [FFmpeg-devel,1/9] avformat/aviobuf: Avoid calling function twice due to FFMAX() | expand

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Andreas Rheinhardt Aug. 5, 2021, 5:42 a.m. UTC
Currently AVIOContext's private fields are all over AVIOContext.
This commit moves them into a new structure in avio_internal.h instead.
Said structure contains the public AVIOContext as its first element
in order to avoid having to allocate a separate AVIOContextInternal
which is costly for those use cases where one just wants to access
an already existing buffer via the AVIOContext-API.
For these cases ffio_init_context() can't fail and always returned zero,
which was typically not checked. Therefore it has been made to not
return anything.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
I like the name FFIOContext (without any "internal" in it, because
it contains more than just the internal fields), but the same can not
be said about the "public" member, i.e. the public AVIOContext. It seems
a bit long. Any better suggestions? pb would lead to expressions like
&pb.pb which seems weird. Maybe just "pub"? Or something completely
else?

 libavformat/aacdec.c        |   6 +--
 libavformat/asfenc.c        |   8 +--
 libavformat/av1.c           |   4 +-
 libavformat/av1dec.c        |  21 ++++----
 libavformat/avio.h          |  64 +++-------------------
 libavformat/avio_internal.h |  44 ++++++++++++++-
 libavformat/aviobuf.c       | 105 +++++++++++++++++++-----------------
 libavformat/dashdec.c       |  14 ++---
 libavformat/hls.c           |  23 ++++----
 libavformat/id3v2.c         |   6 +--
 libavformat/matroskadec.c   |  13 ++---
 libavformat/matroskaenc.c   |   5 +-
 libavformat/mmst.c          |   4 +-
 libavformat/mov.c           |   9 ++--
 libavformat/mp3dec.c        |   2 +-
 libavformat/mpegts.c        |  76 +++++++++++++-------------
 libavformat/mpjpegdec.c     |   4 +-
 libavformat/oggenc.c        |   6 +--
 libavformat/rdt.c           |  33 ++++++------
 libavformat/rtpdec_asf.c    |  26 ++++-----
 libavformat/rtpdec_qt.c     |  35 ++++++------
 libavformat/rtsp.c          |   4 +-
 libavformat/sapdec.c        |   4 +-
 libavformat/subtitles.c     |   3 +-
 libavformat/subtitles.h     |   3 +-
 libavformat/thp.c           |   9 ++--
 libavformat/utils.c         |  20 ++++---
 libavformat/vividas.c       |  10 ++--
 28 files changed, 290 insertions(+), 271 deletions(-)
diff mbox series

Patch

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'