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::Code::INVALID_STANDARD && i.code() != dcp::VerificationNote::Code::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 for (auto i: inputs) {
132 dcp::DCP input_dcp (i);
135 BOOST_REQUIRE (input_dcp.cpls().size() == 1);
136 auto input_cpl = input_dcp.cpls().front();
138 auto output_cpl = pointer_to_id_in_vector (input_cpl, output_dcp.cpls());
139 BOOST_REQUIRE (output_cpl);
141 for (auto i: input_dcp.assets(true)) {
142 auto o = pointer_to_id_in_vector(i, output_dcp.assets());
143 BOOST_REQUIRE_MESSAGE (o, "Could not find " << i->id() << " in combined DCP.");
144 BOOST_CHECK (i->equals(o, options, note_handler));
150 BOOST_AUTO_TEST_CASE (combine_single_dcp_test)
152 using namespace boost::algorithm;
153 using namespace boost::filesystem;
154 boost::filesystem::path const out = "build/test/combine_single_dcp_test";
158 inputs.push_back ("test/ref/DCP/dcp_test1");
162 dcp::String::compose("libdcp %1", dcp::version),
163 dcp::String::compose("libdcp %1", dcp::version),
164 dcp::LocalTime().as_string(),
168 check_no_errors (out);
169 check_combined (inputs, out);
173 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_same_asset_filenames_test)
175 using namespace boost::algorithm;
176 using namespace boost::filesystem;
177 boost::filesystem::path const out = "build/test/combine_two_dcps_with_same_asset_filenames_test";
179 shared_ptr<dcp::DCP> second = make_simple ("build/test/combine_input2");
180 second->write_xml (dcp::Standard::SMPTE);
184 inputs.push_back ("test/ref/DCP/dcp_test1");
185 inputs.push_back ("build/test/combine_input2");
186 dcp::combine (inputs, out);
188 check_no_errors (out);
189 check_combined (inputs, out);
193 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_interop_subs_test)
195 using namespace boost::algorithm;
196 using namespace boost::filesystem;
197 boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_subs_test";
199 shared_ptr<dcp::DCP> first = make_simple_with_interop_subs ("build/test/combine_input1");
200 first->write_xml (dcp::Standard::INTEROP);
202 shared_ptr<dcp::DCP> second = make_simple_with_interop_subs ("build/test/combine_input2");
203 second->write_xml (dcp::Standard::INTEROP);
207 inputs.push_back ("build/test/combine_input1");
208 inputs.push_back ("build/test/combine_input2");
209 dcp::combine (inputs, out);
211 check_no_errors (out);
212 check_combined (inputs, out);
216 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_smpte_subs_test)
218 using namespace boost::algorithm;
219 using namespace boost::filesystem;
220 boost::filesystem::path const out = "build/test/combine_two_dcps_with_smpte_subs_test";
222 shared_ptr<dcp::DCP> first = make_simple_with_smpte_subs ("build/test/combine_input1");
223 first->write_xml (dcp::Standard::SMPTE);
225 shared_ptr<dcp::DCP> second = make_simple_with_smpte_subs ("build/test/combine_input2");
226 second->write_xml (dcp::Standard::SMPTE);
230 inputs.push_back ("build/test/combine_input1");
231 inputs.push_back ("build/test/combine_input2");
232 dcp::combine (inputs, out);
234 check_no_errors (out);
235 check_combined (inputs, out);
239 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_interop_ccaps_test)
241 using namespace boost::algorithm;
242 using namespace boost::filesystem;
243 boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_ccaps_test";
245 shared_ptr<dcp::DCP> first = make_simple_with_interop_ccaps ("build/test/combine_input1");
246 first->write_xml (dcp::Standard::INTEROP);
248 shared_ptr<dcp::DCP> second = make_simple_with_interop_ccaps ("build/test/combine_input2");
249 second->write_xml (dcp::Standard::INTEROP);
253 inputs.push_back ("build/test/combine_input1");
254 inputs.push_back ("build/test/combine_input2");
255 dcp::combine (inputs, out);
257 check_no_errors (out);
258 check_combined (inputs, out);
262 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_smpte_ccaps_test)
264 using namespace boost::algorithm;
265 using namespace boost::filesystem;
266 boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_ccaps_test";
268 shared_ptr<dcp::DCP> first = make_simple_with_smpte_ccaps ("build/test/combine_input1");
269 first->write_xml (dcp::Standard::SMPTE);
271 shared_ptr<dcp::DCP> second = make_simple_with_smpte_ccaps ("build/test/combine_input2");
272 second->write_xml (dcp::Standard::SMPTE);
276 inputs.push_back ("build/test/combine_input1");
277 inputs.push_back ("build/test/combine_input2");
278 dcp::combine (inputs, out);
280 check_no_errors (out);
281 check_combined (inputs, out);
285 BOOST_AUTO_TEST_CASE (combine_two_multi_reel_dcps)
287 using namespace boost::algorithm;
288 using namespace boost::filesystem;
289 boost::filesystem::path const out = "build/test/combine_two_multi_reel_dcps";
291 shared_ptr<dcp::DCP> first = make_simple ("build/test/combine_input1", 4);
292 first->write_xml (dcp::Standard::SMPTE);
294 shared_ptr<dcp::DCP> second = make_simple ("build/test/combine_input2", 4);
295 second->write_xml (dcp::Standard::SMPTE);
299 inputs.push_back ("build/test/combine_input1");
300 inputs.push_back ("build/test/combine_input2");
301 dcp::combine (inputs, out);
303 check_no_errors (out);
304 check_combined (inputs, out);
308 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_shared_asset)
310 using namespace boost::filesystem;
311 boost::filesystem::path const out = "build/test/combine_two_dcps_with_shared_asset";
313 shared_ptr<dcp::DCP> first = make_simple ("build/test/combine_input1", 1);
314 first->write_xml (dcp::Standard::SMPTE);
316 remove_all ("build/test/combine_input2");
317 shared_ptr<dcp::DCP> second(new dcp::DCP("build/test/combine_input2"));
319 dcp::MXFMetadata mxf_meta;
320 mxf_meta.company_name = "OpenDCP";
321 mxf_meta.product_version = "0.0.25";
323 auto cpl = make_shared<dcp::CPL>("A Test DCP", dcp::ContentKind::TRAILER);
324 cpl->set_content_version (
325 dcp::ContentVersion("urn:uuid:75ac29aa-42ac-1234-ecae-49251abefd11","content-version-label-text")
327 cpl->set_main_sound_configuration ("L,C,R,Lfe,-,-");
328 cpl->set_main_sound_sample_rate (48000);
329 cpl->set_main_picture_stored_area (dcp::Size(1998, 1080));
330 cpl->set_main_picture_active_area (dcp::Size(1440, 1080));
331 cpl->set_version_number(1);
333 auto pic = make_shared<dcp::ReelMonoPictureAsset>(simple_picture("build/test/combine_input2", ""), 0);
334 auto sound = make_shared<dcp::ReelSoundAsset>(first->cpls().front()->reels().front()->main_sound()->asset(), 0);
335 auto reel = make_shared<dcp::Reel>(pic, sound);
336 reel->add (simple_markers());
339 second->write_xml (dcp::Standard::SMPTE);
343 inputs.push_back ("build/test/combine_input1");
344 inputs.push_back ("build/test/combine_input2");
345 dcp::combine (inputs, out);
347 check_no_errors (out);
348 check_combined (inputs, out);
352 /* XXX: same CPL names */
353 /* XXX: Interop PNG subs */