diff options
| author | Carl Hetherington <cth@carlh.net> | 2022-05-16 00:37:30 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2022-05-16 21:39:28 +0200 |
| commit | 6b09eaaf8a972aa0d607c5f26da9e19720b5a668 (patch) | |
| tree | 2214fc15397b7b1f8c4b88dbc56a3df60e4b13df | |
| parent | eaee1cd5601a93037bc2fb0956b99b12fe1f90e6 (diff) | |
Make EmptyVideo work with stereo a little better.
| -rw-r--r-- | src/lib/empty_video.cc | 53 | ||||
| -rw-r--r-- | src/lib/empty_video.h | 9 | ||||
| -rw-r--r-- | src/lib/player.cc | 5 | ||||
| -rw-r--r-- | test/empty_test.cc | 99 | ||||
| -rw-r--r-- | test/player_test.cc | 2 |
5 files changed, 145 insertions, 23 deletions
diff --git a/src/lib/empty_video.cc b/src/lib/empty_video.cc index c578559e0..b99f911f2 100644 --- a/src/lib/empty_video.cc +++ b/src/lib/empty_video.cc @@ -35,23 +35,54 @@ using std::cout; using std::dynamic_pointer_cast; using std::function; using std::list; +using std::make_pair; +using std::pair; using std::shared_ptr; using namespace dcpomatic; EmptyVideo::EmptyVideo (shared_ptr<const Film> film, shared_ptr<const Playlist> playlist, DCPTime length) { - list<DCPTimePeriod> full; + list<DCPTimePeriod> full_left; + list<DCPTimePeriod> full_right; + list<DCPTimePeriod> full_both; for (auto i: playlist->content()) { if (i->video && i->video->use() && i->can_be_played() && i->paths_valid()) { - full.push_back (DCPTimePeriod(i->position(), i->end(film))); + auto period = DCPTimePeriod(i->position(), i->end(film)); + if (i->video->frame_type() == VideoFrameType::THREE_D_LEFT) { + full_left.push_back (period); + } else if (i->video->frame_type() == VideoFrameType::THREE_D_RIGHT) { + full_right.push_back (period); + } else { + full_both.push_back (period); + } } } - _periods = subtract (DCPTimePeriod(DCPTime(), length), coalesce(full)); + auto const whole = DCPTimePeriod(DCPTime(), length); + + auto empty_both = subtract(subtract(subtract({whole}, full_left), full_right), full_both); + auto empty_left = subtract(subtract(subtract({whole}, full_left), full_both), empty_both); + auto empty_right = subtract(subtract(subtract({whole}, full_right), full_both), empty_both); + + for (auto left: empty_left) { + _periods.push_back (make_pair(left, Eyes::LEFT)); + } + + for (auto right: empty_right) { + _periods.push_back (make_pair(right, Eyes::RIGHT)); + } + + for (auto both: empty_both) { + _periods.push_back (make_pair(both, Eyes::BOTH)); + } + + _periods.sort([](std::pair<DCPTimePeriod, Eyes> const& a, std::pair<DCPTimePeriod, Eyes> const& b) { + return a.first < b.first; + }); if (!_periods.empty()) { - _position = _periods.front().from; + _position = _periods.front().first.from; } } @@ -62,26 +93,26 @@ EmptyVideo::set_position (DCPTime position) _position = position; for (auto i: _periods) { - if (i.contains(_position)) { + if (i.first.contains(_position)) { return; } } for (auto i: _periods) { - if (i.from > _position) { - _position = i.from; + if (i.first.from > _position) { + _position = i.first.from; return; } } } -DCPTimePeriod +pair<DCPTimePeriod, Eyes> EmptyVideo::period_at_position () const { for (auto i: _periods) { - if (i.contains(_position)) { - return DCPTimePeriod (_position, i.to); + if (i.first.contains(_position)) { + return make_pair(DCPTimePeriod(_position, i.first.to), i.second); } } @@ -94,7 +125,7 @@ EmptyVideo::done () const { DCPTime latest; for (auto i: _periods) { - latest = max (latest, i.to); + latest = max (latest, i.first.to); } return _position >= latest; diff --git a/src/lib/empty_video.h b/src/lib/empty_video.h index cf315bc44..5659ba504 100644 --- a/src/lib/empty_video.h +++ b/src/lib/empty_video.h @@ -27,12 +27,15 @@ #include "dcpomatic_time.h" #include "playlist.h" #include <list> +#include <utility> struct empty_video_test1; struct empty_video_test2; struct empty_video_test3; struct empty_video_test_with_overlapping_content; +struct empty_video_test_with_three_d1; +struct empty_video_test_with_three_d2; struct player_subframe_test; @@ -46,7 +49,7 @@ public: return _position; } - dcpomatic::DCPTimePeriod period_at_position () const; + std::pair<dcpomatic::DCPTimePeriod, Eyes> period_at_position () const; bool done () const; @@ -57,9 +60,11 @@ private: friend struct ::empty_video_test2; friend struct ::empty_video_test3; friend struct ::empty_video_test_with_overlapping_content; + friend struct empty_video_test_with_three_d1; + friend struct empty_video_test_with_three_d2; friend struct ::player_subframe_test; - std::list<dcpomatic::DCPTimePeriod> _periods; + std::list<std::pair<dcpomatic::DCPTimePeriod, Eyes>> _periods; dcpomatic::DCPTime _position; }; diff --git a/src/lib/player.cc b/src/lib/player.cc index 66b731645..392c929a3 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -710,10 +710,13 @@ Player::pass () break; } case BLACK: + { LOG_DEBUG_PLAYER ("Emit black for gap at %1", to_string(_black.position())); - emit_video (black_player_video_frame(Eyes::BOTH), _black.position()); + auto period = _black.period_at_position(); + emit_video (black_player_video_frame(period.second), _black.position()); _black.set_position (_black.position() + one_video_frame()); break; + } case SILENT: { LOG_DEBUG_PLAYER ("Emit silence for gap at %1", to_string(_silent.position())); diff --git a/test/empty_test.cc b/test/empty_test.cc index 5e6424a2a..758ceee18 100644 --- a/test/empty_test.cc +++ b/test/empty_test.cc @@ -72,11 +72,11 @@ BOOST_AUTO_TEST_CASE (empty_video_test1) EmptyVideo black (film, film->playlist(), film->playlist()->length(film)); BOOST_REQUIRE_EQUAL (black._periods.size(), 2U); auto i = black._periods.begin(); - BOOST_CHECK (i->from == DCPTime::from_frames(0, vfr)); - BOOST_CHECK (i->to == DCPTime::from_frames(2, vfr)); + BOOST_CHECK (i->first.from == DCPTime::from_frames(0, vfr)); + BOOST_CHECK (i->first.to == DCPTime::from_frames(2, vfr)); ++i; - BOOST_CHECK (i->from == DCPTime::from_frames(5, vfr)); - BOOST_CHECK (i->to == DCPTime::from_frames(7, vfr)); + BOOST_CHECK (i->first.from == DCPTime::from_frames(5, vfr)); + BOOST_CHECK (i->first.to == DCPTime::from_frames(7, vfr)); } @@ -140,8 +140,8 @@ BOOST_AUTO_TEST_CASE (empty_video_test2) EmptyVideo black (film, film->playlist(), film->playlist()->length(film)); BOOST_REQUIRE_EQUAL (black._periods.size(), 1U); - BOOST_CHECK (black._periods.front().from == DCPTime::from_frames(3, vfr)); - BOOST_CHECK (black._periods.front().to == DCPTime::from_frames(7, vfr)); + BOOST_CHECK (black._periods.front().first.from == DCPTime::from_frames(3, vfr)); + BOOST_CHECK (black._periods.front().first.to == DCPTime::from_frames(7, vfr)); /* position should initially be the start of the first empty period */ BOOST_CHECK (black.position() == DCPTime::from_frames(3, vfr)); @@ -224,8 +224,8 @@ BOOST_AUTO_TEST_CASE (empty_video_test3) playlist->add (film, contentB); EmptyVideo black (film, playlist, playlist->length(film)); BOOST_REQUIRE_EQUAL (black._periods.size(), 1U); - BOOST_CHECK (black._periods.front().from == DCPTime::from_frames(0, vfr)); - BOOST_CHECK (black._periods.front().to == DCPTime::from_frames(7, vfr)); + BOOST_CHECK (black._periods.front().first.from == DCPTime::from_frames(0, vfr)); + BOOST_CHECK (black._periods.front().first.to == DCPTime::from_frames(7, vfr)); /* position should initially be the start of the first empty period */ BOOST_CHECK (black.position() == DCPTime::from_frames(0, vfr)); @@ -321,3 +321,86 @@ BOOST_AUTO_TEST_CASE (empty_audio_test_with_overlapping_content) BOOST_REQUIRE (silent._periods.empty()); } + +BOOST_AUTO_TEST_CASE (empty_video_test_with_three_d1) +{ + auto film = new_test_film2 ("empty_video_test_with_three_d1"); + film->set_sequence (false); + + auto both1 = make_shared<ImageContent>("test/data/simple_testcard_640x480.png"); + auto left = make_shared<ImageContent>("test/data/simple_testcard_640x480.png"); + auto right = make_shared<ImageContent>("test/data/simple_testcard_640x480.png"); + auto both2 = make_shared<ImageContent>("test/data/simple_testcard_640x480.png"); + + film->examine_and_add_content (both1); + film->examine_and_add_content (left); + film->examine_and_add_content (right); + film->examine_and_add_content (both2); + BOOST_REQUIRE (!wait_for_jobs()); + + int const vfr = film->video_frame_rate (); + + both1->video->set_length (vfr * 1); + both1->set_position (film, DCPTime(0)); + + left->video->set_length (vfr * 2); + left->video->set_frame_type (VideoFrameType::THREE_D_LEFT); + left->set_position (film, DCPTime::from_seconds(2)); + + right->video->set_length (vfr * 2); + right->video->set_frame_type (VideoFrameType::THREE_D_RIGHT); + right->set_position (film, DCPTime::from_seconds(3)); + + both2->video->set_length (vfr * 1); + both2->set_position (film, DCPTime::from_seconds(6)); + + EmptyVideo black(film, film->playlist(), film->playlist()->length(film)); + + for (auto i: black._periods) { + std::cout << to_string(i.first.from) << " " << to_string(i.first.to) << " " << static_cast<int>(i.second) << "\n"; + } + BOOST_REQUIRE_EQUAL (black._periods.size(), 4U); + auto i = black._periods.begin(); + BOOST_CHECK (i->first.from == DCPTime::from_seconds(1)); + BOOST_CHECK (i->first.to == DCPTime::from_seconds(2)); + BOOST_CHECK (i->second == Eyes::BOTH); + ++i; + BOOST_CHECK (i->first.from == DCPTime::from_seconds(2)); + BOOST_CHECK (i->first.to == DCPTime::from_seconds(3)); + BOOST_CHECK (i->second == Eyes::RIGHT); + ++i; + BOOST_CHECK (i->first.from == DCPTime::from_seconds(4)); + BOOST_CHECK (i->first.to == DCPTime::from_seconds(5)); + BOOST_CHECK (i->second == Eyes::LEFT); + ++i; + BOOST_CHECK (i->first.from == DCPTime::from_seconds(5)); + BOOST_CHECK (i->first.to == DCPTime::from_seconds(6)); + BOOST_CHECK (i->second == Eyes::BOTH); +} + + +BOOST_AUTO_TEST_CASE (empty_video_test_with_three_d2) +{ + auto film = new_test_film2 ("empty_video_test_with_three_d2"); + film->set_sequence (false); + + auto both = make_shared<ImageContent>("test/data/simple_testcard_640x480.png"); + auto right = make_shared<ImageContent>("test/data/simple_testcard_640x480.png"); + + film->examine_and_add_content (both); + film->examine_and_add_content (right); + BOOST_REQUIRE (!wait_for_jobs()); + + int const vfr = film->video_frame_rate (); + + both->video->set_length (vfr * 1); + both->set_position (film, DCPTime(0)); + + right->video->set_length (vfr * 1); + right->video->set_frame_type (VideoFrameType::THREE_D_RIGHT); + right->set_position (film, DCPTime::from_seconds(0)); + + EmptyVideo black(film, film->playlist(), film->playlist()->length(film)); + BOOST_REQUIRE (black._periods.empty()); +} + diff --git a/test/player_test.cc b/test/player_test.cc index 3fb8691a5..3954fbbae 100644 --- a/test/player_test.cc +++ b/test/player_test.cc @@ -166,7 +166,7 @@ BOOST_AUTO_TEST_CASE (player_subframe_test) auto player = std::make_shared<Player>(film, Image::Alignment::COMPACT); player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_black._periods.size(), 1U); - BOOST_CHECK (player->_black._periods.front() == DCPTimePeriod(DCPTime::from_frames(3 * 24, 24), DCPTime::from_frames(3 * 24 + 1, 24))); + BOOST_CHECK (player->_black._periods.front().first == DCPTimePeriod(DCPTime::from_frames(3 * 24, 24), DCPTime::from_frames(3 * 24 + 1, 24))); BOOST_REQUIRE_EQUAL (player->_silent._periods.size(), 1U); BOOST_CHECK (player->_silent._periods.front() == DCPTimePeriod(DCPTime(289920), DCPTime::from_frames(3 * 24 + 1, 24))); } |
