30c5ca3043bee7adec913ce6ddec826a6fcc2421
[libdcp.git] / test / dcp_test.cc
1 /*
2     Copyright (C) 2013-2019 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 #include "dcp.h"
35 #include "metadata.h"
36 #include "cpl.h"
37 #include "mono_picture_asset.h"
38 #include "stereo_picture_asset.h"
39 #include "picture_asset_writer.h"
40 #include "sound_asset_writer.h"
41 #include "sound_asset.h"
42 #include "atmos_asset.h"
43 #include "reel.h"
44 #include "test.h"
45 #include "file.h"
46 #include "reel_mono_picture_asset.h"
47 #include "reel_stereo_picture_asset.h"
48 #include "reel_sound_asset.h"
49 #include "reel_atmos_asset.h"
50 #include <asdcp/KM_util.h>
51 #include <sndfile.h>
52 #include <boost/test/unit_test.hpp>
53
54 using std::string;
55 using boost::shared_ptr;
56
57
58 /** Test creation of a 2D SMPTE DCP from very simple inputs */
59 BOOST_AUTO_TEST_CASE (dcp_test1)
60 {
61         RNGFixer fixer;
62
63         dcp::XMLMetadata xml_meta;
64         xml_meta.annotation_text = "Created by libdcp";
65         xml_meta.issuer = "OpenDCP 0.0.25";
66         xml_meta.creator = "OpenDCP 0.0.25";
67         xml_meta.issue_date = "2012-07-17T04:45:18+00:00";
68         make_simple("build/test/DCP/dcp_test1")->write_xml (dcp::SMPTE, xml_meta);
69         /* build/test/DCP/dcp_test1 is checked against test/ref/DCP/dcp_test1 by run/tests */
70 }
71
72 /** Test creation of a 3D DCP from very simple inputs */
73 BOOST_AUTO_TEST_CASE (dcp_test2)
74 {
75         RNGFixer fix;
76
77         /* Some known metadata */
78         dcp::XMLMetadata xml_meta;
79         xml_meta.annotation_text = "A Test DCP";
80         xml_meta.issuer = "OpenDCP 0.0.25";
81         xml_meta.creator = "OpenDCP 0.0.25";
82         xml_meta.issue_date = "2012-07-17T04:45:18+00:00";
83         dcp::MXFMetadata mxf_meta;
84         mxf_meta.company_name = "OpenDCP";
85         mxf_meta.product_name = "OpenDCP";
86         mxf_meta.product_version = "0.0.25";
87
88         /* We're making build/test/DCP/dcp_test2 */
89         boost::filesystem::remove_all ("build/test/DCP/dcp_test2");
90         boost::filesystem::create_directories ("build/test/DCP/dcp_test2");
91         dcp::DCP d ("build/test/DCP/dcp_test2");
92         shared_ptr<dcp::CPL> cpl (new dcp::CPL ("A Test DCP", dcp::FEATURE));
93         cpl->set_content_version_id ("urn:uri:81fb54df-e1bf-4647-8788-ea7ba154375b_2012-07-17T04:45:18+00:00");
94         cpl->set_content_version_label_text ("81fb54df-e1bf-4647-8788-ea7ba154375b_2012-07-17T04:45:18+00:00");
95         cpl->set_issuer (xml_meta.issuer);
96         cpl->set_creator (xml_meta.creator);
97         cpl->set_issue_date (xml_meta.issue_date);
98         cpl->set_annotation_text (xml_meta.annotation_text);
99
100         shared_ptr<dcp::StereoPictureAsset> mp (new dcp::StereoPictureAsset (dcp::Fraction (24, 1), dcp::SMPTE));
101         mp->set_metadata (mxf_meta);
102         shared_ptr<dcp::PictureAssetWriter> picture_writer = mp->start_write ("build/test/DCP/dcp_test2/video.mxf", false);
103         dcp::File j2c ("test/data/32x32_red_square.j2c");
104         for (int i = 0; i < 24; ++i) {
105                 /* Left */
106                 picture_writer->write (j2c.data (), j2c.size ());
107                 /* Right */
108                 picture_writer->write (j2c.data (), j2c.size ());
109         }
110         picture_writer->finalize ();
111
112         shared_ptr<dcp::SoundAsset> ms (new dcp::SoundAsset (dcp::Fraction (24, 1), 48000, 1, dcp::SMPTE));
113         ms->set_metadata (mxf_meta);
114         shared_ptr<dcp::SoundAssetWriter> sound_writer = ms->start_write ("build/test/DCP/dcp_test2/audio.mxf");
115
116         SF_INFO info;
117         info.format = 0;
118         SNDFILE* sndfile = sf_open ("test/data/1s_24-bit_48k_silence.wav", SFM_READ, &info);
119         BOOST_CHECK (sndfile);
120         float buffer[4096*6];
121         float* channels[1];
122         channels[0] = buffer;
123         while (1) {
124                 sf_count_t N = sf_readf_float (sndfile, buffer, 4096);
125                 sound_writer->write (channels, N);
126                 if (N < 4096) {
127                         break;
128                 }
129         }
130
131         sound_writer->finalize ();
132
133         cpl->add (shared_ptr<dcp::Reel> (
134                           new dcp::Reel (
135                                   shared_ptr<dcp::ReelStereoPictureAsset> (new dcp::ReelStereoPictureAsset (mp, 0)),
136                                   shared_ptr<dcp::ReelSoundAsset> (new dcp::ReelSoundAsset (ms, 0))
137                                   )
138                           ));
139
140         d.add (cpl);
141
142         xml_meta.annotation_text = "Created by libdcp";
143         d.write_xml (dcp::SMPTE, xml_meta);
144
145         /* build/test/DCP/dcp_test2 is checked against test/ref/DCP/dcp_test2 by run/tests */
146 }
147
148 static void
149 note (dcp::NoteType, string)
150 {
151
152 }
153
154 /** Test comparison of a DCP with itself */
155 BOOST_AUTO_TEST_CASE (dcp_test3)
156 {
157         dcp::DCP A ("test/ref/DCP/dcp_test1");
158         A.read ();
159         dcp::DCP B ("test/ref/DCP/dcp_test1");
160         B.read ();
161
162         BOOST_CHECK (A.equals (B, dcp::EqualityOptions(), boost::bind (&note, _1, _2)));
163 }
164
165 /** Test comparison of a DCP with a different DCP */
166 BOOST_AUTO_TEST_CASE (dcp_test4)
167 {
168         dcp::DCP A ("test/ref/DCP/dcp_test1");
169         A.read ();
170         dcp::DCP B ("test/ref/DCP/dcp_test2");
171         B.read ();
172
173         BOOST_CHECK (!A.equals (B, dcp::EqualityOptions(), boost::bind (&note, _1, _2)));
174 }
175
176 /** Test creation of a 2D DCP with an Atmos track */
177 BOOST_AUTO_TEST_CASE (dcp_test5)
178 {
179         RNGFixer fix;
180
181         /* Some known metadata */
182         dcp::XMLMetadata xml_meta;
183         xml_meta.annotation_text = "A Test DCP";
184         xml_meta.issuer = "OpenDCP 0.0.25";
185         xml_meta.creator = "OpenDCP 0.0.25";
186         xml_meta.issue_date = "2012-07-17T04:45:18+00:00";
187         dcp::MXFMetadata mxf_meta;
188         mxf_meta.company_name = "OpenDCP";
189         mxf_meta.product_name = "OpenDCP";
190         mxf_meta.product_version = "0.0.25";
191
192         /* We're making build/test/DCP/dcp_test5 */
193         boost::filesystem::remove_all ("build/test/DCP/dcp_test5");
194         boost::filesystem::create_directories ("build/test/DCP/dcp_test5");
195         dcp::DCP d ("build/test/DCP/dcp_test5");
196         shared_ptr<dcp::CPL> cpl (new dcp::CPL ("A Test DCP", dcp::FEATURE));
197         cpl->set_content_version_id ("urn:uri:81fb54df-e1bf-4647-8788-ea7ba154375b_2012-07-17T04:45:18+00:00");
198         cpl->set_content_version_label_text ("81fb54df-e1bf-4647-8788-ea7ba154375b_2012-07-17T04:45:18+00:00");
199         cpl->set_issuer (xml_meta.issuer);
200         cpl->set_creator (xml_meta.creator);
201         cpl->set_issue_date (xml_meta.issue_date);
202         cpl->set_annotation_text (xml_meta.annotation_text);
203
204         shared_ptr<dcp::MonoPictureAsset> mp (new dcp::MonoPictureAsset (dcp::Fraction (24, 1), dcp::SMPTE));
205         mp->set_metadata (mxf_meta);
206         shared_ptr<dcp::PictureAssetWriter> picture_writer = mp->start_write ("build/test/DCP/dcp_test5/video.mxf", false);
207         dcp::File j2c ("test/data/32x32_red_square.j2c");
208         for (int i = 0; i < 24; ++i) {
209                 picture_writer->write (j2c.data (), j2c.size ());
210         }
211         picture_writer->finalize ();
212
213         shared_ptr<dcp::SoundAsset> ms (new dcp::SoundAsset (dcp::Fraction (24, 1), 48000, 1, dcp::SMPTE));
214         ms->set_metadata (mxf_meta);
215         shared_ptr<dcp::SoundAssetWriter> sound_writer = ms->start_write ("build/test/DCP/dcp_test5/audio.mxf");
216
217         SF_INFO info;
218         info.format = 0;
219         SNDFILE* sndfile = sf_open ("test/data/1s_24-bit_48k_silence.wav", SFM_READ, &info);
220         BOOST_CHECK (sndfile);
221         float buffer[4096*6];
222         float* channels[1];
223         channels[0] = buffer;
224         while (true) {
225                 sf_count_t N = sf_readf_float (sndfile, buffer, 4096);
226                 sound_writer->write (channels, N);
227                 if (N < 4096) {
228                         break;
229                 }
230         }
231
232         sound_writer->finalize ();
233
234         shared_ptr<dcp::AtmosAsset> am (new dcp::AtmosAsset (private_test / "20160218_NameOfFilm_FTR_OV_EN_A_dcs_r01.mxf"));
235
236         cpl->add (shared_ptr<dcp::Reel> (
237                           new dcp::Reel (
238                                   shared_ptr<dcp::ReelMonoPictureAsset> (new dcp::ReelMonoPictureAsset (mp, 0)),
239                                   shared_ptr<dcp::ReelSoundAsset> (new dcp::ReelSoundAsset (ms, 0)),
240                                   shared_ptr<dcp::ReelSubtitleAsset> (),
241                                   shared_ptr<dcp::ReelMarkersAsset> (),
242                                   shared_ptr<dcp::ReelAtmosAsset> (new dcp::ReelAtmosAsset (am, 0))
243                                   )
244                           ));
245
246         d.add (cpl);
247
248         xml_meta.annotation_text = "Created by libdcp";
249         d.write_xml (dcp::SMPTE, xml_meta);
250
251         /* build/test/DCP/dcp_test5 is checked against test/ref/DCP/dcp_test5 by run/tests */
252 }
253
254 /** Basic tests of reading a 2D DCP with an Atmos track */
255 BOOST_AUTO_TEST_CASE (dcp_test6)
256 {
257         dcp::DCP dcp ("test/ref/DCP/dcp_test5");
258         dcp.read ();
259
260         BOOST_REQUIRE_EQUAL (dcp.cpls().size(), 1);
261         BOOST_REQUIRE_EQUAL (dcp.cpls().front()->reels().size(), 1);
262         BOOST_CHECK (dcp.cpls().front()->reels().front()->main_picture());
263         BOOST_CHECK (dcp.cpls().front()->reels().front()->main_sound());
264         BOOST_CHECK (!dcp.cpls().front()->reels().front()->main_subtitle());
265         BOOST_CHECK (dcp.cpls().front()->reels().front()->atmos());
266 }
267
268 /** Test creation of a 2D Interop DCP from very simple inputs */
269 BOOST_AUTO_TEST_CASE (dcp_test7)
270 {
271         RNGFixer fix;
272
273         dcp::XMLMetadata xml_meta;
274         xml_meta.annotation_text = "Created by libdcp";
275         xml_meta.issuer = "OpenDCP 0.0.25";
276         xml_meta.creator = "OpenDCP 0.0.25";
277         xml_meta.issue_date = "2012-07-17T04:45:18+00:00";
278         make_simple("build/test/DCP/dcp_test7")->write_xml (dcp::INTEROP, xml_meta);
279         /* build/test/DCP/dcp_test7 is checked against test/ref/DCP/dcp_test7 by run/tests */
280 }
281
282 /** Test reading of a DCP with multiple CPLs */
283 BOOST_AUTO_TEST_CASE (dcp_test8)
284 {
285         dcp::DCP dcp (private_test / "data/SMPTE_TST-B1PB2P_S_EN-EN-CCAP_5171-HI-VI_2K_ISDCF_20151123_DPPT_SMPTE_combo/");
286         dcp.read ();
287
288         BOOST_REQUIRE_EQUAL (dcp.cpls().size(), 2);
289 }