diff options
| author | Carl Hetherington <cth@carlh.net> | 2024-11-29 21:04:45 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2024-11-30 22:18:51 +0100 |
| commit | 5db5da477ce02166481d79df322bbfb7abc8f24c (patch) | |
| tree | f2858f605a05d87a0e4a2e4bea77d6d66d6d4f7f | |
| parent | 052abf06a9fed23f61eaa934ac0e8662bbe142ce (diff) | |
Fix mis-handling of reels with Atmos content (#2901).v2.17.26
We must have reel boundaries at least on Atmos content boundaries as I
don't know for sure how to insert silence into an Atmos stream.
| -rw-r--r-- | src/lib/film.cc | 45 | ||||
| -rw-r--r-- | src/lib/film.h | 1 | ||||
| -rw-r--r-- | test/reels_test.cc | 31 |
3 files changed, 77 insertions, 0 deletions
diff --git a/src/lib/film.cc b/src/lib/film.cc index 5b845d8b4..a4734d4c3 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -1610,6 +1610,51 @@ Film::playlist_change (ChangeType type) set_dirty (true); } + +void +Film::check_reel_boundaries_for_atmos() +{ + /* Find Atmos boundaries */ + std::set<dcpomatic::DCPTime> atmos_boundaries; + for (auto i: content()) { + if (i->atmos) { + atmos_boundaries.insert(i->position()); + atmos_boundaries.insert(i->end(shared_from_this())); + } + } + + /* Find reel boundaries */ + vector<dcpomatic::DCPTime> reel_boundaries; + bool first = true; + for (auto period: reels()) { + if (first) { + reel_boundaries.push_back(period.from); + first = false; + } + reel_boundaries.push_back(period.to); + } + + /* There must be a reel boundary at all the Atmos boundaries */ + auto remake_boundaries = std::any_of(atmos_boundaries.begin(), atmos_boundaries.end(), [&reel_boundaries](dcpomatic::DCPTime time) { + return std::find(reel_boundaries.begin(), reel_boundaries.end(), time) == reel_boundaries.end(); + }); + + if (remake_boundaries) { + vector<dcpomatic::DCPTime> required_boundaries; + std::copy_if(atmos_boundaries.begin(), atmos_boundaries.end(), std::back_inserter(required_boundaries), [this](dcpomatic::DCPTime time) { + return time.get() != 0 && time != length(); + }); + if (!required_boundaries.empty()) { + set_reel_type(ReelType::CUSTOM); + set_custom_reel_boundaries(required_boundaries); + } else { + set_reel_type(ReelType::SINGLE); + } + Message(variant::insert_dcpomatic("%1 had to change your reel settings to accomodate the Atmos content")); + } +} + + /** Check for (and if necessary fix) impossible settings combinations, like * video set to being referenced when it can't be. */ diff --git a/src/lib/film.h b/src/lib/film.h index 815c6ae74..8718e8f7d 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -502,6 +502,7 @@ private: void maybe_set_container_and_resolution (); void set_dirty (bool dirty); void write_ui_state() const; + void check_reel_boundaries_for_atmos(); /** Log to write to */ std::shared_ptr<Log> _log; diff --git a/test/reels_test.cc b/test/reels_test.cc index 7ba01b8a9..5feff84f2 100644 --- a/test/reels_test.cc +++ b/test/reels_test.cc @@ -34,10 +34,12 @@ #include "lib/make_dcp.h" #include "lib/ratio.h" #include "lib/string_text_file_content.h" +#include "lib/variant.h" #include "lib/video_content.h" #include "test.h" #include <dcp/cpl.h> #include <dcp/reel.h> +#include <dcp/reel_atmos_asset.h> #include <dcp/reel_picture_asset.h> #include <dcp/reel_sound_asset.h> #include <boost/test/unit_test.hpp> @@ -647,3 +649,32 @@ BOOST_AUTO_TEST_CASE (repeated_dcp_into_reels) BOOST_REQUIRE_EQUAL(cpl->reels()[i]->main_sound()->id(), sound->id()); } } + + +/** Check that reel lengths are adapted to cope with Atmos content, as I don't know how to fill gaps with Atmos silence */ +BOOST_AUTO_TEST_CASE(reel_assets_same_length_with_atmos) +{ + auto atmos = content_factory("test/data/atmos_0.mxf")[0]; + auto film = new_test_film("reel_assets_same_length_with_atmos", { atmos }); + + vector<string> messages; + film->Message.connect([&messages](string message) { + messages.push_back(message); + }); + + auto picture = content_factory("test/data/flat_red.png")[0]; + film->examine_and_add_content(picture); + wait_for_jobs(); + picture->video->set_length(480); + + BOOST_REQUIRE_EQUAL(messages.size(), 1U); + BOOST_CHECK_EQUAL(messages[0], variant::insert_dcpomatic("%1 had to change your reel settings to accomodate the Atmos content")); + + auto const reels = film->reels(); + BOOST_CHECK_EQUAL(reels.size(), 2U); + BOOST_CHECK(reels[0] == dcpomatic::DCPTimePeriod({}, dcpomatic::DCPTime::from_frames(240, 24))); + BOOST_CHECK(reels[1] == dcpomatic::DCPTimePeriod(dcpomatic::DCPTime::from_frames(240, 24), dcpomatic::DCPTime::from_frames(480, 24))); + + make_and_verify_dcp(film, { dcp::VerificationNote::Code::MISSING_CPL_METADATA }); +} + |
