diff options
| author | Carl Hetherington <cth@carlh.net> | 2016-11-20 22:08:11 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2016-11-20 22:08:11 +0000 |
| commit | 4337694dfd488e88f56b63898ad35ce8ce9bb3c3 (patch) | |
| tree | 8bba36173e1781eb18a81081e1ae27de4d4962ff /src/lib | |
| parent | 31724651675fc01a33ffa0818d4397858493dd56 (diff) | |
Fix subtitles (seen in DVB) which have a specified `to' time but
then are terminated earlier than that by a num_rects=0 subtitle.
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/ffmpeg_decoder.cc | 12 | ||||
| -rw-r--r-- | src/lib/ffmpeg_examiner.cc | 38 | ||||
| -rw-r--r-- | src/lib/ffmpeg_subtitle_stream.cc | 16 | ||||
| -rw-r--r-- | src/lib/ffmpeg_subtitle_stream.h | 1 |
4 files changed, 37 insertions, 30 deletions
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index ddc563b98..b7dced34d 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -510,13 +510,11 @@ FFmpegDecoder::decode_subtitle_packet () ContentTimePeriod period; period.from = sub_period.from + _pts_offset; subtitle->set_position (period.from); - if (sub_period.to) { - /* We already know the subtitle period `to' time */ - period.to = sub_period.to.get() + _pts_offset; - } else { - /* We have to look up the `to' time in the stream's records */ - period.to = ffmpeg_content()->subtitle_stream()->find_subtitle_to (subtitle_id (sub)); - } + /* We can't trust the `to' time from sub_period as there are some decoders which + give a sub_period time for `to' which is subsequently overridden by a `stop' subtitle; + see also FFmpegExaminer. + */ + period.to = ffmpeg_content()->subtitle_stream()->find_subtitle_to (subtitle_id (sub)); for (unsigned int i = 0; i < sub.num_rects; ++i) { AVSubtitleRect const * rect = sub.rects[i]; diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc index 4c2040f52..271180d5d 100644 --- a/src/lib/ffmpeg_examiner.cc +++ b/src/lib/ffmpeg_examiner.cc @@ -236,32 +236,24 @@ FFmpegExaminer::subtitle_packet (AVCodecContext* context, shared_ptr<FFmpegSubti FFmpegSubtitlePeriod const period = subtitle_period (sub); bool const starts_image = subtitle_starts_image (sub); + /* Some streams (notably DVB streams) have subtitles which have a specified end time + but which are then stopped earlier than this by a zero-num_rect subtitle. + */ + LastSubtitleMap::iterator last = _last_subtitle_start.find (stream); - if (last != _last_subtitle_start.end() && last->second) { - /* We have seen the start of a subtitle but not yet the end. Whatever this is - finishes the previous subtitle, so add it */ - if (last->second->image) { - stream->add_image_subtitle (last->second->id, ContentTimePeriod (last->second->time, period.from)); - } else { - stream->add_text_subtitle (last->second->id, ContentTimePeriod (last->second->time, period.from)); - } - if (sub.num_rects == 0) { - /* This is a `proper' end-of-subtitle */ - _last_subtitle_start[stream] = optional<SubtitleStart> (); + if (sub.num_rects == 0 && last != _last_subtitle_start.end() && last->second) { + /* Set (or fix) the `to' time for the last subtitle */ + stream->set_subtitle_to (last->second->id, period.from); + _last_subtitle_start[stream] = optional<SubtitleStart> (); + } else if (sub.num_rects > 0) { + /* Add a subtitle; if we don't know the `to' time we set it to the from time and fix it later */ + if (starts_image) { + stream->add_image_subtitle (id, ContentTimePeriod (period.from, period.to.get_value_or (period.from))); } else { - /* This is just another subtitle, so we start again */ - _last_subtitle_start[stream] = SubtitleStart (id, starts_image, period.from); - } - } else if (sub.num_rects >= 1) { - if (period.to) { - if (starts_image) { - stream->add_image_subtitle (id, ContentTimePeriod (period.from, period.to.get ())); - } else { - stream->add_text_subtitle (id, ContentTimePeriod (period.from, period.to.get ())); - } - } else { - _last_subtitle_start[stream] = SubtitleStart (id, starts_image, period.from); + stream->add_text_subtitle (id, ContentTimePeriod (period.from, period.to.get_value_or (period.from))); } + + _last_subtitle_start[stream] = SubtitleStart (id, starts_image, period.from); } for (unsigned int i = 0; i < sub.num_rects; ++i) { diff --git a/src/lib/ffmpeg_subtitle_stream.cc b/src/lib/ffmpeg_subtitle_stream.cc index 627b0fef1..57c54e1ea 100644 --- a/src/lib/ffmpeg_subtitle_stream.cc +++ b/src/lib/ffmpeg_subtitle_stream.cc @@ -219,3 +219,19 @@ FFmpegSubtitleStream::has_image () const { return !_image_subtitles.empty (); } + +void +FFmpegSubtitleStream::set_subtitle_to (string id, ContentTime to) +{ + PeriodMap::iterator i = _image_subtitles.find (id); + if (i != _image_subtitles.end ()) { + i->second.to = to; + } else { + i = _text_subtitles.find (id); + if (i != _text_subtitles.end ()) { + i->second.to = to; + } else { + DCPOMATIC_ASSERT (false); + } + } +} diff --git a/src/lib/ffmpeg_subtitle_stream.h b/src/lib/ffmpeg_subtitle_stream.h index 6d4853b8d..33247558f 100644 --- a/src/lib/ffmpeg_subtitle_stream.h +++ b/src/lib/ffmpeg_subtitle_stream.h @@ -36,6 +36,7 @@ public: void add_image_subtitle (std::string id, ContentTimePeriod period); void add_text_subtitle (std::string id, ContentTimePeriod period); + void set_subtitle_to (std::string id, ContentTime to); std::list<ContentTimePeriod> image_subtitles_during (ContentTimePeriod period, bool starting) const; std::list<ContentTimePeriod> text_subtitles_during (ContentTimePeriod period, bool starting) const; ContentTime find_subtitle_to (std::string id) const; |
