diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 1c44f87837..2d62b5b4f0 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2085,7 +2085,8 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt); * correct values. * @endparblock * - * @return 0 on success, a negative AVERROR on error. + * @return 0 on success, a negative AVERROR on error. Libavformat will always + * take care of freeing the packet, even if this function fails. * * @see av_write_frame(), AVFormatContext.max_interleave_delta */ diff --git a/libavformat/mux.c b/libavformat/mux.c index 0b89406f4e..14e72e8cd8 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -808,22 +808,26 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) ret = check_packet(s, pkt); if (ret < 0) - return ret; + goto fail; if (pkt) { AVStream *st = s->streams[pkt->stream_index]; //FIXME/XXX/HACK drop zero sized packets - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->size == 0) - return 0; + if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->size == 0) { + ret = 0; + goto fail; + } av_dlog(s, "av_interleaved_write_frame size:%d dts:%s pts:%s\n", pkt->size, av_ts2str(pkt->dts), av_ts2str(pkt->pts)); if ((ret = compute_pkt_fields2(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) - return ret; + goto fail; - if (pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) - return AVERROR(EINVAL); + if (pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { + ret = AVERROR(EINVAL); + goto fail; + } } else { av_dlog(s, "av_interleaved_write_frame FLUSH\n"); flush = 1; @@ -832,6 +836,11 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) for (;; ) { AVPacket opkt; int ret = interleave_packet(s, &opkt, pkt, flush); + if (pkt) { + memset(pkt, 0, sizeof(*pkt)); + av_init_packet(pkt); + pkt = NULL; + } if (ret <= 0) //FIXME cleanup needed for ret<0 ? return ret; @@ -840,13 +849,15 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) s->streams[opkt.stream_index]->nb_frames++; av_free_packet(&opkt); - pkt = NULL; if (ret < 0) return ret; if(s->pb && s->pb->error) return s->pb->error; } +fail: + av_packet_unref(pkt); + return ret; } int av_write_trailer(AVFormatContext *s)