[FFmpeg-devel] [PATCH 1/4] ffmpeg: Flush output BSFs when encode reaches EOF
wm4
nfxjfg at googlemail.com
Mon Jun 19 11:21:57 EEST 2017
On Sun, 18 Jun 2017 23:09:23 +0100
Mark Thompson <sw at jkqxz.net> wrote:
> Before this, output bitstream filters would never see EOF and
> therefore would not be able to flush any delayed packets.
>
> (cherry picked from commit f64d1100a54d12c78ce436181bb64229c56da6b3)
> ---
> ffmpeg.c | 30 +++++++++++++++++++-----------
> 1 file changed, 19 insertions(+), 11 deletions(-)
>
> diff --git a/ffmpeg.c b/ffmpeg.c
> index 6170bd453c..f265980fdd 100644
> --- a/ffmpeg.c
> +++ b/ffmpeg.c
> @@ -814,7 +814,8 @@ static void close_output_stream(OutputStream *ost)
> }
> }
>
> -static void output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
> +static void output_packet(OutputFile *of, AVPacket *pkt,
> + OutputStream *ost, int eof)
> {
> int ret = 0;
>
> @@ -822,10 +823,11 @@ static void output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
> if (ost->nb_bitstream_filters) {
> int idx;
>
> - ret = av_bsf_send_packet(ost->bsf_ctx[0], pkt);
> + ret = av_bsf_send_packet(ost->bsf_ctx[0], eof ? NULL : pkt);
> if (ret < 0)
> goto finish;
>
> + eof = 0;
> idx = 1;
> while (idx) {
> /* get a packet from the previous filter up the chain */
> @@ -834,19 +836,24 @@ static void output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
> ret = 0;
> idx--;
> continue;
> + } else if (ret == AVERROR_EOF) {
> + eof = 1;
> } else if (ret < 0)
> goto finish;
>
> /* send it to the next filter down the chain or to the muxer */
> if (idx < ost->nb_bitstream_filters) {
> - ret = av_bsf_send_packet(ost->bsf_ctx[idx], pkt);
> + ret = av_bsf_send_packet(ost->bsf_ctx[idx], eof ? NULL : pkt);
> if (ret < 0)
> goto finish;
> idx++;
> - } else
> + eof = 0;
> + } else if (eof)
> + goto finish;
> + else
> write_packet(of, pkt, ost, 0);
> }
> - } else
> + } else if (!eof)
> write_packet(of, pkt, ost, 0);
>
> finish:
> @@ -922,7 +929,7 @@ static void do_audio_out(OutputFile *of, OutputStream *ost,
> av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &enc->time_base));
> }
>
> - output_packet(of, &pkt, ost);
> + output_packet(of, &pkt, ost, 0);
> }
>
> return;
> @@ -1010,7 +1017,7 @@ static void do_subtitle_out(OutputFile *of,
> pkt.pts += av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase);
> }
> pkt.dts = pkt.pts;
> - output_packet(of, &pkt, ost);
> + output_packet(of, &pkt, ost, 0);
> }
> }
>
> @@ -1196,7 +1203,7 @@ static void do_video_out(OutputFile *of,
> pkt.pts = av_rescale_q(in_picture->pts, enc->time_base, ost->mux_timebase);
> pkt.flags |= AV_PKT_FLAG_KEY;
>
> - output_packet(of, &pkt, ost);
> + output_packet(of, &pkt, ost, 0);
> } else
> #endif
> {
> @@ -1299,7 +1306,7 @@ static void do_video_out(OutputFile *of,
> }
>
> frame_size = pkt.size;
> - output_packet(of, &pkt, ost);
> + output_packet(of, &pkt, ost, 0);
>
> /* if two pass, output log */
> if (ost->logfile && enc->stats_out) {
> @@ -1930,6 +1937,7 @@ static void flush_encoders(void)
> fprintf(ost->logfile, "%s", enc->stats_out);
> }
> if (ret == AVERROR_EOF) {
> + output_packet(of, &pkt, ost, 1);
> break;
> }
> if (ost->finished & MUXER_FINISHED) {
> @@ -1938,7 +1946,7 @@ static void flush_encoders(void)
> }
> av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase);
> pkt_size = pkt.size;
> - output_packet(of, &pkt, ost);
> + output_packet(of, &pkt, ost, 0);
> if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) {
> do_video_stats(ost, pkt_size);
> }
> @@ -2077,7 +2085,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
> }
> #endif
>
> - output_packet(of, &opkt, ost);
> + output_packet(of, &opkt, ost, 0);
> }
>
> int guess_input_channel_layout(InputStream *ist)
Not sure why flushing can't just be done with output_packet(of, NULL,
ost)?
But if it works ok I guess (and preferable to having different code
than in Libav).
More information about the ffmpeg-devel
mailing list