In-line run of subs_in_out so that it gets the environment more easily.
[libdcp.git] / test / cpl_metadata_test.cc
1 /*
2     Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net>
3
4     This file is part of libdcp.
5
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.
10
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.
15
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/>.
18
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
23     including the two.
24
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.
32 */
33
34
35 #include "certificate_chain.h"
36 #include "compose.hpp"
37 #include "cpl.h"
38 #include "exceptions.h"
39 #include "language_tag.h"
40 #include "reel.h"
41 #include "reel_mono_picture_asset.h"
42 #include "reel_smpte_subtitle_asset.h"
43 #include "reel_sound_asset.h"
44 #include "stream_operators.h"
45 #include "test.h"
46 #include <memory>
47 #include <boost/test/unit_test.hpp>
48
49
50 using std::list;
51 using std::make_shared;
52 using std::shared_ptr;
53 using std::string;
54 using std::vector;
55
56
57 BOOST_AUTO_TEST_CASE (cpl_metadata_bad_values_test)
58 {
59         dcp::CPL cpl("", dcp::ContentKind::FEATURE, dcp::Standard::SMPTE);
60         BOOST_CHECK_THROW (cpl.set_version_number(-1), dcp::BadSettingError);
61
62         vector<dcp::ContentVersion> cv = {
63                 dcp::ContentVersion("same-id", "version 1"),
64                 dcp::ContentVersion("same-id", "version 2")
65         };
66         BOOST_CHECK_THROW (cpl.set_content_versions(cv), dcp::DuplicateIdError);
67 }
68
69
70 BOOST_AUTO_TEST_CASE (main_sound_configuration_test1)
71 {
72         dcp::MainSoundConfiguration msc("51/L,R,C,LFE,-,-");
73         BOOST_CHECK_EQUAL (msc.to_string(), "51/L,R,C,LFE,-,-");
74         BOOST_CHECK_EQUAL (msc.channels(), 6);
75         BOOST_CHECK_EQUAL (msc.field(), dcp::MCASoundField::FIVE_POINT_ONE);
76         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
77         BOOST_CHECK_EQUAL (msc.mapping(1).get(), dcp::Channel::RIGHT);
78         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
79         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
80         BOOST_CHECK (!msc.mapping(4));
81         BOOST_CHECK (!msc.mapping(5));
82 }
83
84
85 BOOST_AUTO_TEST_CASE (main_sound_configuration_test2)
86 {
87         dcp::MainSoundConfiguration msc("71/L,R,C,LFE,-,-");
88         BOOST_CHECK_EQUAL (msc.to_string(), "71/L,R,C,LFE,-,-");
89         BOOST_CHECK_EQUAL (msc.channels(), 6);
90         BOOST_CHECK_EQUAL (msc.field(), dcp::MCASoundField::SEVEN_POINT_ONE);
91         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
92         BOOST_CHECK_EQUAL (msc.mapping(1).get(), dcp::Channel::RIGHT);
93         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
94         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
95         BOOST_CHECK (!msc.mapping(4));
96         BOOST_CHECK (!msc.mapping(5));
97 }
98
99
100 BOOST_AUTO_TEST_CASE (main_sound_configuration_test3)
101 {
102         dcp::MainSoundConfiguration msc("71/L,-,C,LFE,Lss,Rss");
103         BOOST_CHECK_EQUAL (msc.to_string(), "71/L,-,C,LFE,Lss,Rss");
104         BOOST_CHECK_EQUAL (msc.channels(), 6);
105         BOOST_CHECK_EQUAL (msc.field(), dcp::MCASoundField::SEVEN_POINT_ONE);
106         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
107         BOOST_CHECK (!msc.mapping(1));
108         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
109         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
110         BOOST_CHECK_EQUAL (msc.mapping(4).get(), dcp::Channel::LS);
111         BOOST_CHECK_EQUAL (msc.mapping(5).get(), dcp::Channel::RS);
112 }
113
114
115 BOOST_AUTO_TEST_CASE (main_sound_configuration_test4)
116 {
117         dcp::MainSoundConfiguration msc("71/L,-,C,LFE,Lss,Rss,-,-,-,-,-,-,-,-,-");
118         BOOST_CHECK_EQUAL (msc.to_string(), "71/L,-,C,LFE,Lss,Rss,-,-,-,-,-,-,-,-,-");
119         BOOST_CHECK_EQUAL (msc.channels(), 15);
120         BOOST_CHECK_EQUAL (msc.field(), dcp::MCASoundField::SEVEN_POINT_ONE);
121         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
122         BOOST_CHECK (!msc.mapping(1));
123         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
124         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
125         BOOST_CHECK_EQUAL (msc.mapping(4).get(), dcp::Channel::LS);
126         BOOST_CHECK_EQUAL (msc.mapping(5).get(), dcp::Channel::RS);
127         for (int i = 6; i < 15; ++i) {
128                 BOOST_CHECK (!msc.mapping(i));
129         }
130 }
131
132
133 BOOST_AUTO_TEST_CASE (main_sound_configuration_test5)
134 {
135         dcp::MainSoundConfiguration msc("71/L,-,C,LFE,Lss,Rss,HI,VIN,-,-,Lrs,Rrs,DBOX,FSKSync,SLVS");
136         BOOST_CHECK_EQUAL (msc.to_string(), "71/L,-,C,LFE,Lss,Rss,HI,VIN,-,-,Lrs,Rrs,DBOX,FSKSync,SLVS");
137         BOOST_CHECK_EQUAL (msc.channels(), 15);
138         BOOST_CHECK_EQUAL (msc.field(), dcp::MCASoundField::SEVEN_POINT_ONE);
139         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
140         BOOST_CHECK (!msc.mapping(1));
141         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
142         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
143         BOOST_CHECK_EQUAL (msc.mapping(4).get(), dcp::Channel::LS);
144         BOOST_CHECK_EQUAL (msc.mapping(5).get(), dcp::Channel::RS);
145         BOOST_CHECK_EQUAL (msc.mapping(6).get(), dcp::Channel::HI);
146         BOOST_CHECK_EQUAL (msc.mapping(7).get(), dcp::Channel::VI);
147         BOOST_CHECK (!msc.mapping(8));
148         BOOST_CHECK (!msc.mapping(9));
149         BOOST_CHECK_EQUAL (msc.mapping(10).get(), dcp::Channel::BSL);
150         BOOST_CHECK_EQUAL (msc.mapping(11).get(), dcp::Channel::BSR);
151         BOOST_CHECK_EQUAL (msc.mapping(12).get(), dcp::Channel::MOTION_DATA);
152         BOOST_CHECK_EQUAL (msc.mapping(13).get(), dcp::Channel::SYNC_SIGNAL);
153         BOOST_CHECK_EQUAL (msc.mapping(14).get(), dcp::Channel::SIGN_LANGUAGE);
154 }
155
156
157 BOOST_AUTO_TEST_CASE(main_sound_configuration_test6)
158 {
159         dcp::MainSoundConfiguration msc("WTF/L,R,C,LFE,LsLss,RsRss,HI,VIN,Lc,Rc,Lrs,Rrs,Mtn,FSKSync,SLVS,-");
160         BOOST_CHECK_EQUAL(msc.channels(), 16);
161         BOOST_CHECK_EQUAL(msc.field(), dcp::MCASoundField::OTHER);
162         BOOST_CHECK_EQUAL(msc.mapping(0).get(), dcp::Channel::LEFT);
163         BOOST_CHECK_EQUAL(msc.mapping(1).get(), dcp::Channel::RIGHT);
164         BOOST_CHECK_EQUAL(msc.mapping(2).get(), dcp::Channel::CENTRE);
165         BOOST_CHECK_EQUAL(msc.mapping(3).get(), dcp::Channel::LFE);
166         BOOST_CHECK_EQUAL(msc.mapping(4).get(), dcp::Channel::LS);
167         BOOST_CHECK_EQUAL(msc.mapping(5).get(), dcp::Channel::RS);
168         BOOST_CHECK_EQUAL(msc.mapping(6).get(), dcp::Channel::HI);
169         BOOST_CHECK_EQUAL(msc.mapping(7).get(), dcp::Channel::VI);
170         BOOST_CHECK_EQUAL(msc.mapping(8).get(), dcp::Channel::LC);
171         BOOST_CHECK_EQUAL(msc.mapping(9).get(), dcp::Channel::RC);
172         BOOST_CHECK_EQUAL(msc.mapping(10).get(), dcp::Channel::BSL);
173         BOOST_CHECK_EQUAL(msc.mapping(11).get(), dcp::Channel::BSR);
174         BOOST_CHECK_EQUAL(msc.mapping(12).get(), dcp::Channel::MOTION_DATA);
175         BOOST_CHECK_EQUAL(msc.mapping(13).get(), dcp::Channel::SYNC_SIGNAL);
176         BOOST_CHECK_EQUAL(msc.mapping(14).get(), dcp::Channel::SIGN_LANGUAGE);
177         BOOST_CHECK(!msc.mapping(15));
178 }
179
180
181 /* 482-12 says that implementations may use case-insensitive comparisons for the channel identifiers,
182  * and there is one DCP in the private test suite (made by Disney) that uses LS for left surround.
183  */
184 BOOST_AUTO_TEST_CASE(main_sound_configuration_test_case_insensitive)
185 {
186         dcp::MainSoundConfiguration msc("51/L,-,C,LFE,LS,RS,HI,VIN");
187         BOOST_CHECK_EQUAL(msc.to_string(), "51/L,-,C,LFE,Ls,Rs,HI,VIN");
188         BOOST_CHECK_EQUAL(msc.channels(), 8);
189         BOOST_CHECK_EQUAL(msc.field(), dcp::MCASoundField::FIVE_POINT_ONE);
190         BOOST_CHECK_EQUAL(msc.mapping(0).get(), dcp::Channel::LEFT);
191         BOOST_CHECK(!msc.mapping(1));
192         BOOST_CHECK_EQUAL(msc.mapping(2).get(), dcp::Channel::CENTRE);
193         BOOST_CHECK_EQUAL(msc.mapping(3).get(), dcp::Channel::LFE);
194         BOOST_CHECK_EQUAL(msc.mapping(4).get(), dcp::Channel::LS);
195         BOOST_CHECK_EQUAL(msc.mapping(5).get(), dcp::Channel::RS);
196         BOOST_CHECK_EQUAL(msc.mapping(6).get(), dcp::Channel::HI);
197         BOOST_CHECK_EQUAL(msc.mapping(7).get(), dcp::Channel::VI);
198 }
199
200
201 BOOST_AUTO_TEST_CASE (luminance_test1)
202 {
203         BOOST_CHECK_NO_THROW (dcp::Luminance(4, dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE));
204         BOOST_CHECK_THROW (dcp::Luminance(-4, dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE), dcp::MiscError);
205 }
206
207
208 BOOST_AUTO_TEST_CASE (luminance_test2)
209 {
210         auto doc = make_shared<cxml::Document>("Luminance");
211
212         doc->read_string (
213                 "<Luminance units=\"candela-per-square-metre\">4.5</Luminance>"
214                 );
215
216         dcp::Luminance lum (doc);
217         BOOST_CHECK (lum.unit() == dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE);
218         BOOST_CHECK_CLOSE (lum.value(), 4.5, 0.1);
219 }
220
221
222 BOOST_AUTO_TEST_CASE (luminance_test3)
223 {
224         auto doc = make_shared<cxml::Document>("Luminance");
225
226         doc->read_string (
227                 "<Luminance units=\"candela-per-square-motre\">4.5</Luminance>"
228                 );
229
230         BOOST_CHECK_THROW (new dcp::Luminance(doc), dcp::XMLError);
231 }
232
233
234 BOOST_AUTO_TEST_CASE (luminance_test4)
235 {
236         auto doc = make_shared<cxml::Document>("Luminance");
237
238         doc->read_string (
239                 "<Luminance units=\"candela-per-square-metre\">-4.5</Luminance>"
240                 );
241
242         /* We tolerate out-of-range values when reading from XML */
243         dcp::Luminance lum (doc);
244         BOOST_CHECK (lum.unit() == dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE);
245         BOOST_CHECK_CLOSE (lum.value(), -4.5, 0.1);
246 }
247
248
249 /** A test where most CPL metadata is present */
250 BOOST_AUTO_TEST_CASE (cpl_metadata_read_test1)
251 {
252         dcp::CPL cpl("test/ref/cpl_metadata_test1.xml");
253
254         BOOST_CHECK_EQUAL (cpl.full_content_title_text().get(), "full-content-title");
255         BOOST_CHECK (cpl.full_content_title_text_language().get() == "de");
256         BOOST_CHECK (cpl.release_territory().get() == "ES");
257         BOOST_CHECK_EQUAL (cpl.version_number().get(), 2);
258         BOOST_CHECK_EQUAL (cpl.status().get(), dcp::Status::FINAL);
259         BOOST_CHECK_EQUAL (cpl.chain().get(), "the-chain");
260         BOOST_CHECK_EQUAL (cpl.distributor().get(), "the-distributor");
261         BOOST_CHECK_EQUAL (cpl.facility().get(), "the-facility");
262         BOOST_CHECK (cpl.luminance() == dcp::Luminance(4.5, dcp::Luminance::Unit::FOOT_LAMBERT));
263
264         dcp::MainSoundConfiguration msc(cpl.main_sound_configuration().get());
265         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
266         BOOST_CHECK_EQUAL (msc.mapping(1).get(), dcp::Channel::RIGHT);
267         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
268         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
269         BOOST_CHECK (!msc.mapping(4));
270         BOOST_CHECK (!msc.mapping(5));
271         BOOST_CHECK (!msc.mapping(6));
272         BOOST_CHECK (!msc.mapping(7));
273         BOOST_CHECK (!msc.mapping(8));
274         BOOST_CHECK (!msc.mapping(9));
275         BOOST_CHECK (!msc.mapping(10));
276         BOOST_CHECK (!msc.mapping(11));
277         BOOST_CHECK (!msc.mapping(12));
278         BOOST_CHECK_EQUAL (msc.mapping(13).get(), dcp::Channel::SYNC_SIGNAL);
279
280         BOOST_CHECK_EQUAL (cpl.main_sound_sample_rate().get(), 48000);
281         BOOST_CHECK (cpl.main_picture_stored_area().get() == dcp::Size(1998, 1080));
282         BOOST_CHECK (cpl.main_picture_active_area().get() == dcp::Size(1440, 1080));
283
284         auto reels = cpl.reels ();
285         BOOST_REQUIRE_EQUAL (reels.size(), 1U);
286         BOOST_REQUIRE (reels.front()->main_subtitle()->language());
287         BOOST_CHECK_EQUAL (reels.front()->main_subtitle()->language().get(), "de-DE");
288
289         auto asl = cpl.additional_subtitle_languages();
290         BOOST_REQUIRE_EQUAL (asl.size(), 2U);
291         BOOST_CHECK_EQUAL (asl[0], "en-US");
292         BOOST_CHECK_EQUAL (asl[1], "fr-ZA");
293
294         BOOST_CHECK (cpl.additional_subtitle_languages() == asl);
295 }
296
297
298 /** A test where most CPL metadata is present */
299 BOOST_AUTO_TEST_CASE (cpl_metadata_write_test1)
300 {
301         RNGFixer fix;
302
303         dcp::CPL cpl("", dcp::ContentKind::FEATURE, dcp::Standard::SMPTE);
304         cpl.set_issue_date ("2020-08-28T13:35:06+02:00");
305
306         vector<dcp::ContentVersion> cv = {
307                 dcp::ContentVersion("some-id", "version 1"),
308                 dcp::ContentVersion("another-id", "version 2")
309         };;
310         cpl.set_content_versions (cv);
311
312         cpl.set_full_content_title_text ("full-content-title");
313         cpl.set_full_content_title_text_language (dcp::LanguageTag("de"));
314         cpl.set_release_territory (dcp::LanguageTag::RegionSubtag("ES"));
315         cpl.set_version_number (2);
316         cpl.set_status (dcp::Status::FINAL);
317         cpl.set_chain ("the-chain");
318         cpl.set_distributor ("the-distributor");
319         cpl.set_facility ("the-facility");
320         cpl.set_luminance (dcp::Luminance(4.5, dcp::Luminance::Unit::FOOT_LAMBERT));
321         cpl.set_issuer ("libdcp1.6.4devel");
322         cpl.set_creator ("libdcp1.6.4devel");
323
324         dcp::MainSoundConfiguration msc(dcp::MCASoundField::SEVEN_POINT_ONE, 16);
325         msc.set_mapping (0, dcp::Channel::LEFT);
326         msc.set_mapping (1, dcp::Channel::RIGHT);
327         msc.set_mapping (2, dcp::Channel::CENTRE);
328         msc.set_mapping (3, dcp::Channel::LFE);
329         msc.set_mapping (13, dcp::Channel::SYNC_SIGNAL);
330         cpl.set_main_sound_configuration(msc);
331
332         cpl.set_main_sound_sample_rate (48000);
333         cpl.set_main_picture_stored_area (dcp::Size(1998, 1080));
334         cpl.set_main_picture_active_area (dcp::Size(1440, 1080));
335
336         auto doc = make_shared<cxml::Document>("MainSubtitle");
337
338         doc->read_string (
339                 "<MainSubtitle>"
340                 "<Id>urn:uuid:8bca1489-aab1-9259-a4fd-8150abc1de12</Id>"
341                 "<AnnotationText>Goodbye world!</AnnotationText>"
342                 "<EditRate>25 1</EditRate>"
343                 "<IntrinsicDuration>1870</IntrinsicDuration>"
344                 "<EntryPoint>0</EntryPoint>"
345                 "<Duration>525</Duration>"
346                 "<KeyId>urn:uuid:540cbf10-ab14-0233-ab1f-fb31501cabfa</KeyId>"
347                 "<Hash>3EABjX9BB1CAWhLUtHhrGSyLgOY=</Hash>"
348                 "<Language>de-DE</Language>"
349                 "</MainSubtitle>"
350                 );
351
352         auto reel = make_shared<dcp::Reel>();
353         reel->add (black_picture_asset("build/test/cpl_metadata_write_test1"));
354         reel->add (make_shared<dcp::ReelSMPTESubtitleAsset>(doc));
355         cpl.add (reel);
356
357         auto lt = { dcp::LanguageTag("en-US"), dcp::LanguageTag("fr-ZA") };
358         cpl.set_additional_subtitle_languages (lt);
359
360         cpl.set_sign_language_video_language (dcp::LanguageTag("bzs"));
361
362         cpl.write_xml ("build/test/cpl_metadata_write_test1.xml", {});
363         check_xml (
364                 dcp::file_to_string("test/ref/cpl_metadata_test1.xml"),
365                 dcp::file_to_string("build/test/cpl_metadata_write_test1.xml"),
366                 {"Id", "Hash"}
367                 );
368 }
369
370
371 /** A test where most CPL metadata is present */
372 BOOST_AUTO_TEST_CASE (cpl_metadata_roundtrip_test_1)
373 {
374         dcp::CPL cpl ("test/ref/cpl_metadata_test1.xml");
375         cpl.write_xml ("build/test/cpl_metadata_roundtrip_test1.xml", shared_ptr<dcp::CertificateChain>());
376         check_xml (
377                 dcp::file_to_string("test/ref/cpl_metadata_test1.xml"),
378                 dcp::file_to_string("build/test/cpl_metadata_roundtrip_test1.xml"),
379                 {"Id"}
380                 );
381 }
382
383
384 /** A test where only a bare minimum of CPL metadata is present */
385 BOOST_AUTO_TEST_CASE (cpl_metadata_write_test2)
386 {
387         RNGFixer fix;
388
389         dcp::CPL cpl("", dcp::ContentKind::FEATURE, dcp::Standard::SMPTE);
390         cpl.set_issue_date ("2020-08-28T13:35:06+02:00");
391         cpl.set_content_version (dcp::ContentVersion("id", "version"));
392         cpl.set_issuer ("libdcp1.6.4devel");
393         cpl.set_creator ("libdcp1.6.4devel");
394
395         dcp::MainSoundConfiguration msc(dcp::MCASoundField::SEVEN_POINT_ONE, 16);
396         msc.set_mapping (0, dcp::Channel::LEFT);
397         msc.set_mapping (1, dcp::Channel::RIGHT);
398         msc.set_mapping (2, dcp::Channel::CENTRE);
399         msc.set_mapping (3, dcp::Channel::LFE);
400         msc.set_mapping (13, dcp::Channel::SYNC_SIGNAL);
401         cpl.set_main_sound_configuration(msc);
402
403         cpl.set_main_sound_sample_rate (48000);
404         cpl.set_main_picture_stored_area (dcp::Size(1998, 1080));
405         cpl.set_main_picture_active_area (dcp::Size(1440, 1080));
406
407         auto reel = make_shared<dcp::Reel>();
408         reel->add (black_picture_asset("build/test/cpl_metadata_write_test1"));
409         cpl.add (reel);
410
411         cpl.write_xml ("build/test/cpl_metadata_write_test2.xml", {});
412         check_xml (
413                 dcp::file_to_string("test/ref/cpl_metadata_test2.xml"),
414                 dcp::file_to_string("build/test/cpl_metadata_write_test2.xml"),
415                 {"Id", "Hash"}
416                 );
417 }
418
419
420 /** A test where only a bare minimum of CPL metadata is present */
421 BOOST_AUTO_TEST_CASE (cpl_metadata_read_test2)
422 {
423         dcp::CPL cpl("test/ref/cpl_metadata_test2.xml");
424
425         BOOST_CHECK_EQUAL (cpl.full_content_title_text().get(), "");
426         BOOST_CHECK (!cpl.full_content_title_text_language());
427         BOOST_CHECK (!cpl.release_territory());
428         BOOST_CHECK (!cpl.version_number());
429         BOOST_CHECK (!cpl.status());
430         BOOST_CHECK (!cpl.chain());
431         BOOST_CHECK (!cpl.distributor());
432         BOOST_CHECK (!cpl.facility());
433         BOOST_CHECK (!cpl.luminance());
434
435         dcp::MainSoundConfiguration msc(cpl.main_sound_configuration().get());
436         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
437         BOOST_CHECK_EQUAL (msc.mapping(1).get(), dcp::Channel::RIGHT);
438         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
439         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
440         BOOST_CHECK (!msc.mapping(4));
441         BOOST_CHECK (!msc.mapping(5));
442         BOOST_CHECK (!msc.mapping(6));
443         BOOST_CHECK (!msc.mapping(7));
444         BOOST_CHECK (!msc.mapping(8));
445         BOOST_CHECK (!msc.mapping(9));
446         BOOST_CHECK (!msc.mapping(10));
447         BOOST_CHECK (!msc.mapping(11));
448         BOOST_CHECK (!msc.mapping(12));
449         BOOST_CHECK_EQUAL (msc.mapping(13).get(), dcp::Channel::SYNC_SIGNAL);
450
451         BOOST_CHECK_EQUAL (cpl.main_sound_sample_rate().get(), 48000);
452         BOOST_CHECK (cpl.main_picture_stored_area().get() == dcp::Size(1998, 1080));
453         BOOST_CHECK (cpl.main_picture_active_area().get() == dcp::Size(1440, 1080));
454
455         auto reels = cpl.reels ();
456         BOOST_REQUIRE_EQUAL (reels.size(), 1U);
457 }
458
459
460 /** A test where only a bare minimum of CPL metadata is present */
461 BOOST_AUTO_TEST_CASE (cpl_metadata_roundtrip_test_2)
462 {
463         dcp::CPL cpl ("test/ref/cpl_metadata_test2.xml");
464         cpl.write_xml ("build/test/cpl_metadata_roundtrip_test2.xml", shared_ptr<dcp::CertificateChain>());
465         check_xml (
466                 dcp::file_to_string("test/ref/cpl_metadata_test2.xml"),
467                 dcp::file_to_string("build/test/cpl_metadata_roundtrip_test2.xml"),
468                 {"Id"}
469                 );
470 }
471
472
473 BOOST_AUTO_TEST_CASE(check_that_missing_full_content_title_text_is_tolerated)
474 {
475         dcp::CPL cpl("test/ref/cpl_metadata_test3.xml");
476 }
477
478
479 BOOST_AUTO_TEST_CASE(check_sign_language_video_language)
480 {
481         dcp::CPL cpl("test/ref/cpl_metadata_test3.xml");
482         cpl.set_sign_language_video_language(dcp::LanguageTag("es-PT"));
483         cpl.write_xml("build/test/check_sign_language_video_language.xml", {});
484         check_xml(
485                 dcp::file_to_string("test/ref/cpl_metadata_test4.xml"),
486                 dcp::file_to_string("build/test/check_sign_language_video_language.xml"),
487                 {"Id"}
488                 );
489
490         dcp::CPL check("build/test/check_sign_language_video_language.xml");
491         BOOST_CHECK_EQUAL(check.sign_language_video_language().get_value_or(""), "es-PT");
492
493 }
494
495
496 BOOST_AUTO_TEST_CASE(check_dolby_edr_metadata)
497 {
498         dcp::CPL cpl("test/ref/cpl_metadata_test3.xml");
499         cpl.set_dolby_edr_image_transfer_function("PQ10K");
500         cpl.write_xml("build/test/check_dolby_edr_metadata.xml", {});
501         check_xml(
502                 dcp::file_to_string("test/ref/cpl_metadata_test5.xml"),
503                 dcp::file_to_string("build/test/check_dolby_edr_metadata.xml"),
504                 {"Id"}
505                 );
506
507         dcp::CPL check("build/test/check_dolby_edr_metadata.xml");
508         BOOST_CHECK_EQUAL(check.dolby_edr_image_transfer_function().get_value_or(""), "PQ10K");
509 }
510