Handle end-trim correctly in player; there is scope to make this more efficient by...
authorCarl Hetherington <cth@carlh.net>
Thu, 2 Mar 2017 00:01:18 +0000 (00:01 +0000)
committerCarl Hetherington <cth@carlh.net>
Wed, 19 Apr 2017 22:04:32 +0000 (23:04 +0100)
src/lib/player.cc
test/torture_test.cc

index 035af81feba6215ee61a52eac3fa453f3fa205f8..844706e4beaa40928ca7fff407d58cd6e9a7d62e 100644 (file)
@@ -362,7 +362,7 @@ DCPTime
 Player::resampled_audio_to_dcp (shared_ptr<const Piece> piece, Frame f) const
 {
        /* See comment in dcp_to_content_video */
-       DCPTime const d = DCPTime::from_frames (f, _film->audio_frame_rate()) - DCPTime (piece->content->trim_start (), piece->frc);
+       DCPTime const d = DCPTime::from_frames (f, _film->audio_frame_rate()) - DCPTime (piece->content->trim_start(), piece->frc);
        return max (DCPTime (), d + piece->content->position ());
 }
 
@@ -760,12 +760,12 @@ Player::audio (weak_ptr<Piece> wp, AudioStreamPtr stream, ContentAudio content_a
                content_audio.frame = ro.second;
        }
 
-       /* XXX: end-trimming used to be checked here */
-
        /* Compute time in the DCP */
        DCPTime time = resampled_audio_to_dcp (piece, content_audio.frame) + DCPTime::from_seconds (content->delay() / 1000.0);
+       /* And the end of this block in the DCP */
+       DCPTime end = time + DCPTime::from_frames(content_audio.audio->frames(), content->resampled_frame_rate());
 
-       /* Remove anything that comes before the start of the content */
+       /* Remove anything that comes before the start or after the end of the content */
        if (time < piece->content->position()) {
                DCPTime const discard_time = piece->content->position() - time;
                Frame discard_frames = discard_time.frames_round(_film->audio_frame_rate());
@@ -778,6 +778,14 @@ Player::audio (weak_ptr<Piece> wp, AudioStreamPtr stream, ContentAudio content_a
                cut->copy_from (content_audio.audio.get(), remaining_frames, discard_frames, 0);
                content_audio.audio = cut;
                time += discard_time;
+       } else if (time > piece->content->end()) {
+               /* Discard it all */
+               return;
+       } else if (end > piece->content->end()) {
+               Frame const remaining_frames = DCPTime(piece->content->end() - time).frames_round(_film->audio_frame_rate());
+               shared_ptr<AudioBuffers> cut (new AudioBuffers (content_audio.audio->channels(), remaining_frames));
+               cut->copy_from (content_audio.audio.get(), remaining_frames, 0, 0);
+               content_audio.audio = cut;
        }
 
        audio_transform (content, stream, content_audio, time);
index 7d85f5d7d9e6c853531c3bb754b3fb94e29ae746..21494e5d80a7dbd5fe40bbb96fdac81398100b79 100644 (file)
@@ -40,26 +40,36 @@ using boost::shared_ptr;
 /** Test a fairly complex arrangement of content */
 BOOST_AUTO_TEST_CASE (torture_test1)
 {
-       shared_ptr<Film> film = new_test_film ("player_torture_test");
+       shared_ptr<Film> film = new_test_film ("torture_test");
        film->set_dcp_content_type (DCPContentType::from_isdcf_name ("FTR"));
-       film->set_name ("player_torture_test");
+       film->set_name ("torture_test");
        film->set_container (Ratio::from_id ("185"));
        film->set_sequence (false);
 
        /* Staircase at an offset of 2000 samples, trimmed both start and end, with a gain of 6dB */
-       shared_ptr<Content> staircase = content_factory(film, "test/data/staircase.mov").front ();
+       shared_ptr<Content> staircase = content_factory(film, "test/data/staircase.wav").front ();
        film->examine_and_add_content (staircase);
        wait_for_jobs ();
        staircase->set_position (DCPTime::from_frames (2000, film->audio_frame_rate()));
        staircase->set_trim_start (ContentTime::from_frames (12, 48000));
        staircase->set_trim_end (ContentTime::from_frames (35, 48000));
-//     staircase->audio->set_gain (20 * log10(2));
+       staircase->audio->set_gain (20 * log10(2));
+
+       /* And again at an offset of 50000 samples, trimmed both start and end, with a gain of 6dB */
+       staircase = content_factory(film, "test/data/staircase.wav").front ();
+       film->examine_and_add_content (staircase);
+       wait_for_jobs ();
+       staircase->set_position (DCPTime::from_frames (50000, film->audio_frame_rate()));
+       staircase->set_trim_start (ContentTime::from_frames (12, 48000));
+       staircase->set_trim_end (ContentTime::from_frames (35, 48000));
+       staircase->audio->set_gain (20 * log10(2));
 
        film->set_video_frame_rate (24);
+       film->write_metadata ();
        film->make_dcp ();
        wait_for_jobs ();
 
-       dcp::DCP dcp ("build/test/player_torture_test/" + film->dcp_name(false));
+       dcp::DCP dcp ("build/test/torture_test/" + film->dcp_name(false));
        dcp.read ();
 
        list<shared_ptr<dcp::CPL> > cpls = dcp.cpls ();
@@ -82,7 +92,7 @@ BOOST_AUTO_TEST_CASE (torture_test1)
                }
        }
 
-       /* The staircase is 4800 - 12 - 35 = 4753 samples.  One frame is 2000 samples, so we span 3 frames */
+       /* The first staircase is 4800 - 12 - 35 = 4753 samples.  One frame is 2000 samples, so we span 3 frames */
 
        BOOST_REQUIRE_EQUAL (fr->samples(), 2000);
 
@@ -92,10 +102,10 @@ BOOST_AUTO_TEST_CASE (torture_test1)
        for (int i = 0; i < fr->samples(); ++i) {
                for (int j = 0; j < 6; ++j) {
                        if (j == 2) {
-                               BOOST_CHECK_EQUAL (fr->get(j, i) >> 8, stair);
+                               BOOST_CHECK_EQUAL ((fr->get(j, i) + 128) >> 8, stair * 2);
                                ++stair;
                        } else {
-                               BOOST_CHECK_EQUAL ((fr->get(j, i) + 128) >> 8, 0);
+                               BOOST_CHECK_EQUAL (fr->get(j, i), 0);
                        }
                }
        }
@@ -104,7 +114,7 @@ BOOST_AUTO_TEST_CASE (torture_test1)
        for (int i = 0; i < fr->samples(); ++i) {
                for (int j = 0; j < 6; ++j) {
                        if (j == 2) {
-                               BOOST_CHECK_EQUAL (fr->get(j, i) >> 8, stair);
+                               BOOST_CHECK_EQUAL ((fr->get(j, i) + 128) >> 8, stair * 2);
                                ++stair;
                        } else {
                                BOOST_CHECK_EQUAL (fr->get(j, i), 0);
@@ -113,10 +123,60 @@ BOOST_AUTO_TEST_CASE (torture_test1)
        }
 
        fr = sound_reader->get_frame (3);
-       for (int i = 0; i < 4753 - (2000 * 2); ++i) {
+       for (int i = 0; i < fr->samples(); ++i) {
+               for (int j = 0; j < 6; ++j) {
+                       if (j == 2 && i < (4753 - (2000 * 2))) {
+                               BOOST_CHECK_EQUAL ((fr->get(j, i) + 128) >> 8, stair * 2);
+                               ++stair;
+                       } else {
+                               BOOST_CHECK_EQUAL (fr->get(j, i), 0);
+                       }
+               }
+       }
+
+       /* Then some silence */
+
+       for (int i = 4; i < 24; ++i) {
+               fr = sound_reader->get_frame (i);
+               for (int j = 0; j < fr->samples(); ++j) {
+                       for (int k = 0; k < 6; ++k) {
+                               BOOST_CHECK_EQUAL (fr->get(k, j), 0);
+                       }
+               }
+       }
+
+       /* Then the same thing again */
+       stair = 12;
+
+       fr = sound_reader->get_frame (25);
+       for (int i = 0; i < fr->samples(); ++i) {
+               for (int j = 0; j < 6; ++j) {
+                       if (j == 2) {
+                               BOOST_CHECK_EQUAL ((fr->get(j, i) + 128) >> 8, stair * 2);
+                               ++stair;
+                       } else {
+                               BOOST_CHECK_EQUAL (fr->get(j, i), 0);
+                       }
+               }
+       }
+
+       fr = sound_reader->get_frame (26);
+       for (int i = 0; i < fr->samples(); ++i) {
                for (int j = 0; j < 6; ++j) {
                        if (j == 2) {
-                               BOOST_CHECK_EQUAL (fr->get(j, i) >> 8, stair);
+                               BOOST_CHECK_EQUAL ((fr->get(j, i) + 128) >> 8, stair * 2);
+                               ++stair;
+                       } else {
+                               BOOST_CHECK_EQUAL (fr->get(j, i), 0);
+                       }
+               }
+       }
+
+       fr = sound_reader->get_frame (27);
+       for (int i = 0; i < fr->samples(); ++i) {
+               for (int j = 0; j < 6; ++j) {
+                       if (j == 2 && i < (4753 - (2000 * 2))) {
+                               BOOST_CHECK_EQUAL ((fr->get(j, i) + 128) >> 8, stair * 2);
                                ++stair;
                        } else {
                                BOOST_CHECK_EQUAL (fr->get(j, i), 0);