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 <boost/algorithm/string.hpp>
46 #include <boost/foreach.hpp>
47 #include <boost/optional.hpp>
48 #include <boost/test/unit_test.hpp>
55 using boost::optional;
56 using std::shared_ptr;
60 stage (string, optional<boost::filesystem::path>)
73 dump_notes (vector<dcp::VerificationNote> const & notes)
75 BOOST_FOREACH (dcp::VerificationNote i, notes) {
76 std::cout << dcp::note_to_string(i) << "\n";
83 check_no_errors (boost::filesystem::path path)
85 vector<boost::filesystem::path> directories;
86 directories.push_back (path);
87 auto notes = dcp::verify (directories, &stage, &progress, xsd_test);
88 vector<dcp::VerificationNote> filtered_notes;
89 std::copy_if (notes.begin(), notes.end(), std::back_inserter(filtered_notes), [](dcp::VerificationNote const& i) {
90 return i.code() != dcp::VerificationNote::NOT_SMPTE && i.code() != dcp::VerificationNote::SUBTITLE_TOO_SHORT;
92 dump_notes (filtered_notes);
93 BOOST_CHECK (filtered_notes.empty());
99 pointer_to_id_in_vector (shared_ptr<T> needle, vector<shared_ptr<T> > haystack)
101 BOOST_FOREACH (shared_ptr<T> i, haystack) {
102 if (i->id() == needle->id()) {
107 return shared_ptr<T>();
113 note_handler (dcp::NoteType, std::string)
115 // std::cout << "> " << n << "\n";
121 check_combined (vector<boost::filesystem::path> inputs, boost::filesystem::path output)
123 dcp::DCP output_dcp (output);
126 dcp::EqualityOptions options;
127 options.load_font_nodes_can_differ = true;
129 BOOST_FOREACH (boost::filesystem::path i, inputs)
131 dcp::DCP input_dcp (i);
134 BOOST_REQUIRE (input_dcp.cpls().size() == 1);
135 shared_ptr<dcp::CPL> input_cpl = input_dcp.cpls().front();
137 shared_ptr<dcp::CPL> output_cpl = pointer_to_id_in_vector (input_cpl, output_dcp.cpls());
138 BOOST_REQUIRE (output_cpl);
140 BOOST_FOREACH (shared_ptr<dcp::Asset> i, input_dcp.assets(true)) {
141 shared_ptr<dcp::Asset> o = pointer_to_id_in_vector(i, output_dcp.assets());
142 BOOST_REQUIRE_MESSAGE (o, "Could not find " << i->id() << " in combined DCP.");
143 BOOST_CHECK (i->equals(o, options, note_handler));
149 BOOST_AUTO_TEST_CASE (combine_single_dcp_test)
151 using namespace boost::algorithm;
152 using namespace boost::filesystem;
153 boost::filesystem::path const out = "build/test/combine_single_dcp_test";
157 inputs.push_back ("test/ref/DCP/dcp_test1");
158 dcp::combine (inputs, out);
160 check_no_errors (out);
161 check_combined (inputs, out);
165 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_same_asset_filenames_test)
167 using namespace boost::algorithm;
168 using namespace boost::filesystem;
169 boost::filesystem::path const out = "build/test/combine_two_dcps_with_same_asset_filenames_test";
171 shared_ptr<dcp::DCP> second = make_simple ("build/test/combine_input2");
172 second->write_xml (dcp::SMPTE);
176 inputs.push_back ("test/ref/DCP/dcp_test1");
177 inputs.push_back ("build/test/combine_input2");
178 dcp::combine (inputs, out);
180 check_no_errors (out);
181 check_combined (inputs, out);
185 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_interop_subs_test)
187 using namespace boost::algorithm;
188 using namespace boost::filesystem;
189 boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_subs_test";
191 shared_ptr<dcp::DCP> first = make_simple_with_interop_subs ("build/test/combine_input1");
192 first->write_xml (dcp::INTEROP);
194 shared_ptr<dcp::DCP> second = make_simple_with_interop_subs ("build/test/combine_input2");
195 second->write_xml (dcp::INTEROP);
199 inputs.push_back ("build/test/combine_input1");
200 inputs.push_back ("build/test/combine_input2");
201 dcp::combine (inputs, out);
203 check_no_errors (out);
204 check_combined (inputs, out);
208 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_smpte_subs_test)
210 using namespace boost::algorithm;
211 using namespace boost::filesystem;
212 boost::filesystem::path const out = "build/test/combine_two_dcps_with_smpte_subs_test";
214 shared_ptr<dcp::DCP> first = make_simple_with_smpte_subs ("build/test/combine_input1");
215 first->write_xml (dcp::SMPTE);
217 shared_ptr<dcp::DCP> second = make_simple_with_smpte_subs ("build/test/combine_input2");
218 second->write_xml (dcp::SMPTE);
222 inputs.push_back ("build/test/combine_input1");
223 inputs.push_back ("build/test/combine_input2");
224 dcp::combine (inputs, out);
226 check_no_errors (out);
227 check_combined (inputs, out);
231 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_interop_ccaps_test)
233 using namespace boost::algorithm;
234 using namespace boost::filesystem;
235 boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_ccaps_test";
237 shared_ptr<dcp::DCP> first = make_simple_with_interop_ccaps ("build/test/combine_input1");
238 first->write_xml (dcp::INTEROP);
240 shared_ptr<dcp::DCP> second = make_simple_with_interop_ccaps ("build/test/combine_input2");
241 second->write_xml (dcp::INTEROP);
245 inputs.push_back ("build/test/combine_input1");
246 inputs.push_back ("build/test/combine_input2");
247 dcp::combine (inputs, out);
249 check_no_errors (out);
250 check_combined (inputs, out);
254 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_smpte_ccaps_test)
256 using namespace boost::algorithm;
257 using namespace boost::filesystem;
258 boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_ccaps_test";
260 shared_ptr<dcp::DCP> first = make_simple_with_smpte_ccaps ("build/test/combine_input1");
261 first->write_xml (dcp::SMPTE);
263 shared_ptr<dcp::DCP> second = make_simple_with_smpte_ccaps ("build/test/combine_input2");
264 second->write_xml (dcp::SMPTE);
268 inputs.push_back ("build/test/combine_input1");
269 inputs.push_back ("build/test/combine_input2");
270 dcp::combine (inputs, out);
272 check_no_errors (out);
273 check_combined (inputs, out);
277 BOOST_AUTO_TEST_CASE (combine_two_multi_reel_dcps)
279 using namespace boost::algorithm;
280 using namespace boost::filesystem;
281 boost::filesystem::path const out = "build/test/combine_two_multi_reel_dcps";
283 shared_ptr<dcp::DCP> first = make_simple ("build/test/combine_input1", 4);
284 first->write_xml (dcp::SMPTE);
286 shared_ptr<dcp::DCP> second = make_simple ("build/test/combine_input2", 4);
287 second->write_xml (dcp::SMPTE);
291 inputs.push_back ("build/test/combine_input1");
292 inputs.push_back ("build/test/combine_input2");
293 dcp::combine (inputs, out);
295 check_no_errors (out);
296 check_combined (inputs, out);
300 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_shared_asset)
302 using namespace boost::filesystem;
303 boost::filesystem::path const out = "build/test/combine_two_dcps_with_shared_asset";
305 shared_ptr<dcp::DCP> first = make_simple ("build/test/combine_input1", 1);
306 first->write_xml (dcp::SMPTE);
308 remove_all ("build/test/combine_input2");
309 shared_ptr<dcp::DCP> second(new dcp::DCP("build/test/combine_input2"));
311 dcp::MXFMetadata mxf_meta;
312 mxf_meta.company_name = "OpenDCP";
313 mxf_meta.product_version = "0.0.25";
315 shared_ptr<dcp::CPL> cpl (new dcp::CPL("A Test DCP", dcp::TRAILER));
316 cpl->set_content_version (
317 dcp::ContentVersion("urn:uuid:75ac29aa-42ac-1234-ecae-49251abefd11","content-version-label-text")
320 shared_ptr<dcp::ReelMonoPictureAsset> pic(new dcp::ReelMonoPictureAsset(simple_picture("build/test/combine_input2", ""), 0));
321 shared_ptr<dcp::ReelSoundAsset> sound(new dcp::ReelSoundAsset(first->cpls().front()->reels().front()->main_sound()->asset(), 0));
322 cpl->add (shared_ptr<dcp::Reel>(new dcp::Reel(pic, sound)));
324 second->write_xml (dcp::SMPTE);
328 inputs.push_back ("build/test/combine_input1");
329 inputs.push_back ("build/test/combine_input2");
330 dcp::combine (inputs, out);
332 check_no_errors (out);
333 check_combined (inputs, out);
337 /* XXX: same CPL names */
338 /* XXX: Interop PNG subs */