[FFmpeg-devel] [PATCH] ffmpeg: insert bitmap subtitles as video in filters.

Stefano Sabatini stefasab at gmail.com
Wed Aug 1 22:30:16 CEST 2012


On date Wednesday 2012-08-01 16:06:26 +0200, Nicolas George encoded:
> With this feature, it becomes possible to perform commonly
> requested tasks, such as hardcoding bitmap subtitles.
> 
> This will be reverted once libavfilter has proper support
> for subtitles. All the changes have the string "sub2video"
> in them, it makes it easy to spot the parts.
> 
> Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
> ---
>  Changelog       |    1 +
>  doc/ffmpeg.texi |   16 +++++
>  ffmpeg.c        |  174 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 187 insertions(+), 4 deletions(-)
> 
> 
> Updated according to Stefano's remarks.
[...]
> +static void sub2video_heartbeat(InputStream *ist, int64_t pts)
> +{
> +    InputFile *infile = input_files[ist->file_index];
> +    int i, j, nb_reqs;
> +    int64_t pts2;
> +
> +    /* When a frame is read from a file, examine all sub2video streams in
> +       the same file and send the sub2video frame again. Otherwise, decoded
> +       video frames could be accumulating in the filter graph while a filter
> +       (possibly overlay) is desperately waiting for a subtitle frame. */
> +    for (i = 0; i < infile->nb_streams; i++) {
> +        InputStream *ist2 = input_streams[infile->ist_index + i];
> +        if (!ist2->sub2video.ref)
> +            continue;
> +        /* subtitles seem to be usually muxed ahead of other streams;
> +           if not, substracting a reasonable time here is necessary */
> +        pts2 = av_rescale_q(pts, ist->st->time_base, ist2->st->time_base);
> +        /* do not send the heartbeat frame if the subtitle is already ahead */
> +        if (pts2 <= ist2->sub2video.last_pts)
> +            continue;

> +        for (j = 0, nb_reqs = 0; j < ist2->nb_filters; j++)
> +            nb_reqs += av_buffersrc_get_nb_failed_requests(ist2->filters[j]->filter);
> +        if (nb_reqs)
> +            sub2video_push_ref(ist2, pts2);

I suppose that means that the frames are pushed only if thery were
previously requested on any of the buffersrc sources connected to the
stream, but could not have been provided.

> +    }
[...]
> @@ -2633,13 +2794,16 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
>      AVSubtitle subtitle;
>      int i, ret = avcodec_decode_subtitle2(ist->st->codec,
>                                            &subtitle, got_output, pkt);
> -    if (ret < 0)
> -        return ret;
> -    if (!*got_output)
> +    if (ret < 0 || !*got_output) {
> +        if (!pkt->size)
> +            sub2video_flush(ist);
>          return ret;
> +    }
>  
>      rate_emu_sleep(ist);
>  
> +    sub2video_update(ist, &subtitle, pkt->pts);
> +
>      for (i = 0; i < nb_output_streams; i++) {
>          OutputStream *ost = output_streams[i];
>  
> @@ -3844,6 +4008,8 @@ static int transcode(void)
>              }
>          }
>  

> +        sub2video_heartbeat(ist, pkt.pts);

Should we call this function only for video packets?

[...]

I couldn't spot any apparent error in the logic, so it is fine to me
if reasonably tested and works.

Thanks for the nice "hack".
-- 
FFmpeg = Frightening and Forgiving Muttering Practical EnGraver


More information about the ffmpeg-devel mailing list