Commit eb447d51 authored by Martin Storsjö's avatar Martin Storsjö

segment: Free and reinit the muxer before calling avformat_write_header

This makes sure the muxers are set up in the way they expect
with no data left around from the previous run (which could
cause various issues including memory leaks, depending on the chaine
muxer).

This fixes memory leaks with the mpegts and flv muxers. It also
makes the usage of chained muxers correct.
Signed-off-by: 's avatarMartin Storsjö <martin@martin.st>
parent 73871dc9
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
typedef struct { typedef struct {
const AVClass *class; /**< Class for private options. */ const AVClass *class; /**< Class for private options. */
int number; int number;
AVOutputFormat *oformat;
AVFormatContext *avf; AVFormatContext *avf;
char *format; /**< Set by a private option. */ char *format; /**< Set by a private option. */
char *list; /**< Set by a private option. */ char *list; /**< Set by a private option. */
...@@ -45,12 +46,42 @@ typedef struct { ...@@ -45,12 +46,42 @@ typedef struct {
AVIOContext *pb; AVIOContext *pb;
} SegmentContext; } SegmentContext;
static int segment_mux_init(AVFormatContext *s)
{
SegmentContext *seg = s->priv_data;
AVFormatContext *oc;
int i;
seg->avf = oc = avformat_alloc_context();
if (!oc)
return AVERROR(ENOMEM);
oc->oformat = seg->oformat;
oc->interrupt_callback = s->interrupt_callback;
for (i = 0; i < s->nb_streams; i++) {
AVStream *st;
if (!(st = avformat_new_stream(oc, NULL)))
return AVERROR(ENOMEM);
avcodec_copy_context(st->codec, s->streams[i]->codec);
st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
}
return 0;
}
static int segment_start(AVFormatContext *s) static int segment_start(AVFormatContext *s)
{ {
SegmentContext *c = s->priv_data; SegmentContext *c = s->priv_data;
AVFormatContext *oc = c->avf; AVFormatContext *oc = c->avf;
int err = 0; int err = 0;
avformat_free_context(oc);
c->avf = NULL;
if ((err = segment_mux_init(s)) < 0)
return err;
oc = c->avf;
if (c->wrap) if (c->wrap)
c->number %= c->wrap; c->number %= c->wrap;
...@@ -81,18 +112,13 @@ static int segment_end(AVFormatContext *oc) ...@@ -81,18 +112,13 @@ static int segment_end(AVFormatContext *oc)
static int seg_write_header(AVFormatContext *s) static int seg_write_header(AVFormatContext *s)
{ {
SegmentContext *seg = s->priv_data; SegmentContext *seg = s->priv_data;
AVFormatContext *oc; AVFormatContext *oc = NULL;
int ret, i; int ret, i;
seg->number = 0; seg->number = 0;
seg->offset_time = 0; seg->offset_time = 0;
seg->recording_time = seg->time * 1000000; seg->recording_time = seg->time * 1000000;
oc = avformat_alloc_context();
if (!oc)
return AVERROR(ENOMEM);
if (seg->list) if (seg->list)
if ((ret = avio_open2(&seg->pb, seg->list, AVIO_FLAG_WRITE, if ((ret = avio_open2(&seg->pb, seg->list, AVIO_FLAG_WRITE,
&s->interrupt_callback, NULL)) < 0) &s->interrupt_callback, NULL)) < 0)
...@@ -107,31 +133,22 @@ static int seg_write_header(AVFormatContext *s) ...@@ -107,31 +133,22 @@ static int seg_write_header(AVFormatContext *s)
"More than a single video stream present, " "More than a single video stream present, "
"expect issues decoding it.\n"); "expect issues decoding it.\n");
oc->oformat = av_guess_format(seg->format, s->filename, NULL); seg->oformat = av_guess_format(seg->format, s->filename, NULL);
if (!oc->oformat) { if (!seg->oformat) {
ret = AVERROR_MUXER_NOT_FOUND; ret = AVERROR_MUXER_NOT_FOUND;
goto fail; goto fail;
} }
if (oc->oformat->flags & AVFMT_NOFILE) { if (seg->oformat->flags & AVFMT_NOFILE) {
av_log(s, AV_LOG_ERROR, "format %s not supported.\n", av_log(s, AV_LOG_ERROR, "format %s not supported.\n",
oc->oformat->name); oc->oformat->name);
ret = AVERROR(EINVAL); ret = AVERROR(EINVAL);
goto fail; goto fail;
} }
oc->interrupt_callback = s->interrupt_callback; if ((ret = segment_mux_init(s)) < 0)
seg->avf = oc; goto fail;
oc = seg->avf;
for (i = 0; i < s->nb_streams; i++) {
AVStream *st;
if (!(st = avformat_new_stream(oc, NULL))) {
ret = AVERROR(ENOMEM);
goto fail;
}
avcodec_copy_context(st->codec, s->streams[i]->codec);
st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
}
if (av_get_frame_filename(oc->filename, sizeof(oc->filename), if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
s->filename, seg->number++) < 0) { s->filename, seg->number++) < 0) {
...@@ -157,7 +174,8 @@ fail: ...@@ -157,7 +174,8 @@ fail:
if (ret) { if (ret) {
if (seg->list) if (seg->list)
avio_close(seg->pb); avio_close(seg->pb);
avformat_free_context(oc); if (seg->avf)
avformat_free_context(seg->avf);
} }
return ret; return ret;
} }
...@@ -186,6 +204,8 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -186,6 +204,8 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
if (ret) if (ret)
goto fail; goto fail;
oc = seg->avf;
if (seg->list) { if (seg->list) {
avio_printf(seg->pb, "%s\n", oc->filename); avio_printf(seg->pb, "%s\n", oc->filename);
avio_flush(seg->pb); avio_flush(seg->pb);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment