diff options
| author | Carl Hetherington <cth@carlh.net> | 2021-04-23 22:40:05 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2021-05-07 09:29:58 +0200 |
| commit | aef193a1fff119ed2420885ce6933444294aea4c (patch) | |
| tree | cf89d412da5acd31aaa52ff49e5cb4dfe9469f2c | |
| parent | 39055af213d1fd0c437d17422488dd6567706704 (diff) | |
Move time calculation methods from Player into Piece.
| -rw-r--r-- | src/lib/piece.cc | 41 | ||||
| -rw-r--r-- | src/lib/piece.h | 5 | ||||
| -rw-r--r-- | src/lib/player.cc | 59 | ||||
| -rw-r--r-- | src/lib/player.h | 4 | ||||
| -rw-r--r-- | test/time_calculation_test.cc | 80 |
5 files changed, 95 insertions, 94 deletions
diff --git a/src/lib/piece.cc b/src/lib/piece.cc index e0eeedc2d..3656cfe1a 100644 --- a/src/lib/piece.cc +++ b/src/lib/piece.cc @@ -21,6 +21,7 @@ #include "audio_content.h" #include "content.h" +#include "film.h" #include "piece.h" @@ -62,3 +63,43 @@ Piece::set_last_push_end (AudioStreamPtr stream, DCPTime end) _stream_last_push_end[stream] = end; } + +DCPTime +Piece::content_video_to_dcp (Frame f) const +{ + /* See comment in resampled_audio_to_dcp */ + auto const d = DCPTime::from_frames(f * frc.factor(), frc.dcp) - DCPTime(content->trim_start(), frc); + return d + content->position(); +} + + +DCPTime +Piece::resampled_audio_to_dcp (Frame f, shared_ptr<const Film> film) const +{ + /* It might seem more logical here to convert s to a ContentTime (using the FrameRateChange) + then convert that ContentTime to frames at the content's rate. However this fails for + situations like content at 29.9978733fps, DCP at 30fps. The accuracy of the Time type is not + enough to distinguish between the two with low values of time (e.g. 3200 in Time units). + + Instead we convert the DCPTime using the DCP video rate then account for any skip/repeat. + */ + return DCPTime::from_frames(f, film->audio_frame_rate()) + - DCPTime(content->trim_start(), frc) + + content->position(); +} + + +ContentTime +Piece::dcp_to_content_time (DCPTime t, shared_ptr<const Film> film) const +{ + auto s = t - content->position (); + s = min (content->length_after_trim(film), s); + return max (ContentTime(), ContentTime(s, frc) + content->trim_start()); +} + + +DCPTime +Piece::content_time_to_dcp (ContentTime t) const +{ + return max (DCPTime(), DCPTime(t - content->trim_start(), frc) + content->position()); +} diff --git a/src/lib/piece.h b/src/lib/piece.h index be9792491..7d04b8c21 100644 --- a/src/lib/piece.h +++ b/src/lib/piece.h @@ -42,6 +42,11 @@ public: void update_pull_to (dcpomatic::DCPTime& pull_to) const; void set_last_push_end (AudioStreamPtr stream, dcpomatic::DCPTime last_push_end); + dcpomatic::DCPTime content_video_to_dcp (Frame f) const; + dcpomatic::DCPTime resampled_audio_to_dcp (Frame f, std::shared_ptr<const Film> film) const; + dcpomatic::ContentTime dcp_to_content_time (dcpomatic::DCPTime t, std::shared_ptr<const Film> film) const; + dcpomatic::DCPTime content_time_to_dcp (dcpomatic::ContentTime t) const; + std::shared_ptr<Content> content; std::shared_ptr<Decoder> decoder; boost::optional<dcpomatic::DCPTimePeriod> ignore_video; diff --git a/src/lib/player.cc b/src/lib/player.cc index 346a99de3..1f7d1ac1d 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -399,47 +399,6 @@ Player::black_player_video_frame (Eyes eyes) const } -DCPTime -Player::content_video_to_dcp (shared_ptr<const Piece> piece, Frame f) const -{ - /* See comment in resampled_audio_to_dcp */ - auto const d = DCPTime::from_frames (f * piece->frc.factor(), piece->frc.dcp) - DCPTime(piece->content->trim_start(), piece->frc); - return d + piece->content->position(); -} - - -DCPTime -Player::resampled_audio_to_dcp (shared_ptr<const Piece> piece, Frame f) const -{ - /* It might seem more logical here to convert s to a ContentTime (using the FrameRateChange) - then convert that ContentTime to frames at the content's rate. However this fails for - situations like content at 29.9978733fps, DCP at 30fps. The accuracy of the Time type is not - enough to distinguish between the two with low values of time (e.g. 3200 in Time units). - - Instead we convert the DCPTime using the DCP video rate then account for any skip/repeat. - */ - return DCPTime::from_frames (f, _film->audio_frame_rate()) - - DCPTime (piece->content->trim_start(), piece->frc) - + piece->content->position(); -} - - -ContentTime -Player::dcp_to_content_time (shared_ptr<const Piece> piece, DCPTime t) const -{ - auto s = t - piece->content->position (); - s = min (piece->content->length_after_trim(_film), s); - return max (ContentTime (), ContentTime (s, piece->frc) + piece->content->trim_start()); -} - - -DCPTime -Player::content_time_to_dcp (shared_ptr<const Piece> piece, ContentTime t) const -{ - return max (DCPTime(), DCPTime(t - piece->content->trim_start(), piece->frc) + piece->content->position()); -} - - vector<FontData> Player::get_subtitle_fonts () { @@ -627,7 +586,7 @@ Player::pass () continue; } - auto const t = content_time_to_dcp (i, max(i->decoder->position(), i->content->trim_start())); + auto const t = i->content_time_to_dcp (max(i->decoder->position(), i->content->trim_start())); if (t > i->content->end(_film)) { i->done = true; } else { @@ -823,7 +782,7 @@ Player::video (weak_ptr<Piece> wp, ContentVideo video) } /* Time of the first frame we will emit */ - DCPTime const time = content_video_to_dcp (piece, video.frame); + DCPTime const time = piece->content_video_to_dcp (video.frame); LOG_DEBUG_PLAYER("Received video frame %1 at %2", video.frame, to_string(time)); /* Discard if it's before the content's period or the last accurate seek. We can't discard @@ -931,7 +890,7 @@ Player::audio (weak_ptr<Piece> wp, AudioStreamPtr stream, ContentAudio content_a int const rfr = content->resampled_frame_rate (_film); /* Compute time in the DCP */ - auto time = resampled_audio_to_dcp (piece, content_audio.frame); + auto time = piece->resampled_audio_to_dcp (content_audio.frame, _film); LOG_DEBUG_PLAYER("Received audio frame %1 at %2", content_audio.frame, to_string(time)); /* And the end of this block in the DCP */ @@ -1017,7 +976,7 @@ Player::bitmap_text_start (weak_ptr<Piece> wp, weak_ptr<const TextContent> wc, C dcp::Size scaled_size (width, height); ps.bitmap.push_back (BitmapText(image->scale(scaled_size, dcp::YUVToRGB::REC601, image->pixel_format(), true, _fast), subtitle.sub.rectangle)); - DCPTime from (content_time_to_dcp (piece, subtitle.from())); + DCPTime from (piece->content_time_to_dcp(subtitle.from())); _active_texts[static_cast<int>(text->type())].add_from (wc, ps, from); } @@ -1033,7 +992,7 @@ Player::plain_text_start (weak_ptr<Piece> wp, weak_ptr<const TextContent> wc, Co } PlayerText ps; - DCPTime const from (content_time_to_dcp (piece, subtitle.from())); + DCPTime const from (piece->content_time_to_dcp(subtitle.from())); if (from > piece->content->end(_film)) { return; @@ -1085,7 +1044,7 @@ Player::subtitle_stop (weak_ptr<Piece> wp, weak_ptr<const TextContent> wc, Conte return; } - DCPTime const dcp_to = content_time_to_dcp (piece, to); + auto const dcp_to = piece->content_time_to_dcp(to); if (dcp_to > piece->content->end(_film)) { return; @@ -1133,11 +1092,11 @@ Player::seek (DCPTime time, bool accurate) content we may not start right at the beginning of the next, causing a gap (if the next content has been trimmed to a point between keyframes, or something). */ - i->decoder->seek (dcp_to_content_time (i, i->content->position()), true); + i->decoder->seek (i->dcp_to_content_time(i->content->position(), _film), true); i->done = false; } else if (i->content->position() <= time && time < i->content->end(_film)) { /* During; seek to position */ - i->decoder->seek (dcp_to_content_time (i, time), accurate); + i->decoder->seek (i->dcp_to_content_time(time, _film), accurate); i->done = false; } else { /* After; this piece is done */ @@ -1301,7 +1260,7 @@ Player::content_time_to_dcp (shared_ptr<Content> content, ContentTime t) for (auto i: _pieces) { if (i->content == content) { - return content_time_to_dcp (i, t); + return i->content_time_to_dcp(t); } } diff --git a/src/lib/player.h b/src/lib/player.h index fd3bbf205..229dac91b 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -131,10 +131,6 @@ private: void film_change (ChangeType, Film::Property); void playlist_change (ChangeType); void playlist_content_change (ChangeType, int, bool); - dcpomatic::DCPTime content_video_to_dcp (std::shared_ptr<const Piece> piece, Frame f) const; - dcpomatic::DCPTime resampled_audio_to_dcp (std::shared_ptr<const Piece> piece, Frame f) const; - dcpomatic::ContentTime dcp_to_content_time (std::shared_ptr<const Piece> piece, dcpomatic::DCPTime t) const; - dcpomatic::DCPTime content_time_to_dcp (std::shared_ptr<const Piece> piece, dcpomatic::ContentTime t) const; std::shared_ptr<PlayerVideo> black_player_video_frame (Eyes eyes) const; void video (std::weak_ptr<Piece>, ContentVideo); diff --git a/test/time_calculation_test.cc b/test/time_calculation_test.cc index 9c5ca2f0e..b967ed4ed 100644 --- a/test/time_calculation_test.cc +++ b/test/time_calculation_test.cc @@ -207,9 +207,9 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); shared_ptr<Piece> piece = player->_pieces.front (); - BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0).get(), 0); - BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 12).get(), DCPTime::from_seconds(0.5).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72).get(), DCPTime::from_seconds(3.0).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(0).get(), 0); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(12).get(), DCPTime::from_seconds(0.5).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(72).get(), DCPTime::from_seconds(3.0).get()); /* Position 3s, no trim, content rate = DCP rate */ content->set_position (film, DCPTime::from_seconds(3)); @@ -219,9 +219,9 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); piece = player->_pieces.front (); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 0).get(), DCPTime::from_seconds(3.00).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 36).get(), DCPTime::from_seconds(4.50).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 162).get(), DCPTime::from_seconds(9.75).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(0).get(), DCPTime::from_seconds(3.00).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(36).get(), DCPTime::from_seconds(4.50).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(162).get(), DCPTime::from_seconds(9.75).get()); /* Position 3s, 1.5s trim, content rate = DCP rate */ content->set_position (film, DCPTime::from_seconds(3)); @@ -231,10 +231,10 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); piece = player->_pieces.front (); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 0).get(), DCPTime::from_seconds(1.50).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 36).get(), DCPTime::from_seconds(3.00).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 72).get(), DCPTime::from_seconds(4.50).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 198).get(), DCPTime::from_seconds(9.75).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(0).get(), DCPTime::from_seconds(1.50).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(36).get(), DCPTime::from_seconds(3.00).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(72).get(), DCPTime::from_seconds(4.50).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(198).get(), DCPTime::from_seconds(9.75).get()); /* Position 0, no trim, content rate 24, DCP rate 25. Now, for example, a DCPTime position of 3s means 3s at 25fps. Since we run the video @@ -247,9 +247,9 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); piece = player->_pieces.front (); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 0).get(), 0); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 15).get(), DCPTime::from_seconds(0.6).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 75).get(), DCPTime::from_seconds(3.0).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(0).get(), 0); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(15).get(), DCPTime::from_seconds(0.6).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(75).get(), DCPTime::from_seconds(3.0).get()); /* Position 3s, no trim, content rate 24, DCP rate 25 */ content->set_position (film, DCPTime::from_seconds(3)); @@ -259,9 +259,9 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); piece = player->_pieces.front (); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 0).get(), DCPTime::from_seconds(3.00).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 40).get(), DCPTime::from_seconds(4.60).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 169).get(), DCPTime::from_seconds(9.76).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(0).get(), DCPTime::from_seconds(3.00).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(40).get(), DCPTime::from_seconds(4.60).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(169).get(), DCPTime::from_seconds(9.76).get()); /* Position 3s, 1.6s trim, content rate 24, DCP rate 25, so the 1.6s trim is at 24fps */ content->set_position (film, DCPTime::from_seconds(3)); @@ -271,10 +271,10 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); piece = player->_pieces.front (); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 0).get(), 142080); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 40).get(), 295680); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 80).get(), 449280); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 209).get(), 944640); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(0).get(), 142080); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(40).get(), 295680); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(80).get(), 449280); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(209).get(), 944640); /* Position 0, no trim, content rate 24, DCP rate 48 Now, for example, a DCPTime position of 3s means 3s at 48fps. Since we run the video @@ -289,9 +289,9 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); piece = player->_pieces.front (); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 0).get(), 0); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 12).get(), DCPTime::from_seconds(0.5).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 72).get(), DCPTime::from_seconds(3.0).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(0).get(), 0); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(12).get(), DCPTime::from_seconds(0.5).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(72).get(), DCPTime::from_seconds(3.0).get()); /* Position 3s, no trim, content rate 24, DCP rate 48 */ content->set_position (film, DCPTime::from_seconds(3)); @@ -301,9 +301,9 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); piece = player->_pieces.front (); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 0).get(), DCPTime::from_seconds(3.00).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 36).get(), DCPTime::from_seconds(4.50).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 162).get(), DCPTime::from_seconds(9.75).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(0).get(), DCPTime::from_seconds(3.00).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(36).get(), DCPTime::from_seconds(4.50).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(162).get(), DCPTime::from_seconds(9.75).get()); /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */ content->set_position (film, DCPTime::from_seconds(3)); @@ -313,10 +313,10 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); piece = player->_pieces.front (); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 0).get(), DCPTime::from_seconds(1.50).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 36).get(), DCPTime::from_seconds(3.00).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 72).get(), DCPTime::from_seconds(4.50).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 198).get(), DCPTime::from_seconds(9.75).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(0).get(), DCPTime::from_seconds(1.50).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(36).get(), DCPTime::from_seconds(3.00).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(72).get(), DCPTime::from_seconds(4.50).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(198).get(), DCPTime::from_seconds(9.75).get()); /* Position 0, no trim, content rate 48, DCP rate 24 Now, for example, a DCPTime position of 3s means 3s at 24fps. Since we run the video @@ -330,9 +330,9 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); piece = player->_pieces.front (); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 0).get(), 0); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 24).get(), DCPTime::from_seconds(0.5).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 144).get(), DCPTime::from_seconds(3.0).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(0).get(), 0); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(24).get(), DCPTime::from_seconds(0.5).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(144).get(), DCPTime::from_seconds(3.0).get()); /* Position 3s, no trim, content rate 24, DCP rate 48 */ content->set_position (film, DCPTime::from_seconds(3)); @@ -342,9 +342,9 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); piece = player->_pieces.front (); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 0).get(), DCPTime::from_seconds(3.00).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 72).get(), DCPTime::from_seconds(4.50).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 324).get(), DCPTime::from_seconds(9.75).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(0).get(), DCPTime::from_seconds(3.00).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(72).get(), DCPTime::from_seconds(4.50).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(324).get(), DCPTime::from_seconds(9.75).get()); /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */ content->set_position (film, DCPTime::from_seconds(3)); @@ -354,9 +354,9 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); piece = player->_pieces.front (); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 0).get(), DCPTime::from_seconds(1.50).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 72).get(), DCPTime::from_seconds(3.00).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 144).get(), DCPTime::from_seconds(4.50).get()); - BOOST_CHECK_EQUAL (player->content_video_to_dcp(piece, 396).get(), DCPTime::from_seconds(9.75).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(0).get(), DCPTime::from_seconds(1.50).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(72).get(), DCPTime::from_seconds(3.00).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(144).get(), DCPTime::from_seconds(4.50).get()); + BOOST_CHECK_EQUAL (piece->content_video_to_dcp(396).get(), DCPTime::from_seconds(9.75).get()); } |
