[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