Change how video timing is done.
[dcpomatic.git] / test / shuffler_test.cc
1 #include "lib/shuffler.h"
2 #include "lib/piece.h"
3 #include "lib/content_video.h"
4 #include <boost/test/unit_test.hpp>
5
6 using std::list;
7 using std::shared_ptr;
8 using std::weak_ptr;
9 using boost::optional;
10 #if BOOST_VERSION >= 106100
11 using namespace boost::placeholders;
12 #endif
13 using namespace dcpomatic;
14
15
16 static void
17 push(Shuffler& s, int frame, Eyes eyes)
18 {
19         shared_ptr<Piece> piece (new Piece (shared_ptr<Content>(), shared_ptr<Decoder>(), FrameRateChange(24, 24)));
20         ContentVideo cv;
21         cv.time = ContentTime::from_frames(frame, 24);
22         cv.eyes = eyes;
23         s.video (piece, cv);
24 }
25
26 list<ContentVideo> pending_cv;
27
28 static void
29 receive (weak_ptr<Piece>, ContentVideo cv)
30 {
31         pending_cv.push_back (cv);
32 }
33
34 static void
35 check (int frame, Eyes eyes, int line)
36 {
37         auto const time = ContentTime::from_frames(frame, 24);
38         BOOST_REQUIRE_MESSAGE (!pending_cv.empty(), "Check at " << line << " failed.");
39         BOOST_CHECK_MESSAGE (pending_cv.front().time == time, "Check at " << line << " failed.");
40         BOOST_CHECK_MESSAGE (pending_cv.front().eyes == eyes, "Check at " << line << " failed.");
41         pending_cv.pop_front();
42 }
43
44 /** A perfect sequence */
45 BOOST_AUTO_TEST_CASE (shuffler_test1)
46 {
47         Shuffler s;
48         s.Video.connect (boost::bind (&receive, _1, _2));
49
50         for (int i = 0; i < 10; ++i) {
51                 push (s, i, Eyes::LEFT);
52                 push (s, i, Eyes::RIGHT);
53                 check (i, Eyes::LEFT, __LINE__);
54                 check (i, Eyes::RIGHT, __LINE__);
55         }
56 }
57
58 /** Everything present but some simple shuffling needed */
59 BOOST_AUTO_TEST_CASE (shuffler_test2)
60 {
61         Shuffler s;
62         s.Video.connect (boost::bind (&receive, _1, _2));
63
64         for (int i = 0; i < 10; i += 2) {
65                 push (s, i, Eyes::LEFT);
66                 push (s, i + 1, Eyes::LEFT);
67                 push (s, i, Eyes::RIGHT);
68                 push (s, i + 1, Eyes::RIGHT);
69                 check (i, Eyes::LEFT, __LINE__);
70                 check (i, Eyes::RIGHT, __LINE__);
71                 check (i + 1, Eyes::LEFT, __LINE__);
72                 check (i + 1, Eyes::RIGHT, __LINE__);
73         }
74 }
75
76 /** One missing left eye image */
77 BOOST_AUTO_TEST_CASE (shuffler_test3)
78 {
79         Shuffler s;
80         s.Video.connect (boost::bind (&receive, _1, _2));
81
82         push (s, 0, Eyes::LEFT);
83         check (0, Eyes::LEFT, __LINE__);
84         push (s, 0, Eyes::RIGHT);
85         check (0, Eyes::RIGHT, __LINE__);
86         push (s, 1, Eyes::LEFT);
87         check (1, Eyes::LEFT, __LINE__);
88         push (s, 1, Eyes::RIGHT);
89         check (1, Eyes::RIGHT, __LINE__);
90         push (s, 2, Eyes::RIGHT);
91         push (s, 3, Eyes::LEFT);
92         push (s, 3, Eyes::RIGHT);
93         push (s, 4, Eyes::LEFT);
94         push (s, 4, Eyes::RIGHT);
95         s.flush ();
96         check (2, Eyes::RIGHT, __LINE__);
97         check (3, Eyes::LEFT, __LINE__);
98         check (3, Eyes::RIGHT, __LINE__);
99         check (4, Eyes::LEFT, __LINE__);
100         check (4, Eyes::RIGHT, __LINE__);
101 }
102
103 /** One missing right eye image */
104 BOOST_AUTO_TEST_CASE (shuffler_test4)
105 {
106         Shuffler s;
107         s.Video.connect (boost::bind (&receive, _1, _2));
108
109         push (s, 0, Eyes::LEFT);
110         check (0, Eyes::LEFT, __LINE__);
111         push (s, 0, Eyes::RIGHT);
112         check (0, Eyes::RIGHT, __LINE__);
113         push (s, 1, Eyes::LEFT);
114         check (1, Eyes::LEFT, __LINE__);
115         push (s, 1, Eyes::RIGHT);
116         check (1, Eyes::RIGHT, __LINE__);
117         push (s, 2, Eyes::LEFT);
118         push (s, 3, Eyes::LEFT);
119         push (s, 3, Eyes::RIGHT);
120         push (s, 4, Eyes::LEFT);
121         push (s, 4, Eyes::RIGHT);
122         s.flush ();
123         check (2, Eyes::LEFT, __LINE__);
124         check (3, Eyes::LEFT, __LINE__);
125         check (3, Eyes::RIGHT, __LINE__);
126         check (4, Eyes::LEFT, __LINE__);
127         check (4, Eyes::RIGHT, __LINE__);
128 }
129
130 /** Only one eye */
131 BOOST_AUTO_TEST_CASE (shuffler_test5)
132 {
133         Shuffler s;
134         s.Video.connect (boost::bind (&receive, _1, _2));
135
136         /* One left should come out straight away */
137         push (s, 0, Eyes::LEFT);
138         check (0, Eyes::LEFT, __LINE__);
139
140         /* More lefts should be kept in the shuffler in the hope that some rights arrive */
141         for (int i = 0; i < s._max_size; ++i) {
142                 push (s, i + 1, Eyes::LEFT);
143         }
144         BOOST_CHECK (pending_cv.empty ());
145
146         /* If enough lefts come the shuffler should conclude that there's no rights and start
147            giving out the lefts.
148         */
149         push (s, s._max_size + 1, Eyes::LEFT);
150         check (1, Eyes::LEFT, __LINE__);
151 }
152
153 /** One complete frame (L+R) missing.
154     Shuffler should carry on, skipping this frame, as the player will cope with it.
155 */
156 BOOST_AUTO_TEST_CASE (shuffler_test6)
157 {
158         Shuffler s;
159         s.Video.connect (boost::bind (&receive, _1, _2));
160
161         push (s, 0, Eyes::LEFT);
162         check (0, Eyes::LEFT, __LINE__);
163         push (s, 0, Eyes::RIGHT);
164         check (0, Eyes::RIGHT, __LINE__);
165
166         push (s, 2, Eyes::LEFT);
167         push (s, 2, Eyes::RIGHT);
168         check (2, Eyes::LEFT, __LINE__);
169         check (2, Eyes::RIGHT, __LINE__);
170
171         push (s, 3, Eyes::LEFT);
172         check (3, Eyes::LEFT, __LINE__);
173         push (s, 3, Eyes::RIGHT);
174         check (3, Eyes::RIGHT, __LINE__);
175 }