2 Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
4 This file is part of libdcp.
6 libdcp 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 libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
19 In addition, as a special exception, the copyright holders give
20 permission to link the code of portions of this program with the
21 OpenSSL library under certain conditions as described in each
22 individual source file, and distribute linked combinations
25 You must obey the GNU General Public License in all respects
26 for all of the code used other than OpenSSL. If you modify
27 file(s) with this exception, you may extend this exception to your
28 version of the file(s), but you are not obligated to do so. If you
29 do not wish to do so, delete this exception statement from your
30 version. If you delete this exception statement from all source
31 files in the program, then also delete it here.
34 #include "interop_subtitle_asset.h"
35 #include "interop_load_font_node.h"
36 #include "subtitle_string.h"
37 #include "subtitle_image.h"
38 #include <boost/test/unit_test.hpp>
43 using std::shared_ptr;
44 using std::dynamic_pointer_cast;
46 /** Load some subtitle content from Interop XML and check that it is read correctly */
47 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1)
49 dcp::InteropSubtitleAsset subs ("test/data/subs1.xml");
51 BOOST_CHECK_EQUAL (subs.id(), "cab5c268-222b-41d2-88ae-6d6999441b17");
52 BOOST_CHECK_EQUAL (subs.movie_title(), "Movie Title");
53 BOOST_CHECK_EQUAL (subs.reel_number(), "1");
54 BOOST_CHECK_EQUAL (subs.language(), "French");
56 list<shared_ptr<dcp::LoadFontNode> > lfn = subs.load_font_nodes ();
57 BOOST_REQUIRE_EQUAL (lfn.size(), 1);
58 shared_ptr<dcp::InteropLoadFontNode> interop_lfn = dynamic_pointer_cast<dcp::InteropLoadFontNode> (lfn.front ());
59 BOOST_REQUIRE (interop_lfn);
60 BOOST_CHECK_EQUAL (interop_lfn->id, "theFontId");
61 BOOST_CHECK_EQUAL (interop_lfn->uri, "arial.ttf");
63 list<shared_ptr<dcp::Subtitle> > s = subs.subtitles_during (dcp::Time (0, 0, 6, 1, 250), dcp::Time (0, 0, 6, 2, 250), false);
64 BOOST_REQUIRE_EQUAL (s.size(), 1);
65 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.front()));
66 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.front()), dcp::SubtitleString (
71 dcp::Colour (255, 255, 255),
74 dcp::Time (0, 0, 5, 198, 250),
75 dcp::Time (0, 0, 7, 115, 250),
81 "My jacket was Idi Amin's",
83 dcp::Colour (0, 0, 0),
84 dcp::Time (0, 0, 0, 1, 250),
85 dcp::Time (0, 0, 0, 1, 250)
88 s = subs.subtitles_during (dcp::Time (0, 0, 7, 190, 250), dcp::Time (0, 0, 7, 191, 250), false);
89 BOOST_REQUIRE_EQUAL (s.size(), 2);
90 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.front()));
91 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.front()), dcp::SubtitleString (
96 dcp::Colour (255, 255, 255),
99 dcp::Time (0, 0, 7, 177, 250),
100 dcp::Time (0, 0, 11, 31, 250),
106 "My corset was H.M. The Queen's",
108 dcp::Colour (0, 0, 0),
109 dcp::Time (0, 0, 0, 1, 250),
110 dcp::Time (0, 0, 0, 1, 250)
112 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.back()));
113 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.back()), dcp::SubtitleString (
114 string ("theFontId"),
118 dcp::Colour (255, 255, 255),
121 dcp::Time (0, 0, 7, 177, 250),
122 dcp::Time (0, 0, 11, 31, 250),
128 "My large wonderbra",
130 dcp::Colour (0, 0, 0),
131 dcp::Time (0, 0, 0, 1, 250),
132 dcp::Time (0, 0, 0, 1, 250)
135 s = subs.subtitles_during (dcp::Time (0, 0, 11, 95, 250), dcp::Time (0, 0, 11, 96, 250), false);
136 BOOST_REQUIRE_EQUAL (s.size(), 1);
137 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.back()));
138 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.back()), dcp::SubtitleString (
139 string ("theFontId"),
143 dcp::Colour (255, 255, 255),
146 dcp::Time (0, 0, 11, 94, 250),
147 dcp::Time (0, 0, 13, 63, 250),
153 "Once belonged to the Shah",
155 dcp::Colour (0, 0, 0),
156 dcp::Time (0, 0, 0, 1, 250),
157 dcp::Time (0, 0, 0, 1, 250)
160 s = subs.subtitles_during (dcp::Time (0, 0, 14, 42, 250), dcp::Time (0, 0, 14, 43, 250), false);
161 BOOST_REQUIRE_EQUAL (s.size(), 1);
162 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.back()));
163 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.back()), dcp::SubtitleString (
164 string ("theFontId"),
168 dcp::Colour (255, 255, 255),
171 dcp::Time (0, 0, 13, 104, 250),
172 dcp::Time (0, 0, 15, 177, 250),
178 "And these are Roy Hattersley's jeans",
180 dcp::Colour (0, 0, 0),
181 dcp::Time (0, 0, 0, 1, 250),
182 dcp::Time (0, 0, 0, 1, 250)
186 /** And similarly for another one */
187 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
189 dcp::InteropSubtitleAsset subs ("test/data/subs2.xml");
191 list<shared_ptr<dcp::Subtitle> > s = subs.subtitles_during (dcp::Time (0, 0, 42, 100, 250), dcp::Time (0, 0, 42, 101, 250), false);
192 BOOST_REQUIRE_EQUAL (s.size(), 2);
193 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.front()));
194 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.front()), dcp::SubtitleString (
199 dcp::Colour (255, 255, 255),
202 dcp::Time (0, 0, 41, 62, 250),
203 dcp::Time (0, 0, 43, 52, 250),
209 "At afternoon tea with John Peel",
211 dcp::Colour (0, 0, 0),
212 dcp::Time (0, 0, 0, 0, 250),
213 dcp::Time (0, 0, 0, 0, 250)
215 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.back()));
216 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.back()), dcp::SubtitleString (
221 dcp::Colour (255, 255, 255),
224 dcp::Time (0, 0, 41, 62, 250),
225 dcp::Time (0, 0, 43, 52, 250),
231 "I enquired if his accent was real",
233 dcp::Colour (0, 0, 0),
234 dcp::Time (0, 0, 0, 0, 250),
235 dcp::Time (0, 0, 0, 0, 250)
238 s = subs.subtitles_during (dcp::Time (0, 0, 50, 50, 250), dcp::Time (0, 0, 50, 51, 250), false);
239 BOOST_REQUIRE_EQUAL (s.size(), 2);
240 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.front()));
241 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.front()), dcp::SubtitleString (
246 dcp::Colour (255, 255, 255),
249 dcp::Time (0, 0, 50, 42, 250),
250 dcp::Time (0, 0, 52, 21, 250),
256 "He said \"out of the house",
258 dcp::Colour (0, 0, 0),
259 dcp::Time (0, 0, 0, 0, 250),
260 dcp::Time (0, 0, 0, 0, 250)
262 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.back()));
263 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.back()), dcp::SubtitleString (
268 dcp::Colour (255, 255, 255),
271 dcp::Time (0, 0, 50, 42, 250),
272 dcp::Time (0, 0, 52, 21, 250),
278 "I'm incredibly scouse",
280 dcp::Colour (0, 0, 0),
281 dcp::Time (0, 0, 0, 0, 250),
282 dcp::Time (0, 0, 0, 0, 250)
285 s = subs.subtitles_during (dcp::Time (0, 1, 2, 300, 250), dcp::Time (0, 1, 2, 301, 250), false);
286 BOOST_REQUIRE_EQUAL (s.size(), 2);
287 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.front()));
288 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.front()), dcp::SubtitleString (
293 dcp::Colour (255, 255, 255),
296 dcp::Time (0, 1, 2, 208, 250),
297 dcp::Time (0, 1, 4, 10, 250),
303 "At home it depends how I feel.\"",
305 dcp::Colour (0, 0, 0),
306 dcp::Time (0, 0, 0, 0, 250),
307 dcp::Time (0, 0, 0, 0, 250)
309 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.back()));
310 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.back()), dcp::SubtitleString (
315 dcp::Colour (255, 255, 255),
318 dcp::Time (0, 1, 2, 208, 250),
319 dcp::Time (0, 1, 4, 10, 250),
325 "I spent a long weekend in Brighton",
327 dcp::Colour (0, 0, 0),
328 dcp::Time (0, 0, 0, 0, 250),
329 dcp::Time (0, 0, 0, 0, 250)
332 s = subs.subtitles_during (dcp::Time (0, 1, 15, 50, 250), dcp::Time (0, 1, 15, 51, 250), false);
333 BOOST_REQUIRE_EQUAL (s.size(), 2);
334 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.front()));
335 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.front()), dcp::SubtitleString (
340 dcp::Colour (255, 255, 255),
343 dcp::Time (0, 1, 15, 42, 250),
344 dcp::Time (0, 1, 16, 42, 250),
350 "With the legendary Miss Enid Blyton",
352 dcp::Colour (0, 0, 0),
353 dcp::Time (0, 0, 0, 0, 250),
354 dcp::Time (0, 0, 0, 0, 250)
356 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.back()));
357 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.back()), dcp::SubtitleString (
362 dcp::Colour (255, 255, 255),
365 dcp::Time (0, 1, 15, 42, 250),
366 dcp::Time (0, 1, 16, 42, 250),
372 "She said \"you be Noddy",
374 dcp::Colour (0, 0, 0),
375 dcp::Time (0, 0, 0, 0, 250),
376 dcp::Time (0, 0, 0, 0, 250)
379 s = subs.subtitles_during (dcp::Time (0, 1, 27, 200, 250), dcp::Time (0, 1, 27, 201, 250), false);
380 BOOST_REQUIRE_EQUAL (s.size(), 2);
381 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.front()));
382 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.front()), dcp::SubtitleString (
387 dcp::Colour (255, 255, 255),
390 dcp::Time (0, 1, 27, 115, 250),
391 dcp::Time (0, 1, 28, 208, 250),
397 "That curious creature the Sphinx",
399 dcp::Colour (0, 0, 0),
400 dcp::Time (0, 0, 0, 0, 250),
401 dcp::Time (0, 0, 0, 0, 250)
403 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.back()));
404 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.back()), dcp::SubtitleString (
409 dcp::Colour (255, 255, 255),
412 dcp::Time (0, 1, 27, 115, 250),
413 dcp::Time (0, 1, 28, 208, 250),
419 "Is smarter than anyone thinks",
421 dcp::Colour (0, 0, 0),
422 dcp::Time (0, 0, 0, 0, 250),
423 dcp::Time (0, 0, 0, 0, 250)
426 s = subs.subtitles_during (dcp::Time (0, 1, 42, 300, 250), dcp::Time (0, 1, 42, 301, 250), false);
427 BOOST_REQUIRE_EQUAL (s.size(), 2);
428 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.front()));
429 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.front()), dcp::SubtitleString (
434 dcp::Colour (255, 255, 255),
437 dcp::Time (0, 1, 42, 229, 250),
438 dcp::Time (0, 1, 45, 62, 250),
444 "It sits there and smirks",
446 dcp::Colour (0, 0, 0),
447 dcp::Time (0, 0, 0, 0, 250),
448 dcp::Time (0, 0, 0, 0, 250)
450 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.back()));
451 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.back()), dcp::SubtitleString (
456 dcp::Colour (255, 255, 255),
459 dcp::Time (0, 1, 42, 229, 250),
460 dcp::Time (0, 1, 45, 62, 250),
466 "And you don't think it works",
468 dcp::Colour (0, 0, 0),
469 dcp::Time (0, 0, 0, 0, 250),
470 dcp::Time (0, 0, 0, 0, 250)
473 s = subs.subtitles_during (dcp::Time (0, 1, 45, 200, 250), dcp::Time (0, 1, 45, 201, 250), false);
474 BOOST_REQUIRE_EQUAL (s.size(), 2);
475 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.front()));
476 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.front()), dcp::SubtitleString (
481 dcp::Colour (255, 255, 255),
484 dcp::Time (0, 1, 45, 146, 250),
485 dcp::Time (0, 1, 47, 94, 250),
491 "Then when you're not looking, it winks.",
493 dcp::Colour (0, 0, 0),
494 dcp::Time (0, 0, 0, 0, 250),
495 dcp::Time (0, 0, 0, 0, 250)
497 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.back()));
498 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.back()), dcp::SubtitleString (
503 dcp::Colour (255, 255, 255),
506 dcp::Time (0, 1, 45, 146, 250),
507 dcp::Time (0, 1, 47, 94, 250),
513 "When it snows you will find Sister Sledge",
515 dcp::Colour (0, 0, 0),
516 dcp::Time (0, 0, 0, 0, 250),
517 dcp::Time (0, 0, 0, 0, 250)
520 s = subs.subtitles_during (dcp::Time (0, 1, 47, 249, 250), dcp::Time (0, 1, 47, 250, 250), false);
521 BOOST_REQUIRE_EQUAL (s.size(), 2);
522 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.front()));
523 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.front()), dcp::SubtitleString (
528 dcp::Colour (255, 255, 255),
531 dcp::Time (0, 1, 47, 146, 250),
532 dcp::Time (0, 1, 48, 167, 250),
538 "Out mooning, at night, on the ledge",
540 dcp::Colour (0, 0, 0),
541 dcp::Time (0, 0, 0, 0, 250),
542 dcp::Time (0, 0, 0, 0, 250)
544 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.back()));
545 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.back()), dcp::SubtitleString (
550 dcp::Colour (255, 255, 255),
553 dcp::Time (0, 1, 47, 146, 250),
554 dcp::Time (0, 1, 48, 167, 250),
562 dcp::Colour (0, 0, 0),
563 dcp::Time (0, 0, 0, 0, 250),
564 dcp::Time (0, 0, 0, 0, 250)
567 s = subs.subtitles_during (dcp::Time (0, 2, 6, 210, 250), dcp::Time (0, 2, 6, 211, 250), false);
568 BOOST_REQUIRE_EQUAL (s.size(), 2);
569 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.front()));
570 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.front()), dcp::SubtitleString (
575 dcp::Colour (255, 255, 255),
578 dcp::Time (0, 2, 5, 208, 250),
579 dcp::Time (0, 2, 7, 31, 250),
587 dcp::Colour (0, 0, 0),
588 dcp::Time (0, 0, 0, 0, 250),
589 dcp::Time (0, 0, 0, 0, 250)
591 BOOST_REQUIRE (dynamic_pointer_cast<dcp::SubtitleString>(s.back()));
592 BOOST_CHECK_EQUAL (*dynamic_pointer_cast<dcp::SubtitleString>(s.back()), dcp::SubtitleString (
597 dcp::Colour (255, 255, 255),
600 dcp::Time (0, 2, 5, 208, 250),
601 dcp::Time (0, 2, 7, 31, 250),
609 dcp::Colour (0, 0, 0),
610 dcp::Time (0, 0, 0, 0, 250),
611 dcp::Time (0, 0, 0, 0, 250)
615 /** And one with bitmap subtitles */
616 BOOST_AUTO_TEST_CASE (read_interop_subtitle_test3)
618 dcp::InteropSubtitleAsset subs ("test/data/subs3.xml");
620 BOOST_REQUIRE_EQUAL (subs.subtitles().size(), 1);
621 shared_ptr<dcp::SubtitleImage> si = dynamic_pointer_cast<dcp::SubtitleImage>(subs.subtitles().front());
623 BOOST_CHECK (si->png_image() == dcp::ArrayData("test/data/sub.png"));