diff options
| author | Carl Hetherington <cth@carlh.net> | 2017-10-18 23:54:23 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2017-10-18 23:54:23 +0100 |
| commit | 19988f49c34b6f420da5a7014fc7c205e8e895a2 (patch) | |
| tree | ac55a92358daa0acfdb20c40d923e59893c1b173 | |
| parent | 5c4d1e131d516683925cb543913c6182a3de0506 (diff) | |
Pre-roll subtitles when accurate seeking in DCPs to avoid disappearing subs on frame-advance (and in other cases).
| -rw-r--r-- | src/lib/dcp_decoder.cc | 60 | ||||
| -rw-r--r-- | src/lib/dcp_decoder.h | 1 |
2 files changed, 50 insertions, 11 deletions
diff --git a/src/lib/dcp_decoder.cc b/src/lib/dcp_decoder.cc index 59a85e051..44053c5df 100644 --- a/src/lib/dcp_decoder.cc +++ b/src/lib/dcp_decoder.cc @@ -158,6 +158,27 @@ DCPDecoder::pass () audio->emit (_dcp_content->audio->stream(), data, ContentTime::from_frames (_offset, vfr) + _next); } + pass_subtitles (_next); + + _next += ContentTime::from_frames (1, vfr); + + if ((*_reel)->main_picture ()) { + if (_next.frames_round (vfr) >= (*_reel)->main_picture()->duration()) { + next_reel (); + _next = ContentTime (); + } + } + + return false; +} + +void +DCPDecoder::pass_subtitles (ContentTime next) +{ + double const vfr = _dcp_content->active_video_frame_rate (); + /* Frame within the (played part of the) reel that is coming up next */ + int64_t const frame = next.frames_round (vfr); + if ((*_reel)->main_subtitle() && (_decode_referenced || !_dcp_content->reference_subtitle())) { int64_t const entry_point = (*_reel)->main_subtitle()->entry_point (); list<dcp::SubtitleString> subs = (*_reel)->main_subtitle()->asset()->subtitles_during ( @@ -177,17 +198,6 @@ DCPDecoder::pass () ); } } - - _next += ContentTime::from_frames (1, vfr); - - if ((*_reel)->main_picture ()) { - if (_next.frames_round (vfr) >= (*_reel)->main_picture()->duration()) { - next_reel (); - _next = ContentTime (); - } - } - - return false; } void @@ -241,6 +251,34 @@ DCPDecoder::seek (ContentTime t, bool accurate) _offset = 0; get_readers (); + if (accurate) { + int const pre_roll_seconds = 2; + + /* Pre-roll for subs */ + + ContentTime pre = t - ContentTime::from_seconds (pre_roll_seconds); + if (pre < ContentTime()) { + pre = ContentTime (); + } + + /* Seek to pre-roll position */ + + while (_reel != _reels.end() && pre >= ContentTime::from_frames ((*_reel)->main_picture()->duration(), _dcp_content->active_video_frame_rate ())) { + pre -= ContentTime::from_frames ((*_reel)->main_picture()->duration(), _dcp_content->active_video_frame_rate ()); + next_reel (); + } + + /* Pass subtitles in the pre-roll */ + + double const vfr = _dcp_content->active_video_frame_rate (); + for (int i = 0; i < pre_roll_seconds * vfr; ++i) { + pass_subtitles (pre); + pre += ContentTime::from_frames (1, vfr); + } + } + + /* Seek to correct position */ + while (_reel != _reels.end() && t >= ContentTime::from_frames ((*_reel)->main_picture()->duration(), _dcp_content->active_video_frame_rate ())) { t -= ContentTime::from_frames ((*_reel)->main_picture()->duration(), _dcp_content->active_video_frame_rate ()); next_reel (); diff --git a/src/lib/dcp_decoder.h b/src/lib/dcp_decoder.h index 6ec9de684..7238f3bb2 100644 --- a/src/lib/dcp_decoder.h +++ b/src/lib/dcp_decoder.h @@ -56,6 +56,7 @@ private: void next_reel (); void get_readers (); + void pass_subtitles (ContentTime next); /** Time of next thing to return from pass relative to the start of _reel */ ContentTime _next; |
