2 Copyright (C) 2015-2020 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
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.
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.
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/>.
21 /** @file test/reels_test.cc
22 * @brief Check manipulation of reels in various ways.
27 #include "lib/ratio.h"
28 #include "lib/ffmpeg_content.h"
29 #include "lib/image_content.h"
30 #include "lib/dcp_content_type.h"
31 #include "lib/dcp_content.h"
32 #include "lib/video_content.h"
33 #include "lib/string_text_file_content.h"
34 #include "lib/content_factory.h"
36 #include <boost/test/unit_test.hpp>
43 using std::shared_ptr;
44 using boost::function;
45 using namespace dcpomatic;
47 /** Test Film::reels() */
48 BOOST_AUTO_TEST_CASE (reels_test1)
50 shared_ptr<Film> film = new_test_film ("reels_test1");
51 film->set_container (Ratio::from_id ("185"));
52 shared_ptr<FFmpegContent> A (new FFmpegContent("test/data/test.mp4"));
53 film->examine_and_add_content (A);
54 shared_ptr<FFmpegContent> B (new FFmpegContent("test/data/test.mp4"));
55 film->examine_and_add_content (B);
56 BOOST_REQUIRE (!wait_for_jobs());
57 BOOST_CHECK_EQUAL (A->full_length(film).get(), 288000);
59 film->set_reel_type (REELTYPE_SINGLE);
60 list<DCPTimePeriod> r = film->reels ();
61 BOOST_CHECK_EQUAL (r.size(), 1U);
62 BOOST_CHECK_EQUAL (r.front().from.get(), 0);
63 BOOST_CHECK_EQUAL (r.front().to.get(), 288000 * 2);
65 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
67 BOOST_CHECK_EQUAL (r.size(), 2U);
68 BOOST_CHECK_EQUAL (r.front().from.get(), 0);
69 BOOST_CHECK_EQUAL (r.front().to.get(), 288000);
70 BOOST_CHECK_EQUAL (r.back().from.get(), 288000);
71 BOOST_CHECK_EQUAL (r.back().to.get(), 288000 * 2);
73 film->set_j2k_bandwidth (100000000);
74 film->set_reel_type (REELTYPE_BY_LENGTH);
75 /* This is just over 2.5s at 100Mbit/s; should correspond to 60 frames */
76 film->set_reel_length (31253154);
78 BOOST_CHECK_EQUAL (r.size(), 3U);
79 list<DCPTimePeriod>::const_iterator i = r.begin ();
80 BOOST_CHECK_EQUAL (i->from.get(), 0);
81 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_frames(60, 24).get());
83 BOOST_CHECK_EQUAL (i->from.get(), DCPTime::from_frames(60, 24).get());
84 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_frames(120, 24).get());
86 BOOST_CHECK_EQUAL (i->from.get(), DCPTime::from_frames(120, 24).get());
87 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_frames(144, 24).get());
90 /** Make a short DCP with multi reels split by video content, then import
91 * this into a new project and make a new DCP referencing it.
93 BOOST_AUTO_TEST_CASE (reels_test2)
95 shared_ptr<Film> film = new_test_film ("reels_test2");
96 film->set_name ("reels_test2");
97 film->set_container (Ratio::from_id ("185"));
98 film->set_interop (false);
99 film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
102 shared_ptr<ImageContent> c (new ImageContent("test/data/flat_red.png"));
103 film->examine_and_add_content (c);
104 BOOST_REQUIRE (!wait_for_jobs());
105 c->video->set_length (24);
109 shared_ptr<ImageContent> c (new ImageContent("test/data/flat_green.png"));
110 film->examine_and_add_content (c);
111 BOOST_REQUIRE (!wait_for_jobs());
112 c->video->set_length (24);
116 shared_ptr<ImageContent> c (new ImageContent("test/data/flat_blue.png"));
117 film->examine_and_add_content (c);
118 BOOST_REQUIRE (!wait_for_jobs());
119 c->video->set_length (24);
122 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
123 BOOST_CHECK_EQUAL (film->reels().size(), 3U);
124 BOOST_REQUIRE (!wait_for_jobs());
127 BOOST_REQUIRE (!wait_for_jobs());
129 check_dcp ("test/data/reels_test2", film->dir (film->dcp_name()));
131 shared_ptr<Film> film2 = new_test_film ("reels_test2b");
132 film2->set_name ("reels_test2b");
133 film2->set_container (Ratio::from_id ("185"));
134 film2->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
135 film2->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
137 shared_ptr<DCPContent> c (new DCPContent(film->dir(film->dcp_name())));
138 film2->examine_and_add_content (c);
139 BOOST_REQUIRE (!wait_for_jobs ());
141 list<DCPTimePeriod> r = film2->reels ();
142 BOOST_CHECK_EQUAL (r.size(), 3U);
143 list<DCPTimePeriod>::const_iterator i = r.begin ();
144 BOOST_CHECK_EQUAL (i->from.get(), 0);
145 BOOST_CHECK_EQUAL (i->to.get(), 96000);
147 BOOST_CHECK_EQUAL (i->from.get(), 96000);
148 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 2);
150 BOOST_CHECK_EQUAL (i->from.get(), 96000 * 2);
151 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 3);
153 c->set_reference_video (true);
154 c->set_reference_audio (true);
157 BOOST_REQUIRE (!wait_for_jobs());
160 /** Check that REELTYPE_BY_VIDEO_CONTENT adds an extra reel, if necessary, at the end
161 * of all the video content to mop up anything afterward.
163 BOOST_AUTO_TEST_CASE (reels_test3)
165 shared_ptr<Film> film = new_test_film ("reels_test3");
166 film->set_name ("reels_test3");
167 film->set_container (Ratio::from_id ("185"));
168 film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
169 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
171 shared_ptr<Content> dcp (new DCPContent("test/data/reels_test2"));
172 film->examine_and_add_content (dcp);
173 shared_ptr<Content> sub (new StringTextFileContent("test/data/subrip.srt"));
174 film->examine_and_add_content (sub);
175 BOOST_REQUIRE (!wait_for_jobs());
177 list<DCPTimePeriod> reels = film->reels();
178 BOOST_REQUIRE_EQUAL (reels.size(), 4U);
179 list<DCPTimePeriod>::const_iterator i = reels.begin ();
180 BOOST_CHECK_EQUAL (i->from.get(), 0);
181 BOOST_CHECK_EQUAL (i->to.get(), 96000);
183 BOOST_CHECK_EQUAL (i->from.get(), 96000);
184 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 2);
186 BOOST_CHECK_EQUAL (i->from.get(), 96000 * 2);
187 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 3);
189 BOOST_CHECK_EQUAL (i->from.get(), 96000 * 3);
190 BOOST_CHECK_EQUAL (i->to.get(), sub->full_length(film).ceil(film->video_frame_rate()).get());
193 /** Check creation of a multi-reel DCP with a single .srt subtitle file;
194 * make sure that the reel subtitle timing is done right.
196 BOOST_AUTO_TEST_CASE (reels_test4)
198 shared_ptr<Film> film = new_test_film ("reels_test4");
199 film->set_name ("reels_test4");
200 film->set_container (Ratio::from_id ("185"));
201 film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
202 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
203 film->set_interop (false);
205 /* 4 piece of 1s-long content */
206 shared_ptr<ImageContent> content[4];
207 for (int i = 0; i < 4; ++i) {
208 content[i].reset (new ImageContent("test/data/flat_green.png"));
209 film->examine_and_add_content (content[i]);
210 BOOST_REQUIRE (!wait_for_jobs());
211 content[i]->video->set_length (24);
214 shared_ptr<StringTextFileContent> subs (new StringTextFileContent("test/data/subrip3.srt"));
215 film->examine_and_add_content (subs);
216 BOOST_REQUIRE (!wait_for_jobs());
218 list<DCPTimePeriod> reels = film->reels();
219 BOOST_REQUIRE_EQUAL (reels.size(), 4U);
220 list<DCPTimePeriod>::const_iterator i = reels.begin ();
221 BOOST_CHECK_EQUAL (i->from.get(), 0);
222 BOOST_CHECK_EQUAL (i->to.get(), 96000);
224 BOOST_CHECK_EQUAL (i->from.get(), 96000);
225 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 2);
227 BOOST_CHECK_EQUAL (i->from.get(), 96000 * 2);
228 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 3);
230 BOOST_CHECK_EQUAL (i->from.get(), 96000 * 3);
231 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 4);
234 BOOST_REQUIRE (!wait_for_jobs());
236 check_dcp ("test/data/reels_test4", film->dir (film->dcp_name()));
239 BOOST_AUTO_TEST_CASE (reels_test5)
241 shared_ptr<Film> film = new_test_film ("reels_test5");
242 film->set_sequence (false);
243 shared_ptr<DCPContent> dcp (new DCPContent("test/data/reels_test4"));
244 film->examine_and_add_content (dcp);
245 BOOST_REQUIRE (!wait_for_jobs ());
247 /* Set to 2123 but it will be rounded up to the next frame (4000) */
248 dcp->set_position(film, DCPTime(2123));
251 list<DCPTimePeriod> p = dcp->reels (film);
252 BOOST_REQUIRE_EQUAL (p.size(), 4U);
253 list<DCPTimePeriod>::const_iterator i = p.begin();
254 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 0), DCPTime(4000 + 96000)));
255 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 96000), DCPTime(4000 + 192000)));
256 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 192000), DCPTime(4000 + 288000)));
257 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 288000), DCPTime(4000 + 384000)));
261 dcp->set_trim_start (ContentTime::from_seconds (0.5));
262 list<DCPTimePeriod> p = dcp->reels (film);
263 BOOST_REQUIRE_EQUAL (p.size(), 4U);
264 list<DCPTimePeriod>::const_iterator i = p.begin();
265 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 0), DCPTime(4000 + 48000)));
266 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 48000), DCPTime(4000 + 144000)));
267 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 144000), DCPTime(4000 + 240000)));
268 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 240000), DCPTime(4000 + 336000)));
272 dcp->set_trim_end (ContentTime::from_seconds (0.5));
273 list<DCPTimePeriod> p = dcp->reels (film);
274 BOOST_REQUIRE_EQUAL (p.size(), 4U);
275 list<DCPTimePeriod>::const_iterator i = p.begin();
276 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 0), DCPTime(4000 + 48000)));
277 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 48000), DCPTime(4000 + 144000)));
278 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 144000), DCPTime(4000 + 240000)));
279 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 240000), DCPTime(4000 + 288000)));
283 dcp->set_trim_start (ContentTime::from_seconds (1.5));
284 list<DCPTimePeriod> p = dcp->reels (film);
285 BOOST_REQUIRE_EQUAL (p.size(), 3U);
286 list<DCPTimePeriod>::const_iterator i = p.begin();
287 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 0), DCPTime(4000 + 48000)));
288 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 48000), DCPTime(4000 + 144000)));
289 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 144000), DCPTime(4000 + 192000)));
293 /** Check reel split with a muxed video/audio source */
294 BOOST_AUTO_TEST_CASE (reels_test6)
296 shared_ptr<Film> film = new_test_film ("reels_test6");
297 film->set_name ("reels_test6");
298 film->set_container (Ratio::from_id ("185"));
299 film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
300 shared_ptr<FFmpegContent> A (new FFmpegContent("test/data/test2.mp4"));
301 film->examine_and_add_content (A);
302 BOOST_REQUIRE (!wait_for_jobs ());
304 film->set_j2k_bandwidth (100000000);
305 film->set_reel_type (REELTYPE_BY_LENGTH);
306 /* This is just over 2.5s at 100Mbit/s; should correspond to 60 frames */
307 film->set_reel_length (31253154);
309 BOOST_REQUIRE (!wait_for_jobs ());
312 /** Check the case where the last bit of audio hangs over the end of the video
313 * and we are using REELTYPE_BY_VIDEO_CONTENT.
315 BOOST_AUTO_TEST_CASE (reels_test7)
317 shared_ptr<Film> film = new_test_film ("reels_test7");
318 film->set_name ("reels_test7");
319 film->set_container (Ratio::from_id ("185"));
320 film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
321 shared_ptr<Content> A = content_factory("test/data/flat_red.png").front();
322 film->examine_and_add_content (A);
323 BOOST_REQUIRE (!wait_for_jobs ());
324 shared_ptr<Content> B = content_factory("test/data/awkward_length.wav").front();
325 film->examine_and_add_content (B);
326 BOOST_REQUIRE (!wait_for_jobs ());
327 film->set_video_frame_rate (24);
328 A->video->set_length (2 * 24);
330 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
331 BOOST_REQUIRE_EQUAL (film->reels().size(), 2U);
332 BOOST_CHECK (film->reels().front() == DCPTimePeriod(DCPTime(0), DCPTime::from_frames(2 * 24, 24)));
333 BOOST_CHECK (film->reels().back() == DCPTimePeriod(DCPTime::from_frames(2 * 24, 24), DCPTime::from_frames(3 * 24 + 1, 24)));
336 BOOST_REQUIRE (!wait_for_jobs ());
339 /** Check a reels-related error; make_dcp() would raise a ProgrammingError */
340 BOOST_AUTO_TEST_CASE (reels_test8)
342 shared_ptr<Film> film = new_test_film ("reels_test8");
343 film->set_name ("reels_test8");
344 film->set_container (Ratio::from_id ("185"));
345 film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
346 shared_ptr<FFmpegContent> A (new FFmpegContent("test/data/test2.mp4"));
347 film->examine_and_add_content (A);
348 BOOST_REQUIRE (!wait_for_jobs ());
350 A->set_trim_end (ContentTime::from_seconds (1));
352 BOOST_REQUIRE (!wait_for_jobs ());
355 /** Check another reels-related error; make_dcp() would raise a ProgrammingError */
356 BOOST_AUTO_TEST_CASE (reels_test9)
358 shared_ptr<Film> film = new_test_film2("reels_test9a");
359 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
360 film->examine_and_add_content(A);
361 BOOST_REQUIRE(!wait_for_jobs());
362 A->video->set_length(5 * 24);
363 film->set_video_frame_rate(24);
365 BOOST_REQUIRE(!wait_for_jobs());
367 shared_ptr<Film> film2 = new_test_film2("reels_test9b");
368 shared_ptr<DCPContent> B(new DCPContent(film->dir(film->dcp_name())));
369 film2->examine_and_add_content(B);
370 film2->examine_and_add_content(content_factory("test/data/dcp_sub4.xml").front());
371 B->set_reference_video(true);
372 B->set_reference_audio(true);
373 BOOST_REQUIRE(!wait_for_jobs());
374 film2->set_reel_type(REELTYPE_BY_VIDEO_CONTENT);
375 film2->write_metadata();
377 BOOST_REQUIRE(!wait_for_jobs());
380 /** Another reels-related error; make_dcp() would raise a ProgrammingError
381 * in AudioBuffers::allocate due to an attempt to allocate a negatively-sized buffer.
382 * This was triggered by a VF where there are referenced audio reels followed by
383 * VF audio. When the VF audio arrives the Writer did not correctly skip over the
386 BOOST_AUTO_TEST_CASE (reels_test10)
389 shared_ptr<Film> ov = new_test_film2("reels_test10_ov");
390 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
391 ov->examine_and_add_content (A);
392 BOOST_REQUIRE (!wait_for_jobs());
393 A->video->set_length (5 * 24);
395 shared_ptr<FFmpegContent> B(new FFmpegContent("test/data/flat_red.png"));
396 ov->examine_and_add_content (B);
397 BOOST_REQUIRE (!wait_for_jobs());
398 B->video->set_length (5 * 24);
400 ov->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
402 BOOST_REQUIRE (!wait_for_jobs());
403 ov->write_metadata ();
405 /* Now try to make the VF; this used to fail */
406 shared_ptr<Film> vf = new_test_film2("reels_test10_vf");
407 shared_ptr<DCPContent> ov_dcp(new DCPContent(ov->dir(ov->dcp_name())));
408 vf->examine_and_add_content (ov_dcp);
409 BOOST_REQUIRE (!wait_for_jobs());
410 vf->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
411 ov_dcp->set_reference_video (true);
412 ov_dcp->set_reference_audio (true);
413 vf->examine_and_add_content (content_factory("test/data/15s.srt").front());
414 BOOST_REQUIRE (!wait_for_jobs());
417 BOOST_REQUIRE (!wait_for_jobs());
418 vf->write_metadata ();
421 /** Another reels error; REELTYPE_BY_VIDEO_CONTENT when the first content is not
424 BOOST_AUTO_TEST_CASE (reels_test11)
426 shared_ptr<Film> film = new_test_film2 ("reels_test11");
427 film->set_video_frame_rate (24);
428 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
429 film->examine_and_add_content (A);
430 BOOST_REQUIRE (!wait_for_jobs());
431 A->video->set_length (240);
432 A->set_video_frame_rate (24);
433 A->set_position (film, DCPTime::from_seconds(1));
434 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
436 BOOST_REQUIRE (!wait_for_jobs());
437 BOOST_CHECK_EQUAL (A->position().get(), DCPTime::from_seconds(1).get());
438 BOOST_CHECK_EQUAL (A->end(film).get(), DCPTime::from_seconds(1 + 10).get());
440 list<DCPTimePeriod> r = film->reels ();
441 BOOST_CHECK_EQUAL (r.size(), 2U);
442 BOOST_CHECK_EQUAL (r.front().from.get(), 0);
443 BOOST_CHECK_EQUAL (r.front().to.get(), DCPTime::from_seconds(1).get());
444 BOOST_CHECK_EQUAL (r.back().from.get(), DCPTime::from_seconds(1).get());
445 BOOST_CHECK_EQUAL (r.back().to.get(), DCPTime::from_seconds(1 + 10).get());
448 /** For VFs to work right we have to make separate reels for empty bits between
451 BOOST_AUTO_TEST_CASE (reels_test12)
453 shared_ptr<Film> film = new_test_film2 ("reels_test12");
454 film->set_video_frame_rate (24);
455 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
456 film->set_sequence (false);
458 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
459 film->examine_and_add_content (A);
460 BOOST_REQUIRE (!wait_for_jobs());
461 A->video->set_length (240);
462 A->set_video_frame_rate (24);
463 A->set_position (film, DCPTime::from_seconds(1));
465 shared_ptr<FFmpegContent> B(new FFmpegContent("test/data/flat_red.png"));
466 film->examine_and_add_content (B);
467 BOOST_REQUIRE (!wait_for_jobs());
468 B->video->set_length (120);
469 B->set_video_frame_rate (24);
470 B->set_position (film, DCPTime::from_seconds(14));
472 list<DCPTimePeriod> r = film->reels ();
473 BOOST_REQUIRE_EQUAL (r.size(), 4U);
474 list<DCPTimePeriod>::const_iterator i = r.begin ();
476 BOOST_CHECK_EQUAL (i->from.get(), 0);
477 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_seconds(1).get());
479 BOOST_CHECK_EQUAL (i->from.get(), DCPTime::from_seconds(1).get());
480 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_seconds(11).get());
482 BOOST_CHECK_EQUAL (i->from.get(), DCPTime::from_seconds(11).get());
483 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_seconds(14).get());
485 BOOST_CHECK_EQUAL (i->from.get(), DCPTime::from_seconds(14).get());
486 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_seconds(19).get());
496 dump_notes (vector<dcp::VerificationNote> const & notes)
498 for (auto i: notes) {
499 std::cout << dcp::note_to_string(i) << "\n";
504 /** Using less than 1 second's worth of content should not result in a reel
505 * of less than 1 second's duration.
507 BOOST_AUTO_TEST_CASE (reels_should_not_be_short1)
509 shared_ptr<Film> film = new_test_film2 ("reels_should_not_be_short1");
510 film->set_video_frame_rate (24);
512 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
513 film->examine_and_add_content (A);
514 BOOST_REQUIRE (!wait_for_jobs());
515 A->video->set_length (23);
517 shared_ptr<FFmpegContent> B(new FFmpegContent("test/data/flat_red.png"));
518 film->examine_and_add_content (B);
519 BOOST_REQUIRE (!wait_for_jobs());
520 B->video->set_length (23);
521 B->set_position (film, DCPTime::from_frames(23, 24));
524 BOOST_REQUIRE (!wait_for_jobs());
526 vector<boost::filesystem::path> dirs;
527 dirs.push_back (film->dir(film->dcp_name(false)));
528 auto notes = dcp::verify(dirs, boost::bind(&no_op), boost::bind(&no_op), TestPaths::xsd());
530 BOOST_REQUIRE (notes.empty());
533 /** Leaving less than 1 second's gap between two pieces of content with
534 * REELTYPE_BY_VIDEO_CONTENT should not make a <1s reel.
536 BOOST_AUTO_TEST_CASE (reels_should_not_be_short2)
538 shared_ptr<Film> film = new_test_film2 ("reels_should_not_be_short2");
539 film->set_video_frame_rate (24);
540 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
542 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
543 film->examine_and_add_content (A);
544 BOOST_REQUIRE (!wait_for_jobs());
545 A->video->set_length (240);
547 shared_ptr<FFmpegContent> B(new FFmpegContent("test/data/flat_red.png"));
548 film->examine_and_add_content (B);
549 BOOST_REQUIRE (!wait_for_jobs());
550 B->video->set_length (240);
551 B->set_position (film, DCPTime::from_seconds(10.2));
554 BOOST_REQUIRE (!wait_for_jobs());
556 vector<boost::filesystem::path> dirs;
557 dirs.push_back (film->dir(film->dcp_name(false)));
558 auto const notes = dcp::verify(dirs, boost::bind(&no_op), boost::bind(&no_op), TestPaths::xsd());
560 BOOST_REQUIRE (notes.empty());
563 /** Setting REELTYPE_BY_LENGTH and using a small length value should not make
566 BOOST_AUTO_TEST_CASE (reels_should_not_be_short3)
568 shared_ptr<Film> film = new_test_film2 ("reels_should_not_be_short3");
569 film->set_video_frame_rate (24);
570 film->set_reel_type (REELTYPE_BY_LENGTH);
571 film->set_reel_length (1024 * 1024 * 10);
573 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
574 film->examine_and_add_content (A);
575 BOOST_REQUIRE (!wait_for_jobs());
576 A->video->set_length (240);
579 BOOST_REQUIRE (!wait_for_jobs());
581 vector<boost::filesystem::path> dirs;
582 auto const notes = dcp::verify(dirs, boost::bind(&no_op), boost::bind(&no_op), TestPaths::xsd());
584 BOOST_REQUIRE (notes.empty());
587 /** Having one piece of content less than 1s long in REELTYPE_BY_VIDEO_CONTENT
588 * should not make a reel less than 1s long.
590 BOOST_AUTO_TEST_CASE (reels_should_not_be_short4)
592 shared_ptr<Film> film = new_test_film2 ("reels_should_not_be_short4");
593 film->set_video_frame_rate (24);
594 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
596 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
597 film->examine_and_add_content (A);
598 BOOST_REQUIRE (!wait_for_jobs());
599 A->video->set_length (240);
601 shared_ptr<FFmpegContent> B(new FFmpegContent("test/data/flat_red.png"));
602 film->examine_and_add_content (B);
603 BOOST_REQUIRE (!wait_for_jobs());
604 B->video->set_length (23);
605 B->set_position (film, DCPTime::from_frames(240, 24));
608 BOOST_REQUIRE (!wait_for_jobs());
610 vector<boost::filesystem::path> dirs;
611 dirs.push_back (film->dir(film->dcp_name(false)));
612 auto const notes = dcp::verify(dirs, boost::bind(&no_op), boost::bind(&no_op), TestPaths::xsd());
614 BOOST_REQUIRE (notes.empty());