Previously only 1:1 bitstream filters were supported, the end of the stream was not signalled to the bitstream filters and time base changes were ignored.
Signed-off-by: Marton Balint <c...@passwd.hu> --- libavformat/mux.c | 91 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 34 deletions(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index 4118d221e0..c2b6d4461e 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -822,14 +822,13 @@ static int prepare_input_packet(AVFormatContext *s, AVPacket *pkt) return 0; } -static int do_packet_auto_bsf(AVFormatContext *s, AVPacket *pkt) { - AVStream *st = s->streams[pkt->stream_index]; +static int need_auto_bsf(AVFormatContext *s, AVStream *st, AVPacket *pkt) { int ret; if (!(s->flags & AVFMT_FLAG_AUTO_BSF)) - return 1; + return 0; - if (s->oformat->check_bitstream) { + if (pkt && s->oformat->check_bitstream) { if (!st->internal->bitstream_checked) { if ((ret = s->oformat->check_bitstream(s, pkt)) < 0) return ret; @@ -838,31 +837,7 @@ static int do_packet_auto_bsf(AVFormatContext *s, AVPacket *pkt) { } } - if (st->internal->bsfc) { - AVBSFContext *ctx = st->internal->bsfc; - // TODO: when any bitstream filter requires flushing at EOF, we'll need to - // flush each stream's BSF chain on write_trailer. - if ((ret = av_bsf_send_packet(ctx, pkt)) < 0) { - av_log(ctx, AV_LOG_ERROR, - "Failed to send packet to filter %s for stream %d\n", - ctx->filter->name, pkt->stream_index); - return ret; - } - // TODO: when any automatically-added bitstream filter is generating multiple - // output packets for a single input one, we'll need to call this in a loop - // and write each output packet. - if ((ret = av_bsf_receive_packet(ctx, pkt)) < 0) { - if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) - return 0; - av_log(ctx, AV_LOG_ERROR, - "Failed to receive packet from filter %s for stream %d\n", - ctx->filter->name, pkt->stream_index); - if (s->error_recognition & AV_EF_EXPLODE) - return ret; - return 0; - } - } - return 1; + return !!st->internal->bsfc; } static int interleaved_write_packet(AVFormatContext *s, AVPacket *pkt, int flush); @@ -889,17 +864,56 @@ static int write_packet_common(AVFormatContext *s, AVStream *st, AVPacket *pkt, } } +static int write_packets_from_bsfs(AVFormatContext *s, AVStream *st, AVPacket *pkt, int interleaved) +{ + AVBSFContext *bsfc = st->internal->bsfc; + AVPacket opkt = {0}; + int ret; + + if ((ret = av_bsf_send_packet(bsfc, pkt)) < 0) { + av_log(s, AV_LOG_ERROR, + "Failed to send packet to filter %s for stream %d\n", + bsfc->filter->name, st->index); + return ret; + } + + do { + ret = av_bsf_receive_packet(bsfc, &opkt); + if (ret < 0) { + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + ret = 0; + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Error applying bitstream filters to an output " + "packet for stream #%d: %s\n", st->index, av_err2str(ret)); + if (!(s->error_recognition & AV_EF_EXPLODE) && ret != AVERROR(ENOMEM)) + continue; + } + return ret; + } + av_packet_rescale_ts(&opkt, bsfc->time_base_out, st->time_base); + ret = write_packet_common(s, st, &opkt, interleaved); + if (!interleaved) // write_packet_common already unrefed opkt for interleaved + av_packet_unref(&opkt); + } while (ret >= 0); + + return ret; +} + static int write_packets_common(AVFormatContext *s, AVStream *st, AVPacket *pkt, int interleaved) { int ret = prepare_input_packet(s, pkt); if (ret < 0) return ret; - ret = do_packet_auto_bsf(s, pkt); - if (ret <= 0) + ret = need_auto_bsf(s, st, pkt); + if (ret < 0) return ret; - return write_packet_common(s, st, pkt, interleaved); + if (ret) { + return write_packets_from_bsfs(s, st, pkt, interleaved); + } else { + return write_packet_common(s, st, pkt, interleaved); + } } int av_write_frame(AVFormatContext *s, AVPacket *in) @@ -1254,9 +1268,18 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) int av_write_trailer(AVFormatContext *s) { - int ret, i; + int i, ret1, ret = 0; - ret = interleaved_write_packet(s, NULL, 1); + for (i = 0; i < s->nb_streams; i++) { + if (need_auto_bsf(s, s->streams[i], NULL)) { + ret1 = write_packets_from_bsfs(s, s->streams[i], NULL, 1/*interleaved*/); + if (ret >= 0) + ret = ret1; + } + } + ret1 = interleaved_write_packet(s, NULL, 1); + if (ret >= 0) + ret = ret1; if (s->oformat->write_trailer) { if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) -- 2.16.4 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".