summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2019-12-16 23:00:12 +0000
committerCarl Hetherington <cth@carlh.net>2019-12-17 00:03:11 +0100
commit5be0db4041bdfc469668de290e44ff5443708cf6 (patch)
tree4beccaa25dee40d3729b0a8431f1400023ae689f
parentf35edd74c46c0291fee6d39dba1c73bac688c849 (diff)
Flush audio decoder when a DCPDecoder finishes so that
resamplers are emptied and hence we don't lose any samples. Fixes #1691. Back-ported from 1444299fa4582fc65c5237edd6c115921f20f872 in master.
-rw-r--r--src/lib/dcp_decoder.cc9
-rw-r--r--test/player_test.cc40
2 files changed, 48 insertions, 1 deletions
diff --git a/src/lib/dcp_decoder.cc b/src/lib/dcp_decoder.cc
index 826b4e8d3..a3c42a321 100644
--- a/src/lib/dcp_decoder.cc
+++ b/src/lib/dcp_decoder.cc
@@ -125,7 +125,14 @@ DCPDecoder::DCPDecoder (shared_ptr<const Film> film, shared_ptr<const DCPContent
bool
DCPDecoder::pass ()
{
- if (_reel == _reels.end () || !_dcp_content->can_be_played ()) {
+ if (!_dcp_content->can_be_played()) {
+ return true;
+ }
+
+ if (_reel == _reels.end()) {
+ if (audio) {
+ audio->flush ();
+ }
return true;
}
diff --git a/test/player_test.cc b/test/player_test.cc
index 390ecf444..b2b32ba2b 100644
--- a/test/player_test.cc
+++ b/test/player_test.cc
@@ -40,6 +40,7 @@
#include "lib/cross.h"
#include "test.h"
#include <boost/test/unit_test.hpp>
+#include <boost/algorithm/string.hpp>
#include <iostream>
using std::cout;
@@ -416,3 +417,42 @@ BOOST_AUTO_TEST_CASE (player_3d_test_2)
BOOST_REQUIRE (!wait_for_jobs());
}
+/** Test a crash when there is video-only content at the end of the DCP and a frame-rate conversion is happening;
+ * #1691.
+ */
+BOOST_AUTO_TEST_CASE (player_silence_at_end_crash)
+{
+ /* 25fps DCP with some audio */
+ shared_ptr<Film> film1 = new_test_film2 ("player_silence_at_end_crash_1");
+ shared_ptr<Content> content1 = content_factory("test/data/flat_red.png").front();
+ film1->examine_and_add_content (content1);
+ BOOST_REQUIRE (!wait_for_jobs());
+ content1->video->set_length (25);
+ film1->set_video_frame_rate (25);
+ film1->make_dcp ();
+ BOOST_REQUIRE (!wait_for_jobs());
+
+ /* Make another project importing this DCP */
+ shared_ptr<Film> film2 = new_test_film2 ("player_silence_at_end_crash_2");
+ shared_ptr<Content> content2(new DCPContent(film1->dir(film1->dcp_name())));
+ film2->examine_and_add_content (content2);
+ BOOST_REQUIRE (!wait_for_jobs());
+
+ /* and importing just the video MXF on its own at the end */
+ optional<boost::filesystem::path> video;
+ for (boost::filesystem::directory_iterator i(film1->dir(film1->dcp_name())); i != boost::filesystem::directory_iterator(); ++i) {
+ if (boost::starts_with(i->path().filename().string(), "j2c_")) {
+ video = i->path();
+ }
+ }
+
+ BOOST_REQUIRE (video);
+ shared_ptr<Content> content3 = content_factory(*video).front();
+ film2->examine_and_add_content (content3);
+ BOOST_REQUIRE (!wait_for_jobs());
+ content3->set_position (film2, DCPTime::from_seconds(1.5));
+ film2->set_video_frame_rate (24);
+ std::cout << "Here we go.\n";
+ film2->make_dcp ();
+ BOOST_REQUIRE (!wait_for_jobs());
+}