/* Copyright (C) 2012-2015 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file src/dcp.cc * @brief DCP class. */ #include "raw_convert.h" #include "dc_package.h" #include "sound_asset.h" #include "picture_asset.h" #include "interop_subtitle_asset.h" #include "smpte_subtitle_asset.h" #include "mono_picture_asset.h" #include "stereo_picture_asset.h" #include "reel_subtitle_asset.h" #include "util.h" #include "metadata.h" #include "exceptions.h" #include "dc_cpl.h" #include "certificate_chain.h" #include "compose.hpp" #include "AS_DCP.h" #include "decrypted_kdm.h" #include "decrypted_kdm_key.h" #include "dcp_assert.h" #include "reel_asset.h" #include "font_asset.h" #include "package.h" #include #include #include #include #include #include #include using std::string; using std::list; using std::cout; using std::ostream; using std::make_pair; using std::map; using std::cout; using std::cerr; using std::exception; using boost::shared_ptr; using boost::dynamic_pointer_cast; using boost::algorithm::starts_with; using namespace dcp::dc; Package::Package (boost::filesystem::path directory) : dcp::Package (directory) { } bool Package::equals (Package const & other, dcp::EqualityOptions opt, dcp::NoteHandler note) const { list > a = cpls (); list > b = other.cpls (); if (a.size() != b.size()) { note (DCP_ERROR, String::compose ("CPL counts differ: %1 vs %2", a.size(), b.size())); return false; } bool r = true; BOOST_FOREACH (shared_ptr i, a) { list >::const_iterator j = b.begin (); while (j != b.end() && !(*j)->equals (i, opt, note)) { ++j; } if (j == b.end ()) { r = false; } } return r; } bool Package::encrypted () const { BOOST_FOREACH (shared_ptr i, cpls ()) { if (i->encrypted ()) { return true; } } return false; } void Package::add_kdm (DecryptedKDM const & kdm) { list keys = kdm.keys (); BOOST_FOREACH (shared_ptr i, cpls ()) { BOOST_FOREACH (DecryptedKDMKey const & j, kdm.keys ()) { if (j.cpl_id() == i->id()) { i->add (kdm); } } } } /** Write all the XML files for this DCP. * @param standand INTEROP or SMPTE. * @param metadata Metadata to use for PKL and asset map files. * @param signer Signer to use, or 0. */ void Package::write_xml ( Standard standard, dcp::XMLMetadata metadata, shared_ptr signer ) { do_write_xml (standard, metadata, signer); } /** @return All assets (including CPLs) */ list > Package::assets () const { list > assets; BOOST_FOREACH (shared_ptr i, cpls ()) { assets.push_back (i); BOOST_FOREACH (shared_ptr j, i->reel_assets ()) { shared_ptr o = j->asset_ref().asset (); assets.push_back (o); /* More Interop special-casing */ shared_ptr sub = dynamic_pointer_cast (o); if (sub) { sub->add_font_assets (assets); } } } return assets; } shared_ptr Package::xml_asset_factory (boost::filesystem::path file, string root) const { shared_ptr asset; if (root == "CompositionPlaylist") { asset.reset (new CPL (file)); } else if (root == "DCSubtitle") { asset.reset (new InteropSubtitleAsset (file)); } return asset; } shared_ptr Package::mxf_asset_factory (boost::filesystem::path file) const { shared_ptr asset; ASDCP::EssenceType_t type; if (ASDCP::EssenceType (file.string().c_str(), type) != ASDCP::RESULT_OK) { throw PackageReadError ("Could not find essence type"); } switch (type) { case ASDCP::ESS_UNKNOWN: case ASDCP::ESS_MPEG2_VES: throw PackageReadError ("MPEG2 video essences are not supported"); case ASDCP::ESS_JPEG_2000: asset.reset (new MonoPictureAsset (file)); break; case ASDCP::ESS_PCM_24b_48k: case ASDCP::ESS_PCM_24b_96k: asset.reset (new SoundAsset (file)); break; case ASDCP::ESS_JPEG_2000_S: asset.reset (new StereoPictureAsset (file)); break; case ASDCP::ESS_TIMED_TEXT: asset.reset (new SMPTESubtitleAsset (file)); break; default: throw PackageReadError ("Unknown MXF essence type"); } return asset; } string Package::pkl_annotation_text () const { DCP_ASSERT (!_cpls.empty ()); return _cpls.front()->annotation_text (); }