Fix missing subtitles embedded in files decoded by FFmpeg (#2060).
authorCarl Hetherington <cth@carlh.net>
Sun, 12 Sep 2021 20:43:52 +0000 (22:43 +0200)
committerCarl Hetherington <cth@carlh.net>
Sun, 12 Sep 2021 23:22:00 +0000 (01:22 +0200)
Since the FFmpeg 4.4 update it seems that AVSubtitle::pts is no longer
set (it's AV_NOPTS_VALUE, i think).

Instead we apparently need to get the PTS from the packet, which in
turn requires the stream's timebase.

src/lib/ffmpeg.cc
src/lib/ffmpeg.h
src/lib/ffmpeg_decoder.cc

index d476b4c298663c64b367224235b2cadac0ede431..31aa182937d24512d3f48c543bf7d4329f4dcc20 100644 (file)
@@ -284,9 +284,9 @@ FFmpeg::avio_seek (int64_t const pos, int whence)
 
 
 FFmpegSubtitlePeriod
 
 
 FFmpegSubtitlePeriod
-FFmpeg::subtitle_period (AVSubtitle const & sub)
+FFmpeg::subtitle_period (AVPacket const* packet, AVStream const* stream, AVSubtitle const & sub)
 {
 {
-       auto const packet_time = ContentTime::from_seconds (static_cast<double> (sub.pts) / AV_TIME_BASE);
+       auto const packet_time = ContentTime::from_seconds (packet->pts * av_q2d(stream->time_base));
 
        if (sub.end_display_time == static_cast<uint32_t> (-1)) {
                /* End time is not known */
 
        if (sub.end_display_time == static_cast<uint32_t> (-1)) {
                /* End time is not known */
index 58223fa97d82cf94593d0aff6339733a0261376b..b0769971e3e9c9f00f4812c51b3333badd6654f8 100644 (file)
@@ -36,6 +36,7 @@ DCPOMATIC_ENABLE_WARNINGS
 
 struct AVFormatContext;
 struct AVFrame;
 
 struct AVFormatContext;
 struct AVFrame;
+struct AVStream;
 struct AVIOContext;
 
 class FFmpegContent;
 struct AVIOContext;
 
 class FFmpegContent;
@@ -63,7 +64,7 @@ protected:
                std::vector<std::shared_ptr<FFmpegAudioStream>> audio_streams, boost::optional<dcpomatic::ContentTime> first_video, double video_frame_rate
                ) const;
 
                std::vector<std::shared_ptr<FFmpegAudioStream>> audio_streams, boost::optional<dcpomatic::ContentTime> first_video, double video_frame_rate
                ) const;
 
-       static FFmpegSubtitlePeriod subtitle_period (AVSubtitle const & sub);
+       static FFmpegSubtitlePeriod subtitle_period (AVPacket const* packet, AVStream const* stream, AVSubtitle const & sub);
 
        std::shared_ptr<const FFmpegContent> _ffmpeg_content;
 
 
        std::shared_ptr<const FFmpegContent> _ffmpeg_content;
 
index 3202dcd3e7b11750213ef0284fa584e198b382d5..72372fca88ab5b7a01e2411c9b30843f87e62c17 100644 (file)
@@ -622,12 +622,14 @@ FFmpegDecoder::decode_and_process_subtitle_packet (AVPacket* packet)
                return;
        }
 
                return;
        }
 
+       auto sub_period = subtitle_period (packet, ffmpeg_content()->subtitle_stream()->stream(_format_context), sub);
+
        /* Stop any current subtitle, either at the time it was supposed to stop, or now if now is sooner */
        if (_have_current_subtitle) {
                if (_current_subtitle_to) {
        /* Stop any current subtitle, either at the time it was supposed to stop, or now if now is sooner */
        if (_have_current_subtitle) {
                if (_current_subtitle_to) {
-                       only_text()->emit_stop (min(*_current_subtitle_to, subtitle_period(sub).from + _pts_offset));
+                       only_text()->emit_stop (min(*_current_subtitle_to, sub_period.from + _pts_offset));
                } else {
                } else {
-                       only_text()->emit_stop (subtitle_period(sub).from + _pts_offset);
+                       only_text()->emit_stop (sub_period.from + _pts_offset);
                }
                _have_current_subtitle = false;
        }
                }
                _have_current_subtitle = false;
        }
@@ -641,7 +643,6 @@ FFmpegDecoder::decode_and_process_subtitle_packet (AVPacket* packet)
        /* Subtitle PTS (within the source, not taking into account any of the
           source that we may have chopped off for the DCP).
        */
        /* Subtitle PTS (within the source, not taking into account any of the
           source that we may have chopped off for the DCP).
        */
-       auto sub_period = subtitle_period (sub);
        ContentTime from;
        from = sub_period.from + _pts_offset;
        if (sub_period.to) {
        ContentTime from;
        from = sub_period.from + _pts_offset;
        if (sub_period.to) {