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::NOT_SMPTE && i.code() != dcp::VerificationNote::SUBTITLE_TOO_SHORT;
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");
160 dcp::combine (inputs, out);
162 check_no_errors (out);
163 check_combined (inputs, out);
167 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_same_asset_filenames_test)
169 using namespace boost::algorithm;
170 using namespace boost::filesystem;
171 boost::filesystem::path const out = "build/test/combine_two_dcps_with_same_asset_filenames_test";
173 shared_ptr<dcp::DCP> second = make_simple ("build/test/combine_input2");
174 second->write_xml (dcp::SMPTE);
178 inputs.push_back ("test/ref/DCP/dcp_test1");
179 inputs.push_back ("build/test/combine_input2");
180 dcp::combine (inputs, out);
182 check_no_errors (out);
183 check_combined (inputs, out);
187 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_interop_subs_test)
189 using namespace boost::algorithm;
190 using namespace boost::filesystem;
191 boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_subs_test";
193 shared_ptr<dcp::DCP> first = make_simple_with_interop_subs ("build/test/combine_input1");
194 first->write_xml (dcp::INTEROP);
196 shared_ptr<dcp::DCP> second = make_simple_with_interop_subs ("build/test/combine_input2");
197 second->write_xml (dcp::INTEROP);
201 inputs.push_back ("build/test/combine_input1");
202 inputs.push_back ("build/test/combine_input2");
203 dcp::combine (inputs, out);
205 check_no_errors (out);
206 check_combined (inputs, out);
210 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_smpte_subs_test)
212 using namespace boost::algorithm;
213 using namespace boost::filesystem;
214 boost::filesystem::path const out = "build/test/combine_two_dcps_with_smpte_subs_test";
216 shared_ptr<dcp::DCP> first = make_simple_with_smpte_subs ("build/test/combine_input1");
217 first->write_xml (dcp::SMPTE);
219 shared_ptr<dcp::DCP> second = make_simple_with_smpte_subs ("build/test/combine_input2");
220 second->write_xml (dcp::SMPTE);
224 inputs.push_back ("build/test/combine_input1");
225 inputs.push_back ("build/test/combine_input2");
226 dcp::combine (inputs, out);
228 check_no_errors (out);
229 check_combined (inputs, out);
233 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_interop_ccaps_test)
235 using namespace boost::algorithm;
236 using namespace boost::filesystem;
237 boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_ccaps_test";
239 shared_ptr<dcp::DCP> first = make_simple_with_interop_ccaps ("build/test/combine_input1");
240 first->write_xml (dcp::INTEROP);
242 shared_ptr<dcp::DCP> second = make_simple_with_interop_ccaps ("build/test/combine_input2");
243 second->write_xml (dcp::INTEROP);
247 inputs.push_back ("build/test/combine_input1");
248 inputs.push_back ("build/test/combine_input2");
249 dcp::combine (inputs, out);
251 check_no_errors (out);
252 check_combined (inputs, out);
256 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_smpte_ccaps_test)
258 using namespace boost::algorithm;
259 using namespace boost::filesystem;
260 boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_ccaps_test";
262 shared_ptr<dcp::DCP> first = make_simple_with_smpte_ccaps ("build/test/combine_input1");
263 first->write_xml (dcp::SMPTE);
265 shared_ptr<dcp::DCP> second = make_simple_with_smpte_ccaps ("build/test/combine_input2");
266 second->write_xml (dcp::SMPTE);
270 inputs.push_back ("build/test/combine_input1");
271 inputs.push_back ("build/test/combine_input2");
272 dcp::combine (inputs, out);
274 check_no_errors (out);
275 check_combined (inputs, out);
279 BOOST_AUTO_TEST_CASE (combine_two_multi_reel_dcps)
281 using namespace boost::algorithm;
282 using namespace boost::filesystem;
283 boost::filesystem::path const out = "build/test/combine_two_multi_reel_dcps";
285 shared_ptr<dcp::DCP> first = make_simple ("build/test/combine_input1", 4);
286 first->write_xml (dcp::SMPTE);
288 shared_ptr<dcp::DCP> second = make_simple ("build/test/combine_input2", 4);
289 second->write_xml (dcp::SMPTE);
293 inputs.push_back ("build/test/combine_input1");
294 inputs.push_back ("build/test/combine_input2");
295 dcp::combine (inputs, out);
297 check_no_errors (out);
298 check_combined (inputs, out);
302 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_shared_asset)
304 using namespace boost::filesystem;
305 boost::filesystem::path const out = "build/test/combine_two_dcps_with_shared_asset";
307 shared_ptr<dcp::DCP> first = make_simple ("build/test/combine_input1", 1);
308 first->write_xml (dcp::SMPTE);
310 remove_all ("build/test/combine_input2");
311 shared_ptr<dcp::DCP> second(new dcp::DCP("build/test/combine_input2"));
313 dcp::MXFMetadata mxf_meta;
314 mxf_meta.company_name = "OpenDCP";
315 mxf_meta.product_version = "0.0.25";
317 shared_ptr<dcp::CPL> cpl (new dcp::CPL("A Test DCP", dcp::TRAILER));
318 cpl->set_content_version (
319 dcp::ContentVersion("urn:uuid:75ac29aa-42ac-1234-ecae-49251abefd11","content-version-label-text")
322 shared_ptr<dcp::ReelMonoPictureAsset> pic(new dcp::ReelMonoPictureAsset(simple_picture("build/test/combine_input2", ""), 0));
323 shared_ptr<dcp::ReelSoundAsset> sound(new dcp::ReelSoundAsset(first->cpls().front()->reels().front()->main_sound()->asset(), 0));
324 auto reel = make_shared<dcp::Reel>(pic, sound);
325 reel->add (simple_markers());
328 second->write_xml (dcp::SMPTE);
332 inputs.push_back ("build/test/combine_input1");
333 inputs.push_back ("build/test/combine_input2");
334 dcp::combine (inputs, out);
336 check_no_errors (out);
337 check_combined (inputs, out);
341 /* XXX: same CPL names */
342 /* XXX: Interop PNG subs */