summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2022-05-16 00:37:30 +0200
committerCarl Hetherington <cth@carlh.net>2022-05-16 21:39:28 +0200
commit6b09eaaf8a972aa0d607c5f26da9e19720b5a668 (patch)
tree2214fc15397b7b1f8c4b88dbc56a3df60e4b13df
parenteaee1cd5601a93037bc2fb0956b99b12fe1f90e6 (diff)
Make EmptyVideo work with stereo a little better.
-rw-r--r--src/lib/empty_video.cc53
-rw-r--r--src/lib/empty_video.h9
-rw-r--r--src/lib/player.cc5
-rw-r--r--test/empty_test.cc99
-rw-r--r--test/player_test.cc2
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)));
}