Round the length of video-containing content to the nearest frame.
authorCarl Hetherington <cth@carlh.net>
Wed, 20 May 2020 18:20:47 +0000 (20:20 +0200)
committerCarl Hetherington <cth@carlh.net>
Wed, 20 May 2020 19:56:28 +0000 (21:56 +0200)
It seems reasonable, and is in the spirit of how positions are
rounded to frame boundaries.

It also fixes problems with unnecessary frames of black being
created at the end of trimmed files, where there can be
rounding-error-based confusion about where the content stops and
the black begins.

src/lib/content.cc
test/content_test.cc

index 2593c01df2ca7a569cf48f101d55883840dd0bed..4242477d483a06fbfb877d90e8fa74c4f0f5db3c 100644 (file)
@@ -303,7 +303,11 @@ Content::technical_summary () const
 DCPTime
 Content::length_after_trim (shared_ptr<const Film> film) const
 {
 DCPTime
 Content::length_after_trim (shared_ptr<const Film> film) const
 {
-       return max(DCPTime(), full_length(film) - DCPTime(trim_start() + trim_end(), film->active_frame_rate_change(position()))).round(film->video_frame_rate());
+       DCPTime length = max(DCPTime(), full_length(film) - DCPTime(trim_start() + trim_end(), film->active_frame_rate_change(position())));
+       if (video) {
+               length = length.round(film->video_frame_rate());
+       }
+       return length;
 }
 
 /** @return string which changes when something about this content changes which affects
 }
 
 /** @return string which changes when something about this content changes which affects
index fb66b2e082df537c715f0dd3693d8c07f98979cd..1e143f8e4db2317773a251addf1a17955402459b 100644 (file)
@@ -122,3 +122,31 @@ BOOST_AUTO_TEST_CASE (content_test3)
 
        BOOST_CHECK (content->trim_start() == ContentTime::from_seconds (15.0 / 25.0));
 }
 
        BOOST_CHECK (content->trim_start() == ContentTime::from_seconds (15.0 / 25.0));
 }
+
+
+/** Content containing video will have its length rounded to the nearest video frame */
+BOOST_AUTO_TEST_CASE (content_test4)
+{
+       shared_ptr<Film> film = new_test_film2 ("content_test4");
+
+       shared_ptr<Content> video = content_factory("test/data/count300bd24.m2ts").front();
+       film->examine_and_add_content (video);
+       BOOST_REQUIRE (!wait_for_jobs());
+
+       video->set_trim_end (dcpomatic::ContentTime(3000));
+       BOOST_CHECK (video->length_after_trim(film) == DCPTime::from_frames(299, 24));
+}
+
+
+/** Content containing no video will not have its length rounded to the nearest video frame */
+BOOST_AUTO_TEST_CASE (content_test5)
+{
+       shared_ptr<Film> film = new_test_film2 ("content_test5");
+
+       shared_ptr<Content> audio = content_factory("test/data/sine_16_48_220_10.wav").front();
+       film->examine_and_add_content (audio);
+       BOOST_REQUIRE (!wait_for_jobs());
+
+       audio->set_trim_end (dcpomatic::ContentTime(3000));
+       BOOST_CHECK (audio->length_after_trim(film) == DCPTime(957000));
+}