diff --git a/libavformat/avformat.h b/libavformat/avformat.h index f054f7a405..a2af7e9f89 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -553,9 +553,21 @@ typedef struct AVOutputFormat { /** * A format-specific function for interleavement. * If unset, packets will be interleaved by dts. - */ - int (*interleave_packet)(struct AVFormatContext *, AVPacket *out, - AVPacket *in, int flush); + * + * @param s An AVFormatContext for output. pkt will be added to + * resp. taken from its packet buffer. + * @param[in,out] pkt A packet to be interleaved if has_packet is set; + * also used to return packets. If no packet is returned + * (e.g. on error), pkt is blank on return. + * @param flush 1 if no further packets are available as input and + * all remaining packets should be output. + * @param has_packet If set, pkt contains a packet to be interleaved + * on input; otherwise pkt is blank on input. + * @return 1 if a packet was output, 0 if no packet could be output, + * < 0 if an error occurred + */ + int (*interleave_packet)(struct AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet); /** * Test if the given codec can be stored in this container. * diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c index 8cc3bd456e..133d1e9fb3 100644 --- a/libavformat/gxfenc.c +++ b/libavformat/gxfenc.c @@ -992,10 +992,11 @@ static int gxf_compare_field_nb(AVFormatContext *s, const AVPacket *next, (field_nb[1] == field_nb[0] && sc[1]->order > sc[0]->order); } -static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) +static int gxf_interleave_packet(AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet) { int ret; - if (pkt) { + if (has_packet) { AVStream *st = s->streams[pkt->stream_index]; GXFStreamContext *sc = st->priv_data; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) @@ -1006,7 +1007,7 @@ static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pk if ((ret = ff_interleave_add_packet(s, pkt, gxf_compare_field_nb)) < 0) return ret; } - return ff_interleave_packet_per_dts(s, out, NULL, flush); + return ff_interleave_packet_per_dts(s, pkt, flush, 0); } const AVOutputFormat ff_gxf_muxer = { diff --git a/libavformat/internal.h b/libavformat/internal.h index 6f1f1c072a..98341ba217 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -107,7 +107,8 @@ typedef struct FFFormatContext { struct PacketList *parse_queue_end; /** * The generic code uses this as a temporary packet - * to parse packets; it may also be used for other means + * to parse packets or for muxing, especially flushing. + * For demuxers, it may also be used for other means * for short periods that are guaranteed not to overlap * with calls to av_read_frame() (or ff_read_packet()) * or with each other. @@ -746,18 +747,10 @@ int ff_add_attached_pic(AVFormatContext *s, AVStream *st, AVIOContext *pb, /** * Interleave an AVPacket per dts so it can be muxed. - * - * @param s an AVFormatContext for output. pkt resp. out will be added to - * resp. taken from its packet buffer. - * @param out the interleaved packet will be output here - * @param pkt the input packet; will be blank on return if not NULL - * @param flush 1 if no further packets are available as input and all - * remaining packets should be output - * @return 1 if a packet was output, 0 if no packet could be output - * (in which case out may be uninitialized), < 0 if an error occurred - */ -int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, - AVPacket *pkt, int flush); + * See the documentation of AVOutputFormat.interleave_packet for details. + */ +int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet); void ff_free_stream(AVFormatContext *s, AVStream *st); diff --git a/libavformat/mux.c b/libavformat/mux.c index d7b2bdb4b3..d924bb08fc 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -903,8 +903,8 @@ static int interleave_compare_dts(AVFormatContext *s, const AVPacket *next, return comp > 0; } -int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, - AVPacket *pkt, int flush) +int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet) { FFFormatContext *const si = ffformatcontext(s); int stream_count = 0; @@ -912,7 +912,7 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, int ret; int eof = flush; - if (pkt) { + if (has_packet) { if ((ret = ff_interleave_add_packet(s, pkt, interleave_compare_dts)) < 0) return ret; } @@ -1009,7 +1009,7 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVStream *const st = s->streams[pktl->pkt.stream_index]; FFStream *const sti = ffstream(st); - *out = pktl->pkt; + *pkt = pktl->pkt; si->packet_buffer = pktl->next; if (!si->packet_buffer) @@ -1055,20 +1055,16 @@ const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream) } /** - * Interleave an AVPacket correctly so it can be muxed. - * @param out the interleaved packet will be output here - * @param in the input packet; will always be blank on return if not NULL - * @param flush 1 if no further packets are available as input and all - * remaining packets should be output - * @return 1 if a packet was output, 0 if no packet could be output, - * < 0 if an error occurred + * A wrapper around AVOutputFormat.interleave_packet. + * See its documentation for details. */ -static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush) +static int interleave_packet(AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet) { if (s->oformat->interleave_packet) { - return s->oformat->interleave_packet(s, out, in, flush); + return s->oformat->interleave_packet(s, pkt, flush, has_packet); } else - return ff_interleave_packet_per_dts(s, out, in, flush); + return ff_interleave_packet_per_dts(s, pkt, flush, has_packet); } static int check_bitstream(AVFormatContext *s, FFStream *sti, AVPacket *pkt) @@ -1090,20 +1086,18 @@ static int check_bitstream(AVFormatContext *s, FFStream *sti, AVPacket *pkt) return 1; } -static int interleaved_write_packet(AVFormatContext *s, AVPacket *pkt, int flush) +static int interleaved_write_packet(AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet) { for (;; ) { - AVPacket opkt; - int ret = interleave_packet(s, &opkt, pkt, flush); + int ret = interleave_packet(s, pkt, flush, has_packet); if (ret <= 0) return ret; - pkt = NULL; - - ret = write_packet(s, &opkt); - - av_packet_unref(&opkt); + has_packet = 0; + ret = write_packet(s, pkt); + av_packet_unref(pkt); if (ret < 0) return ret; } @@ -1127,7 +1121,7 @@ static int write_packet_common(AVFormatContext *s, AVStream *st, AVPacket *pkt, if (interleaved) { if (pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) return AVERROR(EINVAL); - return interleaved_write_packet(s, pkt, 0); + return interleaved_write_packet(s, pkt, 0, 1); } else { return write_packet(s, pkt); } @@ -1251,7 +1245,7 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) return ret; } else { av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame FLUSH\n"); - return interleaved_write_packet(s, NULL, 1/*flush*/); + return interleaved_write_packet(s, ffformatcontext(s)->parse_pkt, 1/*flush*/, 0); } } @@ -1271,7 +1265,7 @@ int av_write_trailer(AVFormatContext *s) ret = ret1; } } - ret1 = interleaved_write_packet(s, NULL, 1); + ret1 = interleaved_write_packet(s, pkt, 1, 0); if (ret >= 0) ret = ret1; diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 56facbe4b7..c36ebef932 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -3096,7 +3096,7 @@ static void mxf_deinit(AVFormatContext *s) } } -static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) +static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flush) { FFFormatContext *const si = ffformatcontext(s); int i, stream_count = 0; @@ -3161,16 +3161,17 @@ static int mxf_compare_timestamps(AVFormatContext *s, const AVPacket *next, (next->dts == pkt->dts && sc->order < sc2->order); } -static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) +static int mxf_interleave(AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet) { int ret; - if (pkt) { + if (has_packet) { MXFStreamContext *sc = s->streams[pkt->stream_index]->priv_data; pkt->pts = pkt->dts = sc->pkt_cnt++; if ((ret = ff_interleave_add_packet(s, pkt, mxf_compare_timestamps)) < 0) return ret; } - return mxf_interleave_get_packet(s, out, NULL, flush); + return mxf_interleave_get_packet(s, pkt, flush); } #define MXF_COMMON_OPTIONS \