5e6424a2abb5db915d4324aa0a6d1ad8fc598a37
[dcpomatic.git] / test / empty_test.cc
1 /*
2     Copyright (C) 2017-2021 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21
22 /** @file  test/empty_test.cc
23  *  @brief Test the creation of Empty objects.
24  *  @ingroup feature
25  */
26
27
28 #include "lib/audio_content.h"
29 #include "lib/dcp_content_type.h"
30 #include "lib/decoder.h"
31 #include "lib/empty_audio.h"
32 #include "lib/empty_video.h"
33 #include "lib/film.h"
34 #include "lib/image_content.h"
35 #include "lib/player.h"
36 #include "lib/ratio.h"
37 #include "lib/video_content.h"
38 #include "test.h"
39 #include <boost/test/unit_test.hpp>
40
41
42 using std::list;
43 using std::make_shared;
44 using std::shared_ptr;
45 #if BOOST_VERSION >= 106100
46 using namespace boost::placeholders;
47 #endif
48 using namespace dcpomatic;
49
50
51 BOOST_AUTO_TEST_CASE (empty_video_test1)
52 {
53         auto film = new_test_film2 ("empty_video_test1");
54         film->set_sequence (false);
55         auto contentA = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
56         auto contentB = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
57
58         film->examine_and_add_content (contentA);
59         film->examine_and_add_content (contentB);
60         BOOST_REQUIRE (!wait_for_jobs());
61
62         int const vfr = film->video_frame_rate ();
63
64         /* 0 1 2 3 4 5 6 7
65          *     A A A     B
66          */
67         contentA->video->set_length (3);
68         contentA->set_position (film, DCPTime::from_frames(2, vfr));
69         contentB->video->set_length (1);
70         contentB->set_position (film, DCPTime::from_frames(7, vfr));
71
72         EmptyVideo black (film, film->playlist(), film->playlist()->length(film));
73         BOOST_REQUIRE_EQUAL (black._periods.size(), 2U);
74         auto i = black._periods.begin();
75         BOOST_CHECK (i->from == DCPTime::from_frames(0, vfr));
76         BOOST_CHECK (i->to ==   DCPTime::from_frames(2, vfr));
77         ++i;
78         BOOST_CHECK (i->from == DCPTime::from_frames(5, vfr));
79         BOOST_CHECK (i->to ==   DCPTime::from_frames(7, vfr));
80 }
81
82
83 BOOST_AUTO_TEST_CASE (empty_audio_test1)
84 {
85         auto film = new_test_film2 ("empty_audio_test1");
86         film->set_sequence (false);
87         auto contentA = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
88         auto contentB = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
89
90         film->examine_and_add_content (contentA);
91         film->examine_and_add_content (contentB);
92         BOOST_REQUIRE (!wait_for_jobs());
93
94         /* Make this content look like it has audio so we can test the EmptyAudio class */
95         contentA->audio = make_shared<AudioContent>(contentA.get());
96         contentB->audio = make_shared<AudioContent>(contentB.get());
97
98         int const vfr = film->video_frame_rate ();
99
100         /* 0 1 2 3 4 5 6 7
101          *     A A A     B
102          */
103         contentA->video->set_length (3);
104         contentA->set_position (film, DCPTime::from_frames(2, vfr));
105         contentB->video->set_length (1);
106         contentB->set_position (film, DCPTime::from_frames(7, vfr));
107
108         EmptyAudio silent (film, film->playlist(), film->playlist()->length(film));
109         BOOST_REQUIRE_EQUAL (silent._periods.size(), 2U);
110         auto i = silent._periods.begin();
111         BOOST_CHECK (i->from == DCPTime::from_frames(0, vfr));
112         BOOST_CHECK (i->to ==   DCPTime::from_frames(2, vfr));
113         ++i;
114         BOOST_CHECK (i->from == DCPTime::from_frames(5, vfr));
115         BOOST_CHECK (i->to ==   DCPTime::from_frames(7, vfr));
116 }
117
118
119 /** Some tests where the first empty period is not at time 0 */
120 BOOST_AUTO_TEST_CASE (empty_video_test2)
121 {
122         auto film = new_test_film2 ("empty_video_test2");
123         film->set_sequence (false);
124         auto contentA = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
125         auto contentB = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
126
127         film->examine_and_add_content (contentA);
128         film->examine_and_add_content (contentB);
129         BOOST_REQUIRE (!wait_for_jobs());
130
131         int const vfr = film->video_frame_rate ();
132
133         /* 0 1 2 3 4 5 6 7
134          * A A A         B
135          */
136         contentA->video->set_length (3);
137         contentA->set_position (film, DCPTime(0));
138         contentB->video->set_length (1);
139         contentB->set_position (film, DCPTime::from_frames(7, vfr));
140
141         EmptyVideo black (film, film->playlist(), film->playlist()->length(film));
142         BOOST_REQUIRE_EQUAL (black._periods.size(), 1U);
143         BOOST_CHECK (black._periods.front().from == DCPTime::from_frames(3, vfr));
144         BOOST_CHECK (black._periods.front().to == DCPTime::from_frames(7, vfr));
145
146         /* position should initially be the start of the first empty period */
147         BOOST_CHECK (black.position() == DCPTime::from_frames(3, vfr));
148
149         /* check that done() works */
150         BOOST_CHECK (!black.done ());
151         black.set_position (DCPTime::from_frames (4, vfr));
152         BOOST_CHECK (!black.done ());
153         black.set_position (DCPTime::from_frames (7, vfr));
154         BOOST_CHECK (black.done ());
155 }
156
157
158 /** Some tests where the first empty period is not at time 0 */
159 BOOST_AUTO_TEST_CASE (empty_audio_test2)
160 {
161         auto film = new_test_film2 ("empty_audio_test2");
162         film->set_sequence (false);
163         auto contentA = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
164         auto contentB = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
165
166         film->examine_and_add_content (contentA);
167         film->examine_and_add_content (contentB);
168         BOOST_REQUIRE (!wait_for_jobs());
169
170         /* Make this content look like it has audio so we can test the EmptyAudio class */
171         contentA->audio = make_shared<AudioContent>(contentA.get());
172         contentB->audio = make_shared<AudioContent>(contentB.get());
173
174         int const vfr = film->video_frame_rate ();
175
176         /* 0 1 2 3 4 5 6 7
177          * A A A         B
178          */
179         contentA->video->set_length (3);
180         contentA->set_position (film, DCPTime(0));
181         contentB->video->set_length (1);
182         contentB->set_position (film, DCPTime::from_frames(7, vfr));
183
184         EmptyAudio silent (film, film->playlist(), film->playlist()->length(film));
185         BOOST_REQUIRE_EQUAL (silent._periods.size(), 1U);
186         BOOST_CHECK (silent._periods.front().from == DCPTime::from_frames(3, vfr));
187         BOOST_CHECK (silent._periods.front().to == DCPTime::from_frames(7, vfr));
188
189         /* position should initially be the start of the first empty period */
190         BOOST_CHECK (silent.position() == DCPTime::from_frames(3, vfr));
191
192         /* check that done() works */
193         BOOST_CHECK (!silent.done ());
194         silent.set_position (DCPTime::from_frames (4, vfr));
195         BOOST_CHECK (!silent.done ());
196         silent.set_position (DCPTime::from_frames (7, vfr));
197         BOOST_CHECK (silent.done ());
198 }
199
200
201 /** Test for when the film's playlist is not the same as the one passed into Empty */
202 BOOST_AUTO_TEST_CASE (empty_video_test3)
203 {
204         auto film = new_test_film2 ("empty_video_test3");
205         film->set_sequence (false);
206         auto contentA = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
207         auto contentB = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
208
209         film->examine_and_add_content (contentA);
210         film->examine_and_add_content (contentB);
211         BOOST_REQUIRE (!wait_for_jobs());
212
213         int const vfr = film->video_frame_rate ();
214
215         /* 0 1 2 3 4 5 6 7
216          * A A A         B
217          */
218         contentA->video->set_length (3);
219         contentA->set_position (film, DCPTime(0));
220         contentB->video->set_length (1);
221         contentB->set_position (film, DCPTime::from_frames(7, vfr));
222
223         auto playlist = make_shared<Playlist>();
224         playlist->add (film, contentB);
225         EmptyVideo black (film, playlist, playlist->length(film));
226         BOOST_REQUIRE_EQUAL (black._periods.size(), 1U);
227         BOOST_CHECK (black._periods.front().from == DCPTime::from_frames(0, vfr));
228         BOOST_CHECK (black._periods.front().to == DCPTime::from_frames(7, vfr));
229
230         /* position should initially be the start of the first empty period */
231         BOOST_CHECK (black.position() == DCPTime::from_frames(0, vfr));
232 }
233
234
235 /** Test for when the film's playlist is not the same as the one passed into Empty */
236 BOOST_AUTO_TEST_CASE (empty_audio_test3)
237 {
238         auto film = new_test_film2 ("empty_audio_test3");
239         film->set_sequence (false);
240         auto contentA = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
241         auto contentB = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
242
243         film->examine_and_add_content (contentA);
244         film->examine_and_add_content (contentB);
245         BOOST_REQUIRE (!wait_for_jobs());
246
247         /* Make this content look like it has audio so we can test the EmptyAudio class */
248         contentA->audio = make_shared<AudioContent>(contentA.get());
249         contentB->audio = make_shared<AudioContent>(contentB.get());
250
251         int const vfr = film->video_frame_rate ();
252
253         /* 0 1 2 3 4 5 6 7
254          * A A A         B
255          */
256         contentA->video->set_length (3);
257         contentA->set_position (film, DCPTime(0));
258         contentB->video->set_length (1);
259         contentB->set_position (film, DCPTime::from_frames(7, vfr));
260
261         auto playlist = make_shared<Playlist>();
262         playlist->add (film, contentB);
263         EmptyAudio silent (film, playlist, playlist->length(film));
264         BOOST_REQUIRE_EQUAL (silent._periods.size(), 1U);
265         BOOST_CHECK (silent._periods.front().from == DCPTime::from_frames(0, vfr));
266         BOOST_CHECK (silent._periods.front().to == DCPTime::from_frames(7, vfr));
267
268         /* position should initially be the start of the first empty period */
269         BOOST_CHECK (silent.position() == DCPTime::from_frames(0, vfr));
270 }
271
272
273 BOOST_AUTO_TEST_CASE (empty_video_test_with_overlapping_content)
274 {
275         auto film = new_test_film2 ("empty_video_test_with_overlapping_content");
276         film->set_sequence (false);
277         auto contentA = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
278         auto contentB = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
279
280         film->examine_and_add_content (contentA);
281         film->examine_and_add_content (contentB);
282         BOOST_REQUIRE (!wait_for_jobs());
283
284         int const vfr = film->video_frame_rate ();
285
286         contentA->video->set_length (vfr * 3);
287         contentA->set_position (film, DCPTime());
288         contentB->video->set_length (vfr * 1);
289         contentB->set_position (film, DCPTime::from_seconds(1));
290
291         EmptyVideo black(film, film->playlist(), film->playlist()->length(film));
292
293         BOOST_REQUIRE (black._periods.empty());
294 }
295
296
297 BOOST_AUTO_TEST_CASE (empty_audio_test_with_overlapping_content)
298 {
299         auto film = new_test_film2 ("empty_audio_test_with_overlapping_content");
300         film->set_sequence (false);
301         auto contentA = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
302         auto contentB = make_shared<ImageContent>("test/data/simple_testcard_640x480.png");
303
304         film->examine_and_add_content (contentA);
305         film->examine_and_add_content (contentB);
306         BOOST_REQUIRE (!wait_for_jobs());
307
308         /* Make this content look like it has audio so we can test the EmptyAudio class */
309         contentA->audio = make_shared<AudioContent>(contentA.get());
310         contentB->audio = make_shared<AudioContent>(contentB.get());
311
312         int const vfr = film->video_frame_rate ();
313
314         contentA->video->set_length (vfr * 3);
315         contentA->set_position (film, DCPTime());
316         contentB->video->set_length (vfr * 1);
317         contentB->set_position (film, DCPTime::from_seconds(1));
318
319         EmptyAudio silent(film, film->playlist(), film->playlist()->length(film));
320
321         BOOST_REQUIRE (silent._periods.empty());
322 }
323