From a5e1a485a825a0967142fae98488fc79e345cb4a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 1 Feb 2025 15:59:20 +0100 Subject: Fix subtitles being written with negative times when trimmed (#2965). --- src/lib/player.cc | 63 +++++++++++++++++++++++++++++++++++-------------------- src/lib/player.h | 7 +++++-- 2 files changed, 45 insertions(+), 25 deletions(-) (limited to 'src/lib') diff --git a/src/lib/player.cc b/src/lib/player.cc index e5abaae68..b5ee280ae 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -1233,16 +1233,40 @@ Player::audio(weak_ptr weak_piece, AudioStreamPtr stream, ContentAudio co } +/** @return from time if this text should be stored in _active_texts, otherwise nullopt */ +boost::optional +Player::should_store(weak_ptr weak_piece, weak_ptr weak_content, ContentTime subtitle_from) const +{ + if (_suspended) { + return {}; + } + + auto piece = weak_piece.lock(); + auto content = weak_content.lock(); + auto film = _film.lock(); + if (!piece || !content || !film) { + return {}; + } + + DCPTime const from(content_time_to_dcp(piece, subtitle_from)); + if (from > piece->content->end(film)) { + return {}; + } + + return from; +} + + void Player::bitmap_text_start(weak_ptr weak_piece, weak_ptr weak_content, ContentBitmapText subtitle) { - if (_suspended) { + auto from = should_store(weak_piece, weak_content, subtitle.from()); + if (!from) { return; } - auto piece = weak_piece.lock(); auto content = weak_content.lock(); - if (!piece || !content) { + if (!content) { return; } @@ -1274,32 +1298,24 @@ Player::bitmap_text_start(weak_ptr weak_piece, weak_ptrscale(scaled_size, dcp::YUVToRGB::REC601, image->pixel_format(), Image::Alignment::PADDED, _fast), sub.rectangle)); } - DCPTime from(content_time_to_dcp(piece, subtitle.from())); - _active_texts[content->type()].add_from(weak_content, ps, from); + _active_texts[content->type()].add_from(weak_content, ps, *from); } void Player::plain_text_start(weak_ptr weak_piece, weak_ptr weak_content, ContentStringText subtitle) { - if (_suspended) { + auto from = should_store(weak_piece, weak_content, subtitle.from()); + if (!from) { return; } - auto piece = weak_piece.lock(); auto content = weak_content.lock(); - auto film = _film.lock(); - if (!piece || !content || !film) { + if (!content) { return; } PlayerText ps; - DCPTime const from(content_time_to_dcp(piece, subtitle.from())); - - if (from > piece->content->end(film)) { - return; - } - for (auto s: subtitle.subs) { s.set_h_position(s.h_position() + content->x_offset()); s.set_v_position(s.v_position() + content->y_offset()); @@ -1320,11 +1336,11 @@ Player::plain_text_start(weak_ptr weak_piece, weak_ptr s.set_aspect_adjust(xs / ys); } - s.set_in(dcp::Time(from.seconds(), 1000)); - ps.string.push_back(s); + s.set_in(dcp::Time(from->seconds(), 1000)); + ps.string.push_back (s); } - _active_texts[content->type()].add_from(weak_content, ps, from); + _active_texts[content->type()].add_from(weak_content, ps, *from); } @@ -1350,17 +1366,18 @@ Player::text_stop(weak_ptr weak_piece, weak_ptr weak_c return; } - DCPTime const dcp_to = content_time_to_dcp(piece, to); + auto dcp_to = content_time_to_dcp(piece, to); + auto from = _active_texts[content->type()].add_to(weak_content, dcp_to); + auto subtitle_period = DCPTimePeriod(from.second, dcp_to); - if (dcp_to > piece->content->end(film)) { + auto overlap = piece->content->period(film).overlap(subtitle_period); + if (!overlap) { return; } - auto from = _active_texts[content->type()].add_to(weak_content, dcp_to); - bool const always = (content->type() == TextType::OPEN_SUBTITLE && _always_burn_open_subtitles); if (content->use() && !always && !content->burn()) { - Text(from.first, content->type(), content->dcp_track().get_value_or(DCPTextTrack()), DCPTimePeriod(from.second, dcp_to)); + Text(from.first, content->type(), content->dcp_track().get_value_or(DCPTextTrack()), *overlap); } } diff --git a/src/lib/player.h b/src/lib/player.h index 5148ad3a1..8922741bd 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -177,8 +177,11 @@ private: boost::optional open_texts_for_frame(dcpomatic::DCPTime time) const; void emit_video(std::shared_ptr pv, dcpomatic::DCPTime time); void use_video(std::shared_ptr pv, dcpomatic::DCPTime time, dcpomatic::DCPTime end); - void emit_audio(std::shared_ptr data, dcpomatic::DCPTime time); - std::shared_ptr playlist() const; + void emit_audio (std::shared_ptr data, dcpomatic::DCPTime time); + std::shared_ptr playlist () const; + boost::optional should_store( + std::weak_ptr weak_piece, std::weak_ptr weak_content, dcpomatic::ContentTime subtitle_from + ) const; /** Mutex to protect the most of the Player state. When it's used for the preview we have seek() and pass() called from the Butler thread and lots of other stuff called -- cgit v1.2.3