summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2017-10-18 23:54:23 +0100
committerCarl Hetherington <cth@carlh.net>2017-10-18 23:54:23 +0100
commit19988f49c34b6f420da5a7014fc7c205e8e895a2 (patch)
treeac55a92358daa0acfdb20c40d923e59893c1b173
parent5c4d1e131d516683925cb543913c6182a3de0506 (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.cc60
-rw-r--r--src/lib/dcp_decoder.h1
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;