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>
37 #include <boost/foreach.hpp>
44 using boost::shared_ptr;
45 using boost::function;
46 using namespace dcpomatic;
48 /** Test Film::reels() */
49 BOOST_AUTO_TEST_CASE (reels_test1)
51 shared_ptr<Film> film = new_test_film ("reels_test1");
52 film->set_container (Ratio::from_id ("185"));
53 shared_ptr<FFmpegContent> A (new FFmpegContent("test/data/test.mp4"));
54 film->examine_and_add_content (A);
55 shared_ptr<FFmpegContent> B (new FFmpegContent("test/data/test.mp4"));
56 film->examine_and_add_content (B);
57 BOOST_REQUIRE (!wait_for_jobs());
58 BOOST_CHECK_EQUAL (A->full_length(film).get(), 288000);
60 film->set_reel_type (REELTYPE_SINGLE);
61 list<DCPTimePeriod> r = film->reels ();
62 BOOST_CHECK_EQUAL (r.size(), 1U);
63 BOOST_CHECK_EQUAL (r.front().from.get(), 0);
64 BOOST_CHECK_EQUAL (r.front().to.get(), 288000 * 2);
66 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
68 BOOST_CHECK_EQUAL (r.size(), 2U);
69 BOOST_CHECK_EQUAL (r.front().from.get(), 0);
70 BOOST_CHECK_EQUAL (r.front().to.get(), 288000);
71 BOOST_CHECK_EQUAL (r.back().from.get(), 288000);
72 BOOST_CHECK_EQUAL (r.back().to.get(), 288000 * 2);
74 film->set_j2k_bandwidth (100000000);
75 film->set_reel_type (REELTYPE_BY_LENGTH);
76 /* This is just over 2.5s at 100Mbit/s; should correspond to 60 frames */
77 film->set_reel_length (31253154);
79 BOOST_CHECK_EQUAL (r.size(), 3U);
80 list<DCPTimePeriod>::const_iterator i = r.begin ();
81 BOOST_CHECK_EQUAL (i->from.get(), 0);
82 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_frames(60, 24).get());
84 BOOST_CHECK_EQUAL (i->from.get(), DCPTime::from_frames(60, 24).get());
85 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_frames(120, 24).get());
87 BOOST_CHECK_EQUAL (i->from.get(), DCPTime::from_frames(120, 24).get());
88 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_frames(144, 24).get());
91 /** Make a short DCP with multi reels split by video content, then import
92 * this into a new project and make a new DCP referencing it.
94 BOOST_AUTO_TEST_CASE (reels_test2)
96 shared_ptr<Film> film = new_test_film ("reels_test2");
97 film->set_name ("reels_test2");
98 film->set_container (Ratio::from_id ("185"));
99 film->set_interop (false);
100 film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
103 shared_ptr<ImageContent> c (new ImageContent("test/data/flat_red.png"));
104 film->examine_and_add_content (c);
105 BOOST_REQUIRE (!wait_for_jobs());
106 c->video->set_length (24);
110 shared_ptr<ImageContent> c (new ImageContent("test/data/flat_green.png"));
111 film->examine_and_add_content (c);
112 BOOST_REQUIRE (!wait_for_jobs());
113 c->video->set_length (24);
117 shared_ptr<ImageContent> c (new ImageContent("test/data/flat_blue.png"));
118 film->examine_and_add_content (c);
119 BOOST_REQUIRE (!wait_for_jobs());
120 c->video->set_length (24);
123 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
124 BOOST_CHECK_EQUAL (film->reels().size(), 3U);
125 BOOST_REQUIRE (!wait_for_jobs());
128 BOOST_REQUIRE (!wait_for_jobs());
130 check_dcp ("test/data/reels_test2", film->dir (film->dcp_name()));
132 shared_ptr<Film> film2 = new_test_film ("reels_test2b");
133 film2->set_name ("reels_test2b");
134 film2->set_container (Ratio::from_id ("185"));
135 film2->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
136 film2->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
138 shared_ptr<DCPContent> c (new DCPContent(film->dir(film->dcp_name())));
139 film2->examine_and_add_content (c);
140 BOOST_REQUIRE (!wait_for_jobs ());
142 list<DCPTimePeriod> r = film2->reels ();
143 BOOST_CHECK_EQUAL (r.size(), 3U);
144 list<DCPTimePeriod>::const_iterator i = r.begin ();
145 BOOST_CHECK_EQUAL (i->from.get(), 0);
146 BOOST_CHECK_EQUAL (i->to.get(), 96000);
148 BOOST_CHECK_EQUAL (i->from.get(), 96000);
149 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 2);
151 BOOST_CHECK_EQUAL (i->from.get(), 96000 * 2);
152 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 3);
154 c->set_reference_video (true);
155 c->set_reference_audio (true);
158 BOOST_REQUIRE (!wait_for_jobs());
161 /** Check that REELTYPE_BY_VIDEO_CONTENT adds an extra reel, if necessary, at the end
162 * of all the video content to mop up anything afterward.
164 BOOST_AUTO_TEST_CASE (reels_test3)
166 shared_ptr<Film> film = new_test_film ("reels_test3");
167 film->set_name ("reels_test3");
168 film->set_container (Ratio::from_id ("185"));
169 film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
170 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
172 shared_ptr<Content> dcp (new DCPContent("test/data/reels_test2"));
173 film->examine_and_add_content (dcp);
174 shared_ptr<Content> sub (new StringTextFileContent("test/data/subrip.srt"));
175 film->examine_and_add_content (sub);
176 BOOST_REQUIRE (!wait_for_jobs());
178 list<DCPTimePeriod> reels = film->reels();
179 BOOST_REQUIRE_EQUAL (reels.size(), 4U);
180 list<DCPTimePeriod>::const_iterator i = reels.begin ();
181 BOOST_CHECK_EQUAL (i->from.get(), 0);
182 BOOST_CHECK_EQUAL (i->to.get(), 96000);
184 BOOST_CHECK_EQUAL (i->from.get(), 96000);
185 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 2);
187 BOOST_CHECK_EQUAL (i->from.get(), 96000 * 2);
188 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 3);
190 BOOST_CHECK_EQUAL (i->from.get(), 96000 * 3);
191 BOOST_CHECK_EQUAL (i->to.get(), sub->full_length(film).ceil(film->video_frame_rate()).get());
194 /** Check creation of a multi-reel DCP with a single .srt subtitle file;
195 * make sure that the reel subtitle timing is done right.
197 BOOST_AUTO_TEST_CASE (reels_test4)
199 shared_ptr<Film> film = new_test_film ("reels_test4");
200 film->set_name ("reels_test4");
201 film->set_container (Ratio::from_id ("185"));
202 film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
203 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
204 film->set_interop (false);
206 /* 4 piece of 1s-long content */
207 shared_ptr<ImageContent> content[4];
208 for (int i = 0; i < 4; ++i) {
209 content[i].reset (new ImageContent("test/data/flat_green.png"));
210 film->examine_and_add_content (content[i]);
211 BOOST_REQUIRE (!wait_for_jobs());
212 content[i]->video->set_length (24);
215 shared_ptr<StringTextFileContent> subs (new StringTextFileContent("test/data/subrip3.srt"));
216 film->examine_and_add_content (subs);
217 BOOST_REQUIRE (!wait_for_jobs());
219 list<DCPTimePeriod> reels = film->reels();
220 BOOST_REQUIRE_EQUAL (reels.size(), 4U);
221 list<DCPTimePeriod>::const_iterator i = reels.begin ();
222 BOOST_CHECK_EQUAL (i->from.get(), 0);
223 BOOST_CHECK_EQUAL (i->to.get(), 96000);
225 BOOST_CHECK_EQUAL (i->from.get(), 96000);
226 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 2);
228 BOOST_CHECK_EQUAL (i->from.get(), 96000 * 2);
229 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 3);
231 BOOST_CHECK_EQUAL (i->from.get(), 96000 * 3);
232 BOOST_CHECK_EQUAL (i->to.get(), 96000 * 4);
235 BOOST_REQUIRE (!wait_for_jobs());
237 check_dcp ("test/data/reels_test4", film->dir (film->dcp_name()));
240 BOOST_AUTO_TEST_CASE (reels_test5)
242 shared_ptr<Film> film = new_test_film ("reels_test5");
243 film->set_sequence (false);
244 shared_ptr<DCPContent> dcp (new DCPContent("test/data/reels_test4"));
245 film->examine_and_add_content (dcp);
246 BOOST_REQUIRE (!wait_for_jobs ());
248 /* Set to 2123 but it will be rounded up to the next frame (4000) */
249 dcp->set_position(film, DCPTime(2123));
252 list<DCPTimePeriod> p = dcp->reels (film);
253 BOOST_REQUIRE_EQUAL (p.size(), 4U);
254 list<DCPTimePeriod>::const_iterator i = p.begin();
255 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 0), DCPTime(4000 + 96000)));
256 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 96000), DCPTime(4000 + 192000)));
257 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 192000), DCPTime(4000 + 288000)));
258 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 288000), DCPTime(4000 + 384000)));
262 dcp->set_trim_start (ContentTime::from_seconds (0.5));
263 list<DCPTimePeriod> p = dcp->reels (film);
264 BOOST_REQUIRE_EQUAL (p.size(), 4U);
265 list<DCPTimePeriod>::const_iterator i = p.begin();
266 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 0), DCPTime(4000 + 48000)));
267 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 48000), DCPTime(4000 + 144000)));
268 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 144000), DCPTime(4000 + 240000)));
269 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 240000), DCPTime(4000 + 336000)));
273 dcp->set_trim_end (ContentTime::from_seconds (0.5));
274 list<DCPTimePeriod> p = dcp->reels (film);
275 BOOST_REQUIRE_EQUAL (p.size(), 4U);
276 list<DCPTimePeriod>::const_iterator i = p.begin();
277 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 0), DCPTime(4000 + 48000)));
278 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 48000), DCPTime(4000 + 144000)));
279 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 144000), DCPTime(4000 + 240000)));
280 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 240000), DCPTime(4000 + 288000)));
284 dcp->set_trim_start (ContentTime::from_seconds (1.5));
285 list<DCPTimePeriod> p = dcp->reels (film);
286 BOOST_REQUIRE_EQUAL (p.size(), 3U);
287 list<DCPTimePeriod>::const_iterator i = p.begin();
288 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 0), DCPTime(4000 + 48000)));
289 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 48000), DCPTime(4000 + 144000)));
290 BOOST_CHECK (*i++ == DCPTimePeriod (DCPTime(4000 + 144000), DCPTime(4000 + 192000)));
294 /** Check reel split with a muxed video/audio source */
295 BOOST_AUTO_TEST_CASE (reels_test6)
297 shared_ptr<Film> film = new_test_film ("reels_test6");
298 film->set_name ("reels_test6");
299 film->set_container (Ratio::from_id ("185"));
300 film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
301 shared_ptr<FFmpegContent> A (new FFmpegContent("test/data/test2.mp4"));
302 film->examine_and_add_content (A);
303 BOOST_REQUIRE (!wait_for_jobs ());
305 film->set_j2k_bandwidth (100000000);
306 film->set_reel_type (REELTYPE_BY_LENGTH);
307 /* This is just over 2.5s at 100Mbit/s; should correspond to 60 frames */
308 film->set_reel_length (31253154);
310 BOOST_REQUIRE (!wait_for_jobs ());
313 /** Check the case where the last bit of audio hangs over the end of the video
314 * and we are using REELTYPE_BY_VIDEO_CONTENT.
316 BOOST_AUTO_TEST_CASE (reels_test7)
318 shared_ptr<Film> film = new_test_film ("reels_test7");
319 film->set_name ("reels_test7");
320 film->set_container (Ratio::from_id ("185"));
321 film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
322 shared_ptr<Content> A = content_factory("test/data/flat_red.png").front();
323 film->examine_and_add_content (A);
324 BOOST_REQUIRE (!wait_for_jobs ());
325 shared_ptr<Content> B = content_factory("test/data/awkward_length.wav").front();
326 film->examine_and_add_content (B);
327 BOOST_REQUIRE (!wait_for_jobs ());
328 film->set_video_frame_rate (24);
329 A->video->set_length (2 * 24);
331 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
332 BOOST_REQUIRE_EQUAL (film->reels().size(), 2U);
333 BOOST_CHECK (film->reels().front() == DCPTimePeriod(DCPTime(0), DCPTime::from_frames(2 * 24, 24)));
334 BOOST_CHECK (film->reels().back() == DCPTimePeriod(DCPTime::from_frames(2 * 24, 24), DCPTime::from_frames(3 * 24 + 1, 24)));
337 BOOST_REQUIRE (!wait_for_jobs ());
340 /** Check a reels-related error; make_dcp() would raise a ProgrammingError */
341 BOOST_AUTO_TEST_CASE (reels_test8)
343 shared_ptr<Film> film = new_test_film ("reels_test8");
344 film->set_name ("reels_test8");
345 film->set_container (Ratio::from_id ("185"));
346 film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
347 shared_ptr<FFmpegContent> A (new FFmpegContent("test/data/test2.mp4"));
348 film->examine_and_add_content (A);
349 BOOST_REQUIRE (!wait_for_jobs ());
351 A->set_trim_end (ContentTime::from_seconds (1));
353 BOOST_REQUIRE (!wait_for_jobs ());
356 /** Check another reels-related error; make_dcp() would raise a ProgrammingError */
357 BOOST_AUTO_TEST_CASE (reels_test9)
359 shared_ptr<Film> film = new_test_film2("reels_test9a");
360 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
361 film->examine_and_add_content(A);
362 BOOST_REQUIRE(!wait_for_jobs());
363 A->video->set_length(5 * 24);
364 film->set_video_frame_rate(24);
366 BOOST_REQUIRE(!wait_for_jobs());
368 shared_ptr<Film> film2 = new_test_film2("reels_test9b");
369 shared_ptr<DCPContent> B(new DCPContent(film->dir(film->dcp_name())));
370 film2->examine_and_add_content(B);
371 film2->examine_and_add_content(content_factory("test/data/dcp_sub4.xml").front());
372 B->set_reference_video(true);
373 B->set_reference_audio(true);
374 BOOST_REQUIRE(!wait_for_jobs());
375 film2->set_reel_type(REELTYPE_BY_VIDEO_CONTENT);
376 film2->write_metadata();
378 BOOST_REQUIRE(!wait_for_jobs());
381 /** Another reels-related error; make_dcp() would raise a ProgrammingError
382 * in AudioBuffers::allocate due to an attempt to allocate a negatively-sized buffer.
383 * This was triggered by a VF where there are referenced audio reels followed by
384 * VF audio. When the VF audio arrives the Writer did not correctly skip over the
387 BOOST_AUTO_TEST_CASE (reels_test10)
390 shared_ptr<Film> ov = new_test_film2("reels_test10_ov");
391 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
392 ov->examine_and_add_content (A);
393 BOOST_REQUIRE (!wait_for_jobs());
394 A->video->set_length (5 * 24);
396 shared_ptr<FFmpegContent> B(new FFmpegContent("test/data/flat_red.png"));
397 ov->examine_and_add_content (B);
398 BOOST_REQUIRE (!wait_for_jobs());
399 B->video->set_length (5 * 24);
401 ov->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
403 BOOST_REQUIRE (!wait_for_jobs());
404 ov->write_metadata ();
406 /* Now try to make the VF; this used to fail */
407 shared_ptr<Film> vf = new_test_film2("reels_test10_vf");
408 shared_ptr<DCPContent> ov_dcp(new DCPContent(ov->dir(ov->dcp_name())));
409 vf->examine_and_add_content (ov_dcp);
410 BOOST_REQUIRE (!wait_for_jobs());
411 vf->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
412 ov_dcp->set_reference_video (true);
413 ov_dcp->set_reference_audio (true);
414 vf->examine_and_add_content (content_factory("test/data/15s.srt").front());
415 BOOST_REQUIRE (!wait_for_jobs());
418 BOOST_REQUIRE (!wait_for_jobs());
419 vf->write_metadata ();
422 /** Another reels error; REELTYPE_BY_VIDEO_CONTENT when the first content is not
425 BOOST_AUTO_TEST_CASE (reels_test11)
427 shared_ptr<Film> film = new_test_film2 ("reels_test11");
428 film->set_video_frame_rate (24);
429 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
430 film->examine_and_add_content (A);
431 BOOST_REQUIRE (!wait_for_jobs());
432 A->video->set_length (240);
433 A->set_video_frame_rate (24);
434 A->set_position (film, DCPTime::from_seconds(1));
435 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
437 BOOST_REQUIRE (!wait_for_jobs());
438 BOOST_CHECK_EQUAL (A->position().get(), DCPTime::from_seconds(1).get());
439 BOOST_CHECK_EQUAL (A->end(film).get(), DCPTime::from_seconds(1 + 10).get());
441 list<DCPTimePeriod> r = film->reels ();
442 BOOST_CHECK_EQUAL (r.size(), 2U);
443 BOOST_CHECK_EQUAL (r.front().from.get(), 0);
444 BOOST_CHECK_EQUAL (r.front().to.get(), DCPTime::from_seconds(1).get());
445 BOOST_CHECK_EQUAL (r.back().from.get(), DCPTime::from_seconds(1).get());
446 BOOST_CHECK_EQUAL (r.back().to.get(), DCPTime::from_seconds(1 + 10).get());
449 /** For VFs to work right we have to make separate reels for empty bits between
452 BOOST_AUTO_TEST_CASE (reels_test12)
454 shared_ptr<Film> film = new_test_film2 ("reels_test12");
455 film->set_video_frame_rate (24);
456 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
457 film->set_sequence (false);
459 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
460 film->examine_and_add_content (A);
461 BOOST_REQUIRE (!wait_for_jobs());
462 A->video->set_length (240);
463 A->set_video_frame_rate (24);
464 A->set_position (film, DCPTime::from_seconds(1));
466 shared_ptr<FFmpegContent> B(new FFmpegContent("test/data/flat_red.png"));
467 film->examine_and_add_content (B);
468 BOOST_REQUIRE (!wait_for_jobs());
469 B->video->set_length (120);
470 B->set_video_frame_rate (24);
471 B->set_position (film, DCPTime::from_seconds(14));
473 list<DCPTimePeriod> r = film->reels ();
474 BOOST_REQUIRE_EQUAL (r.size(), 4U);
475 list<DCPTimePeriod>::const_iterator i = r.begin ();
477 BOOST_CHECK_EQUAL (i->from.get(), 0);
478 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_seconds(1).get());
480 BOOST_CHECK_EQUAL (i->from.get(), DCPTime::from_seconds(1).get());
481 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_seconds(11).get());
483 BOOST_CHECK_EQUAL (i->from.get(), DCPTime::from_seconds(11).get());
484 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_seconds(14).get());
486 BOOST_CHECK_EQUAL (i->from.get(), DCPTime::from_seconds(14).get());
487 BOOST_CHECK_EQUAL (i->to.get(), DCPTime::from_seconds(19).get());
497 dump_notes (list<dcp::VerificationNote> const & notes)
499 BOOST_FOREACH (dcp::VerificationNote i, notes) {
500 std::cout << dcp::note_to_string(i) << "\n";
505 /** Using less than 1 second's worth of content should not result in a reel
506 * of less than 1 second's duration.
508 BOOST_AUTO_TEST_CASE (reels_should_not_be_short1)
510 shared_ptr<Film> film = new_test_film2 ("reels_should_not_be_short1");
511 film->set_video_frame_rate (24);
513 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
514 film->examine_and_add_content (A);
515 BOOST_REQUIRE (!wait_for_jobs());
516 A->video->set_length (23);
518 shared_ptr<FFmpegContent> B(new FFmpegContent("test/data/flat_red.png"));
519 film->examine_and_add_content (B);
520 BOOST_REQUIRE (!wait_for_jobs());
521 B->video->set_length (23);
522 B->set_position (film, DCPTime::from_frames(23, 24));
525 BOOST_REQUIRE (!wait_for_jobs());
527 vector<boost::filesystem::path> dirs;
528 dirs.push_back (film->dir(film->dcp_name(false)));
529 list<dcp::VerificationNote> const notes = dcp::verify(dirs, boost::bind(&no_op), boost::bind(&no_op), TestPaths::xsd());
531 BOOST_REQUIRE (notes.empty());
534 /** Leaving less than 1 second's gap between two pieces of content with
535 * REELTYPE_BY_VIDEO_CONTENT should not make a <1s reel.
537 BOOST_AUTO_TEST_CASE (reels_should_not_be_short2)
539 shared_ptr<Film> film = new_test_film2 ("reels_should_not_be_short2");
540 film->set_video_frame_rate (24);
541 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
543 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
544 film->examine_and_add_content (A);
545 BOOST_REQUIRE (!wait_for_jobs());
546 A->video->set_length (240);
548 shared_ptr<FFmpegContent> B(new FFmpegContent("test/data/flat_red.png"));
549 film->examine_and_add_content (B);
550 BOOST_REQUIRE (!wait_for_jobs());
551 B->video->set_length (240);
552 B->set_position (film, DCPTime::from_seconds(10.2));
555 BOOST_REQUIRE (!wait_for_jobs());
557 vector<boost::filesystem::path> dirs;
558 dirs.push_back (film->dir(film->dcp_name(false)));
559 list<dcp::VerificationNote> const notes = dcp::verify(dirs, boost::bind(&no_op), boost::bind(&no_op), TestPaths::xsd());
561 BOOST_REQUIRE (notes.empty());
564 /** Setting REELTYPE_BY_LENGTH and using a small length value should not make
567 BOOST_AUTO_TEST_CASE (reels_should_not_be_short3)
569 shared_ptr<Film> film = new_test_film2 ("reels_should_not_be_short3");
570 film->set_video_frame_rate (24);
571 film->set_reel_type (REELTYPE_BY_LENGTH);
572 film->set_reel_length (1024 * 1024 * 10);
574 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
575 film->examine_and_add_content (A);
576 BOOST_REQUIRE (!wait_for_jobs());
577 A->video->set_length (240);
580 BOOST_REQUIRE (!wait_for_jobs());
582 vector<boost::filesystem::path> dirs;
583 list<dcp::VerificationNote> const notes = dcp::verify(dirs, boost::bind(&no_op), boost::bind(&no_op), TestPaths::xsd());
585 BOOST_REQUIRE (notes.empty());
588 /** Having one piece of content less than 1s long in REELTYPE_BY_VIDEO_CONTENT
589 * should not make a reel less than 1s long.
591 BOOST_AUTO_TEST_CASE (reels_should_not_be_short4)
593 shared_ptr<Film> film = new_test_film2 ("reels_should_not_be_short4");
594 film->set_video_frame_rate (24);
595 film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT);
597 shared_ptr<FFmpegContent> A(new FFmpegContent("test/data/flat_red.png"));
598 film->examine_and_add_content (A);
599 BOOST_REQUIRE (!wait_for_jobs());
600 A->video->set_length (240);
602 shared_ptr<FFmpegContent> B(new FFmpegContent("test/data/flat_red.png"));
603 film->examine_and_add_content (B);
604 BOOST_REQUIRE (!wait_for_jobs());
605 B->video->set_length (23);
606 B->set_position (film, DCPTime::from_frames(240, 24));
609 BOOST_REQUIRE (!wait_for_jobs());
611 vector<boost::filesystem::path> dirs;
612 dirs.push_back (film->dir(film->dcp_name(false)));
613 list<dcp::VerificationNote> const notes = dcp::verify(dirs, boost::bind(&no_op), boost::bind(&no_op), TestPaths::xsd());
615 BOOST_REQUIRE (notes.empty());