Some (de)muxers open additional files beyond the main IO context.
Currently, they call avio_open() directly, which
- prevents the caller from using custom IO for such streams
- can be a security issue in some cases, especially when combined with
  the concat protocol

This commit adds callbacks to AVFormatContext that default to
avio_open2()/avio_close(), but can be overridden by the caller. All
muxers and demuxers now have to use those callbacks instead of calling
avio_open()/avio_close() directly.
---
This patch should enable fixing the recently reported HLS+concat security issue
properly.

I didn't add any actual checks to the default open() wrapper yet, because we
should agree on what they should be first. We can also add lavf global options
configuring such checks.

Opinions?
---
 doc/APIchanges                   |  4 ++++
 libavformat/avformat.h           | 33 +++++++++++++++++++++++++++++++++
 libavformat/dashenc.c            |  7 +++++--
 libavformat/hdsenc.c             | 25 ++++++++++---------------
 libavformat/hls.c                |  6 ++++--
 libavformat/hlsenc.c             | 15 ++++++++-------
 libavformat/img2dec.c            |  5 ++---
 libavformat/img2enc.c            |  9 ++++-----
 libavformat/internal.h           |  6 ++++++
 libavformat/mov.c                | 10 +++++-----
 libavformat/movenc.c             |  4 ++--
 libavformat/options.c            | 14 ++++++++++++++
 libavformat/segment.c            | 35 +++++++++++++++++------------------
 libavformat/smoothstreamingenc.c | 18 +++++++++---------
 libavformat/utils.c              |  7 +++++++
 libavformat/version.h            |  2 +-
 16 files changed, 131 insertions(+), 69 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index ffa270e..6f7a141 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,10 @@ libavutil:     2015-08-28
 
 API changes, most recent first:
 
+2016-xx-xx - xxxxxxx - lavf 57.3.0 - avformat.h
+  Add AVFormatContext.opaque, io_open and io_close, allowing custom IO
+  for muxers and demuxers that open additional files.
+
 2015-xx-xx - xxxxxxx - lavc 57.12.0 - avcodec.h
   Add AVCodecDescriptor.profiles and avcodec_profile_name().
 
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index cd53420..4926a35 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1229,6 +1229,39 @@ typedef struct AVFormatContext {
      * Must not be accessed in any way by callers.
      */
     AVFormatInternal *internal;
+
+    /**
+     * Arbitrary user data set by the caller.
+     */
+    void *opaque;
+
+    /**
+     * A callback for opening new IO streams.
+     *
+     * Certain muxers or demuxers (e.g. for various playlist-based formats) 
need
+     * to open additional files during muxing or demuxing. This callback allows
+     * the caller to provide custom IO in such cases.
+     *
+     * @param s the format context
+     * @param pb on success, the newly opened IO context should be returned 
here
+     * @param url the url to open
+     * @param flags a combination of AVIO_FLAG_*
+     * @param options a dictionary of additional options, with the same
+     *                semantics as in avio_open2()
+     * @return 0 on success, a negative AVERROR code on failure
+     *
+     * @note Certain muxers and demuxers do nesting, i.e. they open one or more
+     * additional internal format contexts. Thus the AVFormatContext pointer
+     * passed to this callback may be different from the one facing the caller.
+     * It will, however, have the same 'opaque' field.
+     */
+    int (*io_open)(struct AVFormatContext *s, AVIOContext **pb, const char 
*url,
+                   int flags, AVDictionary **options);
+
+    /**
+     * A callback for closing the streams opened with 
AVFormatContext.io_open().
+     */
+    void (*io_close)(struct AVFormatContext *s, AVIOContext *pb);
 } AVFormatContext;
 
 typedef struct AVPacketList {
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index cedd83b..12d3a8c 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -444,7 +444,7 @@ static int write_manifest(AVFormatContext *s, int final)
     AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
 
     snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename);
-    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, 
&s->interrupt_callback, NULL);
+    ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
         return ret;
@@ -532,7 +532,7 @@ static int write_manifest(AVFormatContext *s, int final)
     avio_printf(out, "\t</Period>\n");
     avio_printf(out, "</MPD>\n");
     avio_flush(out);
-    avio_close(out);
+    ff_format_io_close(s, &out);
     return ff_rename(temp_filename, s->filename);
 }
 
@@ -604,6 +604,9 @@ static int dash_write_header(AVFormatContext *s)
         os->ctx = ctx;
         ctx->oformat = oformat;
         ctx->interrupt_callback = s->interrupt_callback;
+        ctx->opaque             = s->opaque;
+        ctx->io_close           = s->io_close;
+        ctx->io_open            = s->io_open;
 
         if (!(st = avformat_new_stream(ctx, NULL))) {
             ret = AVERROR(ENOMEM);
diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c
index d96a3d5..a2710de 100644
--- a/libavformat/hdsenc.c
+++ b/libavformat/hdsenc.c
@@ -140,8 +140,7 @@ static void hds_free(AVFormatContext *s)
     for (i = 0; i < s->nb_streams; i++) {
         OutputStream *os = &c->streams[i];
         if (os->out)
-            avio_close(os->out);
-        os->out = NULL;
+            ff_format_io_close(s, &os->out);
         if (os->ctx && os->ctx_inited)
             av_write_trailer(os->ctx);
         if (os->ctx && os->ctx->pb)
@@ -171,8 +170,7 @@ static int write_manifest(AVFormatContext *s, int final)
 
     snprintf(filename, sizeof(filename), "%s/index.f4m", s->filename);
     snprintf(temp_filename, sizeof(temp_filename), "%s/index.f4m.tmp", 
s->filename);
-    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE,
-                     &s->interrupt_callback, NULL);
+    ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
         return ret;
@@ -190,7 +188,7 @@ static int write_manifest(AVFormatContext *s, int final)
         int b64_size = AV_BASE64_SIZE(os->metadata_size);
         char *base64 = av_malloc(b64_size);
         if (!base64) {
-            avio_close(out);
+            ff_format_io_close(s, &out);
             return AVERROR(ENOMEM);
         }
         av_base64_encode(base64, b64_size, os->metadata, os->metadata_size);
@@ -203,7 +201,7 @@ static int write_manifest(AVFormatContext *s, int final)
     }
     avio_printf(out, "</manifest>\n");
     avio_flush(out);
-    avio_close(out);
+    ff_format_io_close(s, &out);
     return ff_rename(temp_filename, filename);
 }
 
@@ -240,8 +238,7 @@ static int write_abst(AVFormatContext *s, OutputStream *os, 
int final)
              "%s/stream%d.abst", s->filename, index);
     snprintf(temp_filename, sizeof(temp_filename),
              "%s/stream%d.abst.tmp", s->filename, index);
-    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE,
-                     &s->interrupt_callback, NULL);
+    ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
         return ret;
@@ -284,15 +281,14 @@ static int write_abst(AVFormatContext *s, OutputStream 
*os, int final)
     }
     update_size(out, afrt_pos);
     update_size(out, 0);
-    avio_close(out);
+    ff_format_io_close(s, &out);
     return ff_rename(temp_filename, filename);
 }
 
 static int init_file(AVFormatContext *s, OutputStream *os, int64_t start_ts)
 {
     int ret, i;
-    ret = avio_open2(&os->out, os->temp_filename, AVIO_FLAG_WRITE,
-                     &s->interrupt_callback, NULL);
+    ret = s->io_open(s, &os->out, os->temp_filename, AVIO_FLAG_WRITE, NULL);
     if (ret < 0)
         return ret;
     avio_wb32(os->out, 0);
@@ -305,14 +301,13 @@ static int init_file(AVFormatContext *s, OutputStream 
*os, int64_t start_ts)
     return 0;
 }
 
-static void close_file(OutputStream *os)
+static void close_file(AVFormatContext *s, OutputStream *os)
 {
     int64_t pos = avio_tell(os->out);
     avio_seek(os->out, 0, SEEK_SET);
     avio_wb32(os->out, pos);
     avio_flush(os->out);
-    avio_close(os->out);
-    os->out = NULL;
+    ff_format_io_close(s, &os->out);
 }
 
 static int hds_write_header(AVFormatContext *s)
@@ -476,7 +471,7 @@ static int hds_flush(AVFormatContext *s, OutputStream *os, 
int final,
 
     avio_flush(os->ctx->pb);
     os->packets_written = 0;
-    close_file(os);
+    close_file(s, os);
 
     snprintf(target_filename, sizeof(target_filename),
              "%s/stream%dSeg1-Frag%d", s->filename, index, os->fragment_index);
diff --git a/libavformat/hls.c b/libavformat/hls.c
index dc3ab87..d3b4b58 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -94,6 +94,7 @@ struct variant {
 };
 
 typedef struct HLSContext {
+    AVFormatContext *ctx;
     int n_variants;
     struct variant **variants;
     int cur_seq_no;
@@ -207,7 +208,7 @@ static int open_in(HLSContext *c, AVIOContext **in, const 
char *url)
 
     av_dict_copy(&tmp, c->avio_opts, 0);
 
-    ret = avio_open2(in, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
+    ret = c->ctx->io_open(c->ctx, in, url, AVIO_FLAG_READ, &tmp);
 
     av_dict_free(&tmp);
     return ret;
@@ -370,7 +371,7 @@ static int parse_playlist(HLSContext *c, const char *url,
 fail:
     av_free(new_url);
     if (close_in)
-        avio_close(in);
+        ff_format_io_close(c->ctx, &in);
     return ret;
 }
 
@@ -514,6 +515,7 @@ static int hls_read_header(AVFormatContext *s)
     HLSContext *c = s->priv_data;
     int ret = 0, i, j, stream_offset = 0;
 
+    c->ctx                = s;
     c->interrupt_callback = &s->interrupt_callback;
 
     if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0)
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 8f01047..843f37d 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -74,6 +74,9 @@ static int hls_mux_init(AVFormatContext *s)
 
     oc->oformat            = hls->oformat;
     oc->interrupt_callback = s->interrupt_callback;
+    oc->opaque             = s->opaque;
+    oc->io_open            = s->io_open;
+    oc->io_close           = s->io_close;
 
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st;
@@ -140,8 +143,7 @@ static int hls_window(AVFormatContext *s, int last)
     int64_t sequence = FFMAX(hls->start_sequence, hls->sequence - hls->size);
 
     snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename);
-    if ((ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE,
-                          &s->interrupt_callback, NULL)) < 0)
+    if ((ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL)) < 0)
         goto fail;
 
     for (en = hls->list; en; en = en->next) {
@@ -178,7 +180,7 @@ static int hls_window(AVFormatContext *s, int last)
         avio_printf(out, "#EXT-X-ENDLIST\n");
 
 fail:
-    avio_closep(&out);
+    ff_format_io_close(s, &out);
     if (ret >= 0)
         ff_rename(temp_filename, s->filename);
     return ret;
@@ -195,8 +197,7 @@ static int hls_start(AVFormatContext *s)
         return AVERROR(EINVAL);
     c->number++;
 
-    if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
-                          &s->interrupt_callback, NULL)) < 0)
+    if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 
0)
         return err;
 
     if (oc->oformat->priv_class && oc->priv_data)
@@ -300,7 +301,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket 
*pkt)
         hls->duration = 0;
 
         av_write_frame(oc, NULL); /* Flush any buffered data */
-        avio_close(oc->pb);
+        ff_format_io_close(s, &oc->pb);
 
         ret = hls_start(s);
 
@@ -324,7 +325,7 @@ static int hls_write_trailer(struct AVFormatContext *s)
     AVFormatContext *oc = hls->avf;
 
     av_write_trailer(oc);
-    avio_closep(&oc->pb);
+    ff_format_io_close(s, &oc->pb);
     avformat_free_context(oc);
     av_free(hls->basename);
     append_entry(hls, hls->duration);
diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c
index eb25087..ec3a829 100644
--- a/libavformat/img2dec.c
+++ b/libavformat/img2dec.c
@@ -238,8 +238,7 @@ static int img_read_packet(AVFormatContext *s1, AVPacket 
*pkt)
                                   s->img_number) < 0 && s->img_number > 1)
             return AVERROR(EIO);
         for (i = 0; i < 3; i++) {
-            if (avio_open2(&f[i], filename, AVIO_FLAG_READ,
-                           &s1->interrupt_callback, NULL) < 0) {
+            if (s1->io_open(s1, &f[i], filename, AVIO_FLAG_READ, NULL) < 0) {
                 if (i >= 1)
                     break;
                 av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",
@@ -273,7 +272,7 @@ static int img_read_packet(AVFormatContext *s1, AVPacket 
*pkt)
         if (f[i]) {
             ret[i] = avio_read(f[i], pkt->data + pkt->size, size[i]);
             if (!s->is_pipe)
-                avio_close(f[i]);
+                ff_format_io_close(s1, &f[i]);
             if (ret[i] > 0)
                 pkt->size += ret[i];
         }
diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c
index d5b6646..4071c35 100644
--- a/libavformat/img2enc.c
+++ b/libavformat/img2enc.c
@@ -72,8 +72,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
             return AVERROR(EIO);
         }
         for (i = 0; i < 3; i++) {
-            if (avio_open2(&pb[i], img->tmp, AVIO_FLAG_WRITE,
-                           &s->interrupt_callback, NULL) < 0) {
+            if (s->io_open(s, &pb[i], img->tmp, AVIO_FLAG_WRITE, NULL) < 0) {
                 av_log(s, AV_LOG_ERROR, "Could not open file : %s\n", 
img->tmp);
                 return AVERROR(EIO);
             }
@@ -91,8 +90,8 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
         avio_write(pb[0], pkt->data, ysize);
         avio_write(pb[1], pkt->data + ysize,                           
(pkt->size - ysize) / 2);
         avio_write(pb[2], pkt->data + ysize + (pkt->size - ysize) / 2, 
(pkt->size - ysize) / 2);
-        avio_close(pb[1]);
-        avio_close(pb[2]);
+        ff_format_io_close(s, &pb[1]);
+        ff_format_io_close(s, &pb[2]);
     } else {
         if (ff_guess_image2_codec(s->filename) == AV_CODEC_ID_JPEG2000) {
             AVStream *st = s->streams[0];
@@ -122,7 +121,7 @@ error:
     }
     avio_flush(pb[0]);
     if (!img->is_pipe) {
-        avio_close(pb[0]);
+        ff_format_io_close(s, &pb[0]);
         ff_rename(img->tmp, filename);
     }
 
diff --git a/libavformat/internal.h b/libavformat/internal.h
index 17c45f6..ed98930 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -419,4 +419,10 @@ static inline int ff_rename(const char *oldpath, const 
char *newpath)
     return 0;
 }
 
+/**
+ * A wrapper around AVFormatContext.io_close that should be used
+ * intead of calling the pointer directly.
+ */
+void ff_format_io_close(AVFormatContext *s, AVIOContext **pb);
+
 #endif /* AVFORMAT_INTERNAL_H */
diff --git a/libavformat/mov.c b/libavformat/mov.c
index aaf1c2d..e251ba0 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -2400,8 +2400,8 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
     }
 }
 
-static int mov_open_dref(AVIOContext **pb, char *src, MOVDref *ref,
-                         AVIOInterruptCB *int_cb)
+static int mov_open_dref(AVFormatContext *s, AVIOContext **pb, char *src,
+                         MOVDref *ref)
 {
     /* try relative path, we do not try the absolute because it can leak 
information about our
        system to an attacker */
@@ -2436,7 +2436,7 @@ static int mov_open_dref(AVIOContext **pb, char *src, 
MOVDref *ref,
 
             av_strlcat(filename, ref->path + l + 1, 1024);
 
-            if (!avio_open2(pb, filename, AVIO_FLAG_READ, int_cb, NULL))
+            if (!s->io_open(s, pb, filename, AVIO_FLAG_READ, NULL))
                 return 0;
         }
     }
@@ -2484,7 +2484,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 
     if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
         MOVDref *dref = &sc->drefs[sc->dref_id - 1];
-        if (mov_open_dref(&sc->pb, c->fc->filename, dref, 
&c->fc->interrupt_callback) < 0)
+        if (mov_open_dref(c->fc, &sc->pb, c->fc->filename, dref) < 0)
             av_log(c->fc, AV_LOG_ERROR,
                    "stream %d, error opening alias: path='%s', dir='%s', "
                    "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n",
@@ -3325,7 +3325,7 @@ static int mov_read_close(AVFormatContext *s)
         }
         av_freep(&sc->drefs);
         if (sc->pb && sc->pb != s->pb)
-            avio_close(sc->pb);
+            ff_format_io_close(s, &sc->pb);
 
         av_freep(&sc->chunk_offsets);
         av_freep(&sc->stsc_data);
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 1026bae..c912863 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -4188,7 +4188,7 @@ static int shift_data(AVFormatContext *s)
      * writing, so we re-open the same output, but for reading. It also avoids
      * a read/seek/write/seek back and forth. */
     avio_flush(s->pb);
-    ret = avio_open(&read_pb, s->filename, AVIO_FLAG_READ);
+    ret = s->io_open(s, &read_pb, s->filename, AVIO_FLAG_READ, NULL);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for "
                "the second pass (faststart)\n", s->filename);
@@ -4220,7 +4220,7 @@ static int shift_data(AVFormatContext *s)
         avio_write(s->pb, read_buf[read_buf_id], n);
         pos += n;
     } while (pos < pos_end);
-    avio_close(read_pb);
+    ff_format_io_close(s, &read_pb);
 
 end:
     av_free(buf);
diff --git a/libavformat/options.c b/libavformat/options.c
index a6fbbd2..c7fa51f 100644
--- a/libavformat/options.c
+++ b/libavformat/options.c
@@ -90,12 +90,26 @@ static const AVClass av_format_context_class = {
     .child_class_next = format_child_class_next,
 };
 
+static int io_open_default(AVFormatContext *s, AVIOContext **pb,
+                           const char *url, int flags, AVDictionary **options)
+{
+    return avio_open2(pb, url, flags, &s->interrupt_callback, options);
+}
+
+static void io_close_default(AVFormatContext *s, AVIOContext *pb)
+{
+    avio_close(pb);
+}
+
 static void avformat_get_context_defaults(AVFormatContext *s)
 {
     memset(s, 0, sizeof(AVFormatContext));
 
     s->av_class = &av_format_context_class;
 
+    s->io_open  = io_open_default;
+    s->io_close = io_close_default;
+
     av_opt_set_defaults(s);
 }
 
diff --git a/libavformat/segment.c b/libavformat/segment.c
index 3479134..58e2859 100644
--- a/libavformat/segment.c
+++ b/libavformat/segment.c
@@ -67,6 +67,9 @@ static int segment_mux_init(AVFormatContext *s)
 
     oc->oformat            = seg->oformat;
     oc->interrupt_callback = s->interrupt_callback;
+    oc->opaque             = s->opaque;
+    oc->io_close           = s->io_close;
+    oc->io_open            = s->io_open;
 
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st;
@@ -86,8 +89,7 @@ static int segment_hls_window(AVFormatContext *s, int last)
     int i, ret = 0;
     char buf[1024];
 
-    if ((ret = avio_open2(&seg->pb, seg->list, AVIO_FLAG_WRITE,
-                              &s->interrupt_callback, NULL)) < 0)
+    if ((ret = s->io_open(s, &seg->pb, seg->list, AVIO_FLAG_WRITE, NULL)) < 0)
         goto fail;
 
     avio_printf(seg->pb, "#EXTM3U\n");
@@ -116,7 +118,8 @@ static int segment_hls_window(AVFormatContext *s, int last)
     if (last)
         avio_printf(seg->pb, "#EXT-X-ENDLIST\n");
 fail:
-    avio_closep(&seg->pb);
+    ff_format_io_close(s, &seg->pb);
+
     return ret;
 }
 
@@ -141,8 +144,7 @@ static int segment_start(AVFormatContext *s, int 
write_header)
                               s->filename, c->number++) < 0)
         return AVERROR(EINVAL);
 
-    if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
-                          &s->interrupt_callback, NULL)) < 0)
+    if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 
0)
         return err;
 
     if (oc->oformat->priv_class && oc->priv_data)
@@ -163,7 +165,7 @@ static int segment_end(AVFormatContext *oc, int 
write_trailer)
     av_write_frame(oc, NULL); /* Flush any buffered data (fragmented mp4) */
     if (write_trailer)
         av_write_trailer(oc);
-    avio_close(oc->pb);
+    ff_format_io_close(oc, &oc->pb);
 
     return ret;
 }
@@ -190,7 +192,7 @@ static void close_null_ctx(AVIOContext *pb)
 
 static void seg_free_context(SegmentContext *seg)
 {
-    avio_closep(&seg->pb);
+    ff_format_io_close(seg->avf, &seg->pb);
     avformat_free_context(seg->avf);
     seg->avf = NULL;
 }
@@ -208,8 +210,7 @@ static int seg_write_header(AVFormatContext *s)
         seg->individual_header_trailer = 0;
 
     if (seg->list && seg->list_type != LIST_HLS)
-        if ((ret = avio_open2(&seg->pb, seg->list, AVIO_FLAG_WRITE,
-                              &s->interrupt_callback, NULL)) < 0)
+        if ((ret = s->io_open(s, &seg->pb, seg->list, AVIO_FLAG_WRITE, NULL)) 
< 0)
             goto fail;
 
     for (i = 0; i < s->nb_streams; i++)
@@ -245,8 +246,7 @@ static int seg_write_header(AVFormatContext *s)
     }
 
     if (seg->write_header_trailer) {
-        if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
-                              &s->interrupt_callback, NULL)) < 0)
+        if ((ret = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, 
NULL)) < 0)
             goto fail;
     } else {
         if ((ret = open_null_ctx(&oc->pb)) < 0)
@@ -254,14 +254,13 @@ static int seg_write_header(AVFormatContext *s)
     }
 
     if ((ret = avformat_write_header(oc, NULL)) < 0) {
-        avio_close(oc->pb);
+        ff_format_io_close(oc, &oc->pb);
         goto fail;
     }
 
     if (!seg->write_header_trailer) {
         close_null_ctx(oc->pb);
-        if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
-                              &s->interrupt_callback, NULL)) < 0)
+        if ((ret = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, 
NULL)) < 0)
             goto fail;
     }
 
@@ -321,9 +320,9 @@ static int seg_write_packet(AVFormatContext *s, AVPacket 
*pkt)
                 avio_printf(seg->pb, "%s\n", oc->filename);
                 avio_flush(seg->pb);
                 if (seg->size && !(seg->number % seg->size)) {
-                    avio_closep(&seg->pb);
-                    if ((ret = avio_open2(&seg->pb, seg->list, AVIO_FLAG_WRITE,
-                                          &s->interrupt_callback, NULL)) < 0)
+                    ff_format_io_close(s, &seg->pb);
+                    if ((ret = s->io_open(s, &seg->pb, seg->list,
+                                          AVIO_FLAG_WRITE, NULL)) < 0)
                         goto fail;
                 }
             }
@@ -368,7 +367,7 @@ static int seg_write_trailer(struct AVFormatContext *s)
     }
 
 fail:
-    avio_close(seg->pb);
+    ff_format_io_close(s, &seg->pb);
     avformat_free_context(oc);
     return ret;
 }
diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c
index 6af8b39..8e8a645 100644
--- a/libavformat/smoothstreamingenc.c
+++ b/libavformat/smoothstreamingenc.c
@@ -220,7 +220,7 @@ static int write_manifest(AVFormatContext *s, int final)
 
     snprintf(filename, sizeof(filename), "%s/Manifest", s->filename);
     snprintf(temp_filename, sizeof(temp_filename), "%s/Manifest.tmp", 
s->filename);
-    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, 
&s->interrupt_callback, NULL);
+    ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
     if (ret < 0) {
         av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", 
temp_filename);
         return ret;
@@ -282,7 +282,7 @@ static int write_manifest(AVFormatContext *s, int final)
     }
     avio_printf(out, "</SmoothStreamingMedia>\n");
     avio_flush(out);
-    avio_close(out);
+    ff_format_io_close(s, &out);
     return ff_rename(temp_filename, filename);
 }
 
@@ -409,7 +409,7 @@ static int parse_fragment(AVFormatContext *s, const char 
*filename, int64_t *sta
     AVIOContext *in;
     int ret;
     uint32_t len;
-    if ((ret = avio_open2(&in, filename, AVIO_FLAG_READ, 
&s->interrupt_callback, NULL)) < 0)
+    if ((ret = s->io_open(s, &in, filename, AVIO_FLAG_READ, NULL)) < 0)
         return ret;
     ret = AVERROR(EIO);
     *moof_size = avio_rb32(in);
@@ -450,7 +450,7 @@ static int parse_fragment(AVFormatContext *s, const char 
*filename, int64_t *sta
         avio_seek(in, end, SEEK_SET);
     }
 fail:
-    avio_close(in);
+    ff_format_io_close(s, &in);
     return ret;
 }
 
@@ -486,10 +486,10 @@ static int copy_moof(AVFormatContext *s, const char* 
infile, const char *outfile
 {
     AVIOContext *in, *out;
     int ret = 0;
-    if ((ret = avio_open2(&in, infile, AVIO_FLAG_READ, &s->interrupt_callback, 
NULL)) < 0)
+    if ((ret = s->io_open(s, &in, infile, AVIO_FLAG_READ, NULL)) < 0)
         return ret;
-    if ((ret = avio_open2(&out, outfile, AVIO_FLAG_WRITE, 
&s->interrupt_callback, NULL)) < 0) {
-        avio_close(in);
+    if ((ret = s->io_open(s, &out, outfile, AVIO_FLAG_WRITE, NULL)) < 0) {
+        ff_format_io_close(s, &in);
         return ret;
     }
     while (size > 0) {
@@ -504,8 +504,8 @@ static int copy_moof(AVFormatContext *s, const char* 
infile, const char *outfile
         size -= n;
     }
     avio_flush(out);
-    avio_close(out);
-    avio_close(in);
+    ff_format_io_close(s, &out);
+    ff_format_io_close(s, &in);
     return ret;
 }
 
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 18499af..e727c85 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -3176,3 +3176,10 @@ uint8_t *av_stream_new_side_data(AVStream *st, enum 
AVPacketSideDataType type,
     sd->size = size;
     return data;
 }
+
+void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
+{
+    if (*pb)
+        s->io_close(s, *pb);
+    *pb = NULL;
+}
diff --git a/libavformat/version.h b/libavformat/version.h
index e29e4eb..a003a8b 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -30,7 +30,7 @@
 #include "libavutil/version.h"
 
 #define LIBAVFORMAT_VERSION_MAJOR 57
-#define LIBAVFORMAT_VERSION_MINOR  2
+#define LIBAVFORMAT_VERSION_MINOR  3
 #define LIBAVFORMAT_VERSION_MICRO  0
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
-- 
2.0.0

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to