From 9f61abc8111c7c43f49ca012e957a108b9cc7610 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 16 Jan 2016 17:53:43 +0100 Subject: lavf: allow custom IO for all files 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. --- 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 +++++++ 14 files changed, 126 insertions(+), 68 deletions(-) (limited to 'libavformat') diff --git a/libavformat/avformat.h b/libavformat/avformat.h index cd53420215..4926a354f9 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 cedd83b67b..12d3a8c45b 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\n"); avio_printf(out, "\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 d96a3d5599..a2710ded40 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, "\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 dc3ab87b8a..d3b4b58d01 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 8f01047be0..843f37d82c 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 eb2508738e..ec3a829532 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 d5b664658f..4071c3545c 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 17c45f6dab..ed9893033a 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 28d78e3dcb..06169639ed 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; } } @@ -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); diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 1026baeae2..c91286350c 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 a6fbbd2623..c7fa51f41f 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 3479134ec8..58e285911a 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 6af8b3991c..8e8a64513c 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, "\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 18499af8d6..e727c850b3 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; +} -- cgit v1.2.3