lavf: allow custom IO for all files
authorAnton Khirnov <anton@khirnov.net>
Sat, 16 Jan 2016 16:53:43 +0000 (17:53 +0100)
committerAnton Khirnov <anton@khirnov.net>
Sun, 24 Jan 2016 15:45:32 +0000 (16:45 +0100)
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.

This commit adds callbacks to AVFormatContext that default to
avio_open2()/avio_close(), but can be overridden by the caller. All
muxers and demuxers using AVIO are switched to using those callbacks
instead of calling avio_open()/avio_close() directly.

(de)muxers that use the URLProtocol layer directly instead of AVIO
remain unconverted for now. This should be fixed in later commits.

15 files changed:
doc/APIchanges
libavformat/avformat.h
libavformat/dashenc.c
libavformat/hdsenc.c
libavformat/hls.c
libavformat/hlsenc.c
libavformat/img2dec.c
libavformat/img2enc.c
libavformat/internal.h
libavformat/mov.c
libavformat/movenc.c
libavformat/options.c
libavformat/segment.c
libavformat/smoothstreamingenc.c
libavformat/utils.c

index ffa270e..6f7a141 100644 (file)
@@ -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().
 
index cd53420..4926a35 100644 (file)
@@ -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 {
index cedd83b..12d3a8c 100644 (file)
@@ -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);
index d96a3d5..a2710de 100644 (file)
@@ -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);
index dc3ab87..d3b4b58 100644 (file)
@@ -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)
index 8f01047..843f37d 100644 (file)
@@ -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);
index eb25087..ec3a829 100644 (file)
@@ -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];
         }
index d5b6646..4071c35 100644 (file)
@@ -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);
     }
 
index 17c45f6..ed98930 100644 (file)
@@ -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 */
index 28d78e3..0616963 100644 (file)
@@ -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;
         }
     }
@@ -2485,7 +2485,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 (c->enable_drefs) {
-            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",
@@ -3335,7 +3335,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);
index 1026bae..c912863 100644 (file)
@@ -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);
index a6fbbd2..c7fa51f 100644 (file)
@@ -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);
 }
 
index 3479134..58e2859 100644 (file)
@@ -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;
 }
index 6af8b39..8e8a645 100644 (file)
@@ -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;
 }
 
index 18499af..e727c85 100644 (file)
@@ -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;
+}