From d5e7b00770b2b3c536f784b650cb980c694e7493 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 22 Mar 2019 21:31:37 +0000 Subject: [PATCH] Fix referencing of trimmed multi-reel DCPs (#1495). --- src/lib/player.cc | 77 +++++++++++++++++++++++++---------------------- test/vf_test.cc | 19 +++++++++++- 2 files changed, 59 insertions(+), 37 deletions(-) diff --git a/src/lib/player.cc b/src/lib/player.cc index 537a71906..96c963e70 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -463,6 +463,19 @@ Player::set_play_referenced () setup_pieces_unlocked (); } +static void +maybe_add_asset (list& a, shared_ptr r, Frame reel_trim_start, Frame reel_trim_end, DCPTime from, int const ffr) +{ + DCPOMATIC_ASSERT (r); + r->set_entry_point (r->entry_point() + reel_trim_start); + r->set_duration (r->duration() - reel_trim_start - reel_trim_end); + if (r->duration() > 0) { + a.push_back ( + ReferencedReelAsset(r, DCPTimePeriod(from, from + DCPTime::from_frames(r->duration(), ffr))) + ); + } +} + list Player::get_reel_assets () { @@ -483,59 +496,51 @@ Player::get_reel_assets () return a; } - int64_t offset = 0; + DCPOMATIC_ASSERT (j->video_frame_rate ()); + double const cfr = j->video_frame_rate().get(); + Frame const trim_start = j->trim_start().frames_round (cfr); + Frame const trim_end = j->trim_end().frames_round (cfr); + int const ffr = _film->video_frame_rate (); + + /* position in the asset from the start */ + int64_t offset_from_start = 0; + /* position in the asset from the end */ + int64_t offset_from_end = 0; + BOOST_FOREACH (shared_ptr k, decoder->reels()) { + /* Assume that main picture duration is the length of the reel */ + offset_from_end += k->main_picture()->duration(); + } + BOOST_FOREACH (shared_ptr k, decoder->reels()) { - DCPOMATIC_ASSERT (j->video_frame_rate ()); - double const cfr = j->video_frame_rate().get(); - Frame const trim_start = j->trim_start().frames_round (cfr); - Frame const trim_end = j->trim_end().frames_round (cfr); - int const ffr = _film->video_frame_rate (); + /* Assume that main picture duration is the length of the reel */ + int64_t const reel_duration = k->main_picture()->duration(); + + /* See doc/design/trim_reels.svg */ + Frame const reel_trim_start = min(reel_duration, max(0L, trim_start - offset_from_start)); + Frame const reel_trim_end = min(reel_duration, max(0L, reel_duration - (offset_from_end - trim_end))); - DCPTime const from = i->position() + DCPTime::from_frames (offset, _film->video_frame_rate()); + DCPTime const from = i->position() + DCPTime::from_frames (offset_from_start, _film->video_frame_rate()); if (j->reference_video ()) { - shared_ptr ra = k->main_picture (); - DCPOMATIC_ASSERT (ra); - ra->set_entry_point (ra->entry_point() + trim_start); - ra->set_duration (ra->duration() - trim_start - trim_end); - a.push_back ( - ReferencedReelAsset (ra, DCPTimePeriod (from, from + DCPTime::from_frames (ra->duration(), ffr))) - ); + maybe_add_asset (a, k->main_picture(), reel_trim_start, reel_trim_end, from, ffr); } if (j->reference_audio ()) { - shared_ptr ra = k->main_sound (); - DCPOMATIC_ASSERT (ra); - ra->set_entry_point (ra->entry_point() + trim_start); - ra->set_duration (ra->duration() - trim_start - trim_end); - a.push_back ( - ReferencedReelAsset (ra, DCPTimePeriod (from, from + DCPTime::from_frames (ra->duration(), ffr))) - ); + maybe_add_asset (a, k->main_sound(), reel_trim_start, reel_trim_end, from, ffr); } if (j->reference_text (TEXT_OPEN_SUBTITLE)) { - shared_ptr ra = k->main_subtitle (); - DCPOMATIC_ASSERT (ra); - ra->set_entry_point (ra->entry_point() + trim_start); - ra->set_duration (ra->duration() - trim_start - trim_end); - a.push_back ( - ReferencedReelAsset (ra, DCPTimePeriod (from, from + DCPTime::from_frames (ra->duration(), ffr))) - ); + maybe_add_asset (a, k->main_subtitle(), reel_trim_start, reel_trim_end, from, ffr); } if (j->reference_text (TEXT_CLOSED_CAPTION)) { BOOST_FOREACH (shared_ptr l, k->closed_captions()) { - DCPOMATIC_ASSERT (l); - l->set_entry_point (l->entry_point() + trim_start); - l->set_duration (l->duration() - trim_start - trim_end); - a.push_back ( - ReferencedReelAsset (l, DCPTimePeriod (from, from + DCPTime::from_frames (l->duration(), ffr))) - ); + maybe_add_asset (a, l, reel_trim_start, reel_trim_end, from, ffr); } } - /* Assume that main picture duration is the length of the reel */ - offset += k->main_picture()->duration (); + offset_from_start += reel_duration; + offset_from_end -= reel_duration; } } diff --git a/test/vf_test.cc b/test/vf_test.cc index 540e8da88..b36cc6567 100644 --- a/test/vf_test.cc +++ b/test/vf_test.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2015-2017 Carl Hetherington + Copyright (C) 2015-2019 Carl Hetherington This file is part of DCP-o-matic. @@ -29,6 +29,8 @@ #include "lib/content_factory.h" #include "lib/dcp_content_type.h" #include "lib/video_content.h" +#include "lib/referenced_reel_asset.h" +#include "lib/player.h" #include "test.h" #include #include @@ -36,6 +38,7 @@ #include #include #include +#include using std::list; using std::string; @@ -283,4 +286,18 @@ BOOST_AUTO_TEST_CASE (vf_test5) dcp->set_trim_end (ContentTime::from_seconds(15)); vf->make_dcp (); BOOST_REQUIRE (!wait_for_jobs()); + + /* Check that the selected reel assets are right */ + shared_ptr player (new Player(vf, vf->playlist())); + list a = player->get_reel_assets(); + BOOST_REQUIRE_EQUAL (a.size(), 4); + list::const_iterator i = a.begin(); + BOOST_CHECK (i->period == DCPTimePeriod(DCPTime(0), DCPTime(960000))); + ++i; + BOOST_CHECK (i->period == DCPTimePeriod(DCPTime(0), DCPTime(960000))); + ++i; + BOOST_CHECK (i->period == DCPTimePeriod(DCPTime(960000), DCPTime(1440000))); + ++i; + BOOST_CHECK (i->period == DCPTimePeriod(DCPTime(960000), DCPTime(1440000))); + ++i; } -- 2.30.2