2 Copyright (C) 2020 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.
38 #include "interop_subtitle_asset.h"
39 #include "reel_subtitle_asset.h"
40 #include "reel_mono_picture_asset.h"
41 #include "reel_sound_asset.h"
45 #include "reel_markers_asset.h"
46 #include <boost/algorithm/string.hpp>
47 #include <boost/foreach.hpp>
48 #include <boost/optional.hpp>
49 #include <boost/test/unit_test.hpp>
55 using std::make_shared;
57 using std::shared_ptr;
58 using boost::optional;
62 stage (string, optional<boost::filesystem::path>)
75 dump_notes (vector<dcp::VerificationNote> const & notes)
77 BOOST_FOREACH (dcp::VerificationNote i, notes) {
78 std::cout << dcp::note_to_string(i) << "\n";
85 check_no_errors (boost::filesystem::path path)
87 vector<boost::filesystem::path> directories;
88 directories.push_back (path);
89 auto notes = dcp::verify (directories, &stage, &progress, xsd_test);
90 vector<dcp::VerificationNote> filtered_notes;
91 std::copy_if (notes.begin(), notes.end(), std::back_inserter(filtered_notes), [](dcp::VerificationNote const& i) {
92 return i.code() != dcp::VerificationNote::INVALID_STANDARD && i.code() != dcp::VerificationNote::INVALID_SUBTITLE_DURATION;
94 dump_notes (filtered_notes);
95 BOOST_CHECK (filtered_notes.empty());
101 pointer_to_id_in_vector (shared_ptr<T> needle, vector<shared_ptr<T> > haystack)
103 BOOST_FOREACH (shared_ptr<T> i, haystack) {
104 if (i->id() == needle->id()) {
109 return shared_ptr<T>();
115 note_handler (dcp::NoteType, std::string)
117 // std::cout << "> " << n << "\n";
123 check_combined (vector<boost::filesystem::path> inputs, boost::filesystem::path output)
125 dcp::DCP output_dcp (output);
128 dcp::EqualityOptions options;
129 options.load_font_nodes_can_differ = true;
131 BOOST_FOREACH (boost::filesystem::path i, inputs)
133 dcp::DCP input_dcp (i);
136 BOOST_REQUIRE (input_dcp.cpls().size() == 1);
137 shared_ptr<dcp::CPL> input_cpl = input_dcp.cpls().front();
139 shared_ptr<dcp::CPL> output_cpl = pointer_to_id_in_vector (input_cpl, output_dcp.cpls());
140 BOOST_REQUIRE (output_cpl);
142 BOOST_FOREACH (shared_ptr<dcp::Asset> i, input_dcp.assets(true)) {
143 shared_ptr<dcp::Asset> o = pointer_to_id_in_vector(i, output_dcp.assets());
144 BOOST_REQUIRE_MESSAGE (o, "Could not find " << i->id() << " in combined DCP.");
145 BOOST_CHECK (i->equals(o, options, note_handler));
151 BOOST_AUTO_TEST_CASE (combine_single_dcp_test)
153 using namespace boost::algorithm;
154 using namespace boost::filesystem;
155 boost::filesystem::path const out = "build/test/combine_single_dcp_test";
159 inputs.push_back ("test/ref/DCP/dcp_test1");
163 dcp::String::compose("libdcp %1", dcp::version),
164 dcp::String::compose("libdcp %1", dcp::version),
165 dcp::LocalTime().as_string(),
169 check_no_errors (out);
170 check_combined (inputs, out);
174 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_same_asset_filenames_test)
176 using namespace boost::algorithm;
177 using namespace boost::filesystem;
178 boost::filesystem::path const out = "build/test/combine_two_dcps_with_same_asset_filenames_test";
180 shared_ptr<dcp::DCP> second = make_simple ("build/test/combine_input2");
181 second->write_xml (dcp::SMPTE);
185 inputs.push_back ("test/ref/DCP/dcp_test1");
186 inputs.push_back ("build/test/combine_input2");
187 dcp::combine (inputs, out);
189 check_no_errors (out);
190 check_combined (inputs, out);
194 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_interop_subs_test)
196 using namespace boost::algorithm;
197 using namespace boost::filesystem;
198 boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_subs_test";
200 shared_ptr<dcp::DCP> first = make_simple_with_interop_subs ("build/test/combine_input1");
201 first->write_xml (dcp::INTEROP);
203 shared_ptr<dcp::DCP> second = make_simple_with_interop_subs ("build/test/combine_input2");
204 second->write_xml (dcp::INTEROP);
208 inputs.push_back ("build/test/combine_input1");
209 inputs.push_back ("build/test/combine_input2");
210 dcp::combine (inputs, out);
212 check_no_errors (out);
213 check_combined (inputs, out);
217 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_smpte_subs_test)
219 using namespace boost::algorithm;
220 using namespace boost::filesystem;
221 boost::filesystem::path const out = "build/test/combine_two_dcps_with_smpte_subs_test";
223 shared_ptr<dcp::DCP> first = make_simple_with_smpte_subs ("build/test/combine_input1");
224 first->write_xml (dcp::SMPTE);
226 shared_ptr<dcp::DCP> second = make_simple_with_smpte_subs ("build/test/combine_input2");
227 second->write_xml (dcp::SMPTE);
231 inputs.push_back ("build/test/combine_input1");
232 inputs.push_back ("build/test/combine_input2");
233 dcp::combine (inputs, out);
235 check_no_errors (out);
236 check_combined (inputs, out);
240 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_interop_ccaps_test)
242 using namespace boost::algorithm;
243 using namespace boost::filesystem;
244 boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_ccaps_test";
246 shared_ptr<dcp::DCP> first = make_simple_with_interop_ccaps ("build/test/combine_input1");
247 first->write_xml (dcp::INTEROP);
249 shared_ptr<dcp::DCP> second = make_simple_with_interop_ccaps ("build/test/combine_input2");
250 second->write_xml (dcp::INTEROP);
254 inputs.push_back ("build/test/combine_input1");
255 inputs.push_back ("build/test/combine_input2");
256 dcp::combine (inputs, out);
258 check_no_errors (out);
259 check_combined (inputs, out);
263 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_smpte_ccaps_test)
265 using namespace boost::algorithm;
266 using namespace boost::filesystem;
267 boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_ccaps_test";
269 shared_ptr<dcp::DCP> first = make_simple_with_smpte_ccaps ("build/test/combine_input1");
270 first->write_xml (dcp::SMPTE);
272 shared_ptr<dcp::DCP> second = make_simple_with_smpte_ccaps ("build/test/combine_input2");
273 second->write_xml (dcp::SMPTE);
277 inputs.push_back ("build/test/combine_input1");
278 inputs.push_back ("build/test/combine_input2");
279 dcp::combine (inputs, out);
281 check_no_errors (out);
282 check_combined (inputs, out);
286 BOOST_AUTO_TEST_CASE (combine_two_multi_reel_dcps)
288 using namespace boost::algorithm;
289 using namespace boost::filesystem;
290 boost::filesystem::path const out = "build/test/combine_two_multi_reel_dcps";
292 shared_ptr<dcp::DCP> first = make_simple ("build/test/combine_input1", 4);
293 first->write_xml (dcp::SMPTE);
295 shared_ptr<dcp::DCP> second = make_simple ("build/test/combine_input2", 4);
296 second->write_xml (dcp::SMPTE);
300 inputs.push_back ("build/test/combine_input1");
301 inputs.push_back ("build/test/combine_input2");
302 dcp::combine (inputs, out);
304 check_no_errors (out);
305 check_combined (inputs, out);
309 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_shared_asset)
311 using namespace boost::filesystem;
312 boost::filesystem::path const out = "build/test/combine_two_dcps_with_shared_asset";
314 shared_ptr<dcp::DCP> first = make_simple ("build/test/combine_input1", 1);
315 first->write_xml (dcp::SMPTE);
317 remove_all ("build/test/combine_input2");
318 shared_ptr<dcp::DCP> second(new dcp::DCP("build/test/combine_input2"));
320 dcp::MXFMetadata mxf_meta;
321 mxf_meta.company_name = "OpenDCP";
322 mxf_meta.product_version = "0.0.25";
324 shared_ptr<dcp::CPL> cpl (new dcp::CPL("A Test DCP", dcp::TRAILER));
325 cpl->set_content_version (
326 dcp::ContentVersion("urn:uuid:75ac29aa-42ac-1234-ecae-49251abefd11","content-version-label-text")
328 cpl->set_main_sound_configuration ("L,C,R,Lfe,-,-");
329 cpl->set_main_sound_sample_rate (48000);
330 cpl->set_main_picture_stored_area (dcp::Size(1998, 1080));
331 cpl->set_main_picture_active_area (dcp::Size(1440, 1080));
332 cpl->set_version_number(1);
334 shared_ptr<dcp::ReelMonoPictureAsset> pic(new dcp::ReelMonoPictureAsset(simple_picture("build/test/combine_input2", ""), 0));
335 shared_ptr<dcp::ReelSoundAsset> sound(new dcp::ReelSoundAsset(first->cpls().front()->reels().front()->main_sound()->asset(), 0));
336 auto reel = make_shared<dcp::Reel>(pic, sound);
337 reel->add (simple_markers());
340 second->write_xml (dcp::SMPTE);
344 inputs.push_back ("build/test/combine_input1");
345 inputs.push_back ("build/test/combine_input2");
346 dcp::combine (inputs, out);
348 check_no_errors (out);
349 check_combined (inputs, out);
353 /* XXX: same CPL names */
354 /* XXX: Interop PNG subs */