From ad04d9cd5f529ab64d950c6a4c627678f3f2500d Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 26 Nov 2016 19:26:31 +0000 Subject: [PATCH] Implement subtitles. --- src/lib/player.cc | 119 +++++++++++++++++++++++++++++++++++-- src/lib/player.h | 2 + src/lib/player_subtitles.h | 9 +-- src/lib/writer.cc | 2 +- 4 files changed, 119 insertions(+), 13 deletions(-) diff --git a/src/lib/player.cc b/src/lib/player.cc index ae37d9117..94c2ea37a 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -573,10 +573,36 @@ Player::video (weak_ptr wp, ContentVideo video) return; } - /* XXX: get subs to burn in and burn them in */ + /* Time and period of the frame we will emit */ + DCPTime const time = content_video_to_dcp (piece, video.frame.index()); + DCPTimePeriod const period (time, time + DCPTime::from_frames (1, _film->video_frame_rate())); + /* Get any subtitles */ - DCPTime const time = content_video_to_dcp (piece, video.frame.index()); + optional subtitles; + + BOOST_FOREACH (PlayerSubtitles i, _subtitles) { + + if (!i.period.overlap (period)) { + continue; + } + + list sub_images; + + /* Image subtitles */ + list c = transform_image_subtitles (i.image); + copy (c.begin(), c.end(), back_inserter (sub_images)); + + /* Text subtitles (rendered to an image) */ + if (!i.text.empty ()) { + list s = render_subtitles (i.text, i.fonts, _video_container_size, time); + copy (s.begin (), s.end (), back_inserter (sub_images)); + } + + if (!sub_images.empty ()) { + subtitles = merge (sub_images); + } + } /* Fill gaps */ @@ -606,10 +632,27 @@ Player::video (weak_ptr wp, ContentVideo video) ) ); + if (subtitles) { + _last_video->set_subtitle (subtitles.get ()); + } + _last_video_time = time; cout << "Video @ " << to_string(_last_video_time.get()) << "\n"; Video (_last_video); + + /* Discard any subtitles we no longer need */ + + for (list::iterator i = _subtitles.begin (); i != _subtitles.end(); ) { + list::iterator tmp = i; + ++tmp; + + if (i->period.to < time) { + _subtitles.erase (i); + } + + i = tmp; + } } void @@ -665,15 +708,79 @@ Player::audio (weak_ptr wp, AudioStreamPtr stream, ContentAudio content_a } void -Player::image_subtitle (weak_ptr piece, ContentImageSubtitle subtitle) +Player::image_subtitle (weak_ptr wp, ContentImageSubtitle subtitle) { - /* XXX: Store for video to see */ + shared_ptr piece = wp.lock (); + if (!piece) { + return; + } + + /* Apply content's subtitle offsets */ + subtitle.sub.rectangle.x += piece->content->subtitle->x_offset (); + subtitle.sub.rectangle.y += piece->content->subtitle->y_offset (); + + /* Apply content's subtitle scale */ + subtitle.sub.rectangle.width *= piece->content->subtitle->x_scale (); + subtitle.sub.rectangle.height *= piece->content->subtitle->y_scale (); + + /* Apply a corrective translation to keep the subtitle centred after that scale */ + subtitle.sub.rectangle.x -= subtitle.sub.rectangle.width * (piece->content->subtitle->x_scale() - 1); + subtitle.sub.rectangle.y -= subtitle.sub.rectangle.height * (piece->content->subtitle->y_scale() - 1); + + PlayerSubtitles ps; + ps.image.push_back (subtitle.sub); + ps.period = DCPTimePeriod (content_time_to_dcp (piece, subtitle.period().from), content_time_to_dcp (piece, subtitle.period().to)); + + if (piece->content->subtitle->use() && (piece->content->subtitle->burn() || _always_burn_subtitles)) { + _subtitles.push_back (ps); + } else { + Subtitle (ps); + } } void -Player::text_subtitle (weak_ptr piece, ContentTextSubtitle subtitle) +Player::text_subtitle (weak_ptr wp, ContentTextSubtitle subtitle) { - /* XXX: Store for video to see, or emit */ + shared_ptr piece = wp.lock (); + if (!piece) { + return; + } + + PlayerSubtitles ps; + + BOOST_FOREACH (dcp::SubtitleString s, subtitle.subs) { + s.set_h_position (s.h_position() + piece->content->subtitle->x_offset ()); + s.set_v_position (s.v_position() + piece->content->subtitle->y_offset ()); + float const xs = piece->content->subtitle->x_scale(); + float const ys = piece->content->subtitle->y_scale(); + float size = s.size(); + + /* Adjust size to express the common part of the scaling; + e.g. if xs = ys = 0.5 we scale size by 2. + */ + if (xs > 1e-5 && ys > 1e-5) { + size *= 1 / min (1 / xs, 1 / ys); + } + s.set_size (size); + + /* Then express aspect ratio changes */ + if (fabs (1.0 - xs / ys) > dcp::ASPECT_ADJUST_EPSILON) { + s.set_aspect_adjust (xs / ys); + } + + ps.period = DCPTimePeriod (content_time_to_dcp (piece, subtitle.period().from), content_time_to_dcp (piece, subtitle.period().to)); + + s.set_in (dcp::Time(ps.period.from.seconds(), 1000)); + s.set_out (dcp::Time(ps.period.to.seconds(), 1000)); + ps.text.push_back (SubtitleString (s, piece->content->subtitle->outline_width())); + ps.add_fonts (piece->content->subtitle->fonts ()); + } + + if (piece->content->subtitle->use() && (piece->content->subtitle->burn() || _always_burn_subtitles)) { + _subtitles.push_back (ps); + } else { + Subtitle (ps); + } } void diff --git a/src/lib/player.h b/src/lib/player.h index 80fc9fb70..c04b3367c 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -137,6 +137,8 @@ private: AudioMerger _audio_merger; DCPTime _last_audio_time; + std::list _subtitles; + boost::shared_ptr _audio_processor; boost::signals2::scoped_connection _film_changed_connection; diff --git a/src/lib/player_subtitles.h b/src/lib/player_subtitles.h index a202cf4f8..9ec7b1056 100644 --- a/src/lib/player_subtitles.h +++ b/src/lib/player_subtitles.h @@ -27,18 +27,15 @@ class Font; +/** A set of subtitles which span the same time period */ class PlayerSubtitles { public: - PlayerSubtitles (DCPTime f) - : from (f) - {} - void add_fonts (std::list > fonts_); - - DCPTime from; std::list > fonts; + DCPTimePeriod period; + /** ImageSubtitles, with their rectangles transformed as specified by their content */ std::list image; std::list text; diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 6e6bedb8f..67b00987d 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -548,7 +548,7 @@ Writer::write (PlayerSubtitles subs) return; } - if (_subtitle_reel->period().to <= subs.from) { + if (_subtitle_reel->period().to <= subs.period.from) { ++_subtitle_reel; } -- 2.30.2