[FFmpeg-devel] ffmpeg: prevent premature EOF in sub2video with nullptr AVSubtitles

Submitted by Jan Ekström on March 31, 2018, 10:12 p.m.

Details

Message ID CAEu79SYk+cHD_3OzkvCN=bFGv7LRFSBZFWrJmqgu3d+8VextJA@mail.gmail.com
State New
Headers show

Commit Message

Jan Ekström March 31, 2018, 10:12 p.m.
On Sat, Mar 31, 2018 at 8:09 PM, Jan Ekström <jeebjp@gmail.com> wrote:
> With certain types of input and the filter chain getting re-initialized
> or re-configured, multiple nullptr AVSubtitles can get pushed into
> sub2video_update() in a row from sub2video_heartbeat.
>
> This causes end_pts, and on the next round pts, to become INT64_MAX,
> latter of which signals EOF in framesync, leading to complete loss of
> subtitles from that point on.
>
> Thus, check that the sub2video.end_pts is smaller than INT64_MAX
> in a similar fashion to sub2video_flush before sending out the
> nullptr AVSubtitle. This keeps premature EOFs from happening in
> framesync and the subtitle overlay is kept past the filter chain
> re-initializations/configurations.
> ---
>  fftools/ffmpeg.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
> index 4724f62fff..d3bc382dec 100644
> --- a/fftools/ffmpeg.c
> +++ b/fftools/ffmpeg.c
> @@ -285,7 +285,8 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts)
>          /* do not send the heartbeat frame if the subtitle is already ahead */
>          if (pts2 <= ist2->sub2video.last_pts)
>              continue;
> -        if (pts2 >= ist2->sub2video.end_pts || !ist2->sub2video.frame->data[0])
> +        if (pts2 >= ist2->sub2video.end_pts ||
> +            (!ist2->sub2video.frame->data[0] && ist2->sub2video.end_pts < INT64_MAX))
>              sub2video_update(ist2, NULL);
>          for (j = 0, nb_reqs = 0; j < ist2->nb_filters; j++)
>              nb_reqs += av_buffersrc_get_nb_failed_requests(ist2->filters[j]->filter);
> --
> 2.14.3
>

A diff which I utilized to help with testing this. I can share a
sample to test this over on IRC.

Jan
---

     if (sub2video_get_blank_frame(ist) < 0) {
         av_log(ist->dec_ctx, AV_LOG_ERROR,

Patch hide | download patch | download mbox

--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -247,10 +247,17 @@  void sub2video_update(InputStream *ist, AVSubtitle *sub)
         end_pts   = av_rescale_q(sub->pts + sub->end_display_time   * 1000LL,
                                  AV_TIME_BASE_Q, ist->st->time_base);
         num_rects = sub->num_rects;
+        av_log(ist->dec_ctx, AV_LOG_WARNING,
+               "normal AVSubtitle: utilized values: pts=%"PRId64",
end_pts=%"PRId64", "
+               "num_rects=%d\n",
+               pts, end_pts, num_rects);
     } else {
         pts       = ist->sub2video.end_pts;
         end_pts   = INT64_MAX;
         num_rects = 0;
+        av_log(ist->dec_ctx, AV_LOG_WARNING,
+               "nullptr AVSubtitle: utilized values: pts=%"PRId64",
end_pts=%"PRId64"\n",
+               pts, end_pts);
     }