From 080051edd655be1a8aa4b8dc21d0c262282d8444 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 2 Mar 2017 00:01:18 +0000 Subject: [PATCH] Handle end-trim correctly in player; there is scope to make this more efficient by adjusting decoders. --- src/lib/player.cc | 16 ++++++--- test/torture_test.cc | 82 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 83 insertions(+), 15 deletions(-) diff --git a/src/lib/player.cc b/src/lib/player.cc index 035af81fe..844706e4b 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -362,7 +362,7 @@ DCPTime Player::resampled_audio_to_dcp (shared_ptr 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 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 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 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); diff --git a/test/torture_test.cc b/test/torture_test.cc index 7d85f5d7d..21494e5d8 100644 --- a/test/torture_test.cc +++ b/test/torture_test.cc @@ -40,26 +40,36 @@ using boost::shared_ptr; /** Test a fairly complex arrangement of content */ BOOST_AUTO_TEST_CASE (torture_test1) { - shared_ptr film = new_test_film ("player_torture_test"); + shared_ptr 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 staircase = content_factory(film, "test/data/staircase.mov").front (); + shared_ptr 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 > 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); -- 2.30.2