Disallow referencing DCPs of different frame rates to the project.
authorCarl Hetherington <cth@carlh.net>
Wed, 21 Sep 2016 13:39:42 +0000 (14:39 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 21 Sep 2016 13:39:42 +0000 (14:39 +0100)
Fix reel calculations of DCPContent under trim.

src/lib/dcp_content.cc
src/lib/dcp_content.h
src/wx/video_panel.cc
test/reels_test.cc

index 8b823c61966afe23d4bfdf8dfb78ccad2888c6e1..c180240c886336ecd2bfb4f403b0e58c81913d30 100644 (file)
@@ -362,11 +362,23 @@ DCPContent::reels () const
                return p;
        }
 
-       DCPTime from = position ();
-       BOOST_FOREACH (shared_ptr<dcp::Reel> i, decoder->reels()) {
-               DCPTime const to = from + DCPTime::from_frames (i->main_picture()->duration(), film()->video_frame_rate());
-               p.push_back (DCPTimePeriod (from, to));
-               from = to;
+       /* This content's frame rate must be the same as the output DCP rate, so we can
+          convert `directly' from ContentTime to DCPTime.
+       */
+
+       /* The starting point of this content on the timeline */
+       DCPTime pos = position() - DCPTime (trim_start().get());
+
+       BOOST_FOREACH (shared_ptr<dcp::Reel> i, decoder->reels ()) {
+               /* This reel runs from `pos' to `to' */
+               DCPTime const to = pos + DCPTime::from_frames (i->main_picture()->duration(), film()->video_frame_rate());
+               if (to > position()) {
+                       p.push_back (DCPTimePeriod (max(position(), pos), min(end(), to)));
+                       if (to > end()) {
+                               break;
+                       }
+               }
+               pos = to;
        }
 
        return p;
@@ -396,7 +408,14 @@ DCPContent::can_reference (function<shared_ptr<ContentPart> (shared_ptr<const Co
                }
        }
 
+       /* And the same frame rate */
+       if (!video_frame_rate() || (lrint(video_frame_rate().get()) != film()->video_frame_rate())) {
+               why_not.push_back (_("The film has a different frame rate to this DCP."));
+               return false;
+       }
+
        list<DCPTimePeriod> const fr = film()->reels ();
+
        /* fr must contain reels().  It can also contain other reels, but it must at
           least contain reels().
        */
index 11096037c19eb651246b19ff91045b142a2308b7..f97045484f7318748093dd33d8c04505dd1c8f80 100644 (file)
@@ -120,6 +120,8 @@ public:
        }
 
 private:
+       friend class reels_test5;
+
        void add_properties (std::list<UserProperty>& p) const;
 
        void read_directory (boost::filesystem::path);
index a1457ac6dd5041db5e09cae4e1a69bb6feeeb61e..177799208a2877d457bf66799638d66ca5e440f5 100644 (file)
@@ -252,8 +252,11 @@ void
 VideoPanel::film_changed (Film::Property property)
 {
        switch (property) {
-       case Film::CONTAINER:
        case Film::VIDEO_FRAME_RATE:
+               setup_description ();
+               setup_sensitivity ();
+               break;
+       case Film::CONTAINER:
        case Film::RESOLUTION:
                setup_description ();
                break;
index 9718898e256547f7df4fd0b8fdbded98f5242a53..51cb1f2005dcbe655036bbedc3455a4b8ee71d9c 100644 (file)
@@ -221,3 +221,55 @@ BOOST_AUTO_TEST_CASE (reels_test4)
 
        check_dcp ("test/data/reels_test4", film->dir (film->dcp_name()));
 }
+
+BOOST_AUTO_TEST_CASE (reels_test5)
+{
+       shared_ptr<Film> film = new_test_film ("reels_test4");
+       shared_ptr<DCPContent> dcp (new DCPContent (film, "test/data/reels_test4"));
+       film->examine_and_add_content (dcp);
+       wait_for_jobs ();
+
+       dcp->set_position(DCPTime(123));
+
+       {
+               list<DCPTimePeriod> p = dcp->reels ();
+               BOOST_REQUIRE_EQUAL (p.size(), 4);
+               list<DCPTimePeriod>::const_iterator i = p.begin();
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 0), DCPTime(123 + 96000)));
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 96000), DCPTime(123 + 192000)));
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 192000), DCPTime(123 + 288000)));
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 288000), DCPTime(123 + 384000)));
+       }
+
+       {
+               dcp->set_trim_start (ContentTime::from_seconds (0.5));
+               list<DCPTimePeriod> p = dcp->reels ();
+               BOOST_REQUIRE_EQUAL (p.size(), 4);
+               list<DCPTimePeriod>::const_iterator i = p.begin();
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 0), DCPTime(123 + 48000)));
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 48000), DCPTime(123 + 144000)));
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 144000), DCPTime(123 + 240000)));
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 240000), DCPTime(123 + 336000)));
+       }
+
+       {
+               dcp->set_trim_end (ContentTime::from_seconds (0.5));
+               list<DCPTimePeriod> p = dcp->reels ();
+               BOOST_REQUIRE_EQUAL (p.size(), 4);
+               list<DCPTimePeriod>::const_iterator i = p.begin();
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 0), DCPTime(123 + 48000)));
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 48000), DCPTime(123 + 144000)));
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 144000), DCPTime(123 + 240000)));
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 240000), DCPTime(123 + 288000)));
+       }
+
+       {
+               dcp->set_trim_start (ContentTime::from_seconds (1.5));
+               list<DCPTimePeriod> p = dcp->reels ();
+               BOOST_REQUIRE_EQUAL (p.size(), 3);
+               list<DCPTimePeriod>::const_iterator i = p.begin();
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 0), DCPTime(123 + 48000)));
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 48000), DCPTime(123 + 144000)));
+               BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(123 + 144000), DCPTime(123 + 192000)));
+       }
+}